@decaf-ts/for-typeorm 0.0.6

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 (109) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +93 -0
  3. package/dist/for-typeorm.cjs +2553 -0
  4. package/dist/for-typeorm.esm.cjs +2538 -0
  5. package/lib/TypeORMAdapter.cjs +1129 -0
  6. package/lib/TypeORMAdapter.d.ts +221 -0
  7. package/lib/TypeORMDispatch.cjs +134 -0
  8. package/lib/TypeORMDispatch.d.ts +87 -0
  9. package/lib/TypeORMEventSubscriber.cjs +96 -0
  10. package/lib/TypeORMEventSubscriber.d.ts +56 -0
  11. package/lib/TypeORMRepository.cjs +209 -0
  12. package/lib/TypeORMRepository.d.ts +125 -0
  13. package/lib/constants.cjs +43 -0
  14. package/lib/constants.d.ts +39 -0
  15. package/lib/errors.cjs +28 -0
  16. package/lib/errors.d.ts +21 -0
  17. package/lib/esm/TypeORMAdapter.d.ts +221 -0
  18. package/lib/esm/TypeORMAdapter.js +1124 -0
  19. package/lib/esm/TypeORMDispatch.d.ts +87 -0
  20. package/lib/esm/TypeORMDispatch.js +130 -0
  21. package/lib/esm/TypeORMEventSubscriber.d.ts +56 -0
  22. package/lib/esm/TypeORMEventSubscriber.js +93 -0
  23. package/lib/esm/TypeORMRepository.d.ts +125 -0
  24. package/lib/esm/TypeORMRepository.js +206 -0
  25. package/lib/esm/constants.d.ts +39 -0
  26. package/lib/esm/constants.js +40 -0
  27. package/lib/esm/errors.d.ts +21 -0
  28. package/lib/esm/errors.js +24 -0
  29. package/lib/esm/index.d.ts +22 -0
  30. package/lib/esm/index.js +25 -0
  31. package/lib/esm/indexes/generator.d.ts +50 -0
  32. package/lib/esm/indexes/generator.js +95 -0
  33. package/lib/esm/indexes/index.d.ts +1 -0
  34. package/lib/esm/indexes/index.js +2 -0
  35. package/lib/esm/overrides/Column.d.ts +74 -0
  36. package/lib/esm/overrides/Column.js +70 -0
  37. package/lib/esm/overrides/CreateDateColumn.d.ts +2 -0
  38. package/lib/esm/overrides/CreateDateColumn.js +9 -0
  39. package/lib/esm/overrides/Entity.d.ts +11 -0
  40. package/lib/esm/overrides/Entity.js +28 -0
  41. package/lib/esm/overrides/PrimaryColumn.d.ts +20 -0
  42. package/lib/esm/overrides/PrimaryColumn.js +53 -0
  43. package/lib/esm/overrides/PrimaryGeneratedColumn.d.ts +24 -0
  44. package/lib/esm/overrides/PrimaryGeneratedColumn.js +51 -0
  45. package/lib/esm/overrides/UpdateDateColumn.d.ts +2 -0
  46. package/lib/esm/overrides/UpdateDateColumn.js +9 -0
  47. package/lib/esm/overrides/utils.d.ts +2 -0
  48. package/lib/esm/overrides/utils.js +29 -0
  49. package/lib/esm/query/Paginator.d.ts +86 -0
  50. package/lib/esm/query/Paginator.js +124 -0
  51. package/lib/esm/query/Statement.d.ts +131 -0
  52. package/lib/esm/query/Statement.js +242 -0
  53. package/lib/esm/query/constants.d.ts +52 -0
  54. package/lib/esm/query/constants.js +74 -0
  55. package/lib/esm/query/index.d.ts +4 -0
  56. package/lib/esm/query/index.js +5 -0
  57. package/lib/esm/query/translate.d.ts +34 -0
  58. package/lib/esm/query/translate.js +42 -0
  59. package/lib/esm/raw/postgres.d.ts +36 -0
  60. package/lib/esm/raw/postgres.js +2 -0
  61. package/lib/esm/sequences/Sequence.d.ts +67 -0
  62. package/lib/esm/sequences/Sequence.js +117 -0
  63. package/lib/esm/sequences/index.d.ts +1 -0
  64. package/lib/esm/sequences/index.js +2 -0
  65. package/lib/esm/types.d.ts +67 -0
  66. package/lib/esm/types.js +28 -0
  67. package/lib/esm/utils.d.ts +16 -0
  68. package/lib/esm/utils.js +29 -0
  69. package/lib/index.cjs +42 -0
  70. package/lib/index.d.ts +22 -0
  71. package/lib/indexes/generator.cjs +98 -0
  72. package/lib/indexes/generator.d.ts +50 -0
  73. package/lib/indexes/index.cjs +18 -0
  74. package/lib/indexes/index.d.ts +1 -0
  75. package/lib/overrides/Column.cjs +73 -0
  76. package/lib/overrides/Column.d.ts +74 -0
  77. package/lib/overrides/CreateDateColumn.cjs +12 -0
  78. package/lib/overrides/CreateDateColumn.d.ts +2 -0
  79. package/lib/overrides/Entity.cjs +31 -0
  80. package/lib/overrides/Entity.d.ts +11 -0
  81. package/lib/overrides/PrimaryColumn.cjs +56 -0
  82. package/lib/overrides/PrimaryColumn.d.ts +20 -0
  83. package/lib/overrides/PrimaryGeneratedColumn.cjs +54 -0
  84. package/lib/overrides/PrimaryGeneratedColumn.d.ts +24 -0
  85. package/lib/overrides/UpdateDateColumn.cjs +12 -0
  86. package/lib/overrides/UpdateDateColumn.d.ts +2 -0
  87. package/lib/overrides/utils.cjs +32 -0
  88. package/lib/overrides/utils.d.ts +2 -0
  89. package/lib/query/Paginator.cjs +128 -0
  90. package/lib/query/Paginator.d.ts +86 -0
  91. package/lib/query/Statement.cjs +246 -0
  92. package/lib/query/Statement.d.ts +131 -0
  93. package/lib/query/constants.cjs +77 -0
  94. package/lib/query/constants.d.ts +52 -0
  95. package/lib/query/index.cjs +21 -0
  96. package/lib/query/index.d.ts +4 -0
  97. package/lib/query/translate.cjs +45 -0
  98. package/lib/query/translate.d.ts +34 -0
  99. package/lib/raw/postgres.cjs +3 -0
  100. package/lib/raw/postgres.d.ts +36 -0
  101. package/lib/sequences/Sequence.cjs +121 -0
  102. package/lib/sequences/Sequence.d.ts +67 -0
  103. package/lib/sequences/index.cjs +18 -0
  104. package/lib/sequences/index.d.ts +1 -0
  105. package/lib/types.cjs +31 -0
  106. package/lib/types.d.ts +67 -0
  107. package/lib/utils.cjs +32 -0
  108. package/lib/utils.d.ts +16 -0
  109. package/package.json +128 -0
@@ -0,0 +1,2538 @@
1
+ import { __decorate, __metadata } from 'tslib';
2
+ import { Paginator, PagingError, QueryError, Statement, Repository, OrderDirection, GroupOperator, Operator, Sequence, PersistenceKeys, uses, Dispatch, Adapter, ConnectionError, Cascade, final } from '@decaf-ts/core';
3
+ import { BaseError, findPrimaryKey, InternalError, NotFoundError, DefaultSeparator, Context, OperationKeys, enforceDBDecorators, ValidationError, DBKeys, ConflictError, readonly, UpdateValidationKeys, DEFAULT_ERROR_MESSAGES as DEFAULT_ERROR_MESSAGES$1 } from '@decaf-ts/db-decorators';
4
+ import 'reflect-metadata';
5
+ import { ModelKeys, Model, ValidationKeys, DEFAULT_ERROR_MESSAGES, Decoration, propMetadata, Validation, type, prop, list, required, date } from '@decaf-ts/decorator-validation';
6
+ import { Reflection, apply } from '@decaf-ts/reflection';
7
+ import { Logging } from '@decaf-ts/logging';
8
+ import { EventSubscriber, getMetadataArgsStorage, ColumnTypeUndefinedError, PrimaryColumnCannotBeNullableError, DataSource, In, VersionColumn, OneToOne, JoinColumn, OneToMany, ManyToOne, ManyToMany, JoinTable } from 'typeorm';
9
+ import { ObjectUtils } from 'typeorm/util/ObjectUtils';
10
+
11
+ /**
12
+ * @description Regular expression to identify reserved attributes for SQL contexts.
13
+ * @summary Matches attribute names that conflict with SQL reserved keywords to prevent invalid schema or query generation.
14
+ * @const reservedAttributes
15
+ * @memberOf module:for-typeorm
16
+ */
17
+ const reservedAttributes = /^(select|from|where|and|or|insert|update|delete|drop|create|table|index|primary|key|foreign|references|constraint|unique|check|default|null|not|as|order|by|group|having|limit|offset|join|inner|outer|left|right|full|on|using|values|returning|set|into|case|when|then|else|end|cast|coalesce|exists|any|all|some|in|between|like|ilike|similar|to|is|true|false|asc|desc|distinct|union|intersect|except|natural|lateral|window|over|partition|range|rows|unbounded|preceding|following|current|row|with|recursive|materialized|view|function|trigger|procedure|language|returns|return|declare|begin|commit|rollback|savepoint|transaction|temporary|temp|if|loop|while|for|continue|exit|raise|exception|notice|info|log|debug|assert|execute|perform|get|diagnostics|call|do|alias|comment|vacuum|analyze|explain|copy|grant|revoke|privileges|public|usage|schema|sequence|owned|owner|tablespace|storage|inherits|type|operator|collate|collation|cascade|restrict|add|alter|column|rename|to|enable|disable|force|no|instead|of|before|after|each|statement|row|execute|also|only|exclude|nulls|others|ordinality|ties|nothing|cache|cycle|increment|minvalue|maxvalue|start|restart|by|called|returns|language|immutable|stable|volatile|strict|security|definer|invoker|cost|rows|support|handler|inline|validator|options|storage|inheritance|oids|without|data|dictionary|encoding|lc_collate|lc_ctype|connection|limit|password|valid|until|superuser|nosuperuser|createdb|nocreatedb|createrole|nocreaterole|inherit|noinherit|login|nologin|replication|noreplication|bypassrls|nobypassrls|encrypted|unencrypted|new|old|session_user|current_user|current_role|current_schema|current_catalog|current_date|current_time|current_timestamp|localtime|localtimestamp|current_database|inet|cidr|macaddr|macaddr8|bit|varbit|tsvector|tsquery|uuid|xml|json|jsonb|int|integer|smallint|bigint|decimal|numeric|real|double|precision|float|boolean|bool|char|character|varchar|text|bytea|date|time|timestamp|interval|point|line|lseg|box|path|polygon|circle|money|void)$/i;
18
+ const TypeORMFlavour = "type-orm";
19
+ /**
20
+ * @description Shape of the TypeORMKeys constant.
21
+ * @summary Describes the keys and their meanings used by the TypeORM adapter.
22
+ * @typedef TypeORMKeysDef
23
+ * @property {string} SEPARATOR Separator used to join table and column identifiers.
24
+ * @property {string} ID Default primary key field name.
25
+ * @property {string} VERSION Version field used for optimistic locking.
26
+ * @property {string} DELETED Soft-delete timestamp field.
27
+ * @property {string} TABLE Database table identifier key.
28
+ * @property {string} SCHEMA Database schema identifier key.
29
+ * @property {string} SEQUENCE Database sequence name key.
30
+ * @property {string} INDEX Index identifier key.
31
+ * @memberOf module:for-typeorm
32
+ */
33
+ /**
34
+ * @description Key constants used by the TypeORM adapter.
35
+ * @summary Collection of string constants that identify common database properties and adapter-specific keys.
36
+ * @const TypeORMKeys
37
+ * @type {TypeORMKeysDef}
38
+ * @memberOf module:for-typeorm
39
+ */
40
+ const TypeORMKeys = {
41
+ SEPARATOR: ".",
42
+ ID: "id",
43
+ VERSION: "version",
44
+ DELETED: "deleted_at",
45
+ TABLE: "table_name",
46
+ SCHEMA: "schema_name",
47
+ SEQUENCE: "sequence_name",
48
+ INDEX: "index",
49
+ };
50
+
51
+ /**
52
+ * @description Error thrown when there is an issue with TypeORM indexes.
53
+ * @summary Represents an error related to index generation or handling within the TypeORM adapter.
54
+ * @param {string|Error} msg The error message or Error object.
55
+ * @class
56
+ * @category Errors
57
+ * @example
58
+ * // Example of using IndexError
59
+ * try {
60
+ * // Some code that might throw an index error
61
+ * throw new IndexError("Index not found");
62
+ * } catch (error) {
63
+ * if (error instanceof IndexError) {
64
+ * console.error("Index error occurred:", error.message);
65
+ * }
66
+ * }
67
+ */
68
+ class IndexError extends BaseError {
69
+ constructor(msg) {
70
+ super(IndexError.name, msg, 404);
71
+ }
72
+ }
73
+
74
+ /**
75
+ * @description SQL operators available for building TypeORM queries.
76
+ * @summary Enumeration of common SQL operators intended for use within TypeORM query construction and translation layers.
77
+ * @enum {string}
78
+ * @memberOf module:for-typeorm
79
+ */
80
+ var SQLOperator;
81
+ (function (SQLOperator) {
82
+ SQLOperator["EQUAL"] = "=";
83
+ SQLOperator["NOT_EQUAL"] = "<>";
84
+ SQLOperator["LESS_THAN"] = "<";
85
+ SQLOperator["LESS_THAN_OR_EQUAL"] = "<=";
86
+ SQLOperator["GREATER_THAN"] = ">";
87
+ SQLOperator["GREATER_THAN_OR_EQUAL"] = ">=";
88
+ SQLOperator["IN"] = "IN";
89
+ SQLOperator["NOT_IN"] = "NOT IN";
90
+ SQLOperator["LIKE"] = "LIKE";
91
+ SQLOperator["ILIKE"] = "ILIKE";
92
+ SQLOperator["BETWEEN"] = "BETWEEN";
93
+ SQLOperator["IS_NULL"] = "IS NULL";
94
+ SQLOperator["IS_NOT_NULL"] = "IS NOT NULL";
95
+ SQLOperator["EXISTS"] = "EXISTS";
96
+ SQLOperator["NOT_EXISTS"] = "NOT EXISTS";
97
+ SQLOperator["ANY"] = "ANY";
98
+ SQLOperator["ALL"] = "ALL";
99
+ SQLOperator["SOME"] = "SOME";
100
+ })(SQLOperator || (SQLOperator = {}));
101
+
102
+ /**
103
+ * @description Default query limit for TypeORM-backed queries.
104
+ * @summary Maximum number of records to return in a single page when paginating results.
105
+ * @const TypeORMQueryLimit
106
+ * @memberOf module:for-typeorm
107
+ */
108
+ const TypeORMQueryLimit = 250;
109
+ /**
110
+ * @description Mapping of operator names to SQL operators.
111
+ * @summary Constants for comparison operators used when translating high-level filters into SQL via TypeORM.
112
+ * @typedef {Object} PostgreSQLOperatorType
113
+ * @property {string} EQUAL Equality operator (=)
114
+ * @property {string} DIFFERENT Inequality operator (<>)
115
+ * @property {string} BIGGER Greater than operator (>)
116
+ * @property {string} BIGGER_EQ Greater than or equal operator (>=)
117
+ * @property {string} SMALLER Less than operator (<)
118
+ * @property {string} SMALLER_EQ Less than or equal operator (<=)
119
+ * @property {string} NOT Negation operator (NOT)
120
+ * @property {string} IN In array operator (IN)
121
+ * @property {string} REGEXP Regular expression operator (~)
122
+ * @property {string} IREGEXP Case-insensitive regular expression operator (~*)
123
+ * @property {string} LIKE Pattern matching operator (LIKE)
124
+ * @property {string} ILIKE Case-insensitive pattern matching operator (ILIKE)
125
+ * @property {string} BETWEEN Range operator (BETWEEN)
126
+ * @property {string} IS_NULL NULL check operator (IS NULL)
127
+ * @property {string} IS_NOT_NULL NOT NULL check operator (IS NOT NULL)
128
+ * @const TypeORMOperator
129
+ * @type {PostgreSQLOperatorType}
130
+ * @memberOf module:for-typeorm
131
+ */
132
+ const TypeORMOperator = {
133
+ EQUAL: SQLOperator.EQUAL,
134
+ DIFFERENT: SQLOperator.NOT_EQUAL,
135
+ BIGGER: SQLOperator.GREATER_THAN,
136
+ BIGGER_EQ: SQLOperator.GREATER_THAN_OR_EQUAL,
137
+ SMALLER: SQLOperator.LESS_THAN,
138
+ SMALLER_EQ: SQLOperator.LESS_THAN_OR_EQUAL,
139
+ BETWEEN: SQLOperator.BETWEEN,
140
+ NOT: "NOT",
141
+ IN: SQLOperator.IN,
142
+ IS_NULL: SQLOperator.IS_NULL,
143
+ IS_NOT_NULL: SQLOperator.IS_NOT_NULL,
144
+ REGEXP: "~",
145
+ IREGEXP: "~*",
146
+ LIKE: SQLOperator.LIKE,
147
+ ILIKE: SQLOperator.ILIKE,
148
+ };
149
+ /**
150
+ * @description Mapping of logical operator names to SQL operators.
151
+ * @summary Constants for logical operators used when building WHERE clause groups in TypeORM queries.
152
+ * @typedef {Object} PostgreSQLGroupOperatorType
153
+ * @property {string} AND Logical AND operator (AND)
154
+ * @property {string} OR Logical OR operator (OR)
155
+ * @const TypeORMGroupOperator
156
+ * @type {PostgreSQLGroupOperatorType}
157
+ * @memberOf module:for-typeorm
158
+ */
159
+ const TypeORMGroupOperator = {
160
+ AND: "AND",
161
+ OR: "OR",
162
+ };
163
+ /**
164
+ * @description Special constant values used in queries.
165
+ * @summary String constants representing special values used while composing SQL with TypeORM.
166
+ * @typedef {Object} PostgreSQLConstType
167
+ * @property {string} NULL String representation of null value.
168
+ * @const TypeORMConst
169
+ * @memberOf module:for-typeorm
170
+ */
171
+ const TypeORMConst = {
172
+ NULL: "NULL",
173
+ };
174
+
175
+ /**
176
+ * @description Paginator for TypeORM query results.
177
+ * @summary Implements pagination for TypeORM-built queries using take/skip for efficient navigation through result sets.
178
+ * @template M The model type that extends Model.
179
+ * @template R The result type.
180
+ * @param {TypeORMAdapter} adapter The TypeORM adapter.
181
+ * @param {TypeORMQuery} query The query container to paginate.
182
+ * @param {number} size The page size.
183
+ * @param {Constructor<M>} clazz The model constructor.
184
+ * @class TypeORMPaginator
185
+ * @example
186
+ * // Example of using TypeORMPaginator
187
+ * const paginator = new TypeORMPaginator(adapter, { query: qb }, 10, User);
188
+ * const page1 = await paginator.page(1);
189
+ * const page2 = await paginator.page(2);
190
+ */
191
+ class TypeORMPaginator extends Paginator {
192
+ /**
193
+ * @description Gets the total number of pages
194
+ * @summary Returns the total number of pages based on the record count and page size
195
+ * @return {number} The total number of pages
196
+ */
197
+ get total() {
198
+ return this._totalPages;
199
+ }
200
+ /**
201
+ * @description Gets the total record count
202
+ * @summary Returns the total number of records matching the query
203
+ * @return {number} The total record count
204
+ */
205
+ get count() {
206
+ return this._recordCount;
207
+ }
208
+ get repo() {
209
+ if (!this.__repo) {
210
+ this.__repo = this.adapter.dataSource.getRepository(this.clazz[ModelKeys.ANCHOR]);
211
+ }
212
+ return this.__repo;
213
+ }
214
+ /**
215
+ * @description Creates a new TypeORMPaginator instance.
216
+ * @summary Initializes a paginator for TypeORM query results.
217
+ * @param {TypeORMAdapter} adapter The TypeORM adapter.
218
+ * @param {TypeORMQuery} query The TypeORM query container to paginate.
219
+ * @param {number} size The page size.
220
+ * @param {Constructor<M>} clazz The model constructor.
221
+ */
222
+ constructor(adapter, query, size, clazz) {
223
+ super(adapter, query, size, clazz);
224
+ }
225
+ /**
226
+ * @description Prepares a query for pagination
227
+ * @summary Modifies the raw query to include pagination parameters
228
+ * @param {TypeORMQuery} rawStatement - The original PostgreSQL query
229
+ * @return {TypeORMQuery} The prepared query with pagination parameters
230
+ */
231
+ prepare(rawStatement) {
232
+ const query = { ...rawStatement };
233
+ return query;
234
+ }
235
+ /**
236
+ * @description Retrieves a specific page of results.
237
+ * @summary Executes the query with pagination and processes the results.
238
+ * @param {number} [page=1] The page number to retrieve.
239
+ * @return {Promise<R[]>} A promise that resolves to an array of results.
240
+ * @throws {PagingError} If trying to access an invalid page or if no class is defined.
241
+ * @mermaid
242
+ * sequenceDiagram
243
+ * participant Client
244
+ * participant Paginator as TypeORMPaginator
245
+ * participant Adapter
246
+ * participant DB as Database
247
+ *
248
+ * Client->>Paginator: page(pageNumber)
249
+ * Note over Paginator: Prepare options (skip/take)
250
+ *
251
+ * alt First time or need count
252
+ * Paginator->>Adapter: Get count
253
+ * Adapter->>DB: Execute COUNT
254
+ * DB-->>Adapter: count
255
+ * Adapter-->>Paginator: count
256
+ * Paginator->>Paginator: Calculate total pages
257
+ * end
258
+ *
259
+ * Paginator->>Adapter: Execute query
260
+ * Adapter->>DB: findAndCount(options)
261
+ * DB-->>Adapter: rows, count
262
+ * Adapter-->>Paginator: rows, count
263
+ *
264
+ * Paginator->>Paginator: Map rows to models
265
+ * Paginator-->>Client: results
266
+ */
267
+ async page(page = 1) {
268
+ const statement = { ...this.statement };
269
+ // Get total count if not already calculated
270
+ if (!this._recordCount || !this._totalPages) {
271
+ this._totalPages = this._recordCount = 0;
272
+ }
273
+ const opts = Object.assign(statement, {
274
+ skip: (this.current || 0) * this.size,
275
+ take: this.size,
276
+ });
277
+ // this.validatePage(page);
278
+ const result = await this.repo.findAndCount(opts);
279
+ this._recordCount = result[1];
280
+ this._totalPages = Math.ceil(this._recordCount / this.size);
281
+ if (!this.clazz)
282
+ throw new PagingError("No statement target defined");
283
+ const pkDef = findPrimaryKey(new this.clazz());
284
+ const rows = result[0] || [];
285
+ const results =
286
+ // statement.columns && statement.columns.length
287
+ // ? rows // has columns means it's not full model
288
+ rows.map((row) => {
289
+ return this.adapter.revert(row, this.clazz, pkDef.id, row[pkDef.id]);
290
+ });
291
+ this._currentPage = page;
292
+ return results;
293
+ }
294
+ }
295
+
296
+ /**
297
+ * @description Translates core operators to TypeORM SQL operators.
298
+ * @summary Converts Decaf.ts core operators to their equivalent SQL operators used by the TypeORM adapter.
299
+ * @param {GroupOperator | Operator} operator The core operator to translate.
300
+ * @return {SQLOperator | string} The equivalent SQL operator.
301
+ * @throws {QueryError} If no translation exists for the given operator.
302
+ * @function translateOperators
303
+ * @memberOf module:for-typeorm
304
+ * @mermaid
305
+ * sequenceDiagram
306
+ * participant Caller
307
+ * participant translateOperators
308
+ * participant PostgreSQLOperator
309
+ * participant PostgreSQLGroupOperator
310
+ *
311
+ * Caller->>translateOperators: operator
312
+ *
313
+ * translateOperators->>PostgreSQLOperator: Check for match
314
+ * alt Found in PostgreSQLOperator
315
+ * PostgreSQLOperator-->>translateOperators: Return matching operator
316
+ * translateOperators-->>Caller: Return SQLOperator
317
+ * else Not found
318
+ * translateOperators->>PostgreSQLGroupOperator: Check for match
319
+ * alt Found in PostgreSQLGroupOperator
320
+ * PostgreSQLGroupOperator-->>translateOperators: Return matching operator
321
+ * translateOperators-->>Caller: Return string
322
+ * else Not found
323
+ * translateOperators-->>Caller: Throw QueryError
324
+ * end
325
+ * end
326
+ */
327
+ function translateOperators(operator) {
328
+ for (const operators of [TypeORMOperator, TypeORMGroupOperator]) {
329
+ const el = Object.keys(operators).find((k) => k === operator);
330
+ if (el)
331
+ return operators[el];
332
+ }
333
+ throw new QueryError(`Could not find adapter translation for operator ${operator}`);
334
+ }
335
+
336
+ /**
337
+ * @description Statement builder for TypeORM-backed queries.
338
+ * @summary Provides a fluent interface for building SQL queries via TypeORM's SelectQueryBuilder with type safety and Decaf.ts abstractions.
339
+ * @template M The model type that extends Model.
340
+ * @template R The result type returned from execution.
341
+ * @param {TypeORMAdapter} adapter The TypeORM adapter.
342
+ * @class TypeORMStatement
343
+ * @example
344
+ * // Example using TypeORMStatement
345
+ * const statement = new TypeORMStatement<User, User[]>(adapter);
346
+ * const users = await statement
347
+ * .from(User)
348
+ * .where(Condition.attribute<User>('age').gt(18))
349
+ * .orderBy('lastName', 'asc')
350
+ * .limit(10)
351
+ * .execute();
352
+ */
353
+ class TypeORMStatement extends Statement {
354
+ constructor(adapter) {
355
+ super(adapter);
356
+ }
357
+ /**
358
+ * @description Builds a TypeORM SelectQueryBuilder from the statement.
359
+ * @summary Converts the statement's conditions, selectors, and options into a TypeORM-backed query object.
360
+ * @return {TypeORMQuery} The built TypeORM query container.
361
+ * @throws {Error} If there are invalid query conditions.
362
+ * @mermaid
363
+ * sequenceDiagram
364
+ * participant Statement
365
+ * participant Repository
366
+ * participant parseCondition
367
+ *
368
+ * Statement->>Statement: build()
369
+ * Note over Statement: Initialize query
370
+ * Statement->>Repository: Get table name
371
+ * Repository-->>Statement: Return table name
372
+ * Statement->>Statement: Create base query
373
+ *
374
+ * alt Has selectSelector
375
+ * Statement->>Statement: Add columns to query
376
+ * end
377
+ *
378
+ * alt Has whereCondition
379
+ * Statement->>Statement: Create combined condition with table
380
+ * Statement->>parseCondition: Parse condition
381
+ * parseCondition-->>Statement: Return parsed conditions
382
+ * Statement->>Statement: Add conditions to query
383
+ * end
384
+ *
385
+ * alt Has orderBySelector
386
+ * Statement->>Statement: Add orderBy to query
387
+ * end
388
+ *
389
+ * alt Has limitSelector
390
+ * Statement->>Statement: Set limit
391
+ * else
392
+ * Statement->>Statement: Use default limit
393
+ * end
394
+ *
395
+ * alt Has offsetSelector
396
+ * Statement->>Statement: Set offset
397
+ * end
398
+ *
399
+ * Statement-->>Statement: Return query
400
+ */
401
+ build() {
402
+ const log = this.log.for(this.build);
403
+ const tableName = Repository.table(this.fromSelector);
404
+ const m = new this.fromSelector();
405
+ const q = {
406
+ query: this.adapter.dataSource
407
+ .getRepository(this.fromSelector[ModelKeys.ANCHOR])
408
+ .createQueryBuilder(tableName),
409
+ };
410
+ if (this.selectSelector)
411
+ q.query = q.query.select(this.selectSelector.map((s) => `${tableName}.${s}`));
412
+ else
413
+ q.query = q.query.select();
414
+ //
415
+ // q.query = (q.query as SelectQueryBuilder<any>).from(
416
+ // this.fromSelector[ModelKeys.ANCHOR as keyof typeof this.fromSelector],
417
+ // tableName
418
+ // );
419
+ if (this.whereCondition)
420
+ q.query = this.parseCondition(this.whereCondition, tableName, q.query).query;
421
+ let orderByArgs;
422
+ if (!this.orderBySelector)
423
+ orderByArgs = [
424
+ `${tableName}.${findPrimaryKey(m).id}`,
425
+ OrderDirection.ASC.toUpperCase(),
426
+ ];
427
+ else
428
+ orderByArgs = [
429
+ `${tableName}.${this.orderBySelector[0]}`,
430
+ this.orderBySelector[1].toUpperCase(),
431
+ ];
432
+ q.query = q.query.orderBy(...orderByArgs);
433
+ if (this.limitSelector) {
434
+ q.query = q.query.limit(this.limitSelector);
435
+ }
436
+ else {
437
+ log.debug(`No limit selector defined. Using default limit of ${TypeORMQueryLimit}`);
438
+ q.query = q.query.limit(TypeORMQueryLimit);
439
+ }
440
+ // Add offset
441
+ if (this.offsetSelector)
442
+ q.query = q.query.skip(this.offsetSelector);
443
+ return q;
444
+ }
445
+ /**
446
+ * @description Creates a paginator for the statement.
447
+ * @summary Builds the query and returns a TypeORMPaginator for paginated results.
448
+ * @template R The result type.
449
+ * @param {number} size The page size.
450
+ * @return {Promise<Paginator<M, R, TypeORMQuery>>} A promise that resolves to a paginator.
451
+ * @throws {InternalError} If there's an error building the query.
452
+ */
453
+ async paginate(size) {
454
+ try {
455
+ const query = this.build();
456
+ const transformedQuery = {};
457
+ const a = query.query;
458
+ if (this.whereCondition)
459
+ transformedQuery.where = this.parseConditionForPagination(this.whereCondition, Repository.table(this.fromSelector));
460
+ if (this.orderBySelector)
461
+ transformedQuery.order = {
462
+ [this.orderBySelector[0]]: this.orderBySelector[1].toString(),
463
+ };
464
+ return new TypeORMPaginator(this.adapter, transformedQuery, size, this.fromSelector);
465
+ }
466
+ catch (e) {
467
+ throw new InternalError(e);
468
+ }
469
+ }
470
+ /**
471
+ * @description Processes a record.
472
+ * @summary Converts a raw result row to a model instance using the adapter.
473
+ * @param {any} r The raw record.
474
+ * @param {keyof M} pkAttr The primary key attribute of the model.
475
+ * @param {"Number" | "BigInt" | undefined} sequenceType The type of the sequence.
476
+ * @return {any} The processed record.
477
+ */
478
+ processRecord(r, pkAttr) {
479
+ if (typeof r[pkAttr] !== "undefined") {
480
+ return this.adapter.revert(r, this.fromSelector, pkAttr, r[pkAttr]);
481
+ }
482
+ return r;
483
+ }
484
+ /**
485
+ * @description Executes a raw TypeORM query builder.
486
+ * @summary Sends the built SelectQueryBuilder to the database via TypeORM and returns the results.
487
+ * @template R The result type.
488
+ * @param {TypeORMQuery} rawInput The query container to execute.
489
+ * @return {Promise<R>} A promise that resolves to the query results.
490
+ */
491
+ async raw(rawInput) {
492
+ const log = this.log.for(this.raw);
493
+ log.debug(`Executing raw query: ${rawInput.query.getSql()}`);
494
+ return (await rawInput.query.getMany());
495
+ }
496
+ parseConditionForPagination(condition, tableName, counter = 0, conditionalOp) {
497
+ throw new InternalError("Not implemented");
498
+ }
499
+ /**
500
+ * @description Parses a condition into PostgreSQL conditions
501
+ * @summary Converts a Condition object into PostgreSQL condition structures
502
+ * @param {Condition<M>} condition - The condition to parse
503
+ * @param {string} [tableName] - the positional index of the arguments
504
+ * @return {TypeORMQuery} The PostgresSQL condition
505
+ * @mermaid
506
+ * sequenceDiagram
507
+ * participant Statement
508
+ * participant translateOperators
509
+ * participant parseCondition
510
+ *
511
+ * Statement->>Statement: parseCondition(condition)
512
+ *
513
+ * Note over Statement: Extract condition parts
514
+ *
515
+ * alt Simple comparison operator
516
+ * Statement->>translateOperators: translateOperators(operator)
517
+ * translateOperators-->>Statement: Return PostgreSQL operator
518
+ * Statement->>Statement: Create condition with column, operator, and value
519
+ * else NOT operator
520
+ * Statement->>Statement: parseCondition(attr1)
521
+ * Statement->>Statement: Add NOT to conditions
522
+ * else AND/OR operator
523
+ * Statement->>Statement: parseCondition(attr1)
524
+ * Statement->>Statement: parseCondition(comparison)
525
+ * Statement->>Statement: Combine conditions with AND/OR
526
+ * end
527
+ *
528
+ * Statement-->>Statement: Return conditions array
529
+ */
530
+ parseCondition(condition, tableName, qb, counter = 0, conditionalOp) {
531
+ const { attr1, operator, comparison } = condition;
532
+ function parse() {
533
+ const sqlOperator = translateOperators(operator);
534
+ const attrRef = `${attr1}${counter}`;
535
+ const queryStr = `${tableName}.${attr1} ${sqlOperator} :${attrRef}`;
536
+ const values = {
537
+ [attrRef]: comparison,
538
+ };
539
+ switch (conditionalOp) {
540
+ case GroupOperator.AND:
541
+ return {
542
+ query: qb.andWhere(queryStr, values),
543
+ };
544
+ case GroupOperator.OR:
545
+ return {
546
+ query: qb.orWhere(queryStr, values),
547
+ };
548
+ case Operator.NOT:
549
+ throw new Error("NOT operator not implemented");
550
+ default:
551
+ return {
552
+ query: qb.where(queryStr, values),
553
+ };
554
+ }
555
+ }
556
+ if ([GroupOperator.AND, GroupOperator.OR, Operator.NOT].indexOf(operator) === -1) {
557
+ return parse();
558
+ }
559
+ // For NOT operator
560
+ else if (operator === Operator.NOT) {
561
+ throw new Error("NOT operator not implemented");
562
+ }
563
+ // For AND/OR operators
564
+ else {
565
+ qb = this.parseCondition(attr1, tableName, qb, ++counter)
566
+ .query;
567
+ return this.parseCondition(comparison, tableName, qb, ++counter, operator);
568
+ }
569
+ }
570
+ }
571
+
572
+ /**
573
+ * @description Abstract implementation of a database sequence for TypeORM.
574
+ * @summary Provides the basic functionality for {@link Sequence}s, delegating to the {@link TypeORMAdapter} to fetch and increment values while handling type parsing and error translation.
575
+ * @param {SequenceOptions} options The sequence configuration options (name, type, startWith, incrementBy, etc.).
576
+ * @param {TypeORMAdapter} adapter The TypeORM adapter used to execute sequence operations.
577
+ * @class TypeORMSequence
578
+ * @implements Sequence
579
+ * @example
580
+ * // Create and use a TypeORM-backed sequence
581
+ * const seq = new TypeORMSequence({ name: "user_id_seq", type: "Number", startWith: 1, incrementBy: 1 }, adapter);
582
+ * const nextId = await seq.next();
583
+ *
584
+ * @mermaid
585
+ * sequenceDiagram
586
+ * participant App
587
+ * participant Seq as TypeORMSequence
588
+ * participant Adapter as TypeORMAdapter
589
+ * participant DB as Database
590
+ * App->>Seq: next()
591
+ * Seq->>Seq: current()
592
+ * Seq->>Adapter: raw(SELECT current_value ...)
593
+ * Adapter->>DB: Query current value
594
+ * DB-->>Adapter: current_value
595
+ * Adapter-->>Seq: value
596
+ * Seq->>Seq: increment(current)
597
+ * Seq->>Adapter: raw(nextval(name))
598
+ * Adapter->>DB: nextval()
599
+ * DB-->>Adapter: next value
600
+ * Adapter-->>Seq: value
601
+ * Seq-->>App: parsed next value
602
+ */
603
+ class TypeORMSequence extends Sequence {
604
+ constructor(options, adapter) {
605
+ super(options);
606
+ this.adapter = adapter;
607
+ }
608
+ /**
609
+ * @summary Retrieves the current value for the sequence
610
+ * @protected
611
+ */
612
+ async current() {
613
+ const { name } = this.options;
614
+ try {
615
+ const seq = await this.adapter.raw({
616
+ query: `SELECT current_value FROM information_schema.sequences WHERE sequence_name = $1`,
617
+ values: [name],
618
+ });
619
+ return this.parse(seq.current_value);
620
+ }
621
+ catch (e) {
622
+ throw this.adapter.parseError(e);
623
+ }
624
+ }
625
+ /**
626
+ * @summary Parses the {@link Sequence} value
627
+ *
628
+ * @protected
629
+ * @param value
630
+ */
631
+ parse(value) {
632
+ return Sequence.parseValue(this.options.type, value);
633
+ }
634
+ /**
635
+ * @summary increments the sequence
636
+ * @description Sequence specific implementation
637
+ *
638
+ * @param {string | number | bigint} current
639
+ * @param count
640
+ * @protected
641
+ */
642
+ async increment(current, count) {
643
+ const { type, incrementBy, name, startWith } = this.options;
644
+ if (type !== "Number" && type !== "BigInt")
645
+ throw new InternalError(`Cannot increment sequence of type ${type} with ${count}`);
646
+ let next;
647
+ try {
648
+ next = await this.adapter.raw({
649
+ query: `SELECT nextval($1);`,
650
+ values: [name],
651
+ });
652
+ }
653
+ catch (e) {
654
+ if (!(e instanceof NotFoundError))
655
+ throw e;
656
+ next = await this.adapter.raw({
657
+ query: `CREATE SEQUENCE IF NOT EXISTS $1 START WITH $2 INCREMENT BY $3 NO CYCLE;`,
658
+ values: [name, startWith, incrementBy],
659
+ });
660
+ }
661
+ return next;
662
+ }
663
+ /**
664
+ * @summary Generates the next value in th sequence
665
+ * @description calls {@link Sequence#parse} on the current value
666
+ * followed by {@link Sequence#increment}
667
+ *
668
+ */
669
+ async next() {
670
+ const current = await this.current();
671
+ return this.increment(current);
672
+ }
673
+ async range(count) {
674
+ const current = (await this.current());
675
+ const incrementBy = this.parse(this.options.incrementBy);
676
+ const next = await this.increment(current, this.parse(count) * incrementBy);
677
+ const range = [];
678
+ for (let i = 1; i <= count; i++) {
679
+ range.push(current + incrementBy * this.parse(i));
680
+ }
681
+ if (range[range.length - 1] !== next)
682
+ throw new InternalError("Miscalculation of range");
683
+ return range;
684
+ }
685
+ }
686
+
687
+ /**
688
+ * @description Generates a name for a CouchDB index
689
+ * @summary Creates a standardized name for a CouchDB index by combining name parts, compositions, and direction
690
+ * @param {string[]} name - Array of name parts for the index
691
+ * @param {OrderDirection} [direction] - Optional sort direction for the index
692
+ * @param {string[]} [compositions] - Optional additional attributes to include in the index name
693
+ * @param {string} [separator=DefaultSeparator] - The separator to use between parts of the index name
694
+ * @return {string} The generated index name
695
+ * @memberOf module:for-couchdb
696
+ */
697
+ function generateIndexName(name, direction, compositions, separator = DefaultSeparator) {
698
+ return [
699
+ ...name.map((n) => (n === TypeORMKeys.TABLE ? "table" : n)),
700
+ ...([]),
701
+ ...([]),
702
+ TypeORMKeys.INDEX,
703
+ ].join(separator);
704
+ }
705
+ /**
706
+ * @description Generates CouchDB index configurations for models
707
+ * @summary Creates a set of CouchDB index configurations based on the metadata of the provided models
708
+ * @template M - The model type that extends Model
709
+ * @param models - Array of model constructors to generate indexes for
710
+ * @return {TypeORMQuery} Array of CouchDB index configurations
711
+ * @function generateIndexes
712
+ * @memberOf module:for-couchdb
713
+ * @mermaid
714
+ * sequenceDiagram
715
+ * participant Caller
716
+ * participant generateIndexes
717
+ * participant generateIndexName
718
+ * participant Repository
719
+ *
720
+ * Caller->>generateIndexes: models
721
+ *
722
+ * Note over generateIndexes: Create base table index
723
+ * generateIndexes->>generateIndexName: [CouchDBKeys.TABLE]
724
+ * generateIndexName-->>generateIndexes: tableName
725
+ * generateIndexes->>generateIndexes: Create table index config
726
+ *
727
+ * loop For each model
728
+ * generateIndexes->>Repository: Get indexes metadata
729
+ * Repository-->>generateIndexes: index metadata
730
+ *
731
+ * loop For each index in metadata
732
+ * Note over generateIndexes: Extract index properties
733
+ * generateIndexes->>Repository: Get table name
734
+ * Repository-->>generateIndexes: tableName
735
+ *
736
+ * Note over generateIndexes: Define nested generate function
737
+ *
738
+ * generateIndexes->>generateIndexes: Call generate() for default order
739
+ * Note over generateIndexes: Create index name and config
740
+ *
741
+ * alt Has directions
742
+ * loop For each direction
743
+ * generateIndexes->>generateIndexes: Call generate(direction)
744
+ * Note over generateIndexes: Create ordered index config
745
+ * end
746
+ * end
747
+ * end
748
+ * end
749
+ *
750
+ * generateIndexes-->>Caller: Array of index configurations
751
+ */
752
+ function generateIndexes(models) {
753
+ const tableName = generateIndexName([TypeORMKeys.TABLE]);
754
+ const indexes = {};
755
+ indexes[tableName] = {
756
+ query: ``,
757
+ values: [],
758
+ };
759
+ models.forEach((m) => {
760
+ const ind = Repository.indexes(m);
761
+ Object.entries(ind).forEach(([key, value]) => {
762
+ const k = Object.keys(value)[0];
763
+ let { compositions } = value[k];
764
+ const tableName = Repository.table(m);
765
+ compositions = compositions || [];
766
+ function generate() {
767
+ const name = [key, ...compositions, PersistenceKeys.INDEX].join(DefaultSeparator);
768
+ indexes[name] = {
769
+ query: `CREATE INDEX $1 ON $2 ($3);`,
770
+ values: [name, tableName, key],
771
+ };
772
+ }
773
+ generate();
774
+ });
775
+ });
776
+ return Object.values(indexes);
777
+ }
778
+
779
+ /**
780
+ * @description Repository implementation backed by TypeORM.
781
+ * @summary Provides CRUD operations for a given Model using the {@link TypeORMAdapter}, including bulk operations and query builder access while preserving Decaf.ts repository semantics.
782
+ * @template M Type extending Model that this repository will manage.
783
+ * @param {TypeORMAdapter} adapter The adapter used to execute persistence operations.
784
+ * @param {Constructor<M>} model The Model constructor associated with this repository.
785
+ * @param {...any[]} args Optional arguments forwarded to the base Repository.
786
+ * @class TypeORMRepository
787
+ * @example
788
+ * // Creating a repository
789
+ * const repo = new TypeORMRepository<User>(adapter, User);
790
+ * const created = await repo.create(new User({ name: "Alice" }));
791
+ * const read = await repo.read(created.id);
792
+ *
793
+ * // Bulk create
794
+ * await repo.createAll([new User({ name: "A" }), new User({ name: "B" })]);
795
+ *
796
+ * // Using the query builder
797
+ * const qb = repo.queryBuilder();
798
+ * const rows = await qb.where("name = :name", { name: "Alice" }).getMany();
799
+ *
800
+ * @mermaid
801
+ * sequenceDiagram
802
+ * participant App
803
+ * participant Repo as TypeORMRepository
804
+ * participant Adapter as TypeORMAdapter
805
+ * participant DB as TypeORM/DataSource
806
+ *
807
+ * App->>Repo: create(model)
808
+ * Repo->>Adapter: prepare(model, pk)
809
+ * Adapter-->>Repo: { record, id, transient }
810
+ * Repo->>Adapter: create(table, id, model, ...args)
811
+ * Adapter->>DB: INSERT ...
812
+ * DB-->>Adapter: row
813
+ * Adapter-->>Repo: row
814
+ * Repo->>Adapter: revert(row, clazz, pk, id)
815
+ * Adapter-->>Repo: model
816
+ * Repo-->>App: model
817
+ */
818
+ let TypeORMRepository = class TypeORMRepository extends Repository {
819
+ constructor(adapter, model, ...args) {
820
+ super(adapter, model, ...args);
821
+ }
822
+ /**
823
+ * @description Creates a TypeORM query builder for the repository entity.
824
+ * @summary Returns a SelectQueryBuilder bound to this repository's entity for advanced querying.
825
+ * @return {import("typeorm").SelectQueryBuilder<any>} A TypeORM SelectQueryBuilder instance.
826
+ */
827
+ queryBuilder() {
828
+ const repo = this.adapter.dataSource.getRepository(this.class[ModelKeys.ANCHOR]);
829
+ return repo.createQueryBuilder();
830
+ }
831
+ /**
832
+ * @description Creates and persists a model instance.
833
+ * @summary Prepares the model, delegates insertion to the adapter, and rehydrates the persisted state back into a Model instance.
834
+ * @param {M} model The model to create.
835
+ * @param {...any[]} args Optional arguments/context.
836
+ * @return {Promise<M>} The created model instance.
837
+ */
838
+ async create(model, ...args) {
839
+ // eslint-disable-next-line prefer-const
840
+ let { record, id, transient } = this.adapter.prepare(model, this.pk);
841
+ record = await this.adapter.create(this.class[ModelKeys.ANCHOR], id, model, ...args);
842
+ let c = undefined;
843
+ if (args.length)
844
+ c = args[args.length - 1];
845
+ return this.adapter.revert(record, this.class, this.pk, id, c && c.get("rebuildWithTransient") ? transient : undefined);
846
+ }
847
+ /**
848
+ * @description Reads a model from the database by ID.
849
+ * @summary Retrieves a model instance from the database using its primary key.
850
+ * @param {string|number|bigint} id - The primary key of the model to read.
851
+ * @param {...any[]} args - Additional arguments.
852
+ * @return {Promise<M>} The retrieved model instance.
853
+ */
854
+ async read(id,
855
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
856
+ ...args) {
857
+ const m = await this.adapter.read(this.class[ModelKeys.ANCHOR], id, this.pk);
858
+ return this.adapter.revert(m, this.class, this.pk, id);
859
+ }
860
+ /**
861
+ * @description Updates and persists a model instance.
862
+ * @summary Prepares the model, delegates update to the adapter, and rehydrates the persisted state back into a Model instance.
863
+ * @param {M} model The model to update.
864
+ * @param {...any[]} args Optional arguments/context.
865
+ * @return {Promise<M>} The updated model instance.
866
+ */
867
+ async update(model, ...args) {
868
+ // eslint-disable-next-line prefer-const
869
+ let { record, id, transient } = this.adapter.prepare(model, this.pk);
870
+ record = await this.adapter.update(this.class[ModelKeys.ANCHOR], id, model, ...args);
871
+ return this.adapter.revert(record, this.class, this.pk, id, transient);
872
+ }
873
+ /**
874
+ * @description Deletes a model from the database by ID.
875
+ * @summary Removes a model instance from the database using its primary key.
876
+ * @param {string|number|bigint} id - The primary key of the model to delete.
877
+ * @param {...any[]} args - Additional arguments.
878
+ * @return {Promise<M>} The deleted model instance.
879
+ */
880
+ async delete(id, ...args) {
881
+ const m = await this.adapter.delete(this.class[ModelKeys.ANCHOR], id, this.pk, ...args);
882
+ return this.adapter.revert(m, this.class, this.pk, id);
883
+ }
884
+ /**
885
+ * @description Validates and prepares models for bulk creation.
886
+ * @summary Applies decorator-based validations and returns transformed models with context args for createAll.
887
+ * @param {M[]} models The models to be created.
888
+ * @param {...any[]} args Optional arguments/context.
889
+ * @return {Promise<[M[], ...any[]]>} The prepared models and forwarded args tuple.
890
+ */
891
+ async createAllPrefix(models, ...args) {
892
+ const contextArgs = await Context.args(OperationKeys.CREATE, this.class, args, this.adapter, this._overrides || {});
893
+ if (!models.length)
894
+ return [models, ...contextArgs.args];
895
+ models = await Promise.all(models.map(async (m) => {
896
+ m = new this.class(m);
897
+ await enforceDBDecorators(this, contextArgs.context, m, OperationKeys.CREATE, OperationKeys.ON);
898
+ return m;
899
+ }));
900
+ const errors = models
901
+ .map((m) => m.hasErrors(...(contextArgs.context.get("ignoredValidationProperties") || [])))
902
+ .reduce((accum, e, i) => {
903
+ if (e)
904
+ accum =
905
+ typeof accum === "string"
906
+ ? accum + `\n - ${i}: ${e.toString()}`
907
+ : ` - ${i}: ${e.toString()}`;
908
+ return accum;
909
+ }, undefined);
910
+ if (errors)
911
+ throw new ValidationError(errors);
912
+ return [models, ...contextArgs.args];
913
+ }
914
+ /**
915
+ * @description Creates multiple models at once.
916
+ * @summary Prepares, persists, and rehydrates a batch of models.
917
+ * @param {M[]} models The models to create.
918
+ * @param {...any[]} args Optional arguments/context.
919
+ * @return {Promise<M[]>} The created models.
920
+ */
921
+ async createAll(models, ...args) {
922
+ if (!models.length)
923
+ return models;
924
+ const prepared = models.map((m) => this.adapter.prepare(m, this.pk));
925
+ const ids = prepared.map((p) => p.id);
926
+ let records = prepared.map((p) => p.record);
927
+ records = await this.adapter.createAll(this.class[ModelKeys.ANCHOR], ids, models, ...args);
928
+ return records.map((r, i) => this.adapter.revert(r, this.class, this.pk, ids[i]));
929
+ }
930
+ /**
931
+ * @description Reads multiple models by their primary keys.
932
+ * @summary Retrieves a list of models corresponding to the provided keys.
933
+ * @param {(string[]|number[])} keys The primary keys to read.
934
+ * @param {...any[]} args Optional arguments/context.
935
+ * @return {Promise<M[]>} The retrieved models.
936
+ */
937
+ async readAll(keys, ...args) {
938
+ const records = await this.adapter.readAll(this.class[ModelKeys.ANCHOR], keys, this.pk, ...args);
939
+ return records.map((r, i) => this.adapter.revert(r, this.class, this.pk, keys[i]));
940
+ }
941
+ /**
942
+ * @description Updates multiple models at once.
943
+ * @summary Persists a batch of model updates and returns their rehydrated instances.
944
+ * @param {M[]} models The models to update.
945
+ * @param {...any[]} args Optional arguments/context.
946
+ * @return {Promise<M[]>} The updated models.
947
+ */
948
+ async updateAll(models, ...args) {
949
+ const records = models.map((m) => this.adapter.prepare(m, this.pk));
950
+ const updated = await this.adapter.updateAll(this.class[ModelKeys.ANCHOR], records.map((r) => r.id), models, this.pk, ...args);
951
+ return updated.map((u, i) => this.adapter.revert(u, this.class, this.pk, records[i].id));
952
+ }
953
+ /**
954
+ * @description Deletes multiple models at once.
955
+ * @summary Removes a list of models by their primary keys and returns their last persisted states.
956
+ * @param {(string[]|number[])} keys The primary keys to delete.
957
+ * @param {...any[]} args Optional arguments/context.
958
+ * @return {Promise<M[]>} The deleted models.
959
+ */
960
+ async deleteAll(keys, ...args) {
961
+ const results = await this.adapter.deleteAll(this.class[ModelKeys.ANCHOR], keys, this.pk, ...args);
962
+ return results.map((r, i) => this.adapter.revert(r, this.class, this.pk, keys[i]));
963
+ }
964
+ };
965
+ TypeORMRepository = __decorate([
966
+ uses(TypeORMFlavour),
967
+ __metadata("design:paramtypes", [TypeORMAdapter, Object, Object])
968
+ ], TypeORMRepository);
969
+
970
+ /**
971
+ * @description TypeORM event subscriber that forwards entity lifecycle events to the adapter.
972
+ * @summary Listens for insert, update, and remove events emitted by TypeORM and notifies the Decaf.ts adapter so that observers can be updated accordingly.
973
+ * @param {TypeORMAdapter} adapter The TypeORM adapter used to propagate events and look up metadata.
974
+ * @class
975
+ * @example
976
+ * // Registering the subscriber when creating a DataSource
977
+ * // dataSourceOptions.subscribers = [new TypeORMEventSubscriber(adapter)];
978
+ *
979
+ * @mermaid
980
+ * sequenceDiagram
981
+ * participant TypeORM
982
+ * participant Subscriber as TypeORMEventSubscriber
983
+ * participant Adapter as TypeORMAdapter
984
+ * participant Observers
985
+ *
986
+ * TypeORM->>Subscriber: afterInsert(entity)
987
+ * Subscriber->>Adapter: updateObservers(table, CREATE, [id])
988
+ * Adapter->>Observers: notify(table, CREATE, [id])
989
+ *
990
+ * TypeORM->>Subscriber: afterUpdate(event)
991
+ * Subscriber->>Adapter: updateObservers(table, UPDATE, [id])
992
+ * Adapter->>Observers: notify(table, UPDATE, [id])
993
+ *
994
+ * TypeORM->>Subscriber: afterRemove(event)
995
+ * Subscriber->>Adapter: updateObservers(table, DELETE, [id])
996
+ * Adapter->>Observers: notify(table, DELETE, [id])
997
+ */
998
+ let TypeORMEventSubscriber = class TypeORMEventSubscriber {
999
+ constructor(handler) {
1000
+ this.handler = handler;
1001
+ }
1002
+ /**
1003
+ * @description Handles post-insert events.
1004
+ * @summary Notifies observers about a create operation for the inserted entity.
1005
+ * @param {InsertEvent<any>} event The TypeORM insert event.
1006
+ * @return {Promise<any>|void} A promise when async or void otherwise.
1007
+ */
1008
+ afterInsert(event) {
1009
+ const constructor = Model.get(event.entity.constructor.name);
1010
+ if (!constructor)
1011
+ throw new InternalError(`No registered model found for ${event.entity.constructor.name}`);
1012
+ const tableName = Repository.table(constructor);
1013
+ this.handler(tableName, OperationKeys.CREATE, [event.entityId]);
1014
+ }
1015
+ /**
1016
+ * @description Handles post-remove events.
1017
+ * @summary Notifies observers about a delete operation for the removed entity.
1018
+ * @param {RemoveEvent<any>} event The TypeORM remove event.
1019
+ * @return {Promise<any>|void} A promise when async or void otherwise.
1020
+ */
1021
+ afterRemove(event) {
1022
+ const constructor = Model.get(event.entity.constructor.name);
1023
+ if (!constructor)
1024
+ throw new InternalError(`No registered model found for ${event.entity.constructor.name}`);
1025
+ const tableName = Repository.table(constructor);
1026
+ this.handler(tableName, OperationKeys.DELETE, [event.entityId]);
1027
+ }
1028
+ /**
1029
+ * @description Handles post-update events.
1030
+ * @summary Notifies observers about an update operation for the modified entity.
1031
+ * @param {UpdateEvent<any>} event The TypeORM update event.
1032
+ * @return {Promise<any>|void} A promise when async or void otherwise.
1033
+ */
1034
+ afterUpdate(event) {
1035
+ const constructor = Model.get(event.databaseEntity.constructor.name);
1036
+ if (!constructor)
1037
+ throw new InternalError(`No registered model found for ${event.databaseEntity.constructor.name}`);
1038
+ const tableName = Repository.table(constructor);
1039
+ return this.handler(tableName, OperationKeys.UPDATE, [
1040
+ event.entity["id"],
1041
+ ]);
1042
+ }
1043
+ };
1044
+ TypeORMEventSubscriber = __decorate([
1045
+ EventSubscriber(),
1046
+ __metadata("design:paramtypes", [Function])
1047
+ ], TypeORMEventSubscriber);
1048
+
1049
+ /**
1050
+ * @description Dispatcher for TypeORM-driven change events.
1051
+ * @summary Subscribes a TypeORM DataSource with a custom EntitySubscriber to notify observers when records are created, updated, or deleted.
1052
+ * @param {number} [timeout=5000] Timeout in milliseconds for initialization retries.
1053
+ * @class TypeORMDispatch
1054
+ * @example
1055
+ * // Create a dispatcher for a TypeORM DataSource
1056
+ * const dispatch = new TypeORMDispatch();
1057
+ * await dispatch.observe(adapter, adapter.dataSource.options);
1058
+ *
1059
+ * // The dispatcher registers a TypeORMEventSubscriber and notifies observers when entities change.
1060
+ * @mermaid
1061
+ * classDiagram
1062
+ * class Dispatch {
1063
+ * +initialize()
1064
+ * +updateObservers()
1065
+ * }
1066
+ * class TypeORMDispatch {
1067
+ * -observerLastUpdate?: string
1068
+ * -attemptCounter: number
1069
+ * -timeout: number
1070
+ * +constructor(timeout)
1071
+ * #notificationHandler()
1072
+ * #initialize()
1073
+ * }
1074
+ * Dispatch <|-- TypeORMDispatch
1075
+ */
1076
+ class TypeORMDispatch extends Dispatch {
1077
+ constructor(timeout = 5000) {
1078
+ super();
1079
+ this.timeout = timeout;
1080
+ this.attemptCounter = 0;
1081
+ }
1082
+ /**
1083
+ * @description Processes TypeORM notification events.
1084
+ * @summary Handles change notifications (translated from TypeORM events) and notifies observers about record changes.
1085
+ * @param {string} table The notification payload.
1086
+ * @param {OperationKeys} operation The notification payload.
1087
+ * @param {EventIds} ids The notification payload.
1088
+ * @return {Promise<void>} A promise that resolves when all notifications have been processed.
1089
+ * @mermaid
1090
+ * sequenceDiagram
1091
+ * participant D as PostgreSQLDispatch
1092
+ * participant L as Logger
1093
+ * participant O as Observers
1094
+ * Note over D: Receive notification from PostgreSQL
1095
+ * D->>D: Parse notification payload
1096
+ * D->>D: Extract table, operation, and ids
1097
+ * D->>O: updateObservers(table, operation, ids)
1098
+ * D->>D: Update observerLastUpdate
1099
+ * D->>L: Log successful dispatch
1100
+ */
1101
+ async notificationHandler(table, operation, ids) {
1102
+ const log = this.log.for(this.notificationHandler);
1103
+ try {
1104
+ // Notify observers
1105
+ await this.updateObservers(table, operation, ids);
1106
+ this.observerLastUpdate = new Date().toISOString();
1107
+ log.verbose(`Observer refresh dispatched by ${operation} for ${table}`);
1108
+ log.debug(`pks: ${ids}`);
1109
+ }
1110
+ catch (e) {
1111
+ log.error(`Failed to process notification: ${e}`);
1112
+ }
1113
+ }
1114
+ /**
1115
+ * @description Initializes the dispatcher and subscribes to TypeORM notifications.
1116
+ * @summary Registers the TypeORMEventSubscriber on the DataSource and logs the subscription lifecycle.
1117
+ * @return {Promise<void>} A promise that resolves when the subscription is established.
1118
+ * @mermaid
1119
+ * sequenceDiagram
1120
+ * participant D as TypeORMDispatch
1121
+ * participant S as subscribeToTypeORM
1122
+ * participant DS as TypeORM DataSource
1123
+ * participant L as Logger
1124
+ * D->>S: Call subscribeToTypeORM
1125
+ * S->>S: Check adapter and native
1126
+ * alt No adapter or native
1127
+ * S-->>S: throw InternalError
1128
+ * end
1129
+ * S->>DS: initialize()
1130
+ * S->>DS: subscribers.push(TypeORMEventSubscriber)
1131
+ * alt Success
1132
+ * DS-->>S: Subscription established
1133
+ * S-->>D: Promise resolves
1134
+ * D->>L: Log successful subscription
1135
+ * else Error
1136
+ * DS-->>S: Error
1137
+ * S-->>D: Promise rejects
1138
+ * end
1139
+ */
1140
+ async initialize() {
1141
+ async function subscribeToTypeORM() {
1142
+ if (!this.adapter || !this.native) {
1143
+ throw new InternalError(`No adapter/native observed for dispatch`);
1144
+ }
1145
+ const adapter = this.adapter;
1146
+ try {
1147
+ if (!adapter.dataSource.isInitialized)
1148
+ await adapter.dataSource.initialize();
1149
+ adapter.dataSource.subscribers.push(new TypeORMEventSubscriber(this.notificationHandler.bind(this)));
1150
+ }
1151
+ catch (e) {
1152
+ throw new InternalError(e);
1153
+ }
1154
+ }
1155
+ subscribeToTypeORM
1156
+ .call(this)
1157
+ .then(() => {
1158
+ this.log.info(`Subscribed to TypeORM notifications`);
1159
+ })
1160
+ .catch((e) => {
1161
+ throw new InternalError(`Failed to subscribe to TypeORM notifications: ${e}`);
1162
+ });
1163
+ }
1164
+ /**
1165
+ * Cleanup method to release resources when the dispatcher is no longer needed
1166
+ */
1167
+ cleanup() {
1168
+ // if (this.adapter) {
1169
+ //
1170
+ // const adapter = this.adapter as TypeORMAdapter;
1171
+ // await adapter.dataSource.destroy();
1172
+ // }
1173
+ }
1174
+ }
1175
+
1176
+ /**
1177
+ * @description Converts a JavaScript RegExp pattern to a PostgreSQL POSIX pattern string.
1178
+ * @summary Accepts either a RegExp object or a string representation (/pattern/flags) and returns the raw pattern compatible with PostgreSQL's ~ and ~* operators.
1179
+ * @param {RegExp|string} jsRegex JavaScript RegExp object or pattern string.
1180
+ * @return {string} PostgreSQL-compatible regex pattern string.
1181
+ * @function convertJsRegexToPostgres
1182
+ * @mermaid
1183
+ * sequenceDiagram
1184
+ * participant App
1185
+ * participant Utils as convertJsRegexToPostgres
1186
+ * App->>Utils: convertJsRegexToPostgres(RegExp("foo.*","i"))
1187
+ * Utils->>Utils: Parse string or use RegExp.source
1188
+ * Utils-->>App: "foo.*"
1189
+ * @memberOf module:for-typeorm
1190
+ */
1191
+ function convertJsRegexToPostgres(jsRegex) {
1192
+ const rxp = new RegExp(/^\/(.+)\/(\w+)$/g);
1193
+ if (typeof jsRegex === "string") {
1194
+ const match = rxp.exec(jsRegex);
1195
+ if (match) {
1196
+ const [, p] = match;
1197
+ jsRegex = p;
1198
+ }
1199
+ }
1200
+ const regex = typeof jsRegex === "string" ? new RegExp(jsRegex) : jsRegex;
1201
+ const pattern = regex.source;
1202
+ return pattern;
1203
+ }
1204
+
1205
+ function aggregateOrNewColumn(target, property, columns, options = {}, mode = "regular") {
1206
+ const cols = columns.filter((c) => c.target === target && c.propertyName === property);
1207
+ if (cols.length > 1)
1208
+ throw new Error(`Multiple columns for ${property} found for given target: ${columns.map((c) => c.propertyName).join(", ")}`);
1209
+ if (cols.length === 0) {
1210
+ columns.push({
1211
+ target: target,
1212
+ propertyName: property,
1213
+ mode: mode,
1214
+ options: options,
1215
+ });
1216
+ return;
1217
+ }
1218
+ const column = cols[0];
1219
+ Object.defineProperty(column, "options", {
1220
+ value: { ...column.options, ...options },
1221
+ writable: true,
1222
+ enumerable: true,
1223
+ configurable: true,
1224
+ });
1225
+ if (mode !== "regular")
1226
+ Object.defineProperty(column, "mode", {
1227
+ value: mode,
1228
+ writable: true,
1229
+ enumerable: true,
1230
+ configurable: true,
1231
+ });
1232
+ }
1233
+
1234
+ /**
1235
+ * Column decorator is used to mark a specific class property as a table column.
1236
+ * Only properties decorated with this decorator will be persisted to the database when entity be saved.
1237
+ */
1238
+ function Column(typeOrOptions, options) {
1239
+ return function (object, propertyName) {
1240
+ // normalize parameters
1241
+ let type;
1242
+ if (typeof typeOrOptions === "string" ||
1243
+ typeof typeOrOptions === "function") {
1244
+ type = typeOrOptions;
1245
+ }
1246
+ else if (typeOrOptions) {
1247
+ options = typeOrOptions;
1248
+ type = typeOrOptions.type;
1249
+ }
1250
+ if (!options)
1251
+ options = {};
1252
+ // if type is not given explicitly then try to guess it
1253
+ const reflectMetadataType = Reflect && Reflect.getMetadata
1254
+ ? Reflect.getMetadata("design:type", object, propertyName)
1255
+ : undefined;
1256
+ if (!type && reflectMetadataType)
1257
+ // if type is not given explicitly then try to guess it
1258
+ type = reflectMetadataType;
1259
+ // check if there is no type in column options then set type from first function argument, or guessed one
1260
+ if (!options.type && type)
1261
+ options.type = type;
1262
+ // specify HSTORE type if column is HSTORE
1263
+ if (options.type === "hstore" && !options.hstoreType)
1264
+ options.hstoreType = reflectMetadataType === Object ? "object" : "string";
1265
+ if (typeof typeOrOptions === "function") {
1266
+ // register an embedded
1267
+ getMetadataArgsStorage().embeddeds.push({
1268
+ target: object.constructor,
1269
+ propertyName: propertyName,
1270
+ isArray: reflectMetadataType === Array || options.array === true,
1271
+ prefix: options.prefix !== undefined ? options.prefix : undefined,
1272
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
1273
+ type: typeOrOptions,
1274
+ });
1275
+ }
1276
+ else {
1277
+ // register a regular column
1278
+ // if we still don't have a type then we need to give error to user that type is required
1279
+ if (!options.type)
1280
+ throw new ColumnTypeUndefinedError(object, propertyName);
1281
+ // create unique
1282
+ if (options.unique === true)
1283
+ getMetadataArgsStorage().uniques.push({
1284
+ target: object.constructor,
1285
+ columns: [propertyName],
1286
+ });
1287
+ const columns = getMetadataArgsStorage().columns;
1288
+ aggregateOrNewColumn(object.constructor, propertyName, columns, options);
1289
+ if (options.generated) {
1290
+ getMetadataArgsStorage().generations.push({
1291
+ target: object.constructor,
1292
+ propertyName: propertyName,
1293
+ strategy: typeof options.generated === "string"
1294
+ ? options.generated
1295
+ : "increment",
1296
+ });
1297
+ }
1298
+ }
1299
+ };
1300
+ }
1301
+
1302
+ function UpdateDateColumn(options) {
1303
+ return function (object, propertyName) {
1304
+ const columns = getMetadataArgsStorage().columns;
1305
+ aggregateOrNewColumn(object.constructor, propertyName, columns, {}, "updateDate");
1306
+ };
1307
+ }
1308
+
1309
+ function CreateDateColumn(options) {
1310
+ return function (object, propertyName) {
1311
+ const columns = getMetadataArgsStorage().columns;
1312
+ aggregateOrNewColumn(object.constructor, propertyName, columns, {}, "createDate");
1313
+ };
1314
+ }
1315
+
1316
+ /**
1317
+ * Column decorator is used to mark a specific class property as a table column.
1318
+ * Only properties decorated with this decorator will be persisted to the database when entity be saved.
1319
+ * This column creates an integer PRIMARY COLUMN with generated set to true.
1320
+ */
1321
+ function PrimaryGeneratedColumn(strategyOrOptions, maybeOptions) {
1322
+ // normalize parameters
1323
+ const options = {};
1324
+ let strategy;
1325
+ {
1326
+ strategy = "increment";
1327
+ }
1328
+ if (ObjectUtils.isObject(maybeOptions))
1329
+ Object.assign(options, maybeOptions);
1330
+ return function (object, propertyName) {
1331
+ // if column type is not explicitly set then determine it based on generation strategy
1332
+ if (!options.type) {
1333
+ if (strategy === "increment" || strategy === "identity") {
1334
+ options.type = Number;
1335
+ }
1336
+ else if (strategy === "uuid") {
1337
+ options.type = "uuid";
1338
+ }
1339
+ else if (strategy === "rowid") {
1340
+ options.type = "int";
1341
+ }
1342
+ }
1343
+ // explicitly set a primary and generated to column options
1344
+ options.primary = true;
1345
+ const columns = getMetadataArgsStorage().columns;
1346
+ aggregateOrNewColumn(object.constructor, propertyName, columns, options);
1347
+ // register generated metadata args
1348
+ getMetadataArgsStorage().generations.push({
1349
+ target: object.constructor,
1350
+ propertyName: propertyName,
1351
+ strategy: strategy,
1352
+ });
1353
+ };
1354
+ }
1355
+
1356
+ /**
1357
+ * Column decorator is used to mark a specific class property as a table column.
1358
+ * Only properties decorated with this decorator will be persisted to the database when entity be saved.
1359
+ * Primary columns also creates a PRIMARY KEY for this column in a db.
1360
+ */
1361
+ function PrimaryColumn(typeOrOptions, options) {
1362
+ return function (object, propertyName) {
1363
+ // normalize parameters
1364
+ let type;
1365
+ if (typeof typeOrOptions === "string" ||
1366
+ typeOrOptions === String ||
1367
+ typeOrOptions === Boolean ||
1368
+ typeOrOptions === Number) {
1369
+ type = typeOrOptions;
1370
+ }
1371
+ else {
1372
+ options = Object.assign({}, typeOrOptions);
1373
+ }
1374
+ if (!options)
1375
+ options = {};
1376
+ // if type is not given explicitly then try to guess it
1377
+ const reflectMetadataType = Reflect && Reflect.getMetadata
1378
+ ? Reflect.getMetadata("design:type", object, propertyName)
1379
+ : undefined;
1380
+ if (!type && reflectMetadataType)
1381
+ type = reflectMetadataType;
1382
+ // check if there is no type in column options then set type from first function argument, or guessed one
1383
+ if (!options.type && type)
1384
+ options.type = type;
1385
+ // if we still don't have a type then we need to give error to user that type is required
1386
+ if (!options.type)
1387
+ throw new ColumnTypeUndefinedError(object, propertyName);
1388
+ // check if column is not nullable, because we cannot allow a primary key to be nullable
1389
+ if (options.nullable)
1390
+ throw new PrimaryColumnCannotBeNullableError(object, propertyName);
1391
+ // explicitly set a primary to column options
1392
+ options.primary = true;
1393
+ const columns = getMetadataArgsStorage().columns;
1394
+ aggregateOrNewColumn(object.constructor, propertyName, columns, options);
1395
+ if (options.generated) {
1396
+ getMetadataArgsStorage().generations.push({
1397
+ target: object.constructor,
1398
+ propertyName: propertyName,
1399
+ strategy: typeof options.generated === "string"
1400
+ ? options.generated
1401
+ : "increment",
1402
+ });
1403
+ }
1404
+ };
1405
+ }
1406
+
1407
+ /**
1408
+ * This decorator is used to mark classes that will be an entity (table or document depend on database type).
1409
+ * Database schema will be created for all classes decorated with it, and Repository can be retrieved and used for it.
1410
+ */
1411
+ function Entity(nameOrOptions, maybeOptions) {
1412
+ const options = (ObjectUtils.isObject(nameOrOptions)
1413
+ ? nameOrOptions
1414
+ : maybeOptions) || {};
1415
+ const name = options.name;
1416
+ return function (target) {
1417
+ const tables = getMetadataArgsStorage().tables;
1418
+ tables.push({
1419
+ target: target,
1420
+ name: name,
1421
+ type: "regular",
1422
+ orderBy: options.orderBy ? options.orderBy : undefined,
1423
+ engine: options.engine ? options.engine : undefined,
1424
+ database: options.database ? options.database : undefined,
1425
+ schema: options.schema ? options.schema : undefined,
1426
+ synchronize: options.synchronize,
1427
+ withoutRowid: options.withoutRowid,
1428
+ comment: options.comment ? options.comment : undefined,
1429
+ });
1430
+ };
1431
+ }
1432
+
1433
+ async function createdByOnPostgresCreateUpdate(context, data, key, model) {
1434
+ try {
1435
+ const user = context.get("user");
1436
+ model[key] = user;
1437
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1438
+ }
1439
+ catch (e) {
1440
+ throw new InternalError("No User found in context. Please provide a user in the context");
1441
+ }
1442
+ }
1443
+ /**
1444
+ * @description Adapter for TypeORM-backed persistence operations.
1445
+ * @summary Implements the Decaf.ts Adapter over a TypeORM DataSource, providing CRUD operations, query/statement factories, sequence management, error parsing, and decoration helpers.
1446
+ * @template Y The native configuration type (TypeORM DataSourceOptions).
1447
+ * @template F The repository flags type.
1448
+ * @template C The context type.
1449
+ * @param {DataSourceOptions} scope The DataSource options for the adapter.
1450
+ * @param {string} flavour The flavour of the adapter.
1451
+ * @param {string} [alias] Optional alias for the adapter.
1452
+ * @class TypeORMAdapter
1453
+ * @example
1454
+ * const adapter = new TypeORMAdapter({ type: 'postgres', /* ... *\/ });
1455
+ * await adapter.initialize();
1456
+ * const repo = new (adapter.repository<User>())(adapter, User);
1457
+ * const created = await repo.create(new User({ name: 'Alice' }));
1458
+ *
1459
+ * @mermaid
1460
+ * sequenceDiagram
1461
+ * participant App
1462
+ * participant Adapter as TypeORMAdapter
1463
+ * participant Repo as TypeORMRepository
1464
+ * participant DS as TypeORM DataSource
1465
+ *
1466
+ * App->>Adapter: new TypeORMAdapter(opts)
1467
+ * Adapter->>DS: initialize()
1468
+ * App->>Adapter: repository()
1469
+ * Adapter-->>App: TypeORMRepository
1470
+ * App->>Repo: create(model)
1471
+ * Repo->>Adapter: prepare/create/revert
1472
+ * Adapter-->>Repo: Model
1473
+ * Repo-->>App: Model
1474
+ */
1475
+ class TypeORMAdapter extends Adapter {
1476
+ get dataSource() {
1477
+ if (!this._dataSource) {
1478
+ const models = Adapter.models(this.flavour);
1479
+ this._dataSource = new DataSource(Object.assign(this.native, {
1480
+ entities: models.map((c) => c[ModelKeys.ANCHOR]),
1481
+ }));
1482
+ }
1483
+ return this._dataSource;
1484
+ }
1485
+ // protected dataSou
1486
+ constructor(options, alias) {
1487
+ super(options, TypeORMFlavour, alias);
1488
+ }
1489
+ async flags(operation, model, flags) {
1490
+ const f = await super.flags(operation, model, flags);
1491
+ const newObj = {
1492
+ user: (await TypeORMAdapter.getCurrentUser(this.dataSource)),
1493
+ };
1494
+ const m = new model();
1495
+ const exceptions = [];
1496
+ if (operation === OperationKeys.CREATE) {
1497
+ const pk = findPrimaryKey(m).id;
1498
+ exceptions.push(pk);
1499
+ }
1500
+ if (operation === OperationKeys.CREATE ||
1501
+ operation === OperationKeys.UPDATE) {
1502
+ const decs = Object.keys(m).reduce((accum, key) => {
1503
+ const decs = Reflection.getPropertyDecorators(ValidationKeys.REFLECT, m, key, true);
1504
+ const dec = decs.decorators.find((dec) => dec.key === DBKeys.TIMESTAMP &&
1505
+ dec.props.operation.indexOf(operation) !== -1);
1506
+ if (dec) {
1507
+ accum[key] = dec.props;
1508
+ }
1509
+ return accum;
1510
+ }, {});
1511
+ exceptions.push(...Object.keys(decs));
1512
+ }
1513
+ newObj.ignoredValidationProperties = (f.ignoredValidationProperties ? f.ignoredValidationProperties : []).concat(...exceptions);
1514
+ return Object.assign(f, newObj);
1515
+ }
1516
+ Dispatch() {
1517
+ return new TypeORMDispatch();
1518
+ }
1519
+ repository() {
1520
+ return TypeORMRepository;
1521
+ }
1522
+ /**
1523
+ * @description Creates a new Postgres statement for querying
1524
+ * @summary Factory method that creates a new PostgresStatement instance for building queries
1525
+ * @template M - The model type
1526
+ * @return {TypeORMStatement<M, any>} A new PostgresStatement instance
1527
+ */
1528
+ Statement() {
1529
+ return new TypeORMStatement(this);
1530
+ }
1531
+ /**
1532
+ * @description Creates a new PostgreSQL sequence
1533
+ * @summary Factory method that creates a new PostgreSQLSequence instance for managing sequences
1534
+ * @param {SequenceOptions} options - The options for the sequence
1535
+ * @return {Promise<Sequence>} A promise that resolves to a new Sequence instance
1536
+ */
1537
+ async Sequence(options) {
1538
+ return new TypeORMSequence(options, this);
1539
+ }
1540
+ /**
1541
+ * @description Initializes the adapter by creating indexes for all managed models
1542
+ * @summary Sets up the necessary database indexes for all models managed by this adapter
1543
+ * @return {Promise<void>} A promise that resolves when initialization is complete
1544
+ */
1545
+ async initialize() {
1546
+ const ds = this.dataSource;
1547
+ try {
1548
+ await ds.initialize();
1549
+ }
1550
+ catch (e) {
1551
+ throw this.parseError(e);
1552
+ }
1553
+ const log = this.log.for(this.initialize);
1554
+ log.verbose(`${this.flavour} adapter initialized`);
1555
+ }
1556
+ /**
1557
+ * @description Creates indexes for the given models
1558
+ * @summary Abstract method that must be implemented to create database indexes for the specified models
1559
+ * @template M - The model type
1560
+ * @param {...Constructor<M>} models - The model constructors to create indexes for
1561
+ * @return {Promise<void>} A promise that resolves when all indexes are created
1562
+ */
1563
+ async index(...models) {
1564
+ const indexes = generateIndexes(models);
1565
+ try {
1566
+ await this.dataSource.query("BEGIN");
1567
+ for (const index of indexes) {
1568
+ await this.dataSource.query(index.query, index.values);
1569
+ }
1570
+ await this.dataSource.query("COMMIT");
1571
+ }
1572
+ catch (e) {
1573
+ await this.dataSource.query("ROLLBACK");
1574
+ throw this.parseError(e);
1575
+ }
1576
+ }
1577
+ /**
1578
+ * @description Executes a raw SQL query against the database
1579
+ * @summary Abstract method that must be implemented to execute raw SQL queries
1580
+ * @template R - The result type
1581
+ * @param {TypeORMQuery} q - The query to execute
1582
+ * @return {Promise<R>} A promise that resolves to the query result
1583
+ */
1584
+ async raw(q) {
1585
+ const log = this.log.for(this.raw);
1586
+ try {
1587
+ if (!this.dataSource.isInitialized)
1588
+ await this.dataSource.initialize();
1589
+ }
1590
+ catch (e) {
1591
+ throw this.parseError(e);
1592
+ }
1593
+ try {
1594
+ const { query, values } = q;
1595
+ log.debug(`executing query: ${query.getSql()}`);
1596
+ const response = await this.dataSource.query(query, values);
1597
+ return response;
1598
+ }
1599
+ catch (e) {
1600
+ throw this.parseError(e);
1601
+ }
1602
+ }
1603
+ prepare(model, pk, child = false) {
1604
+ const prepared = super.prepare(model, pk);
1605
+ prepared.record = Object.entries(prepared.record).reduce((accum, [key, value]) => {
1606
+ if (key === PersistenceKeys.METADATA || this.isReserved(key))
1607
+ return accum;
1608
+ if (value === undefined) {
1609
+ return accum;
1610
+ }
1611
+ if (value instanceof Date) {
1612
+ value = new Date(value.getTime());
1613
+ }
1614
+ else if (Model.isModel(value)) {
1615
+ value = this.prepare(value, findPrimaryKey(value).id, true).record;
1616
+ }
1617
+ else {
1618
+ switch (typeof value) {
1619
+ case "string":
1620
+ value = `${value}`;
1621
+ break;
1622
+ //do nothing;
1623
+ }
1624
+ }
1625
+ accum[key] = value;
1626
+ return accum;
1627
+ }, {});
1628
+ const constr = Model.get(model.constructor.name);
1629
+ if (!constr)
1630
+ throw new InternalError(`Model ${model.constructor.name} not found in registry`);
1631
+ const result = child
1632
+ ? new constr[ModelKeys.ANCHOR]()
1633
+ : new constr();
1634
+ if (child)
1635
+ Object.defineProperty(result, "constructor", {
1636
+ configurable: false,
1637
+ enumerable: false,
1638
+ value: constr[ModelKeys.ANCHOR],
1639
+ writable: false,
1640
+ });
1641
+ Object.entries(prepared.record).forEach(([key, val]) => (result[key] = val));
1642
+ prepared.record = result;
1643
+ return prepared;
1644
+ }
1645
+ revert(obj, clazz, pk, id, transient) {
1646
+ const log = this.log.for(this.revert);
1647
+ if (transient) {
1648
+ log.verbose(`re-adding transient properties: ${Object.keys(transient).join(", ")}`);
1649
+ Object.entries(transient).forEach(([key, val]) => {
1650
+ if (key in obj)
1651
+ throw new InternalError(`Transient property ${key} already exists on model ${typeof clazz === "string" ? clazz : clazz.name}. should be impossible`);
1652
+ obj[key] = val;
1653
+ });
1654
+ }
1655
+ return new clazz(obj);
1656
+ }
1657
+ /**
1658
+ * @description Creates a new record in the database
1659
+ * @summary Abstract method that must be implemented to create a new record
1660
+ * @param {string} tableName - The name of the table
1661
+ * @param {string|number} id - The ID of the record
1662
+ * @param {Record<string, any>} model - The model to create
1663
+ * @param {...any[]} args - Additional arguments
1664
+ * @return {Promise<Record<string, any>>} A promise that resolves to the created record
1665
+ */
1666
+ async create(tableName, id, model,
1667
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1668
+ ...args) {
1669
+ const m = tableName;
1670
+ try {
1671
+ const repo = this.dataSource.getRepository(m);
1672
+ return await repo.save(model);
1673
+ }
1674
+ catch (e) {
1675
+ throw this.parseError(e);
1676
+ }
1677
+ }
1678
+ /**
1679
+ * @description Reads a record from the database
1680
+ * @summary Abstract method that must be implemented to read a record
1681
+ * @param {string} tableName - The name of the table
1682
+ * @param {string|number} id - The ID of the record
1683
+ * @param {string} pk - primary key colum
1684
+ * @return {Promise<Record<string, any>>} A promise that resolves to the read record
1685
+ */
1686
+ async read(tableName, id, pk) {
1687
+ const m = tableName;
1688
+ let result;
1689
+ try {
1690
+ const repo = this.dataSource.getRepository(m);
1691
+ const q = {
1692
+ where: {
1693
+ [pk]: id,
1694
+ },
1695
+ };
1696
+ result = (await repo.findOne(q));
1697
+ }
1698
+ catch (e) {
1699
+ throw this.parseError(e);
1700
+ }
1701
+ if (!result)
1702
+ throw new NotFoundError(`Record with id: ${id} not found in table ${typeof tableName === "string" ? tableName : Repository.table(tableName)}`);
1703
+ return result;
1704
+ }
1705
+ /**
1706
+ * @description Updates a record in the database
1707
+ * @summary Abstract method that must be implemented to update a record
1708
+ * @param {string} tableName - The name of the table
1709
+ * @param {string|number} id - The ID of the record
1710
+ * @param {Record<string, any>} model - The model to update
1711
+ * @param {string} pk - Additional arguments
1712
+ * @return A promise that resolves to the updated record
1713
+ */
1714
+ async update(tableName, id, model,
1715
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1716
+ ...args) {
1717
+ const m = tableName;
1718
+ try {
1719
+ const repo = this.dataSource.getRepository(m);
1720
+ return repo.save(model);
1721
+ }
1722
+ catch (e) {
1723
+ throw this.parseError(e);
1724
+ }
1725
+ }
1726
+ /**
1727
+ * @description Deletes a record from the database
1728
+ * @summary Abstract method that must be implemented to delete a record
1729
+ * @param {string} tableName - The name of the table
1730
+ * @param {string|number} id - The ID of the record
1731
+ * @param {string} pk - Additional arguments
1732
+ * @return A promise that resolves to the deleted record
1733
+ */
1734
+ async delete(tableName, id, pk,
1735
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1736
+ ...args) {
1737
+ const m = tableName;
1738
+ try {
1739
+ const repo = this.dataSource.getRepository(m);
1740
+ const model = await this.read(tableName, id, pk);
1741
+ const res = await repo.delete(id);
1742
+ return model;
1743
+ }
1744
+ catch (e) {
1745
+ throw this.parseError(e);
1746
+ }
1747
+ }
1748
+ async createAll(tableName, id, model,
1749
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1750
+ ...args) {
1751
+ const m = tableName;
1752
+ try {
1753
+ const repo = this.dataSource.getRepository(m);
1754
+ const result = await repo.insert(model);
1755
+ return this.readAll(tableName, result.identifiers.map((id) => id.id), "id");
1756
+ }
1757
+ catch (e) {
1758
+ throw this.parseError(e);
1759
+ }
1760
+ }
1761
+ async readAll(tableName, id, pk,
1762
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1763
+ ...args) {
1764
+ if (!id.length)
1765
+ return [];
1766
+ const m = tableName;
1767
+ try {
1768
+ const repo = this.dataSource.getRepository(m);
1769
+ return repo.findBy({ [pk]: In(id) });
1770
+ }
1771
+ catch (e) {
1772
+ throw this.parseError(e);
1773
+ }
1774
+ }
1775
+ async updateAll(tableName, ids, model, pk, ...args) {
1776
+ const result = [];
1777
+ for (const m of model) {
1778
+ result.push(await this.update(tableName, m[pk], m, ...args));
1779
+ }
1780
+ return result;
1781
+ }
1782
+ async deleteAll(tableName, ids, pk,
1783
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1784
+ ...args) {
1785
+ if (!ids.length)
1786
+ return [];
1787
+ const m = tableName;
1788
+ try {
1789
+ const repo = this.dataSource.getRepository(m);
1790
+ const models = await this.readAll(tableName, ids, pk);
1791
+ await repo.delete(ids);
1792
+ return models;
1793
+ }
1794
+ catch (e) {
1795
+ throw this.parseError(e);
1796
+ }
1797
+ }
1798
+ /**
1799
+ * @description Parses an error and converts it to a BaseError
1800
+ * @summary Converts various error types to appropriate BaseError subtypes
1801
+ * @param {Error|string} err - The error to parse
1802
+ * @param {string} [reason] - Optional reason for the error
1803
+ * @return {BaseError} The parsed error as a BaseError
1804
+ */
1805
+ parseError(err, reason) {
1806
+ return TypeORMAdapter.parseError(err, reason);
1807
+ }
1808
+ /**
1809
+ * @description Checks if an attribute is reserved
1810
+ * @summary Determines if an attribute name is reserved in PostgreSQL
1811
+ * @param {string} attr - The attribute name to check
1812
+ * @return {boolean} True if the attribute is reserved, false otherwise
1813
+ */
1814
+ isReserved(attr) {
1815
+ return !!attr.match(reservedAttributes);
1816
+ }
1817
+ /**
1818
+ * @description Static method to parse an error and convert it to a BaseError
1819
+ * @summary Converts various error types to appropriate BaseError subtypes based on PostgreSQL error codes and messages
1820
+ * @param {Error|string} err - The error to parse
1821
+ * @param {string} [reason] - Optional reason for the error
1822
+ * @return {BaseError} The parsed error as a BaseError
1823
+ * @mermaid
1824
+ * sequenceDiagram
1825
+ * participant Caller
1826
+ * participant parseError
1827
+ * participant ErrorTypes
1828
+ *
1829
+ * Caller->>parseError: err, reason
1830
+ * Note over parseError: Check if err is already a BaseError
1831
+ * alt err is BaseError
1832
+ * parseError-->>Caller: return err
1833
+ * else err is string
1834
+ * Note over parseError: Extract code from string
1835
+ * alt code matches "duplicate key|already exists"
1836
+ * parseError->>ErrorTypes: new ConflictError(code)
1837
+ * ErrorTypes-->>Caller: ConflictError
1838
+ * else code matches "does not exist|not found"
1839
+ * parseError->>ErrorTypes: new NotFoundError(code)
1840
+ * ErrorTypes-->>Caller: NotFoundError
1841
+ * end
1842
+ * else err has code property
1843
+ * Note over parseError: Extract code and reason
1844
+ * else
1845
+ * Note over parseError: Use err.message as code
1846
+ * end
1847
+ *
1848
+ * Note over parseError: Switch on PostgreSQL error code
1849
+ * alt code is 23505 (unique_violation)
1850
+ * parseError->>ErrorTypes: new ConflictError(reason)
1851
+ * ErrorTypes-->>Caller: ConflictError
1852
+ * else code is 23503 (foreign_key_violation)
1853
+ * parseError->>ErrorTypes: new ConflictError(reason)
1854
+ * ErrorTypes-->>Caller: ConflictError
1855
+ * else code is 42P01 (undefined_table)
1856
+ * parseError->>ErrorTypes: new NotFoundError(reason)
1857
+ * ErrorTypes-->>Caller: NotFoundError
1858
+ * else code is 42703 (undefined_column)
1859
+ * parseError->>ErrorTypes: new NotFoundError(reason)
1860
+ * ErrorTypes-->>Caller: NotFoundError
1861
+ * else code is 42P07 (duplicate_table)
1862
+ * parseError->>ErrorTypes: new ConflictError(reason)
1863
+ * ErrorTypes-->>Caller: ConflictError
1864
+ * else code is 42P16 (invalid_table_definition)
1865
+ * parseError->>ErrorTypes: new IndexError(err)
1866
+ * ErrorTypes-->>Caller: IndexError
1867
+ * else code matches "ECONNREFUSED"
1868
+ * parseError->>ErrorTypes: new ConnectionError(err)
1869
+ * ErrorTypes-->>Caller: ConnectionError
1870
+ * else
1871
+ * parseError->>ErrorTypes: new InternalError(err)
1872
+ * ErrorTypes-->>Caller: InternalError
1873
+ * end
1874
+ */
1875
+ static parseError(err, reason) {
1876
+ if (err instanceof BaseError)
1877
+ return err;
1878
+ const code = typeof err === "string" ? err : err.message;
1879
+ if (code.match(/duplicate key|already exists/g))
1880
+ return new ConflictError(code);
1881
+ if (code.match(/does not exist|not found/g))
1882
+ return new NotFoundError(code);
1883
+ // PostgreSQL error codes: https://www.postgresql.org/docs/current/errcodes-appendix.html
1884
+ switch (code.toString()) {
1885
+ // Integrity constraint violations
1886
+ case "23505": // unique_violation
1887
+ case "23503": // foreign_key_violation
1888
+ case "42P07": // duplicate_table
1889
+ return new ConflictError(reason);
1890
+ // Object not found errors
1891
+ case "42P01": // undefined_table
1892
+ case "42703": // undefined_column
1893
+ return new NotFoundError(reason);
1894
+ // Invalid object definition
1895
+ case "42P16": // invalid_table_definition
1896
+ return new IndexError(err);
1897
+ // Connection errors
1898
+ default:
1899
+ if (code.toString().match(/ECONNREFUSED/g))
1900
+ return new ConnectionError(err);
1901
+ return new InternalError(err);
1902
+ }
1903
+ }
1904
+ static async connect(config) {
1905
+ const con = new DataSource(config);
1906
+ if (!con.isInitialized)
1907
+ await con.initialize();
1908
+ return con;
1909
+ }
1910
+ static async createDatabase(dataSource, dbName) {
1911
+ const log = Logging.for(this.createDatabase);
1912
+ log.verbose(`Creating database ${dbName}`);
1913
+ try {
1914
+ await dataSource.query(`CREATE DATABASE ${dbName}`);
1915
+ log.info(`Created database ${dbName}`);
1916
+ }
1917
+ catch (e) {
1918
+ throw this.parseError(e);
1919
+ }
1920
+ }
1921
+ static async createNotifyFunction(dataSource, user) {
1922
+ const log = Logging.for(this.createNotifyFunction);
1923
+ log.verbose(`Creating notify function`);
1924
+ try {
1925
+ await dataSource.query(`CREATE OR REPLACE FUNCTION notify_table_changes()
1926
+ RETURNS trigger AS $$
1927
+ BEGIN
1928
+ PERFORM pg_notify(
1929
+ 'table_changes',
1930
+ json_build_object(
1931
+ 'table', TG_TABLE_NAME,
1932
+ 'action', TG_OP,
1933
+ 'data', row_to_json(NEW),
1934
+ 'old_data', row_to_json(OLD)
1935
+ )::text
1936
+ );
1937
+ RETURN NEW;
1938
+ END;
1939
+ $$ LANGUAGE plpgsql SECURITY DEFINER
1940
+ ;`);
1941
+ await dataSource.query(`ALTER FUNCTION notify_table_changes() OWNER TO ${user};`);
1942
+ await dataSource.query(`
1943
+ GRANT EXECUTE ON FUNCTION notify_table_changes() TO public;
1944
+ `);
1945
+ log.info(`Created notify function`);
1946
+ }
1947
+ catch (e) {
1948
+ throw this.parseError(e);
1949
+ }
1950
+ }
1951
+ static async deleteDatabase(dataSource, dbName, user) {
1952
+ try {
1953
+ if (user)
1954
+ await dataSource.query(`DROP OWNED BY ${user} CASCADE;`);
1955
+ await dataSource.query(`DROP DATABASE ${dbName}`);
1956
+ }
1957
+ catch (e) {
1958
+ throw this.parseError(e);
1959
+ }
1960
+ }
1961
+ static async createUser(dataSource, dbName, user, password) {
1962
+ try {
1963
+ await dataSource.query(`CREATE USER ${user} WITH PASSWORD '${password}'`);
1964
+ await dataSource.query(`GRANT CONNECT ON DATABASE ${dbName} TO ${user}`);
1965
+ await dataSource.query(`GRANT USAGE ON SCHEMA public TO ${user}`);
1966
+ await dataSource.query(`GRANT CREATE ON SCHEMA public TO ${user}`);
1967
+ await dataSource.query(`GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO ${user}`);
1968
+ await dataSource.query(`GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO ${user}`);
1969
+ await dataSource.query(`GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO ${user}`);
1970
+ await dataSource.query(`ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO ${user}`);
1971
+ await dataSource.query(`ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON SEQUENCES TO ${user}`);
1972
+ }
1973
+ catch (e) {
1974
+ throw this.parseError(e);
1975
+ }
1976
+ }
1977
+ static async deleteUser(client, user, admin) {
1978
+ try {
1979
+ await client.query(`REASSIGN OWNED BY ${user} TO ${admin}`);
1980
+ await client.query(`REVOKE ALL ON ALL TABLES IN SCHEMA public FROM ${user}`);
1981
+ await client.query(`REVOKE ALL ON SCHEMA public FROM ${user}`);
1982
+ await client.query(`REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM ${user}`);
1983
+ await client.query(`REVOKE ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public FROM ${user}`);
1984
+ await client.query(`ALTER DEFAULT PRIVILEGES FOR ROLE ${admin} IN SCHEMA public REVOKE ALL ON TABLES FROM ${user}`);
1985
+ await client.query(`ALTER DEFAULT PRIVILEGES FOR ROLE ${admin} IN SCHEMA public REVOKE ALL ON SEQUENCES FROM ${user};`);
1986
+ await client.query(`ALTER DEFAULT PRIVILEGES FOR ROLE ${admin} IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM ${user}`);
1987
+ await client.query(`DROP OWNED BY ${user} CASCADE`);
1988
+ await client.query(`DROP USER IF EXISTS "${user}"`);
1989
+ }
1990
+ catch (e) {
1991
+ throw this.parseError(e);
1992
+ }
1993
+ }
1994
+ static parseTypeToPostgres(type, isPk, isFk = false) {
1995
+ switch (type.toLowerCase()) {
1996
+ case "string":
1997
+ return isPk ? "TEXT PRIMARY KEY" : isFk ? "TEXT" : "VARCHAR";
1998
+ case "number":
1999
+ return isPk ? "SERIAL PRIMARY KEY" : "INTEGER";
2000
+ case "boolean":
2001
+ return "BOOLEAN";
2002
+ case "date":
2003
+ return "TIMESTAMP";
2004
+ case "bigint":
2005
+ return isPk ? "BIGINT PRIMARY KEY" : "BIGINT";
2006
+ default: {
2007
+ const m = Model.get(type);
2008
+ if (m) {
2009
+ const mm = new m();
2010
+ const type = Reflection.getTypeFromDecorator(mm, findPrimaryKey(mm).id);
2011
+ return {
2012
+ model: m,
2013
+ pkType: type,
2014
+ };
2015
+ }
2016
+ throw new InternalError(`Unsupported type: ${type}`);
2017
+ }
2018
+ }
2019
+ }
2020
+ static parseValidationToPostgres(prop, type, isPk, key, options) {
2021
+ switch (key) {
2022
+ case ValidationKeys.REQUIRED:
2023
+ return "NOT NULL";
2024
+ case ValidationKeys.MAX_LENGTH:
2025
+ if (isPk || !options || type.toLowerCase() !== "string") {
2026
+ return "";
2027
+ }
2028
+ return `(${options[ValidationKeys.MAX_LENGTH]})`;
2029
+ case ValidationKeys.MIN_LENGTH:
2030
+ return `CONSTRAINT ${prop}_min_length_check CHECK (LENGTH(${prop}) >= ${options[ValidationKeys.MIN_LENGTH]})`;
2031
+ case ValidationKeys.PATTERN:
2032
+ case ValidationKeys.URL:
2033
+ case ValidationKeys.EMAIL:
2034
+ return `CONSTRAINT ${prop}_pattern_check CHECK (${prop} ~ '${convertJsRegexToPostgres(options[ValidationKeys.PATTERN])}')`;
2035
+ case ValidationKeys.TYPE:
2036
+ case ValidationKeys.DATE:
2037
+ return "";
2038
+ case ValidationKeys.MIN:
2039
+ return `CONSTRAINT ${prop}_${key}_check CHECK (${prop} >= ${options[ValidationKeys.MIN]})`;
2040
+ case ValidationKeys.MAX:
2041
+ return `CONSTRAINT ${prop}_${key}_check CHECK (${prop} <= ${options[ValidationKeys.MAX]})`;
2042
+ case ValidationKeys.PASSWORD:
2043
+ default:
2044
+ throw new InternalError(`Unsupported type: ${key}`);
2045
+ }
2046
+ }
2047
+ static parseRelationsToPostgres(prop, clazz, pk, key, options) {
2048
+ const tableName = Repository.table(clazz);
2049
+ const { cascade } = options;
2050
+ const cascadeStr = `${cascade.update ? " ON UPDATE CASCADE" : ""}${cascade.delete ? " ON DELETE CASCADE" : ""}`;
2051
+ switch (`relations${key}`) {
2052
+ case PersistenceKeys.ONE_TO_ONE:
2053
+ return `FOREIGN KEY (${prop}) REFERENCES ${tableName}(${pk})${cascadeStr}`;
2054
+ default:
2055
+ throw new InternalError(`Unsupported operation: ${key}`);
2056
+ }
2057
+ }
2058
+ static async createTable(client, model) {
2059
+ const result = {};
2060
+ const m = new model({});
2061
+ const tableName = Repository.table(model);
2062
+ const { id } = findPrimaryKey(m);
2063
+ let isPk, column;
2064
+ const properties = Object.getOwnPropertyNames(m);
2065
+ for (const prop of properties) {
2066
+ if (typeof this[prop] === "function" ||
2067
+ prop.toString().startsWith("_") ||
2068
+ prop === "constructor") {
2069
+ continue;
2070
+ }
2071
+ isPk = prop === id;
2072
+ column = Repository.column(m, prop.toString());
2073
+ const allDecs = Reflection.getPropertyDecorators(ValidationKeys.REFLECT, m, prop.toString(), false, true);
2074
+ const decoratorData = allDecs.decorators.reduce((accum, el) => {
2075
+ const { key, props } = el;
2076
+ if (key === ModelKeys.TYPE && !accum[ValidationKeys.TYPE]) {
2077
+ accum[ValidationKeys.TYPE] = {
2078
+ customTypes: [props.name],
2079
+ message: DEFAULT_ERROR_MESSAGES.TYPE,
2080
+ description: "defines the accepted types for the attribute",
2081
+ };
2082
+ }
2083
+ else if (key !== ValidationKeys.TYPE) {
2084
+ // do nothing. we can only support basis ctypes at this time
2085
+ accum[key] = props;
2086
+ }
2087
+ return accum;
2088
+ }, {});
2089
+ const dbDecs = Reflection.getPropertyDecorators(Repository.key("relations"), m, prop.toString(), true, true);
2090
+ const query = [];
2091
+ const constraints = [];
2092
+ const foreignKeys = [];
2093
+ let typeData = undefined;
2094
+ let childClass = undefined;
2095
+ let childPk;
2096
+ if (Object.keys(decoratorData).length) {
2097
+ typeData = decoratorData[ValidationKeys.TYPE];
2098
+ if (!typeData) {
2099
+ throw new Error(`Missing type information`);
2100
+ }
2101
+ let parsedType = this.parseTypeToPostgres(typeof typeData.customTypes[0] === "function"
2102
+ ? typeData.customTypes[0]()
2103
+ : typeData.customTypes[0], isPk);
2104
+ if (typeof parsedType === "string") {
2105
+ parsedType = { model: parsedType };
2106
+ }
2107
+ let typeStr = parsedType.model;
2108
+ if (typeof typeStr !== "string") {
2109
+ if (Array.isArray(typeStr)) {
2110
+ console.log(typeStr);
2111
+ }
2112
+ // continue;
2113
+ // const res: Record<string, PostgresTableSpec> = await this.createTable(pool, typeStr);
2114
+ try {
2115
+ childClass = parsedType.model;
2116
+ const m = new childClass();
2117
+ childPk = findPrimaryKey(m);
2118
+ typeStr = this.parseTypeToPostgres(parsedType.pkType, false, true);
2119
+ await this.createTable(client, childClass);
2120
+ }
2121
+ catch (e) {
2122
+ if (!(e instanceof ConflictError))
2123
+ throw e;
2124
+ }
2125
+ }
2126
+ let tp = Array.isArray(typeData.customTypes)
2127
+ ? typeData.customTypes[0]
2128
+ : typeData.customTypes;
2129
+ tp = typeof tp === "function" && !tp.name ? tp() : tp;
2130
+ const validationStr = this.parseValidationToPostgres(column, tp, isPk, ValidationKeys.MAX_LENGTH, decoratorData[ValidationKeys.MAX_LENGTH] || {
2131
+ [ValidationKeys.MAX_LENGTH]: 255,
2132
+ });
2133
+ const q = `${column} ${typeStr}${validationStr}`;
2134
+ if (isPk) {
2135
+ query.unshift(q);
2136
+ }
2137
+ else {
2138
+ query.push(q);
2139
+ }
2140
+ for (const [key, props] of Object.entries(decoratorData).filter(([k]) => ![ValidationKeys.TYPE, ValidationKeys.MAX_LENGTH].includes(k))) {
2141
+ const validation = this.parseValidationToPostgres(column, tp, isPk, key, props);
2142
+ if (validation.startsWith("CONSTRAINT")) {
2143
+ constraints.push(validation);
2144
+ }
2145
+ else {
2146
+ if (validation) {
2147
+ query.push(validation);
2148
+ }
2149
+ }
2150
+ }
2151
+ }
2152
+ // TODO ignore for now. this leaves foreign keys out
2153
+ // eslint-disable-next-line no-constant-binary-expression
2154
+ if ((dbDecs && dbDecs.decorators.length)) {
2155
+ if (!typeData)
2156
+ throw new Error(`Missing type information`);
2157
+ for (const decorator of dbDecs.decorators) {
2158
+ const { key, props } = decorator;
2159
+ const validation = this.parseRelationsToPostgres(column, childClass, childPk.id, key, props);
2160
+ if (validation.startsWith("FOREIGN")) {
2161
+ foreignKeys.push(validation);
2162
+ }
2163
+ else {
2164
+ throw new InternalError(`Unsupported relation: ${key}`);
2165
+ }
2166
+ }
2167
+ }
2168
+ result[prop.toString()] = {
2169
+ query: query.join(" "),
2170
+ values: [],
2171
+ primaryKey: isPk,
2172
+ constraints: constraints,
2173
+ foreignKeys: foreignKeys,
2174
+ };
2175
+ }
2176
+ const values = Object.values(result);
2177
+ const query = values.map((r) => r.query).join(",\n");
2178
+ const constraints = values
2179
+ .filter((c) => !!c.constraints.length)
2180
+ .map((r) => r.constraints)
2181
+ .join(",\n");
2182
+ const foreignKeys = values
2183
+ .filter((c) => !!c.foreignKeys.length)
2184
+ .map((r) => r.foreignKeys)
2185
+ .join(",\n");
2186
+ const vals = [query, constraints];
2187
+ if (foreignKeys) {
2188
+ vals.push(foreignKeys);
2189
+ }
2190
+ const queryString = `CREATE TABLE ${tableName} (${vals.filter((v) => !!v).join(",\n")})`;
2191
+ try {
2192
+ await client.query(queryString);
2193
+ await client.query(`CREATE TRIGGER notify_changes_${tableName}
2194
+ AFTER INSERT OR UPDATE OR DELETE ON ${tableName}
2195
+ FOR EACH ROW
2196
+ EXECUTE FUNCTION notify_table_changes();`);
2197
+ }
2198
+ catch (e) {
2199
+ throw this.parseError(e);
2200
+ }
2201
+ return result;
2202
+ }
2203
+ static async getCurrentUser(client) {
2204
+ const queryString = `SELECT CURRENT_USER;`;
2205
+ try {
2206
+ const result = await client.query(queryString);
2207
+ return result[0].current_user;
2208
+ }
2209
+ catch (e) {
2210
+ throw this.parseError(e);
2211
+ }
2212
+ }
2213
+ static decoration() {
2214
+ // @table() => @Entity()
2215
+ const tableKey = Adapter.key(PersistenceKeys.TABLE);
2216
+ Decoration.flavouredAs(TypeORMFlavour)
2217
+ .for(tableKey)
2218
+ .extend((original) => Entity()(original[ModelKeys.ANCHOR] || original))
2219
+ .apply();
2220
+ // @pk() => @PrimaryGeneratedColumn() | @PrimaryColumn()
2221
+ const pkKey = Repository.key(DBKeys.ID);
2222
+ function pkDec(options) {
2223
+ const decorators = [
2224
+ required(),
2225
+ readonly(),
2226
+ propMetadata(pkKey, options),
2227
+ ];
2228
+ if (options.type)
2229
+ decorators.push(PrimaryGeneratedColumn());
2230
+ else
2231
+ decorators.push(PrimaryColumn({ unique: true }));
2232
+ return apply(...decorators);
2233
+ }
2234
+ Decoration.flavouredAs(TypeORMFlavour)
2235
+ .for(pkKey)
2236
+ .define({
2237
+ decorator: pkDec,
2238
+ })
2239
+ .apply();
2240
+ // @column("columnName") => @Column({name: "columnName"})
2241
+ const columnKey = Adapter.key(PersistenceKeys.COLUMN);
2242
+ Decoration.flavouredAs(TypeORMFlavour)
2243
+ .for(columnKey)
2244
+ .extend({
2245
+ decorator: function columm(name) {
2246
+ return function column(obj, prop) {
2247
+ return Column({
2248
+ name: name || prop,
2249
+ nullable: true,
2250
+ })(obj, prop);
2251
+ };
2252
+ },
2253
+ transform: (args) => {
2254
+ const columnName = args[1];
2255
+ return [columnName];
2256
+ },
2257
+ })
2258
+ .apply();
2259
+ // @unique => @Column({unique: true})
2260
+ const uniqueKey = Adapter.key(PersistenceKeys.UNIQUE);
2261
+ Decoration.flavouredAs(TypeORMFlavour)
2262
+ .for(uniqueKey)
2263
+ .define(propMetadata(uniqueKey, {}))
2264
+ .extend(Column({ unique: true }))
2265
+ .apply();
2266
+ // @required => @Column({ nullable: false })
2267
+ const requiredKey = Validation.key(ValidationKeys.REQUIRED);
2268
+ Decoration.flavouredAs(TypeORMFlavour)
2269
+ .for(requiredKey)
2270
+ .extend(Column({ nullable: false }))
2271
+ .apply();
2272
+ // @version => @VersionColumn()
2273
+ const versionKey = Repository.key(DBKeys.VERSION);
2274
+ Decoration.flavouredAs(TypeORMFlavour)
2275
+ .for(versionKey)
2276
+ .define(type(Number.name), VersionColumn())
2277
+ .apply();
2278
+ function ValidationUpdateKey(key) {
2279
+ return UpdateValidationKeys.REFLECT + key;
2280
+ }
2281
+ // @timestamp(op) => @CreateDateColumn() || @UpdateDateColumn()
2282
+ const timestampKey = ValidationUpdateKey(DBKeys.TIMESTAMP);
2283
+ function ts(operation, format) {
2284
+ const decorators = [
2285
+ date(format, DEFAULT_ERROR_MESSAGES$1.TIMESTAMP.DATE),
2286
+ required(DEFAULT_ERROR_MESSAGES$1.TIMESTAMP.REQUIRED),
2287
+ propMetadata(Validation.key(DBKeys.TIMESTAMP), {
2288
+ operation: operation,
2289
+ format: format,
2290
+ }),
2291
+ ];
2292
+ if (operation.indexOf(OperationKeys.UPDATE) !== -1)
2293
+ decorators.push(propMetadata(timestampKey, {
2294
+ message: DEFAULT_ERROR_MESSAGES$1.TIMESTAMP.INVALID,
2295
+ }));
2296
+ else
2297
+ decorators.push(readonly());
2298
+ return apply(...decorators);
2299
+ }
2300
+ Decoration.flavouredAs(TypeORMFlavour)
2301
+ .for(timestampKey)
2302
+ .define({
2303
+ decorator: ts,
2304
+ })
2305
+ .extend({
2306
+ decorator: function timestamp(...ops) {
2307
+ return function timestamp(obj, prop) {
2308
+ if (ops.indexOf(OperationKeys.UPDATE) !== -1)
2309
+ return UpdateDateColumn()(obj, prop);
2310
+ return CreateDateColumn()(obj, prop);
2311
+ };
2312
+ },
2313
+ transform: (args) => {
2314
+ return args[0];
2315
+ },
2316
+ })
2317
+ .apply();
2318
+ // @oneToOne(clazz) => @OneToOne(() => clazz)
2319
+ const oneToOneKey = Repository.key(PersistenceKeys.ONE_TO_ONE);
2320
+ Decoration.flavouredAs(TypeORMFlavour)
2321
+ .for(oneToOneKey)
2322
+ .define({
2323
+ decorator: function oneToOne(clazz, cascade, populate) {
2324
+ const metadata = {
2325
+ class: (clazz.name ? clazz.name : clazz),
2326
+ cascade: cascade,
2327
+ populate: populate,
2328
+ };
2329
+ const ormMeta = {
2330
+ cascade: cascade.update === Cascade.CASCADE ||
2331
+ cascade.delete === Cascade.CASCADE,
2332
+ onDelete: cascade.delete ? "CASCADE" : "DEFAULT",
2333
+ onUpdate: cascade.update ? "CASCADE" : "DEFAULT",
2334
+ nullable: true,
2335
+ eager: populate,
2336
+ };
2337
+ return apply(prop(PersistenceKeys.RELATIONS), type([
2338
+ (typeof clazz === "function" && !clazz.name
2339
+ ? clazz
2340
+ : clazz.name),
2341
+ String.name,
2342
+ Number.name,
2343
+ BigInt.name,
2344
+ ]), propMetadata(oneToOneKey, metadata), OneToOne(() => {
2345
+ if (!clazz.name)
2346
+ clazz = clazz();
2347
+ if (!clazz[ModelKeys.ANCHOR])
2348
+ throw new InternalError("Original Model not found in constructor");
2349
+ return clazz[ModelKeys.ANCHOR];
2350
+ }, (model) => {
2351
+ const pk = findPrimaryKey(new clazz()).id;
2352
+ return model[pk];
2353
+ }, ormMeta), JoinColumn());
2354
+ },
2355
+ })
2356
+ .apply();
2357
+ // @oneToMany(clazz) => @OneToMany(() => clazz)
2358
+ const oneToManyKey = Repository.key(PersistenceKeys.ONE_TO_MANY);
2359
+ Decoration.flavouredAs(TypeORMFlavour)
2360
+ .for(oneToManyKey)
2361
+ .define({
2362
+ decorator: function oneToMany(clazz, cascade, populate) {
2363
+ const metadata = {
2364
+ class: (clazz.name ? clazz.name : clazz),
2365
+ cascade: cascade,
2366
+ populate: populate,
2367
+ };
2368
+ return apply(prop(PersistenceKeys.RELATIONS), list(clazz), propMetadata(oneToManyKey, metadata), function OneToManyWrapper(obj, prop) {
2369
+ const ormMeta = {
2370
+ cascade: cascade.update === Cascade.CASCADE ||
2371
+ cascade.delete === Cascade.CASCADE,
2372
+ onDelete: cascade.delete ? "CASCADE" : "DEFAULT",
2373
+ onUpdate: cascade.update ? "CASCADE" : "DEFAULT",
2374
+ nullable: true,
2375
+ eager: populate,
2376
+ };
2377
+ return OneToMany(() => {
2378
+ if (!clazz.name)
2379
+ clazz = clazz();
2380
+ if (!clazz[ModelKeys.ANCHOR])
2381
+ throw new InternalError("Original Model not found in constructor");
2382
+ return clazz[ModelKeys.ANCHOR];
2383
+ }, (model) => {
2384
+ if (!clazz.name)
2385
+ clazz = clazz();
2386
+ const m = new clazz();
2387
+ const crossRelationKey = Object.keys(m).find((k) => {
2388
+ const decs = Reflection.getPropertyDecorators(Repository.key(PersistenceKeys.MANY_TO_ONE), m, k, true);
2389
+ if (!decs || !decs.decorators || !decs.decorators.length)
2390
+ return false;
2391
+ const designType = Reflect.getMetadata(ModelKeys.TYPE, m, k);
2392
+ if (!designType)
2393
+ throw new InternalError(`No Type Definition found for ${k} in ${m.constructor.name}`);
2394
+ return designType.name === obj.constructor.name;
2395
+ });
2396
+ if (!crossRelationKey)
2397
+ throw new InternalError(`Cross relation not found. Did you use @manyToOne on the ${clazz.name}?`);
2398
+ return model[crossRelationKey];
2399
+ }, ormMeta)(obj, prop);
2400
+ });
2401
+ },
2402
+ })
2403
+ .apply();
2404
+ // @manyToOne(clazz) => @ManyToOne(() => clazz)
2405
+ const manyToOneKey = Repository.key(PersistenceKeys.MANY_TO_ONE);
2406
+ Decoration.flavouredAs(TypeORMFlavour)
2407
+ .for(manyToOneKey)
2408
+ .define({
2409
+ decorator: function manyToOne(clazz, cascade, populate) {
2410
+ const metadata = {
2411
+ class: (clazz.name ? clazz.name : clazz),
2412
+ cascade: cascade,
2413
+ populate: populate,
2414
+ };
2415
+ ({
2416
+ cascade: cascade.update === Cascade.CASCADE ||
2417
+ cascade.delete === Cascade.CASCADE,
2418
+ onDelete: cascade.delete ? "CASCADE" : "DEFAULT",
2419
+ onUpdate: cascade.update ? "CASCADE" : "DEFAULT"});
2420
+ return apply(prop(PersistenceKeys.RELATIONS), type([
2421
+ (typeof clazz === "function" && !clazz.name
2422
+ ? clazz
2423
+ : clazz.name),
2424
+ String.name,
2425
+ Number.name,
2426
+ BigInt.name,
2427
+ ]), propMetadata(manyToOneKey, metadata), function ManyToOneWrapper(obj, prop) {
2428
+ return ManyToOne(() => {
2429
+ if (!clazz.name)
2430
+ clazz = clazz();
2431
+ if (!clazz[ModelKeys.ANCHOR])
2432
+ throw new InternalError("Original Model not found in constructor");
2433
+ return clazz[ModelKeys.ANCHOR];
2434
+ }, (model) => {
2435
+ if (!clazz.name)
2436
+ clazz = clazz();
2437
+ const m = new clazz();
2438
+ const crossRelationKey = Object.keys(m).find((k) => {
2439
+ const decs = Reflection.getPropertyDecorators(Repository.key(PersistenceKeys.ONE_TO_MANY), m, k, true);
2440
+ if (!decs || !decs.decorators || !decs.decorators.length)
2441
+ return false;
2442
+ const listDec = Reflect.getMetadata(Validation.key(ValidationKeys.LIST), m, k);
2443
+ if (!listDec)
2444
+ throw new InternalError(`No Type Definition found for ${k} in ${m.constructor.name}`);
2445
+ const name = listDec.clazz[0]().name;
2446
+ return name === obj.constructor.name;
2447
+ });
2448
+ if (!crossRelationKey)
2449
+ throw new InternalError(`Cross relation not found. Did you use @manyToOne on the ${clazz.name}?`);
2450
+ return model[crossRelationKey];
2451
+ })(obj, prop);
2452
+ });
2453
+ },
2454
+ })
2455
+ .apply();
2456
+ // @manyToMany(clazz) => @ManyToMany(() => clazz)
2457
+ const manyToManyKey = Repository.key(PersistenceKeys.MANY_TO_MANY);
2458
+ Decoration.flavouredAs(TypeORMFlavour)
2459
+ .for(manyToManyKey)
2460
+ .define({
2461
+ decorator: function manyToMany(clazz, cascade, populate) {
2462
+ const metadata = {
2463
+ class: clazz.name,
2464
+ cascade: cascade,
2465
+ populate: populate,
2466
+ };
2467
+ const ormMeta = {
2468
+ cascade: cascade.update === Cascade.CASCADE ||
2469
+ cascade.delete === Cascade.CASCADE,
2470
+ onDelete: cascade.delete ? "CASCADE" : "DEFAULT",
2471
+ onUpdate: cascade.update ? "CASCADE" : "DEFAULT",
2472
+ nullable: true,
2473
+ eager: populate,
2474
+ };
2475
+ return apply(prop(PersistenceKeys.RELATIONS), list(clazz), propMetadata(manyToManyKey, metadata), ManyToMany(() => {
2476
+ if (!clazz.name)
2477
+ clazz = clazz();
2478
+ if (!clazz[ModelKeys.ANCHOR])
2479
+ throw new InternalError("Original Model not found in constructor");
2480
+ return clazz[ModelKeys.ANCHOR];
2481
+ }, (model) => {
2482
+ if (!clazz.name)
2483
+ clazz = clazz();
2484
+ const pk = findPrimaryKey(new clazz()).id;
2485
+ return model[pk];
2486
+ }, ormMeta), JoinTable());
2487
+ },
2488
+ })
2489
+ .apply();
2490
+ }
2491
+ }
2492
+ __decorate([
2493
+ final(),
2494
+ __metadata("design:type", Function),
2495
+ __metadata("design:paramtypes", []),
2496
+ __metadata("design:returntype", TypeORMDispatch)
2497
+ ], TypeORMAdapter.prototype, "Dispatch", null);
2498
+ __decorate([
2499
+ final(),
2500
+ __metadata("design:type", Function),
2501
+ __metadata("design:paramtypes", []),
2502
+ __metadata("design:returntype", Object)
2503
+ ], TypeORMAdapter.prototype, "repository", null);
2504
+ __decorate([
2505
+ final(),
2506
+ __metadata("design:type", Function),
2507
+ __metadata("design:paramtypes", []),
2508
+ __metadata("design:returntype", TypeORMStatement)
2509
+ ], TypeORMAdapter.prototype, "Statement", null);
2510
+ __decorate([
2511
+ final(),
2512
+ __metadata("design:type", Function),
2513
+ __metadata("design:paramtypes", [Object]),
2514
+ __metadata("design:returntype", Promise)
2515
+ ], TypeORMAdapter.prototype, "Sequence", null);
2516
+ __decorate([
2517
+ final(),
2518
+ __metadata("design:type", Function),
2519
+ __metadata("design:paramtypes", [Object]),
2520
+ __metadata("design:returntype", Promise)
2521
+ ], TypeORMAdapter.prototype, "index", null);
2522
+
2523
+ TypeORMAdapter.decoration();
2524
+ /**
2525
+ * @description TypeORM integration for Decaf.ts.
2526
+ * @summary Provides the TypeORM-backed implementation of the Decaf.ts data access abstractions, including the adapter, repository, statement builder, pagination utilities, index helpers, and type definitions. Key exports include {@link TypeORMAdapter}, {@link TypeORMRepository}, {@link TypeORMStatement}, {@link TypeORMPaginator}, and index generation utilities.
2527
+ * @module for-typeorm
2528
+ */
2529
+ /**
2530
+ * @description Stores the current package version.
2531
+ * @summary The version string of the for-typeorm package.
2532
+ * @const VERSION
2533
+ * @memberOf module:for-typeorm
2534
+ */
2535
+ const VERSION = "0.0.6";
2536
+
2537
+ export { IndexError, SQLOperator, TypeORMAdapter, TypeORMConst, TypeORMDispatch, TypeORMFlavour, TypeORMGroupOperator, TypeORMKeys, TypeORMOperator, TypeORMPaginator, TypeORMQueryLimit, TypeORMRepository, TypeORMSequence, TypeORMStatement, VERSION, convertJsRegexToPostgres, createdByOnPostgresCreateUpdate, generateIndexes, reservedAttributes, translateOperators };
2538
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yLXR5cGVvcm0uZXNtLmNqcyIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbnN0YW50cy50cyIsIi4uL3NyYy9lcnJvcnMudHMiLCIuLi9zcmMvdHlwZXMudHMiLCIuLi9zcmMvcXVlcnkvY29uc3RhbnRzLnRzIiwiLi4vc3JjL3F1ZXJ5L1BhZ2luYXRvci50cyIsIi4uL3NyYy9xdWVyeS90cmFuc2xhdGUudHMiLCIuLi9zcmMvcXVlcnkvU3RhdGVtZW50LnRzIiwiLi4vc3JjL3NlcXVlbmNlcy9TZXF1ZW5jZS50cyIsIi4uL3NyYy9pbmRleGVzL2dlbmVyYXRvci50cyIsIi4uL3NyYy9UeXBlT1JNUmVwb3NpdG9yeS50cyIsIi4uL3NyYy9UeXBlT1JNRXZlbnRTdWJzY3JpYmVyLnRzIiwiLi4vc3JjL1R5cGVPUk1EaXNwYXRjaC50cyIsIi4uL3NyYy91dGlscy50cyIsIi4uL3NyYy9vdmVycmlkZXMvdXRpbHMudHMiLCIuLi9zcmMvb3ZlcnJpZGVzL0NvbHVtbi50cyIsIi4uL3NyYy9vdmVycmlkZXMvVXBkYXRlRGF0ZUNvbHVtbi50cyIsIi4uL3NyYy9vdmVycmlkZXMvQ3JlYXRlRGF0ZUNvbHVtbi50cyIsIi4uL3NyYy9vdmVycmlkZXMvUHJpbWFyeUdlbmVyYXRlZENvbHVtbi50cyIsIi4uL3NyYy9vdmVycmlkZXMvUHJpbWFyeUNvbHVtbi50cyIsIi4uL3NyYy9vdmVycmlkZXMvRW50aXR5LnRzIiwiLi4vc3JjL1R5cGVPUk1BZGFwdGVyLnRzIiwiLi4vc3JjL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGRlc2NyaXB0aW9uIFJlZ3VsYXIgZXhwcmVzc2lvbiB0byBpZGVudGlmeSByZXNlcnZlZCBhdHRyaWJ1dGVzIGZvciBTUUwgY29udGV4dHMuXG4gKiBAc3VtbWFyeSBNYXRjaGVzIGF0dHJpYnV0ZSBuYW1lcyB0aGF0IGNvbmZsaWN0IHdpdGggU1FMIHJlc2VydmVkIGtleXdvcmRzIHRvIHByZXZlbnQgaW52YWxpZCBzY2hlbWEgb3IgcXVlcnkgZ2VuZXJhdGlvbi5cbiAqIEBjb25zdCByZXNlcnZlZEF0dHJpYnV0ZXNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLXR5cGVvcm1cbiAqL1xuZXhwb3J0IGNvbnN0IHJlc2VydmVkQXR0cmlidXRlcyA9XG4gIC9eKHNlbGVjdHxmcm9tfHdoZXJlfGFuZHxvcnxpbnNlcnR8dXBkYXRlfGRlbGV0ZXxkcm9wfGNyZWF0ZXx0YWJsZXxpbmRleHxwcmltYXJ5fGtleXxmb3JlaWdufHJlZmVyZW5jZXN8Y29uc3RyYWludHx1bmlxdWV8Y2hlY2t8ZGVmYXVsdHxudWxsfG5vdHxhc3xvcmRlcnxieXxncm91cHxoYXZpbmd8bGltaXR8b2Zmc2V0fGpvaW58aW5uZXJ8b3V0ZXJ8bGVmdHxyaWdodHxmdWxsfG9ufHVzaW5nfHZhbHVlc3xyZXR1cm5pbmd8c2V0fGludG98Y2FzZXx3aGVufHRoZW58ZWxzZXxlbmR8Y2FzdHxjb2FsZXNjZXxleGlzdHN8YW55fGFsbHxzb21lfGlufGJldHdlZW58bGlrZXxpbGlrZXxzaW1pbGFyfHRvfGlzfHRydWV8ZmFsc2V8YXNjfGRlc2N8ZGlzdGluY3R8dW5pb258aW50ZXJzZWN0fGV4Y2VwdHxuYXR1cmFsfGxhdGVyYWx8d2luZG93fG92ZXJ8cGFydGl0aW9ufHJhbmdlfHJvd3N8dW5ib3VuZGVkfHByZWNlZGluZ3xmb2xsb3dpbmd8Y3VycmVudHxyb3d8d2l0aHxyZWN1cnNpdmV8bWF0ZXJpYWxpemVkfHZpZXd8ZnVuY3Rpb258dHJpZ2dlcnxwcm9jZWR1cmV8bGFuZ3VhZ2V8cmV0dXJuc3xyZXR1cm58ZGVjbGFyZXxiZWdpbnxjb21taXR8cm9sbGJhY2t8c2F2ZXBvaW50fHRyYW5zYWN0aW9ufHRlbXBvcmFyeXx0ZW1wfGlmfGxvb3B8d2hpbGV8Zm9yfGNvbnRpbnVlfGV4aXR8cmFpc2V8ZXhjZXB0aW9ufG5vdGljZXxpbmZvfGxvZ3xkZWJ1Z3xhc3NlcnR8ZXhlY3V0ZXxwZXJmb3JtfGdldHxkaWFnbm9zdGljc3xjYWxsfGRvfGFsaWFzfGNvbW1lbnR8dmFjdXVtfGFuYWx5emV8ZXhwbGFpbnxjb3B5fGdyYW50fHJldm9rZXxwcml2aWxlZ2VzfHB1YmxpY3x1c2FnZXxzY2hlbWF8c2VxdWVuY2V8b3duZWR8b3duZXJ8dGFibGVzcGFjZXxzdG9yYWdlfGluaGVyaXRzfHR5cGV8b3BlcmF0b3J8Y29sbGF0ZXxjb2xsYXRpb258Y2FzY2FkZXxyZXN0cmljdHxhZGR8YWx0ZXJ8Y29sdW1ufHJlbmFtZXx0b3xlbmFibGV8ZGlzYWJsZXxmb3JjZXxub3xpbnN0ZWFkfG9mfGJlZm9yZXxhZnRlcnxlYWNofHN0YXRlbWVudHxyb3d8ZXhlY3V0ZXxhbHNvfG9ubHl8ZXhjbHVkZXxudWxsc3xvdGhlcnN8b3JkaW5hbGl0eXx0aWVzfG5vdGhpbmd8Y2FjaGV8Y3ljbGV8aW5jcmVtZW50fG1pbnZhbHVlfG1heHZhbHVlfHN0YXJ0fHJlc3RhcnR8Ynl8Y2FsbGVkfHJldHVybnN8bGFuZ3VhZ2V8aW1tdXRhYmxlfHN0YWJsZXx2b2xhdGlsZXxzdHJpY3R8c2VjdXJpdHl8ZGVmaW5lcnxpbnZva2VyfGNvc3R8cm93c3xzdXBwb3J0fGhhbmRsZXJ8aW5saW5lfHZhbGlkYXRvcnxvcHRpb25zfHN0b3JhZ2V8aW5oZXJpdGFuY2V8b2lkc3x3aXRob3V0fGRhdGF8ZGljdGlvbmFyeXxlbmNvZGluZ3xsY19jb2xsYXRlfGxjX2N0eXBlfGNvbm5lY3Rpb258bGltaXR8cGFzc3dvcmR8dmFsaWR8dW50aWx8c3VwZXJ1c2VyfG5vc3VwZXJ1c2VyfGNyZWF0ZWRifG5vY3JlYXRlZGJ8Y3JlYXRlcm9sZXxub2NyZWF0ZXJvbGV8aW5oZXJpdHxub2luaGVyaXR8bG9naW58bm9sb2dpbnxyZXBsaWNhdGlvbnxub3JlcGxpY2F0aW9ufGJ5cGFzc3Jsc3xub2J5cGFzc3Jsc3xlbmNyeXB0ZWR8dW5lbmNyeXB0ZWR8bmV3fG9sZHxzZXNzaW9uX3VzZXJ8Y3VycmVudF91c2VyfGN1cnJlbnRfcm9sZXxjdXJyZW50X3NjaGVtYXxjdXJyZW50X2NhdGFsb2d8Y3VycmVudF9kYXRlfGN1cnJlbnRfdGltZXxjdXJyZW50X3RpbWVzdGFtcHxsb2NhbHRpbWV8bG9jYWx0aW1lc3RhbXB8Y3VycmVudF9kYXRhYmFzZXxpbmV0fGNpZHJ8bWFjYWRkcnxtYWNhZGRyOHxiaXR8dmFyYml0fHRzdmVjdG9yfHRzcXVlcnl8dXVpZHx4bWx8anNvbnxqc29uYnxpbnR8aW50ZWdlcnxzbWFsbGludHxiaWdpbnR8ZGVjaW1hbHxudW1lcmljfHJlYWx8ZG91YmxlfHByZWNpc2lvbnxmbG9hdHxib29sZWFufGJvb2x8Y2hhcnxjaGFyYWN0ZXJ8dmFyY2hhcnx0ZXh0fGJ5dGVhfGRhdGV8dGltZXx0aW1lc3RhbXB8aW50ZXJ2YWx8cG9pbnR8bGluZXxsc2VnfGJveHxwYXRofHBvbHlnb258Y2lyY2xlfG1vbmV5fHZvaWQpJC9pO1xuXG5leHBvcnQgY29uc3QgVHlwZU9STUZsYXZvdXIgPSBcInR5cGUtb3JtXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFNoYXBlIG9mIHRoZSBUeXBlT1JNS2V5cyBjb25zdGFudC5cbiAqIEBzdW1tYXJ5IERlc2NyaWJlcyB0aGUga2V5cyBhbmQgdGhlaXIgbWVhbmluZ3MgdXNlZCBieSB0aGUgVHlwZU9STSBhZGFwdGVyLlxuICogQHR5cGVkZWYgVHlwZU9STUtleXNEZWZcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBTRVBBUkFUT1IgU2VwYXJhdG9yIHVzZWQgdG8gam9pbiB0YWJsZSBhbmQgY29sdW1uIGlkZW50aWZpZXJzLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IElEIERlZmF1bHQgcHJpbWFyeSBrZXkgZmllbGQgbmFtZS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBWRVJTSU9OIFZlcnNpb24gZmllbGQgdXNlZCBmb3Igb3B0aW1pc3RpYyBsb2NraW5nLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IERFTEVURUQgU29mdC1kZWxldGUgdGltZXN0YW1wIGZpZWxkLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFRBQkxFIERhdGFiYXNlIHRhYmxlIGlkZW50aWZpZXIga2V5LlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFNDSEVNQSBEYXRhYmFzZSBzY2hlbWEgaWRlbnRpZmllciBrZXkuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gU0VRVUVOQ0UgRGF0YWJhc2Ugc2VxdWVuY2UgbmFtZSBrZXkuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gSU5ERVggSW5kZXggaWRlbnRpZmllciBrZXkuXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci10eXBlb3JtXG4gKi9cbi8qKlxuICogQGRlc2NyaXB0aW9uIEtleSBjb25zdGFudHMgdXNlZCBieSB0aGUgVHlwZU9STSBhZGFwdGVyLlxuICogQHN1bW1hcnkgQ29sbGVjdGlvbiBvZiBzdHJpbmcgY29uc3RhbnRzIHRoYXQgaWRlbnRpZnkgY29tbW9uIGRhdGFiYXNlIHByb3BlcnRpZXMgYW5kIGFkYXB0ZXItc3BlY2lmaWMga2V5cy5cbiAqIEBjb25zdCBUeXBlT1JNS2V5c1xuICogQHR5cGUge1R5cGVPUk1LZXlzRGVmfVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItdHlwZW9ybVxuICovXG5leHBvcnQgY29uc3QgVHlwZU9STUtleXMgPSB7XG4gIFNFUEFSQVRPUjogXCIuXCIsXG4gIElEOiBcImlkXCIsXG4gIFZFUlNJT046IFwidmVyc2lvblwiLFxuICBERUxFVEVEOiBcImRlbGV0ZWRfYXRcIixcbiAgVEFCTEU6IFwidGFibGVfbmFtZVwiLFxuICBTQ0hFTUE6IFwic2NoZW1hX25hbWVcIixcbiAgU0VRVUVOQ0U6IFwic2VxdWVuY2VfbmFtZVwiLFxuICBJTkRFWDogXCJpbmRleFwiLFxufTtcbiIsImltcG9ydCB7IEJhc2VFcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFcnJvciB0aHJvd24gd2hlbiB0aGVyZSBpcyBhbiBpc3N1ZSB3aXRoIFR5cGVPUk0gaW5kZXhlcy5cbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYW4gZXJyb3IgcmVsYXRlZCB0byBpbmRleCBnZW5lcmF0aW9uIG9yIGhhbmRsaW5nIHdpdGhpbiB0aGUgVHlwZU9STSBhZGFwdGVyLlxuICogQHBhcmFtIHtzdHJpbmd8RXJyb3J9IG1zZyBUaGUgZXJyb3IgbWVzc2FnZSBvciBFcnJvciBvYmplY3QuXG4gKiBAY2xhc3NcbiAqIEBjYXRlZ29yeSBFcnJvcnNcbiAqIEBleGFtcGxlXG4gKiAvLyBFeGFtcGxlIG9mIHVzaW5nIEluZGV4RXJyb3JcbiAqIHRyeSB7XG4gKiAgIC8vIFNvbWUgY29kZSB0aGF0IG1pZ2h0IHRocm93IGFuIGluZGV4IGVycm9yXG4gKiAgIHRocm93IG5ldyBJbmRleEVycm9yKFwiSW5kZXggbm90IGZvdW5kXCIpO1xuICogfSBjYXRjaCAoZXJyb3IpIHtcbiAqICAgaWYgKGVycm9yIGluc3RhbmNlb2YgSW5kZXhFcnJvcikge1xuICogICAgIGNvbnNvbGUuZXJyb3IoXCJJbmRleCBlcnJvciBvY2N1cnJlZDpcIiwgZXJyb3IubWVzc2FnZSk7XG4gKiAgIH1cbiAqIH1cbiAqL1xuZXhwb3J0IGNsYXNzIEluZGV4RXJyb3IgZXh0ZW5kcyBCYXNlRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIoSW5kZXhFcnJvci5uYW1lLCBtc2csIDQwNCk7XG4gIH1cbn1cbiIsImltcG9ydCB7IFJlcG9zaXRvcnlGbGFncyB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgU2VsZWN0UXVlcnlCdWlsZGVyIH0gZnJvbSBcInR5cGVvcm1cIjtcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTUUwgb3BlcmF0b3JzIGF2YWlsYWJsZSBmb3IgYnVpbGRpbmcgVHlwZU9STSBxdWVyaWVzLlxuICogQHN1bW1hcnkgRW51bWVyYXRpb24gb2YgY29tbW9uIFNRTCBvcGVyYXRvcnMgaW50ZW5kZWQgZm9yIHVzZSB3aXRoaW4gVHlwZU9STSBxdWVyeSBjb25zdHJ1Y3Rpb24gYW5kIHRyYW5zbGF0aW9uIGxheWVycy5cbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci10eXBlb3JtXG4gKi9cbmV4cG9ydCBlbnVtIFNRTE9wZXJhdG9yIHtcbiAgRVFVQUwgPSBcIj1cIixcbiAgTk9UX0VRVUFMID0gXCI8PlwiLFxuICBMRVNTX1RIQU4gPSBcIjxcIixcbiAgTEVTU19USEFOX09SX0VRVUFMID0gXCI8PVwiLFxuICBHUkVBVEVSX1RIQU4gPSBcIj5cIixcbiAgR1JFQVRFUl9USEFOX09SX0VRVUFMID0gXCI+PVwiLFxuICBJTiA9IFwiSU5cIixcbiAgTk9UX0lOID0gXCJOT1QgSU5cIixcbiAgTElLRSA9IFwiTElLRVwiLFxuICBJTElLRSA9IFwiSUxJS0VcIixcbiAgQkVUV0VFTiA9IFwiQkVUV0VFTlwiLFxuICBJU19OVUxMID0gXCJJUyBOVUxMXCIsXG4gIElTX05PVF9OVUxMID0gXCJJUyBOT1QgTlVMTFwiLFxuICBFWElTVFMgPSBcIkVYSVNUU1wiLFxuICBOT1RfRVhJU1RTID0gXCJOT1QgRVhJU1RTXCIsXG4gIEFOWSA9IFwiQU5ZXCIsXG4gIEFMTCA9IFwiQUxMXCIsXG4gIFNPTUUgPSBcIlNPTUVcIixcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUXVlcnkgY29udGFpbmVyIHVzZWQgYnkgdGhlIFR5cGVPUk0gYWRhcHRlci5cbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgZWl0aGVyIGEgcmF3IFNRTCBzdHJpbmcgb3IgYSBUeXBlT1JNIFNlbGVjdFF1ZXJ5QnVpbGRlciBhbG9uZyB3aXRoIG9wdGlvbmFsIGJvdW5kIHZhbHVlcyB0byBiZSBleGVjdXRlZCBieSB0aGUgYWRhcHRlci5cbiAqIEB0ZW1wbGF0ZSBNIFRoZSBNb2RlbCB0eXBlIGZvciB3aGljaCB0aGUgU2VsZWN0UXVlcnlCdWlsZGVyIGlzIHBhcmFtZXRlcml6ZWQuXG4gKiBAdGVtcGxhdGUgVCBUaGUgdW5kZXJseWluZyBxdWVyeSB0eXBlLCBlaXRoZXIgYSBzdHJpbmcgb3IgYSBTZWxlY3RRdWVyeUJ1aWxkZXI8TT4uXG4gKiBAaW50ZXJmYWNlIFR5cGVPUk1RdWVyeVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItdHlwZW9ybVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFR5cGVPUk1RdWVyeTxcbiAgTSBleHRlbmRzIE1vZGVsID0gTW9kZWwsXG4gIFQgZXh0ZW5kcyBzdHJpbmcgfCBTZWxlY3RRdWVyeUJ1aWxkZXI8TT4gPSBzdHJpbmcsXG4+IHtcbiAgcXVlcnk6IFQ7XG4gIHZhbHVlcz86IGFueVtdO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDb25maWd1cmF0aW9uIGZsYWdzIGZvciBUeXBlT1JNIG9wZXJhdGlvbnMuXG4gKiBAc3VtbWFyeSBFeHRlbmRlZCByZXBvc2l0b3J5IGZsYWdzIGluY2x1ZGluZyBjb25uZWN0aW9uL3VzZXIgY29udGV4dCB0aGF0IGNhbiBiZSBsZXZlcmFnZWQgYnkgdGhlIFR5cGVPUk0gYWRhcHRlci5cbiAqIEBpbnRlcmZhY2UgVHlwZU9STUZsYWdzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci10eXBlb3JtXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVHlwZU9STUZsYWdzIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzIHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVc2VyIGF1dGhlbnRpY2F0aW9uIGluZm9ybWF0aW9uIGZvciBQb3N0Z3JlcyBkYXRhYmFzZSBjb25uZWN0aW9uc1xuICAgKi9cbiAgdXNlcjogc3RyaW5nO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTcGVjaWZpY2F0aW9uIGZvciBhIHRhYmxlIGNyZWF0aW9uL2NoYW5nZSBzdGF0ZW1lbnQgdXNlZCBieSB0aGUgVHlwZU9STSBhZGFwdGVyLlxuICogQHN1bW1hcnkgRXh0ZW5kcyBhIFR5cGVPUk1RdWVyeSB3aXRoIHRhYmxlIG1ldGFkYXRhIHN1Y2ggYXMgcHJpbWFyeSBrZXkgZmxhZywgY29uc3RyYWludHMsIGFuZCBmb3JlaWduIGtleXMuXG4gKiBAdHlwZWRlZiBUeXBlT1JNVGFibGVTcGVjXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IHByaW1hcnlLZXkgSW5kaWNhdGVzIGlmIHRoZSB0YXJnZXQgY29sdW1uIGlzIHBhcnQgb2YgdGhlIHByaW1hcnkga2V5LlxuICogQHByb3BlcnR5IHtzdHJpbmdbXX0gY29uc3RyYWludHMgQSBsaXN0IG9mIHJhdyBTUUwgY29uc3RyYWludHMgdG8gYXBwbHkgdG8gdGhlIHRhYmxlL2NvbHVtbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nW119IGZvcmVpZ25LZXlzIEEgbGlzdCBvZiBmb3JlaWduIGtleSBjb25zdHJhaW50IGRlZmluaXRpb25zLlxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItdHlwZW9ybVxuICovXG5leHBvcnQgdHlwZSBUeXBlT1JNVGFibGVTcGVjID0gVHlwZU9STVF1ZXJ5ICYge1xuICBwcmltYXJ5S2V5OiBib29sZWFuO1xuICBjb25zdHJhaW50czogc3RyaW5nW107XG4gIGZvcmVpZ25LZXlzOiBzdHJpbmdbXTtcbn07XG4iLCJpbXBvcnQgeyBTUUxPcGVyYXRvciB9IGZyb20gXCIuLi90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWZhdWx0IHF1ZXJ5IGxpbWl0IGZvciBUeXBlT1JNLWJhY2tlZCBxdWVyaWVzLlxuICogQHN1bW1hcnkgTWF4aW11bSBudW1iZXIgb2YgcmVjb3JkcyB0byByZXR1cm4gaW4gYSBzaW5nbGUgcGFnZSB3aGVuIHBhZ2luYXRpbmcgcmVzdWx0cy5cbiAqIEBjb25zdCBUeXBlT1JNUXVlcnlMaW1pdFxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItdHlwZW9ybVxuICovXG5leHBvcnQgY29uc3QgVHlwZU9STVF1ZXJ5TGltaXQgPSAyNTA7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIE1hcHBpbmcgb2Ygb3BlcmF0b3IgbmFtZXMgdG8gU1FMIG9wZXJhdG9ycy5cbiAqIEBzdW1tYXJ5IENvbnN0YW50cyBmb3IgY29tcGFyaXNvbiBvcGVyYXRvcnMgdXNlZCB3aGVuIHRyYW5zbGF0aW5nIGhpZ2gtbGV2ZWwgZmlsdGVycyBpbnRvIFNRTCB2aWEgVHlwZU9STS5cbiAqIEB0eXBlZGVmIHtPYmplY3R9IFBvc3RncmVTUUxPcGVyYXRvclR5cGVcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBFUVVBTCBFcXVhbGl0eSBvcGVyYXRvciAoPSlcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBESUZGRVJFTlQgSW5lcXVhbGl0eSBvcGVyYXRvciAoPD4pXG4gKiBAcHJvcGVydHkge3N0cmluZ30gQklHR0VSIEdyZWF0ZXIgdGhhbiBvcGVyYXRvciAoPilcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBCSUdHRVJfRVEgR3JlYXRlciB0aGFuIG9yIGVxdWFsIG9wZXJhdG9yICg+PSlcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBTTUFMTEVSIExlc3MgdGhhbiBvcGVyYXRvciAoPClcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBTTUFMTEVSX0VRIExlc3MgdGhhbiBvciBlcXVhbCBvcGVyYXRvciAoPD0pXG4gKiBAcHJvcGVydHkge3N0cmluZ30gTk9UIE5lZ2F0aW9uIG9wZXJhdG9yIChOT1QpXG4gKiBAcHJvcGVydHkge3N0cmluZ30gSU4gSW4gYXJyYXkgb3BlcmF0b3IgKElOKVxuICogQHByb3BlcnR5IHtzdHJpbmd9IFJFR0VYUCBSZWd1bGFyIGV4cHJlc3Npb24gb3BlcmF0b3IgKH4pXG4gKiBAcHJvcGVydHkge3N0cmluZ30gSVJFR0VYUCBDYXNlLWluc2Vuc2l0aXZlIHJlZ3VsYXIgZXhwcmVzc2lvbiBvcGVyYXRvciAofiopXG4gKiBAcHJvcGVydHkge3N0cmluZ30gTElLRSBQYXR0ZXJuIG1hdGNoaW5nIG9wZXJhdG9yIChMSUtFKVxuICogQHByb3BlcnR5IHtzdHJpbmd9IElMSUtFIENhc2UtaW5zZW5zaXRpdmUgcGF0dGVybiBtYXRjaGluZyBvcGVyYXRvciAoSUxJS0UpXG4gKiBAcHJvcGVydHkge3N0cmluZ30gQkVUV0VFTiBSYW5nZSBvcGVyYXRvciAoQkVUV0VFTilcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBJU19OVUxMIE5VTEwgY2hlY2sgb3BlcmF0b3IgKElTIE5VTEwpXG4gKiBAcHJvcGVydHkge3N0cmluZ30gSVNfTk9UX05VTEwgTk9UIE5VTEwgY2hlY2sgb3BlcmF0b3IgKElTIE5PVCBOVUxMKVxuICogQGNvbnN0IFR5cGVPUk1PcGVyYXRvclxuICogQHR5cGUge1Bvc3RncmVTUUxPcGVyYXRvclR5cGV9XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci10eXBlb3JtXG4gKi9cbmV4cG9ydCBjb25zdCBUeXBlT1JNT3BlcmF0b3I6IFJlY29yZDxzdHJpbmcsIFNRTE9wZXJhdG9yIHwgc3RyaW5nPiA9IHtcbiAgRVFVQUw6IFNRTE9wZXJhdG9yLkVRVUFMLFxuICBESUZGRVJFTlQ6IFNRTE9wZXJhdG9yLk5PVF9FUVVBTCxcbiAgQklHR0VSOiBTUUxPcGVyYXRvci5HUkVBVEVSX1RIQU4sXG4gIEJJR0dFUl9FUTogU1FMT3BlcmF0b3IuR1JFQVRFUl9USEFOX09SX0VRVUFMLFxuICBTTUFMTEVSOiBTUUxPcGVyYXRvci5MRVNTX1RIQU4sXG4gIFNNQUxMRVJfRVE6IFNRTE9wZXJhdG9yLkxFU1NfVEhBTl9PUl9FUVVBTCxcbiAgQkVUV0VFTjogU1FMT3BlcmF0b3IuQkVUV0VFTixcbiAgTk9UOiBcIk5PVFwiLFxuICBJTjogU1FMT3BlcmF0b3IuSU4sXG4gIElTX05VTEw6IFNRTE9wZXJhdG9yLklTX05VTEwsXG4gIElTX05PVF9OVUxMOiBTUUxPcGVyYXRvci5JU19OT1RfTlVMTCxcbiAgUkVHRVhQOiBcIn5cIixcbiAgSVJFR0VYUDogXCJ+KlwiLFxuICBMSUtFOiBTUUxPcGVyYXRvci5MSUtFLFxuICBJTElLRTogU1FMT3BlcmF0b3IuSUxJS0UsXG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBNYXBwaW5nIG9mIGxvZ2ljYWwgb3BlcmF0b3IgbmFtZXMgdG8gU1FMIG9wZXJhdG9ycy5cbiAqIEBzdW1tYXJ5IENvbnN0YW50cyBmb3IgbG9naWNhbCBvcGVyYXRvcnMgdXNlZCB3aGVuIGJ1aWxkaW5nIFdIRVJFIGNsYXVzZSBncm91cHMgaW4gVHlwZU9STSBxdWVyaWVzLlxuICogQHR5cGVkZWYge09iamVjdH0gUG9zdGdyZVNRTEdyb3VwT3BlcmF0b3JUeXBlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gQU5EIExvZ2ljYWwgQU5EIG9wZXJhdG9yIChBTkQpXG4gKiBAcHJvcGVydHkge3N0cmluZ30gT1IgTG9naWNhbCBPUiBvcGVyYXRvciAoT1IpXG4gKiBAY29uc3QgVHlwZU9STUdyb3VwT3BlcmF0b3JcbiAqIEB0eXBlIHtQb3N0Z3JlU1FMR3JvdXBPcGVyYXRvclR5cGV9XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci10eXBlb3JtXG4gKi9cbmV4cG9ydCBjb25zdCBUeXBlT1JNR3JvdXBPcGVyYXRvcjogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgQU5EOiBcIkFORFwiLFxuICBPUjogXCJPUlwiLFxufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU3BlY2lhbCBjb25zdGFudCB2YWx1ZXMgdXNlZCBpbiBxdWVyaWVzLlxuICogQHN1bW1hcnkgU3RyaW5nIGNvbnN0YW50cyByZXByZXNlbnRpbmcgc3BlY2lhbCB2YWx1ZXMgdXNlZCB3aGlsZSBjb21wb3NpbmcgU1FMIHdpdGggVHlwZU9STS5cbiAqIEB0eXBlZGVmIHtPYmplY3R9IFBvc3RncmVTUUxDb25zdFR5cGVcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBOVUxMIFN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBudWxsIHZhbHVlLlxuICogQGNvbnN0IFR5cGVPUk1Db25zdFxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItdHlwZW9ybVxuICovXG5leHBvcnQgY29uc3QgVHlwZU9STUNvbnN0OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICBOVUxMOiBcIk5VTExcIixcbn07XG4iLCJpbXBvcnQgeyBQYWdpbmF0b3IsIFBhZ2luZ0Vycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBUeXBlT1JNUXVlcnkgfSBmcm9tIFwiLi4vdHlwZXNcIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yLCBNb2RlbCwgTW9kZWxLZXlzIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgVHlwZU9STUFkYXB0ZXIgfSBmcm9tIFwiLi4vVHlwZU9STUFkYXB0ZXJcIjtcbmltcG9ydCB7IEZpbmRNYW55T3B0aW9ucywgUmVwb3NpdG9yeSBhcyBSZXBvIH0gZnJvbSBcInR5cGVvcm1cIjtcbmltcG9ydCB7IGZpbmRQcmltYXJ5S2V5IH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFBhZ2luYXRvciBmb3IgVHlwZU9STSBxdWVyeSByZXN1bHRzLlxuICogQHN1bW1hcnkgSW1wbGVtZW50cyBwYWdpbmF0aW9uIGZvciBUeXBlT1JNLWJ1aWx0IHF1ZXJpZXMgdXNpbmcgdGFrZS9za2lwIGZvciBlZmZpY2llbnQgbmF2aWdhdGlvbiB0aHJvdWdoIHJlc3VsdCBzZXRzLlxuICogQHRlbXBsYXRlIE0gVGhlIG1vZGVsIHR5cGUgdGhhdCBleHRlbmRzIE1vZGVsLlxuICogQHRlbXBsYXRlIFIgVGhlIHJlc3VsdCB0eXBlLlxuICogQHBhcmFtIHtUeXBlT1JNQWRhcHRlcn0gYWRhcHRlciBUaGUgVHlwZU9STSBhZGFwdGVyLlxuICogQHBhcmFtIHtUeXBlT1JNUXVlcnl9IHF1ZXJ5IFRoZSBxdWVyeSBjb250YWluZXIgdG8gcGFnaW5hdGUuXG4gKiBAcGFyYW0ge251bWJlcn0gc2l6ZSBUaGUgcGFnZSBzaXplLlxuICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gY2xhenogVGhlIG1vZGVsIGNvbnN0cnVjdG9yLlxuICogQGNsYXNzIFR5cGVPUk1QYWdpbmF0b3JcbiAqIEBleGFtcGxlXG4gKiAvLyBFeGFtcGxlIG9mIHVzaW5nIFR5cGVPUk1QYWdpbmF0b3JcbiAqIGNvbnN0IHBhZ2luYXRvciA9IG5ldyBUeXBlT1JNUGFnaW5hdG9yKGFkYXB0ZXIsIHsgcXVlcnk6IHFiIH0sIDEwLCBVc2VyKTtcbiAqIGNvbnN0IHBhZ2UxID0gYXdhaXQgcGFnaW5hdG9yLnBhZ2UoMSk7XG4gKiBjb25zdCBwYWdlMiA9IGF3YWl0IHBhZ2luYXRvci5wYWdlKDIpO1xuICovXG5leHBvcnQgY2xhc3MgVHlwZU9STVBhZ2luYXRvcjxNIGV4dGVuZHMgTW9kZWwsIFI+IGV4dGVuZHMgUGFnaW5hdG9yPFxuICBNLFxuICBSLFxuICBUeXBlT1JNUXVlcnlcbj4ge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIHRvdGFsIG51bWJlciBvZiBwYWdlc1xuICAgKiBAc3VtbWFyeSBSZXR1cm5zIHRoZSB0b3RhbCBudW1iZXIgb2YgcGFnZXMgYmFzZWQgb24gdGhlIHJlY29yZCBjb3VudCBhbmQgcGFnZSBzaXplXG4gICAqIEByZXR1cm4ge251bWJlcn0gVGhlIHRvdGFsIG51bWJlciBvZiBwYWdlc1xuICAgKi9cbiAgb3ZlcnJpZGUgZ2V0IHRvdGFsKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX3RvdGFsUGFnZXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIHRvdGFsIHJlY29yZCBjb3VudFxuICAgKiBAc3VtbWFyeSBSZXR1cm5zIHRoZSB0b3RhbCBudW1iZXIgb2YgcmVjb3JkcyBtYXRjaGluZyB0aGUgcXVlcnlcbiAgICogQHJldHVybiB7bnVtYmVyfSBUaGUgdG90YWwgcmVjb3JkIGNvdW50XG4gICAqL1xuICBvdmVycmlkZSBnZXQgY291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fcmVjb3JkQ291bnQ7XG4gIH1cblxuICBwcml2YXRlIF9fcmVwbz86IFJlcG88YW55PjtcblxuICBwcm90ZWN0ZWQgZ2V0IHJlcG8oKSB7XG4gICAgaWYgKCF0aGlzLl9fcmVwbykge1xuICAgICAgdGhpcy5fX3JlcG8gPSAodGhpcy5hZGFwdGVyIGFzIFR5cGVPUk1BZGFwdGVyKS5kYXRhU291cmNlLmdldFJlcG9zaXRvcnkoXG4gICAgICAgIHRoaXMuY2xhenpbTW9kZWxLZXlzLkFOQ0hPUiBhcyBrZXlvZiB0eXBlb2YgdGhpcy5jbGF6el1cbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9fcmVwbztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG5ldyBUeXBlT1JNUGFnaW5hdG9yIGluc3RhbmNlLlxuICAgKiBAc3VtbWFyeSBJbml0aWFsaXplcyBhIHBhZ2luYXRvciBmb3IgVHlwZU9STSBxdWVyeSByZXN1bHRzLlxuICAgKiBAcGFyYW0ge1R5cGVPUk1BZGFwdGVyfSBhZGFwdGVyIFRoZSBUeXBlT1JNIGFkYXB0ZXIuXG4gICAqIEBwYXJhbSB7VHlwZU9STVF1ZXJ5fSBxdWVyeSBUaGUgVHlwZU9STSBxdWVyeSBjb250YWluZXIgdG8gcGFnaW5hdGUuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzaXplIFRoZSBwYWdlIHNpemUuXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IGNsYXp6IFRoZSBtb2RlbCBjb25zdHJ1Y3Rvci5cbiAgICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIGFkYXB0ZXI6IFR5cGVPUk1BZGFwdGVyLFxuICAgIHF1ZXJ5OiBUeXBlT1JNUXVlcnksXG4gICAgc2l6ZTogbnVtYmVyLFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPlxuICApIHtcbiAgICBzdXBlcihhZGFwdGVyLCBxdWVyeSwgc2l6ZSwgY2xhenopO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyBhIHF1ZXJ5IGZvciBwYWdpbmF0aW9uXG4gICAqIEBzdW1tYXJ5IE1vZGlmaWVzIHRoZSByYXcgcXVlcnkgdG8gaW5jbHVkZSBwYWdpbmF0aW9uIHBhcmFtZXRlcnNcbiAgICogQHBhcmFtIHtUeXBlT1JNUXVlcnl9IHJhd1N0YXRlbWVudCAtIFRoZSBvcmlnaW5hbCBQb3N0Z3JlU1FMIHF1ZXJ5XG4gICAqIEByZXR1cm4ge1R5cGVPUk1RdWVyeX0gVGhlIHByZXBhcmVkIHF1ZXJ5IHdpdGggcGFnaW5hdGlvbiBwYXJhbWV0ZXJzXG4gICAqL1xuICBwcm90ZWN0ZWQgcHJlcGFyZShyYXdTdGF0ZW1lbnQ6IFR5cGVPUk1RdWVyeSk6IFR5cGVPUk1RdWVyeSB7XG4gICAgY29uc3QgcXVlcnk6IFR5cGVPUk1RdWVyeSA9IHsgLi4ucmF3U3RhdGVtZW50IH07XG4gICAgcmV0dXJuIHF1ZXJ5O1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgYSBzcGVjaWZpYyBwYWdlIG9mIHJlc3VsdHMuXG4gICAqIEBzdW1tYXJ5IEV4ZWN1dGVzIHRoZSBxdWVyeSB3aXRoIHBhZ2luYXRpb24gYW5kIHByb2Nlc3NlcyB0aGUgcmVzdWx0cy5cbiAgICogQHBhcmFtIHtudW1iZXJ9IFtwYWdlPTFdIFRoZSBwYWdlIG51bWJlciB0byByZXRyaWV2ZS5cbiAgICogQHJldHVybiB7UHJvbWlzZTxSW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBvZiByZXN1bHRzLlxuICAgKiBAdGhyb3dzIHtQYWdpbmdFcnJvcn0gSWYgdHJ5aW5nIHRvIGFjY2VzcyBhbiBpbnZhbGlkIHBhZ2Ugb3IgaWYgbm8gY2xhc3MgaXMgZGVmaW5lZC5cbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ2xpZW50XG4gICAqICAgcGFydGljaXBhbnQgUGFnaW5hdG9yIGFzIFR5cGVPUk1QYWdpbmF0b3JcbiAgICogICBwYXJ0aWNpcGFudCBBZGFwdGVyXG4gICAqICAgcGFydGljaXBhbnQgREIgYXMgRGF0YWJhc2VcbiAgICpcbiAgICogICBDbGllbnQtPj5QYWdpbmF0b3I6IHBhZ2UocGFnZU51bWJlcilcbiAgICogICBOb3RlIG92ZXIgUGFnaW5hdG9yOiBQcmVwYXJlIG9wdGlvbnMgKHNraXAvdGFrZSlcbiAgICpcbiAgICogICBhbHQgRmlyc3QgdGltZSBvciBuZWVkIGNvdW50XG4gICAqICAgICBQYWdpbmF0b3ItPj5BZGFwdGVyOiBHZXQgY291bnRcbiAgICogICAgIEFkYXB0ZXItPj5EQjogRXhlY3V0ZSBDT1VOVFxuICAgKiAgICAgREItLT4+QWRhcHRlcjogY291bnRcbiAgICogICAgIEFkYXB0ZXItLT4+UGFnaW5hdG9yOiBjb3VudFxuICAgKiAgICAgUGFnaW5hdG9yLT4+UGFnaW5hdG9yOiBDYWxjdWxhdGUgdG90YWwgcGFnZXNcbiAgICogICBlbmRcbiAgICpcbiAgICogICBQYWdpbmF0b3ItPj5BZGFwdGVyOiBFeGVjdXRlIHF1ZXJ5XG4gICAqICAgQWRhcHRlci0+PkRCOiBmaW5kQW5kQ291bnQob3B0aW9ucylcbiAgICogICBEQi0tPj5BZGFwdGVyOiByb3dzLCBjb3VudFxuICAgKiAgIEFkYXB0ZXItLT4+UGFnaW5hdG9yOiByb3dzLCBjb3VudFxuICAgKlxuICAgKiAgIFBhZ2luYXRvci0+PlBhZ2luYXRvcjogTWFwIHJvd3MgdG8gbW9kZWxzXG4gICAqICAgUGFnaW5hdG9yLS0+PkNsaWVudDogcmVzdWx0c1xuICAgKi9cblxuICBhc3luYyBwYWdlKHBhZ2U6IG51bWJlciA9IDEpOiBQcm9taXNlPFJbXT4ge1xuICAgIGNvbnN0IHN0YXRlbWVudCA9IHsgLi4udGhpcy5zdGF0ZW1lbnQgfTtcblxuICAgIC8vIEdldCB0b3RhbCBjb3VudCBpZiBub3QgYWxyZWFkeSBjYWxjdWxhdGVkXG4gICAgaWYgKCF0aGlzLl9yZWNvcmRDb3VudCB8fCAhdGhpcy5fdG90YWxQYWdlcykge1xuICAgICAgdGhpcy5fdG90YWxQYWdlcyA9IHRoaXMuX3JlY29yZENvdW50ID0gMDtcbiAgICB9XG5cbiAgICBjb25zdCBvcHRzOiBGaW5kTWFueU9wdGlvbnM8TT4gPSBPYmplY3QuYXNzaWduKHN0YXRlbWVudCwge1xuICAgICAgc2tpcDogKHRoaXMuY3VycmVudCB8fCAwKSAqIHRoaXMuc2l6ZSxcbiAgICAgIHRha2U6IHRoaXMuc2l6ZSxcbiAgICB9KTtcblxuICAgIC8vIHRoaXMudmFsaWRhdGVQYWdlKHBhZ2UpO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5yZXBvLmZpbmRBbmRDb3VudChvcHRzKTtcblxuICAgIHRoaXMuX3JlY29yZENvdW50ID0gcmVzdWx0WzFdO1xuICAgIHRoaXMuX3RvdGFsUGFnZXMgPSBNYXRoLmNlaWwodGhpcy5fcmVjb3JkQ291bnQgLyB0aGlzLnNpemUpO1xuXG4gICAgaWYgKCF0aGlzLmNsYXp6KSB0aHJvdyBuZXcgUGFnaW5nRXJyb3IoXCJObyBzdGF0ZW1lbnQgdGFyZ2V0IGRlZmluZWRcIik7XG5cbiAgICBjb25zdCBwa0RlZiA9IGZpbmRQcmltYXJ5S2V5KG5ldyB0aGlzLmNsYXp6KCkpO1xuICAgIGNvbnN0IHJvd3MgPSByZXN1bHRbMF0gfHwgW107XG5cbiAgICBjb25zdCByZXN1bHRzID1cbiAgICAgIC8vIHN0YXRlbWVudC5jb2x1bW5zICYmIHN0YXRlbWVudC5jb2x1bW5zLmxlbmd0aFxuICAgICAgLy8gICA/IHJvd3MgLy8gaGFzIGNvbHVtbnMgbWVhbnMgaXQncyBub3QgZnVsbCBtb2RlbFxuICAgICAgcm93cy5tYXAoKHJvdzogYW55KSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmV2ZXJ0KHJvdywgdGhpcy5jbGF6eiwgcGtEZWYuaWQsIHJvd1twa0RlZi5pZF0pO1xuICAgICAgfSk7XG5cbiAgICB0aGlzLl9jdXJyZW50UGFnZSA9IHBhZ2U7XG4gICAgcmV0dXJuIHJlc3VsdHMgYXMgdW5rbm93biBhcyBSW107XG4gIH1cbn1cbiIsImltcG9ydCB7IEdyb3VwT3BlcmF0b3IsIE9wZXJhdG9yIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBUeXBlT1JNR3JvdXBPcGVyYXRvciwgVHlwZU9STU9wZXJhdG9yIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBRdWVyeUVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBTUUxPcGVyYXRvciB9IGZyb20gXCIuLi90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBUcmFuc2xhdGVzIGNvcmUgb3BlcmF0b3JzIHRvIFR5cGVPUk0gU1FMIG9wZXJhdG9ycy5cbiAqIEBzdW1tYXJ5IENvbnZlcnRzIERlY2FmLnRzIGNvcmUgb3BlcmF0b3JzIHRvIHRoZWlyIGVxdWl2YWxlbnQgU1FMIG9wZXJhdG9ycyB1c2VkIGJ5IHRoZSBUeXBlT1JNIGFkYXB0ZXIuXG4gKiBAcGFyYW0ge0dyb3VwT3BlcmF0b3IgfCBPcGVyYXRvcn0gb3BlcmF0b3IgVGhlIGNvcmUgb3BlcmF0b3IgdG8gdHJhbnNsYXRlLlxuICogQHJldHVybiB7U1FMT3BlcmF0b3IgfCBzdHJpbmd9IFRoZSBlcXVpdmFsZW50IFNRTCBvcGVyYXRvci5cbiAqIEB0aHJvd3Mge1F1ZXJ5RXJyb3J9IElmIG5vIHRyYW5zbGF0aW9uIGV4aXN0cyBmb3IgdGhlIGdpdmVuIG9wZXJhdG9yLlxuICogQGZ1bmN0aW9uIHRyYW5zbGF0ZU9wZXJhdG9yc1xuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItdHlwZW9ybVxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgdHJhbnNsYXRlT3BlcmF0b3JzXG4gKiAgIHBhcnRpY2lwYW50IFBvc3RncmVTUUxPcGVyYXRvclxuICogICBwYXJ0aWNpcGFudCBQb3N0Z3JlU1FMR3JvdXBPcGVyYXRvclxuICpcbiAqICAgQ2FsbGVyLT4+dHJhbnNsYXRlT3BlcmF0b3JzOiBvcGVyYXRvclxuICpcbiAqICAgdHJhbnNsYXRlT3BlcmF0b3JzLT4+UG9zdGdyZVNRTE9wZXJhdG9yOiBDaGVjayBmb3IgbWF0Y2hcbiAqICAgYWx0IEZvdW5kIGluIFBvc3RncmVTUUxPcGVyYXRvclxuICogICAgIFBvc3RncmVTUUxPcGVyYXRvci0tPj50cmFuc2xhdGVPcGVyYXRvcnM6IFJldHVybiBtYXRjaGluZyBvcGVyYXRvclxuICogICAgIHRyYW5zbGF0ZU9wZXJhdG9ycy0tPj5DYWxsZXI6IFJldHVybiBTUUxPcGVyYXRvclxuICogICBlbHNlIE5vdCBmb3VuZFxuICogICAgIHRyYW5zbGF0ZU9wZXJhdG9ycy0+PlBvc3RncmVTUUxHcm91cE9wZXJhdG9yOiBDaGVjayBmb3IgbWF0Y2hcbiAqICAgICBhbHQgRm91bmQgaW4gUG9zdGdyZVNRTEdyb3VwT3BlcmF0b3JcbiAqICAgICAgIFBvc3RncmVTUUxHcm91cE9wZXJhdG9yLS0+PnRyYW5zbGF0ZU9wZXJhdG9yczogUmV0dXJuIG1hdGNoaW5nIG9wZXJhdG9yXG4gKiAgICAgICB0cmFuc2xhdGVPcGVyYXRvcnMtLT4+Q2FsbGVyOiBSZXR1cm4gc3RyaW5nXG4gKiAgICAgZWxzZSBOb3QgZm91bmRcbiAqICAgICAgIHRyYW5zbGF0ZU9wZXJhdG9ycy0tPj5DYWxsZXI6IFRocm93IFF1ZXJ5RXJyb3JcbiAqICAgICBlbmRcbiAqICAgZW5kXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2xhdGVPcGVyYXRvcnMoXG4gIG9wZXJhdG9yOiBHcm91cE9wZXJhdG9yIHwgT3BlcmF0b3Jcbik6IFNRTE9wZXJhdG9yIHwgc3RyaW5nIHtcbiAgZm9yIChjb25zdCBvcGVyYXRvcnMgb2YgW1R5cGVPUk1PcGVyYXRvciwgVHlwZU9STUdyb3VwT3BlcmF0b3JdKSB7XG4gICAgY29uc3QgZWwgPSBPYmplY3Qua2V5cyhvcGVyYXRvcnMpLmZpbmQoKGspID0+IGsgPT09IG9wZXJhdG9yKTtcbiAgICBpZiAoZWwpIHJldHVybiBvcGVyYXRvcnNbZWxdO1xuICB9XG4gIHRocm93IG5ldyBRdWVyeUVycm9yKFxuICAgIGBDb3VsZCBub3QgZmluZCBhZGFwdGVyIHRyYW5zbGF0aW9uIGZvciBvcGVyYXRvciAke29wZXJhdG9yfWBcbiAgKTtcbn1cbiIsImltcG9ydCB7XG4gIENvbmRpdGlvbixcbiAgR3JvdXBPcGVyYXRvcixcbiAgT3BlcmF0b3IsXG4gIE9yZGVyRGlyZWN0aW9uLFxuICBQYWdpbmF0b3IsXG4gIFJlcG9zaXRvcnksXG4gIFN0YXRlbWVudCxcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBNb2RlbCwgTW9kZWxLZXlzIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgdHJhbnNsYXRlT3BlcmF0b3JzIH0gZnJvbSBcIi4vdHJhbnNsYXRlXCI7XG5pbXBvcnQgeyBUeXBlT1JNUXVlcnlMaW1pdCB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgVHlwZU9STVBhZ2luYXRvciB9IGZyb20gXCIuL1BhZ2luYXRvclwiO1xuaW1wb3J0IHsgZmluZFByaW1hcnlLZXksIEludGVybmFsRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IFR5cGVPUk1RdWVyeSB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgVHlwZU9STUFkYXB0ZXIgfSBmcm9tIFwiLi4vVHlwZU9STUFkYXB0ZXJcIjtcbmltcG9ydCB7IEZpbmRNYW55T3B0aW9ucywgU2VsZWN0UXVlcnlCdWlsZGVyIH0gZnJvbSBcInR5cGVvcm1cIjtcbmltcG9ydCB7IEZpbmRPcHRpb25zV2hlcmUgfSBmcm9tIFwidHlwZW9ybS9maW5kLW9wdGlvbnMvRmluZE9wdGlvbnNXaGVyZVwiO1xuaW1wb3J0IHsgRmluZE9wdGlvbnNPcmRlciB9IGZyb20gXCJ0eXBlb3JtL2ZpbmQtb3B0aW9ucy9GaW5kT3B0aW9uc09yZGVyXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFN0YXRlbWVudCBidWlsZGVyIGZvciBUeXBlT1JNLWJhY2tlZCBxdWVyaWVzLlxuICogQHN1bW1hcnkgUHJvdmlkZXMgYSBmbHVlbnQgaW50ZXJmYWNlIGZvciBidWlsZGluZyBTUUwgcXVlcmllcyB2aWEgVHlwZU9STSdzIFNlbGVjdFF1ZXJ5QnVpbGRlciB3aXRoIHR5cGUgc2FmZXR5IGFuZCBEZWNhZi50cyBhYnN0cmFjdGlvbnMuXG4gKiBAdGVtcGxhdGUgTSBUaGUgbW9kZWwgdHlwZSB0aGF0IGV4dGVuZHMgTW9kZWwuXG4gKiBAdGVtcGxhdGUgUiBUaGUgcmVzdWx0IHR5cGUgcmV0dXJuZWQgZnJvbSBleGVjdXRpb24uXG4gKiBAcGFyYW0ge1R5cGVPUk1BZGFwdGVyfSBhZGFwdGVyIFRoZSBUeXBlT1JNIGFkYXB0ZXIuXG4gKiBAY2xhc3MgVHlwZU9STVN0YXRlbWVudFxuICogQGV4YW1wbGVcbiAqIC8vIEV4YW1wbGUgdXNpbmcgVHlwZU9STVN0YXRlbWVudFxuICogY29uc3Qgc3RhdGVtZW50ID0gbmV3IFR5cGVPUk1TdGF0ZW1lbnQ8VXNlciwgVXNlcltdPihhZGFwdGVyKTtcbiAqIGNvbnN0IHVzZXJzID0gYXdhaXQgc3RhdGVtZW50XG4gKiAgIC5mcm9tKFVzZXIpXG4gKiAgIC53aGVyZShDb25kaXRpb24uYXR0cmlidXRlPFVzZXI+KCdhZ2UnKS5ndCgxOCkpXG4gKiAgIC5vcmRlckJ5KCdsYXN0TmFtZScsICdhc2MnKVxuICogICAubGltaXQoMTApXG4gKiAgIC5leGVjdXRlKCk7XG4gKi9cbmV4cG9ydCBjbGFzcyBUeXBlT1JNU3RhdGVtZW50PE0gZXh0ZW5kcyBNb2RlbCwgUj4gZXh0ZW5kcyBTdGF0ZW1lbnQ8XG4gIFR5cGVPUk1RdWVyeTxNPixcbiAgTSxcbiAgUlxuPiB7XG4gIHByb3RlY3RlZCBvdmVycmlkZSBhZGFwdGVyITogVHlwZU9STUFkYXB0ZXI7XG5cbiAgY29uc3RydWN0b3IoYWRhcHRlcjogVHlwZU9STUFkYXB0ZXIpIHtcbiAgICBzdXBlcihhZGFwdGVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQnVpbGRzIGEgVHlwZU9STSBTZWxlY3RRdWVyeUJ1aWxkZXIgZnJvbSB0aGUgc3RhdGVtZW50LlxuICAgKiBAc3VtbWFyeSBDb252ZXJ0cyB0aGUgc3RhdGVtZW50J3MgY29uZGl0aW9ucywgc2VsZWN0b3JzLCBhbmQgb3B0aW9ucyBpbnRvIGEgVHlwZU9STS1iYWNrZWQgcXVlcnkgb2JqZWN0LlxuICAgKiBAcmV0dXJuIHtUeXBlT1JNUXVlcnl9IFRoZSBidWlsdCBUeXBlT1JNIHF1ZXJ5IGNvbnRhaW5lci5cbiAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZXJlIGFyZSBpbnZhbGlkIHF1ZXJ5IGNvbmRpdGlvbnMuXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IFN0YXRlbWVudFxuICAgKiAgIHBhcnRpY2lwYW50IFJlcG9zaXRvcnlcbiAgICogICBwYXJ0aWNpcGFudCBwYXJzZUNvbmRpdGlvblxuICAgKlxuICAgKiAgIFN0YXRlbWVudC0+PlN0YXRlbWVudDogYnVpbGQoKVxuICAgKiAgIE5vdGUgb3ZlciBTdGF0ZW1lbnQ6IEluaXRpYWxpemUgcXVlcnlcbiAgICogICBTdGF0ZW1lbnQtPj5SZXBvc2l0b3J5OiBHZXQgdGFibGUgbmFtZVxuICAgKiAgIFJlcG9zaXRvcnktLT4+U3RhdGVtZW50OiBSZXR1cm4gdGFibGUgbmFtZVxuICAgKiAgIFN0YXRlbWVudC0+PlN0YXRlbWVudDogQ3JlYXRlIGJhc2UgcXVlcnlcbiAgICpcbiAgICogICBhbHQgSGFzIHNlbGVjdFNlbGVjdG9yXG4gICAqICAgICBTdGF0ZW1lbnQtPj5TdGF0ZW1lbnQ6IEFkZCBjb2x1bW5zIHRvIHF1ZXJ5XG4gICAqICAgZW5kXG4gICAqXG4gICAqICAgYWx0IEhhcyB3aGVyZUNvbmRpdGlvblxuICAgKiAgICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBDcmVhdGUgY29tYmluZWQgY29uZGl0aW9uIHdpdGggdGFibGVcbiAgICogICAgIFN0YXRlbWVudC0+PnBhcnNlQ29uZGl0aW9uOiBQYXJzZSBjb25kaXRpb25cbiAgICogICAgIHBhcnNlQ29uZGl0aW9uLS0+PlN0YXRlbWVudDogUmV0dXJuIHBhcnNlZCBjb25kaXRpb25zXG4gICAqICAgICBTdGF0ZW1lbnQtPj5TdGF0ZW1lbnQ6IEFkZCBjb25kaXRpb25zIHRvIHF1ZXJ5XG4gICAqICAgZW5kXG4gICAqXG4gICAqICAgYWx0IEhhcyBvcmRlckJ5U2VsZWN0b3JcbiAgICogICAgIFN0YXRlbWVudC0+PlN0YXRlbWVudDogQWRkIG9yZGVyQnkgdG8gcXVlcnlcbiAgICogICBlbmRcbiAgICpcbiAgICogICBhbHQgSGFzIGxpbWl0U2VsZWN0b3JcbiAgICogICAgIFN0YXRlbWVudC0+PlN0YXRlbWVudDogU2V0IGxpbWl0XG4gICAqICAgZWxzZVxuICAgKiAgICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBVc2UgZGVmYXVsdCBsaW1pdFxuICAgKiAgIGVuZFxuICAgKlxuICAgKiAgIGFsdCBIYXMgb2Zmc2V0U2VsZWN0b3JcbiAgICogICAgIFN0YXRlbWVudC0+PlN0YXRlbWVudDogU2V0IG9mZnNldFxuICAgKiAgIGVuZFxuICAgKlxuICAgKiAgIFN0YXRlbWVudC0tPj5TdGF0ZW1lbnQ6IFJldHVybiBxdWVyeVxuICAgKi9cbiAgcHJvdGVjdGVkIGJ1aWxkKCk6IFR5cGVPUk1RdWVyeTxNPiB7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMuYnVpbGQpO1xuICAgIGNvbnN0IHRhYmxlTmFtZSA9IFJlcG9zaXRvcnkudGFibGUodGhpcy5mcm9tU2VsZWN0b3IpO1xuICAgIGNvbnN0IG0gPSBuZXcgdGhpcy5mcm9tU2VsZWN0b3IoKTtcblxuICAgIGNvbnN0IHE6IFR5cGVPUk1RdWVyeTxNLCBTZWxlY3RRdWVyeUJ1aWxkZXI8TT4+ID0ge1xuICAgICAgcXVlcnk6IHRoaXMuYWRhcHRlci5kYXRhU291cmNlXG4gICAgICAgIC5nZXRSZXBvc2l0b3J5KFxuICAgICAgICAgIHRoaXMuZnJvbVNlbGVjdG9yW01vZGVsS2V5cy5BTkNIT1IgYXMga2V5b2YgdHlwZW9mIHRoaXMuZnJvbVNlbGVjdG9yXVxuICAgICAgICApXG4gICAgICAgIC5jcmVhdGVRdWVyeUJ1aWxkZXIodGFibGVOYW1lKSBhcyBTZWxlY3RRdWVyeUJ1aWxkZXI8TT4sXG4gICAgfTtcblxuICAgIGlmICh0aGlzLnNlbGVjdFNlbGVjdG9yKVxuICAgICAgcS5xdWVyeSA9IHEucXVlcnkuc2VsZWN0KFxuICAgICAgICB0aGlzLnNlbGVjdFNlbGVjdG9yLm1hcCgocykgPT4gYCR7dGFibGVOYW1lfS4ke3MgYXMgc3RyaW5nfWApXG4gICAgICApO1xuICAgIGVsc2UgcS5xdWVyeSA9IHEucXVlcnkuc2VsZWN0KCk7XG4gICAgLy9cbiAgICAvLyBxLnF1ZXJ5ID0gKHEucXVlcnkgYXMgU2VsZWN0UXVlcnlCdWlsZGVyPGFueT4pLmZyb20oXG4gICAgLy8gICB0aGlzLmZyb21TZWxlY3RvcltNb2RlbEtleXMuQU5DSE9SIGFzIGtleW9mIHR5cGVvZiB0aGlzLmZyb21TZWxlY3Rvcl0sXG4gICAgLy8gICB0YWJsZU5hbWVcbiAgICAvLyApO1xuXG4gICAgaWYgKHRoaXMud2hlcmVDb25kaXRpb24pXG4gICAgICBxLnF1ZXJ5ID0gdGhpcy5wYXJzZUNvbmRpdGlvbihcbiAgICAgICAgdGhpcy53aGVyZUNvbmRpdGlvbixcbiAgICAgICAgdGFibGVOYW1lLFxuICAgICAgICBxLnF1ZXJ5IGFzIFNlbGVjdFF1ZXJ5QnVpbGRlcjxhbnk+XG4gICAgICApLnF1ZXJ5IGFzIHVua25vd24gYXMgU2VsZWN0UXVlcnlCdWlsZGVyPE0+O1xuXG4gICAgbGV0IG9yZGVyQnlBcmdzOiBbc3RyaW5nLCBcIkRFU0NcIiB8IFwiQVNDXCJdO1xuICAgIGlmICghdGhpcy5vcmRlckJ5U2VsZWN0b3IpXG4gICAgICBvcmRlckJ5QXJncyA9IFtcbiAgICAgICAgYCR7dGFibGVOYW1lfS4ke2ZpbmRQcmltYXJ5S2V5KG0pLmlkIGFzIHN0cmluZ31gLFxuICAgICAgICBPcmRlckRpcmVjdGlvbi5BU0MudG9VcHBlckNhc2UoKSBhcyBcIkFTQ1wiLFxuICAgICAgXTtcbiAgICBlbHNlXG4gICAgICBvcmRlckJ5QXJncyA9IFtcbiAgICAgICAgYCR7dGFibGVOYW1lfS4ke3RoaXMub3JkZXJCeVNlbGVjdG9yWzBdIGFzIHN0cmluZ31gLFxuICAgICAgICB0aGlzLm9yZGVyQnlTZWxlY3RvclsxXS50b1VwcGVyQ2FzZSgpIGFzIFwiREVTQ1wiIHwgXCJBU0NcIixcbiAgICAgIF07XG5cbiAgICBxLnF1ZXJ5ID0gKHEucXVlcnkgYXMgU2VsZWN0UXVlcnlCdWlsZGVyPGFueT4pLm9yZGVyQnkoLi4ub3JkZXJCeUFyZ3MpO1xuICAgIGlmICh0aGlzLmxpbWl0U2VsZWN0b3IpIHtcbiAgICAgIHEucXVlcnkgPSAocS5xdWVyeSBhcyBTZWxlY3RRdWVyeUJ1aWxkZXI8YW55PikubGltaXQodGhpcy5saW1pdFNlbGVjdG9yKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbG9nLmRlYnVnKFxuICAgICAgICBgTm8gbGltaXQgc2VsZWN0b3IgZGVmaW5lZC4gVXNpbmcgZGVmYXVsdCBsaW1pdCBvZiAke1R5cGVPUk1RdWVyeUxpbWl0fWBcbiAgICAgICk7XG4gICAgICBxLnF1ZXJ5ID0gKHEucXVlcnkgYXMgU2VsZWN0UXVlcnlCdWlsZGVyPGFueT4pLmxpbWl0KFR5cGVPUk1RdWVyeUxpbWl0KTtcbiAgICB9XG5cbiAgICAvLyBBZGQgb2Zmc2V0XG4gICAgaWYgKHRoaXMub2Zmc2V0U2VsZWN0b3IpXG4gICAgICBxLnF1ZXJ5ID0gKHEucXVlcnkgYXMgU2VsZWN0UXVlcnlCdWlsZGVyPGFueT4pLnNraXAodGhpcy5vZmZzZXRTZWxlY3Rvcik7XG5cbiAgICByZXR1cm4gcSBhcyBhbnk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBwYWdpbmF0b3IgZm9yIHRoZSBzdGF0ZW1lbnQuXG4gICAqIEBzdW1tYXJ5IEJ1aWxkcyB0aGUgcXVlcnkgYW5kIHJldHVybnMgYSBUeXBlT1JNUGFnaW5hdG9yIGZvciBwYWdpbmF0ZWQgcmVzdWx0cy5cbiAgICogQHRlbXBsYXRlIFIgVGhlIHJlc3VsdCB0eXBlLlxuICAgKiBAcGFyYW0ge251bWJlcn0gc2l6ZSBUaGUgcGFnZSBzaXplLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFBhZ2luYXRvcjxNLCBSLCBUeXBlT1JNUXVlcnk+Pn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBwYWdpbmF0b3IuXG4gICAqIEB0aHJvd3Mge0ludGVybmFsRXJyb3J9IElmIHRoZXJlJ3MgYW4gZXJyb3IgYnVpbGRpbmcgdGhlIHF1ZXJ5LlxuICAgKi9cbiAgYXN5bmMgcGFnaW5hdGU8Uj4oc2l6ZTogbnVtYmVyKTogUHJvbWlzZTxQYWdpbmF0b3I8TSwgUiwgVHlwZU9STVF1ZXJ5Pj4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBxdWVyeTogVHlwZU9STVF1ZXJ5ID0gdGhpcy5idWlsZCgpO1xuICAgICAgY29uc3QgdHJhbnNmb3JtZWRRdWVyeTogRmluZE1hbnlPcHRpb25zPE0+ID0ge307XG4gICAgICBjb25zdCBhID0gcXVlcnkucXVlcnkgYXMgdW5rbm93biBhcyBTZWxlY3RRdWVyeUJ1aWxkZXI8TT47XG4gICAgICBpZiAodGhpcy53aGVyZUNvbmRpdGlvbilcbiAgICAgICAgdHJhbnNmb3JtZWRRdWVyeS53aGVyZSA9IHRoaXMucGFyc2VDb25kaXRpb25Gb3JQYWdpbmF0aW9uKFxuICAgICAgICAgIHRoaXMud2hlcmVDb25kaXRpb24sXG4gICAgICAgICAgUmVwb3NpdG9yeS50YWJsZSh0aGlzLmZyb21TZWxlY3RvcilcbiAgICAgICAgKTtcblxuICAgICAgaWYgKHRoaXMub3JkZXJCeVNlbGVjdG9yKVxuICAgICAgICB0cmFuc2Zvcm1lZFF1ZXJ5Lm9yZGVyID0ge1xuICAgICAgICAgIFt0aGlzLm9yZGVyQnlTZWxlY3RvclswXV06IHRoaXMub3JkZXJCeVNlbGVjdG9yWzFdLnRvU3RyaW5nKCksXG4gICAgICAgIH0gYXMgYW55O1xuXG4gICAgICByZXR1cm4gbmV3IFR5cGVPUk1QYWdpbmF0b3IoXG4gICAgICAgIHRoaXMuYWRhcHRlciBhcyBhbnksXG4gICAgICAgIHRyYW5zZm9ybWVkUXVlcnkgYXMgYW55LFxuICAgICAgICBzaXplLFxuICAgICAgICB0aGlzLmZyb21TZWxlY3RvclxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGUpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJvY2Vzc2VzIGEgcmVjb3JkLlxuICAgKiBAc3VtbWFyeSBDb252ZXJ0cyBhIHJhdyByZXN1bHQgcm93IHRvIGEgbW9kZWwgaW5zdGFuY2UgdXNpbmcgdGhlIGFkYXB0ZXIuXG4gICAqIEBwYXJhbSB7YW55fSByIFRoZSByYXcgcmVjb3JkLlxuICAgKiBAcGFyYW0ge2tleW9mIE19IHBrQXR0ciBUaGUgcHJpbWFyeSBrZXkgYXR0cmlidXRlIG9mIHRoZSBtb2RlbC5cbiAgICogQHBhcmFtIHtcIk51bWJlclwiIHwgXCJCaWdJbnRcIiB8IHVuZGVmaW5lZH0gc2VxdWVuY2VUeXBlIFRoZSB0eXBlIG9mIHRoZSBzZXF1ZW5jZS5cbiAgICogQHJldHVybiB7YW55fSBUaGUgcHJvY2Vzc2VkIHJlY29yZC5cbiAgICovXG4gIHByaXZhdGUgcHJvY2Vzc1JlY29yZChyOiBhbnksIHBrQXR0cjoga2V5b2YgTSkge1xuICAgIGlmICh0eXBlb2Ygcltwa0F0dHJdICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICByZXR1cm4gdGhpcy5hZGFwdGVyLnJldmVydChyLCB0aGlzLmZyb21TZWxlY3RvciwgcGtBdHRyLCByW3BrQXR0cl0pO1xuICAgIH1cbiAgICByZXR1cm4gcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXhlY3V0ZXMgYSByYXcgVHlwZU9STSBxdWVyeSBidWlsZGVyLlxuICAgKiBAc3VtbWFyeSBTZW5kcyB0aGUgYnVpbHQgU2VsZWN0UXVlcnlCdWlsZGVyIHRvIHRoZSBkYXRhYmFzZSB2aWEgVHlwZU9STSBhbmQgcmV0dXJucyB0aGUgcmVzdWx0cy5cbiAgICogQHRlbXBsYXRlIFIgVGhlIHJlc3VsdCB0eXBlLlxuICAgKiBAcGFyYW0ge1R5cGVPUk1RdWVyeX0gcmF3SW5wdXQgVGhlIHF1ZXJ5IGNvbnRhaW5lciB0byBleGVjdXRlLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFI+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgcXVlcnkgcmVzdWx0cy5cbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIHJhdzxSPihyYXdJbnB1dDogVHlwZU9STVF1ZXJ5PE0+KTogUHJvbWlzZTxSPiB7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMucmF3KTtcbiAgICBsb2cuZGVidWcoXG4gICAgICBgRXhlY3V0aW5nIHJhdyBxdWVyeTogJHsocmF3SW5wdXQucXVlcnkgYXMgdW5rbm93biBhcyBTZWxlY3RRdWVyeUJ1aWxkZXI8TT4pLmdldFNxbCgpfWBcbiAgICApO1xuICAgIHJldHVybiAoYXdhaXQgKFxuICAgICAgcmF3SW5wdXQucXVlcnkgYXMgdW5rbm93biBhcyBTZWxlY3RRdWVyeUJ1aWxkZXI8TT5cbiAgICApLmdldE1hbnkoKSkgYXMgUjtcbiAgfVxuXG4gIHByb3RlY3RlZCBwYXJzZUNvbmRpdGlvbkZvclBhZ2luYXRpb24oXG4gICAgY29uZGl0aW9uOiBDb25kaXRpb248TT4sXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgY291bnRlciA9IDAsXG4gICAgY29uZGl0aW9uYWxPcD86IEdyb3VwT3BlcmF0b3IgfCBPcGVyYXRvclxuICApOiBGaW5kT3B0aW9uc1doZXJlPE0+W10gfCBGaW5kT3B0aW9uc1doZXJlPE0+IHtcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIk5vdCBpbXBsZW1lbnRlZFwiKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUGFyc2VzIGEgY29uZGl0aW9uIGludG8gUG9zdGdyZVNRTCBjb25kaXRpb25zXG4gICAqIEBzdW1tYXJ5IENvbnZlcnRzIGEgQ29uZGl0aW9uIG9iamVjdCBpbnRvIFBvc3RncmVTUUwgY29uZGl0aW9uIHN0cnVjdHVyZXNcbiAgICogQHBhcmFtIHtDb25kaXRpb248TT59IGNvbmRpdGlvbiAtIFRoZSBjb25kaXRpb24gdG8gcGFyc2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IFt0YWJsZU5hbWVdIC0gdGhlIHBvc2l0aW9uYWwgaW5kZXggb2YgdGhlIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJuIHtUeXBlT1JNUXVlcnl9IFRoZSBQb3N0Z3Jlc1NRTCBjb25kaXRpb25cbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgU3RhdGVtZW50XG4gICAqICAgcGFydGljaXBhbnQgdHJhbnNsYXRlT3BlcmF0b3JzXG4gICAqICAgcGFydGljaXBhbnQgcGFyc2VDb25kaXRpb25cbiAgICpcbiAgICogICBTdGF0ZW1lbnQtPj5TdGF0ZW1lbnQ6IHBhcnNlQ29uZGl0aW9uKGNvbmRpdGlvbilcbiAgICpcbiAgICogICBOb3RlIG92ZXIgU3RhdGVtZW50OiBFeHRyYWN0IGNvbmRpdGlvbiBwYXJ0c1xuICAgKlxuICAgKiAgIGFsdCBTaW1wbGUgY29tcGFyaXNvbiBvcGVyYXRvclxuICAgKiAgICAgU3RhdGVtZW50LT4+dHJhbnNsYXRlT3BlcmF0b3JzOiB0cmFuc2xhdGVPcGVyYXRvcnMob3BlcmF0b3IpXG4gICAqICAgICB0cmFuc2xhdGVPcGVyYXRvcnMtLT4+U3RhdGVtZW50OiBSZXR1cm4gUG9zdGdyZVNRTCBvcGVyYXRvclxuICAgKiAgICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBDcmVhdGUgY29uZGl0aW9uIHdpdGggY29sdW1uLCBvcGVyYXRvciwgYW5kIHZhbHVlXG4gICAqICAgZWxzZSBOT1Qgb3BlcmF0b3JcbiAgICogICAgIFN0YXRlbWVudC0+PlN0YXRlbWVudDogcGFyc2VDb25kaXRpb24oYXR0cjEpXG4gICAqICAgICBTdGF0ZW1lbnQtPj5TdGF0ZW1lbnQ6IEFkZCBOT1QgdG8gY29uZGl0aW9uc1xuICAgKiAgIGVsc2UgQU5EL09SIG9wZXJhdG9yXG4gICAqICAgICBTdGF0ZW1lbnQtPj5TdGF0ZW1lbnQ6IHBhcnNlQ29uZGl0aW9uKGF0dHIxKVxuICAgKiAgICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBwYXJzZUNvbmRpdGlvbihjb21wYXJpc29uKVxuICAgKiAgICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBDb21iaW5lIGNvbmRpdGlvbnMgd2l0aCBBTkQvT1JcbiAgICogICBlbmRcbiAgICpcbiAgICogICBTdGF0ZW1lbnQtLT4+U3RhdGVtZW50OiBSZXR1cm4gY29uZGl0aW9ucyBhcnJheVxuICAgKi9cbiAgcHJvdGVjdGVkIHBhcnNlQ29uZGl0aW9uKFxuICAgIGNvbmRpdGlvbjogQ29uZGl0aW9uPE0+LFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIHFiOiBTZWxlY3RRdWVyeUJ1aWxkZXI8YW55PixcbiAgICBjb3VudGVyID0gMCxcbiAgICBjb25kaXRpb25hbE9wPzogR3JvdXBPcGVyYXRvciB8IE9wZXJhdG9yXG4gICk6IFR5cGVPUk1RdWVyeTxNPiB7XG4gICAgY29uc3QgeyBhdHRyMSwgb3BlcmF0b3IsIGNvbXBhcmlzb24gfSA9IGNvbmRpdGlvbiBhcyB1bmtub3duIGFzIHtcbiAgICAgIGF0dHIxOiBzdHJpbmcgfCBDb25kaXRpb248TT47XG4gICAgICBvcGVyYXRvcjogT3BlcmF0b3IgfCBHcm91cE9wZXJhdG9yO1xuICAgICAgY29tcGFyaXNvbjogYW55O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwYXJzZSgpOiBUeXBlT1JNUXVlcnk8TT4ge1xuICAgICAgY29uc3Qgc3FsT3BlcmF0b3IgPSB0cmFuc2xhdGVPcGVyYXRvcnMob3BlcmF0b3IpO1xuICAgICAgY29uc3QgYXR0clJlZiA9IGAke2F0dHIxfSR7Y291bnRlcn1gO1xuICAgICAgY29uc3QgcXVlcnlTdHIgPSBgJHt0YWJsZU5hbWV9LiR7YXR0cjF9ICR7c3FsT3BlcmF0b3J9IDoke2F0dHJSZWZ9YDtcbiAgICAgIGNvbnN0IHZhbHVlcyA9IHtcbiAgICAgICAgW2F0dHJSZWZdOiBjb21wYXJpc29uLFxuICAgICAgfTtcbiAgICAgIHN3aXRjaCAoY29uZGl0aW9uYWxPcCkge1xuICAgICAgICBjYXNlIEdyb3VwT3BlcmF0b3IuQU5EOlxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBxdWVyeTogcWIuYW5kV2hlcmUocXVlcnlTdHIsIHZhbHVlcykgYXMgYW55LFxuICAgICAgICAgIH07XG4gICAgICAgIGNhc2UgR3JvdXBPcGVyYXRvci5PUjpcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcXVlcnk6IHFiLm9yV2hlcmUocXVlcnlTdHIsIHZhbHVlcykgYXMgYW55LFxuICAgICAgICAgIH07XG4gICAgICAgIGNhc2UgT3BlcmF0b3IuTk9UOlxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5PVCBvcGVyYXRvciBub3QgaW1wbGVtZW50ZWRcIik7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHF1ZXJ5OiBxYi53aGVyZShxdWVyeVN0ciwgdmFsdWVzKSBhcyBhbnksXG4gICAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICBbR3JvdXBPcGVyYXRvci5BTkQsIEdyb3VwT3BlcmF0b3IuT1IsIE9wZXJhdG9yLk5PVF0uaW5kZXhPZihcbiAgICAgICAgb3BlcmF0b3IgYXMgR3JvdXBPcGVyYXRvclxuICAgICAgKSA9PT0gLTFcbiAgICApIHtcbiAgICAgIHJldHVybiBwYXJzZSgpO1xuICAgIH1cbiAgICAvLyBGb3IgTk9UIG9wZXJhdG9yXG4gICAgZWxzZSBpZiAob3BlcmF0b3IgPT09IE9wZXJhdG9yLk5PVCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTk9UIG9wZXJhdG9yIG5vdCBpbXBsZW1lbnRlZFwiKTtcbiAgICB9XG4gICAgLy8gRm9yIEFORC9PUiBvcGVyYXRvcnNcbiAgICBlbHNlIHtcbiAgICAgIHFiID0gdGhpcy5wYXJzZUNvbmRpdGlvbihhdHRyMSBhcyBDb25kaXRpb248TT4sIHRhYmxlTmFtZSwgcWIsICsrY291bnRlcilcbiAgICAgICAgLnF1ZXJ5IGFzIHVua25vd24gYXMgU2VsZWN0UXVlcnlCdWlsZGVyPE0+O1xuICAgICAgcmV0dXJuIHRoaXMucGFyc2VDb25kaXRpb24oXG4gICAgICAgIGNvbXBhcmlzb24sXG4gICAgICAgIHRhYmxlTmFtZSxcbiAgICAgICAgcWIsXG4gICAgICAgICsrY291bnRlcixcbiAgICAgICAgb3BlcmF0b3JcbiAgICAgICk7XG4gICAgfVxuICB9XG59XG4iLCJpbXBvcnQgeyBJbnRlcm5hbEVycm9yLCBOb3RGb3VuZEVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBTZXF1ZW5jZU9wdGlvbnMgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IFNlcXVlbmNlIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBUeXBlT1JNQWRhcHRlciB9IGZyb20gXCIuLi9UeXBlT1JNQWRhcHRlclwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBYnN0cmFjdCBpbXBsZW1lbnRhdGlvbiBvZiBhIGRhdGFiYXNlIHNlcXVlbmNlIGZvciBUeXBlT1JNLlxuICogQHN1bW1hcnkgUHJvdmlkZXMgdGhlIGJhc2ljIGZ1bmN0aW9uYWxpdHkgZm9yIHtAbGluayBTZXF1ZW5jZX1zLCBkZWxlZ2F0aW5nIHRvIHRoZSB7QGxpbmsgVHlwZU9STUFkYXB0ZXJ9IHRvIGZldGNoIGFuZCBpbmNyZW1lbnQgdmFsdWVzIHdoaWxlIGhhbmRsaW5nIHR5cGUgcGFyc2luZyBhbmQgZXJyb3IgdHJhbnNsYXRpb24uXG4gKiBAcGFyYW0ge1NlcXVlbmNlT3B0aW9uc30gb3B0aW9ucyBUaGUgc2VxdWVuY2UgY29uZmlndXJhdGlvbiBvcHRpb25zIChuYW1lLCB0eXBlLCBzdGFydFdpdGgsIGluY3JlbWVudEJ5LCBldGMuKS5cbiAqIEBwYXJhbSB7VHlwZU9STUFkYXB0ZXJ9IGFkYXB0ZXIgVGhlIFR5cGVPUk0gYWRhcHRlciB1c2VkIHRvIGV4ZWN1dGUgc2VxdWVuY2Ugb3BlcmF0aW9ucy5cbiAqIEBjbGFzcyBUeXBlT1JNU2VxdWVuY2VcbiAqIEBpbXBsZW1lbnRzIFNlcXVlbmNlXG4gKiBAZXhhbXBsZVxuICogLy8gQ3JlYXRlIGFuZCB1c2UgYSBUeXBlT1JNLWJhY2tlZCBzZXF1ZW5jZVxuICogY29uc3Qgc2VxID0gbmV3IFR5cGVPUk1TZXF1ZW5jZSh7IG5hbWU6IFwidXNlcl9pZF9zZXFcIiwgdHlwZTogXCJOdW1iZXJcIiwgc3RhcnRXaXRoOiAxLCBpbmNyZW1lbnRCeTogMSB9LCBhZGFwdGVyKTtcbiAqIGNvbnN0IG5leHRJZCA9IGF3YWl0IHNlcS5uZXh0KCk7XG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBBcHBcbiAqICAgcGFydGljaXBhbnQgU2VxIGFzIFR5cGVPUk1TZXF1ZW5jZVxuICogICBwYXJ0aWNpcGFudCBBZGFwdGVyIGFzIFR5cGVPUk1BZGFwdGVyXG4gKiAgIHBhcnRpY2lwYW50IERCIGFzIERhdGFiYXNlXG4gKiAgIEFwcC0+PlNlcTogbmV4dCgpXG4gKiAgIFNlcS0+PlNlcTogY3VycmVudCgpXG4gKiAgIFNlcS0+PkFkYXB0ZXI6IHJhdyhTRUxFQ1QgY3VycmVudF92YWx1ZSAuLi4pXG4gKiAgIEFkYXB0ZXItPj5EQjogUXVlcnkgY3VycmVudCB2YWx1ZVxuICogICBEQi0tPj5BZGFwdGVyOiBjdXJyZW50X3ZhbHVlXG4gKiAgIEFkYXB0ZXItLT4+U2VxOiB2YWx1ZVxuICogICBTZXEtPj5TZXE6IGluY3JlbWVudChjdXJyZW50KVxuICogICBTZXEtPj5BZGFwdGVyOiByYXcobmV4dHZhbChuYW1lKSlcbiAqICAgQWRhcHRlci0+PkRCOiBuZXh0dmFsKClcbiAqICAgREItLT4+QWRhcHRlcjogbmV4dCB2YWx1ZVxuICogICBBZGFwdGVyLS0+PlNlcTogdmFsdWVcbiAqICAgU2VxLS0+PkFwcDogcGFyc2VkIG5leHQgdmFsdWVcbiAqL1xuZXhwb3J0IGNsYXNzIFR5cGVPUk1TZXF1ZW5jZSBleHRlbmRzIFNlcXVlbmNlIHtcbiAgY29uc3RydWN0b3IoXG4gICAgb3B0aW9uczogU2VxdWVuY2VPcHRpb25zLFxuICAgIHByb3RlY3RlZCBhZGFwdGVyOiBUeXBlT1JNQWRhcHRlclxuICApIHtcbiAgICBzdXBlcihvcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBSZXRyaWV2ZXMgdGhlIGN1cnJlbnQgdmFsdWUgZm9yIHRoZSBzZXF1ZW5jZVxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuICBhc3luYyBjdXJyZW50KCk6IFByb21pc2U8c3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50PiB7XG4gICAgY29uc3QgeyBuYW1lIH0gPSB0aGlzLm9wdGlvbnM7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHNlcTogYW55ID0gYXdhaXQgdGhpcy5hZGFwdGVyLnJhdyh7XG4gICAgICAgIHF1ZXJ5OiBgU0VMRUNUIGN1cnJlbnRfdmFsdWUgRlJPTSBpbmZvcm1hdGlvbl9zY2hlbWEuc2VxdWVuY2VzIFdIRVJFIHNlcXVlbmNlX25hbWUgPSAkMWAsXG4gICAgICAgIHZhbHVlczogW25hbWVdLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gdGhpcy5wYXJzZShzZXEuY3VycmVudF92YWx1ZSBhcyBzdHJpbmcgfCBudW1iZXIpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IHRoaXMuYWRhcHRlci5wYXJzZUVycm9yKGUgYXMgRXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBQYXJzZXMgdGhlIHtAbGluayBTZXF1ZW5jZX0gdmFsdWVcbiAgICpcbiAgICogQHByb3RlY3RlZFxuICAgKiBAcGFyYW0gdmFsdWVcbiAgICovXG4gIHByaXZhdGUgcGFyc2UodmFsdWU6IHN0cmluZyB8IG51bWJlciB8IGJpZ2ludCk6IHN0cmluZyB8IG51bWJlciB8IGJpZ2ludCB7XG4gICAgcmV0dXJuIFNlcXVlbmNlLnBhcnNlVmFsdWUodGhpcy5vcHRpb25zLnR5cGUsIHZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBpbmNyZW1lbnRzIHRoZSBzZXF1ZW5jZVxuICAgKiBAZGVzY3JpcHRpb24gU2VxdWVuY2Ugc3BlY2lmaWMgaW1wbGVtZW50YXRpb25cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnR9IGN1cnJlbnRcbiAgICogQHBhcmFtIGNvdW50XG4gICAqIEBwcm90ZWN0ZWRcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgaW5jcmVtZW50KFxuICAgIGN1cnJlbnQ6IHN0cmluZyB8IG51bWJlciB8IGJpZ2ludCxcbiAgICBjb3VudD86IG51bWJlclxuICApOiBQcm9taXNlPHN0cmluZyB8IG51bWJlciB8IGJpZ2ludD4ge1xuICAgIGNvbnN0IHsgdHlwZSwgaW5jcmVtZW50QnksIG5hbWUsIHN0YXJ0V2l0aCB9ID0gdGhpcy5vcHRpb25zO1xuICAgIGlmICh0eXBlICE9PSBcIk51bWJlclwiICYmIHR5cGUgIT09IFwiQmlnSW50XCIpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgYENhbm5vdCBpbmNyZW1lbnQgc2VxdWVuY2Ugb2YgdHlwZSAke3R5cGV9IHdpdGggJHtjb3VudH1gXG4gICAgICApO1xuICAgIGxldCBuZXh0OiBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQ7XG4gICAgdHJ5IHtcbiAgICAgIG5leHQgPSBhd2FpdCB0aGlzLmFkYXB0ZXIucmF3KHtcbiAgICAgICAgcXVlcnk6IGBTRUxFQ1QgbmV4dHZhbCgkMSk7YCxcbiAgICAgICAgdmFsdWVzOiBbbmFtZV0sXG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgTm90Rm91bmRFcnJvcikpIHRocm93IGU7XG4gICAgICBuZXh0ID0gYXdhaXQgdGhpcy5hZGFwdGVyLnJhdyh7XG4gICAgICAgIHF1ZXJ5OiBgQ1JFQVRFIFNFUVVFTkNFIElGIE5PVCBFWElTVFMgJDEgU1RBUlQgV0lUSCAkMiBJTkNSRU1FTlQgQlkgJDMgTk8gQ1lDTEU7YCxcbiAgICAgICAgdmFsdWVzOiBbbmFtZSwgc3RhcnRXaXRoLCBpbmNyZW1lbnRCeV0sXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV4dCBhcyBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQ7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgR2VuZXJhdGVzIHRoZSBuZXh0IHZhbHVlIGluIHRoIHNlcXVlbmNlXG4gICAqIEBkZXNjcmlwdGlvbiBjYWxscyB7QGxpbmsgU2VxdWVuY2UjcGFyc2V9IG9uIHRoZSBjdXJyZW50IHZhbHVlXG4gICAqIGZvbGxvd2VkIGJ5IHtAbGluayBTZXF1ZW5jZSNpbmNyZW1lbnR9XG4gICAqXG4gICAqL1xuICBhc3luYyBuZXh0KCk6IFByb21pc2U8bnVtYmVyIHwgc3RyaW5nIHwgYmlnaW50PiB7XG4gICAgY29uc3QgY3VycmVudCA9IGF3YWl0IHRoaXMuY3VycmVudCgpO1xuICAgIHJldHVybiB0aGlzLmluY3JlbWVudChjdXJyZW50KTtcbiAgfVxuXG4gIGFzeW5jIHJhbmdlKGNvdW50OiBudW1iZXIpOiBQcm9taXNlPChudW1iZXIgfCBzdHJpbmcgfCBiaWdpbnQpW10+IHtcbiAgICBjb25zdCBjdXJyZW50ID0gKGF3YWl0IHRoaXMuY3VycmVudCgpKSBhcyBudW1iZXI7XG4gICAgY29uc3QgaW5jcmVtZW50QnkgPSB0aGlzLnBhcnNlKHRoaXMub3B0aW9ucy5pbmNyZW1lbnRCeSkgYXMgbnVtYmVyO1xuICAgIGNvbnN0IG5leHQ6IHN0cmluZyB8IG51bWJlciB8IGJpZ2ludCA9IGF3YWl0IHRoaXMuaW5jcmVtZW50KFxuICAgICAgY3VycmVudCxcbiAgICAgICh0aGlzLnBhcnNlKGNvdW50KSBhcyBudW1iZXIpICogaW5jcmVtZW50QnlcbiAgICApO1xuICAgIGNvbnN0IHJhbmdlOiAobnVtYmVyIHwgc3RyaW5nIHwgYmlnaW50KVtdID0gW107XG4gICAgZm9yIChsZXQgaTogbnVtYmVyID0gMTsgaSA8PSBjb3VudDsgaSsrKSB7XG4gICAgICByYW5nZS5wdXNoKGN1cnJlbnQgKyBpbmNyZW1lbnRCeSAqICh0aGlzLnBhcnNlKGkpIGFzIG51bWJlcikpO1xuICAgIH1cbiAgICBpZiAocmFuZ2VbcmFuZ2UubGVuZ3RoIC0gMV0gIT09IG5leHQpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIk1pc2NhbGN1bGF0aW9uIG9mIHJhbmdlXCIpO1xuICAgIHJldHVybiByYW5nZTtcbiAgfVxufVxuIiwiaW1wb3J0IHtcbiAgSW5kZXhNZXRhZGF0YSxcbiAgT3JkZXJEaXJlY3Rpb24sXG4gIFBlcnNpc3RlbmNlS2V5cyxcbiAgUmVwb3NpdG9yeSxcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBUeXBlT1JNS2V5cyB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IERlZmF1bHRTZXBhcmF0b3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yLCBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IFR5cGVPUk1RdWVyeSB9IGZyb20gXCIuLi90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBHZW5lcmF0ZXMgYSBuYW1lIGZvciBhIENvdWNoREIgaW5kZXhcbiAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBzdGFuZGFyZGl6ZWQgbmFtZSBmb3IgYSBDb3VjaERCIGluZGV4IGJ5IGNvbWJpbmluZyBuYW1lIHBhcnRzLCBjb21wb3NpdGlvbnMsIGFuZCBkaXJlY3Rpb25cbiAqIEBwYXJhbSB7c3RyaW5nW119IG5hbWUgLSBBcnJheSBvZiBuYW1lIHBhcnRzIGZvciB0aGUgaW5kZXhcbiAqIEBwYXJhbSB7T3JkZXJEaXJlY3Rpb259IFtkaXJlY3Rpb25dIC0gT3B0aW9uYWwgc29ydCBkaXJlY3Rpb24gZm9yIHRoZSBpbmRleFxuICogQHBhcmFtIHtzdHJpbmdbXX0gW2NvbXBvc2l0aW9uc10gLSBPcHRpb25hbCBhZGRpdGlvbmFsIGF0dHJpYnV0ZXMgdG8gaW5jbHVkZSBpbiB0aGUgaW5kZXggbmFtZVxuICogQHBhcmFtIHtzdHJpbmd9IFtzZXBhcmF0b3I9RGVmYXVsdFNlcGFyYXRvcl0gLSBUaGUgc2VwYXJhdG9yIHRvIHVzZSBiZXR3ZWVuIHBhcnRzIG9mIHRoZSBpbmRleCBuYW1lXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBnZW5lcmF0ZWQgaW5kZXggbmFtZVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItY291Y2hkYlxuICovXG5mdW5jdGlvbiBnZW5lcmF0ZUluZGV4TmFtZShcbiAgbmFtZTogc3RyaW5nW10sXG4gIGRpcmVjdGlvbj86IE9yZGVyRGlyZWN0aW9uLFxuICBjb21wb3NpdGlvbnM/OiBzdHJpbmdbXSxcbiAgc2VwYXJhdG9yID0gRGVmYXVsdFNlcGFyYXRvclxuKSB7XG4gIHJldHVybiBbXG4gICAgLi4ubmFtZS5tYXAoKG4pID0+IChuID09PSBUeXBlT1JNS2V5cy5UQUJMRSA/IFwidGFibGVcIiA6IG4pKSxcbiAgICAuLi4oY29tcG9zaXRpb25zIHx8IFtdKSxcbiAgICAuLi4oZGlyZWN0aW9uID8gW2RpcmVjdGlvbl0gOiBbXSksXG4gICAgVHlwZU9STUtleXMuSU5ERVgsXG4gIF0uam9pbihzZXBhcmF0b3IpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBHZW5lcmF0ZXMgQ291Y2hEQiBpbmRleCBjb25maWd1cmF0aW9ucyBmb3IgbW9kZWxzXG4gKiBAc3VtbWFyeSBDcmVhdGVzIGEgc2V0IG9mIENvdWNoREIgaW5kZXggY29uZmlndXJhdGlvbnMgYmFzZWQgb24gdGhlIG1ldGFkYXRhIG9mIHRoZSBwcm92aWRlZCBtb2RlbHNcbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUgdGhhdCBleHRlbmRzIE1vZGVsXG4gKiBAcGFyYW0gbW9kZWxzIC0gQXJyYXkgb2YgbW9kZWwgY29uc3RydWN0b3JzIHRvIGdlbmVyYXRlIGluZGV4ZXMgZm9yXG4gKiBAcmV0dXJuIHtUeXBlT1JNUXVlcnl9IEFycmF5IG9mIENvdWNoREIgaW5kZXggY29uZmlndXJhdGlvbnNcbiAqIEBmdW5jdGlvbiBnZW5lcmF0ZUluZGV4ZXNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWNvdWNoZGJcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IGdlbmVyYXRlSW5kZXhlc1xuICogICBwYXJ0aWNpcGFudCBnZW5lcmF0ZUluZGV4TmFtZVxuICogICBwYXJ0aWNpcGFudCBSZXBvc2l0b3J5XG4gKlxuICogICBDYWxsZXItPj5nZW5lcmF0ZUluZGV4ZXM6IG1vZGVsc1xuICpcbiAqICAgTm90ZSBvdmVyIGdlbmVyYXRlSW5kZXhlczogQ3JlYXRlIGJhc2UgdGFibGUgaW5kZXhcbiAqICAgZ2VuZXJhdGVJbmRleGVzLT4+Z2VuZXJhdGVJbmRleE5hbWU6IFtDb3VjaERCS2V5cy5UQUJMRV1cbiAqICAgZ2VuZXJhdGVJbmRleE5hbWUtLT4+Z2VuZXJhdGVJbmRleGVzOiB0YWJsZU5hbWVcbiAqICAgZ2VuZXJhdGVJbmRleGVzLT4+Z2VuZXJhdGVJbmRleGVzOiBDcmVhdGUgdGFibGUgaW5kZXggY29uZmlnXG4gKlxuICogICBsb29wIEZvciBlYWNoIG1vZGVsXG4gKiAgICAgZ2VuZXJhdGVJbmRleGVzLT4+UmVwb3NpdG9yeTogR2V0IGluZGV4ZXMgbWV0YWRhdGFcbiAqICAgICBSZXBvc2l0b3J5LS0+PmdlbmVyYXRlSW5kZXhlczogaW5kZXggbWV0YWRhdGFcbiAqXG4gKiAgICAgbG9vcCBGb3IgZWFjaCBpbmRleCBpbiBtZXRhZGF0YVxuICogICAgICAgTm90ZSBvdmVyIGdlbmVyYXRlSW5kZXhlczogRXh0cmFjdCBpbmRleCBwcm9wZXJ0aWVzXG4gKiAgICAgICBnZW5lcmF0ZUluZGV4ZXMtPj5SZXBvc2l0b3J5OiBHZXQgdGFibGUgbmFtZVxuICogICAgICAgUmVwb3NpdG9yeS0tPj5nZW5lcmF0ZUluZGV4ZXM6IHRhYmxlTmFtZVxuICpcbiAqICAgICAgIE5vdGUgb3ZlciBnZW5lcmF0ZUluZGV4ZXM6IERlZmluZSBuZXN0ZWQgZ2VuZXJhdGUgZnVuY3Rpb25cbiAqXG4gKiAgICAgICBnZW5lcmF0ZUluZGV4ZXMtPj5nZW5lcmF0ZUluZGV4ZXM6IENhbGwgZ2VuZXJhdGUoKSBmb3IgZGVmYXVsdCBvcmRlclxuICogICAgICAgTm90ZSBvdmVyIGdlbmVyYXRlSW5kZXhlczogQ3JlYXRlIGluZGV4IG5hbWUgYW5kIGNvbmZpZ1xuICpcbiAqICAgICAgIGFsdCBIYXMgZGlyZWN0aW9uc1xuICogICAgICAgICBsb29wIEZvciBlYWNoIGRpcmVjdGlvblxuICogICAgICAgICAgIGdlbmVyYXRlSW5kZXhlcy0+PmdlbmVyYXRlSW5kZXhlczogQ2FsbCBnZW5lcmF0ZShkaXJlY3Rpb24pXG4gKiAgICAgICAgICAgTm90ZSBvdmVyIGdlbmVyYXRlSW5kZXhlczogQ3JlYXRlIG9yZGVyZWQgaW5kZXggY29uZmlnXG4gKiAgICAgICAgIGVuZFxuICogICAgICAgZW5kXG4gKiAgICAgZW5kXG4gKiAgIGVuZFxuICpcbiAqICAgZ2VuZXJhdGVJbmRleGVzLS0+PkNhbGxlcjogQXJyYXkgb2YgaW5kZXggY29uZmlndXJhdGlvbnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlSW5kZXhlczxNIGV4dGVuZHMgTW9kZWw+KFxuICBtb2RlbHM6IENvbnN0cnVjdG9yPE0+W11cbik6IFR5cGVPUk1RdWVyeVtdIHtcbiAgY29uc3QgdGFibGVOYW1lID0gZ2VuZXJhdGVJbmRleE5hbWUoW1R5cGVPUk1LZXlzLlRBQkxFXSk7XG4gIGNvbnN0IGluZGV4ZXM6IFJlY29yZDxzdHJpbmcsIFR5cGVPUk1RdWVyeT4gPSB7fTtcbiAgaW5kZXhlc1t0YWJsZU5hbWVdID0ge1xuICAgIHF1ZXJ5OiBgYCxcbiAgICB2YWx1ZXM6IFtdLFxuICB9O1xuXG4gIG1vZGVscy5mb3JFYWNoKChtKSA9PiB7XG4gICAgY29uc3QgaW5kOiBSZWNvcmQ8c3RyaW5nLCBJbmRleE1ldGFkYXRhPiA9IFJlcG9zaXRvcnkuaW5kZXhlcyhtKTtcbiAgICBPYmplY3QuZW50cmllcyhpbmQpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgY29uc3QgayA9IE9iamVjdC5rZXlzKHZhbHVlKVswXTtcblxuICAgICAgbGV0IHsgY29tcG9zaXRpb25zIH0gPSAodmFsdWUgYXMgYW55KVtrXTtcbiAgICAgIGNvbnN0IHRhYmxlTmFtZSA9IFJlcG9zaXRvcnkudGFibGUobSk7XG4gICAgICBjb21wb3NpdGlvbnMgPSBjb21wb3NpdGlvbnMgfHwgW107XG5cbiAgICAgIGZ1bmN0aW9uIGdlbmVyYXRlKCkge1xuICAgICAgICBjb25zdCBuYW1lID0gW2tleSwgLi4uKGNvbXBvc2l0aW9ucyBhcyBbXSksIFBlcnNpc3RlbmNlS2V5cy5JTkRFWF0uam9pbihcbiAgICAgICAgICBEZWZhdWx0U2VwYXJhdG9yXG4gICAgICAgICk7XG5cbiAgICAgICAgaW5kZXhlc1tuYW1lXSA9IHtcbiAgICAgICAgICBxdWVyeTogYENSRUFURSBJTkRFWCAkMSBPTiAkMiAoJDMpO2AsXG4gICAgICAgICAgdmFsdWVzOiBbbmFtZSwgdGFibGVOYW1lLCBrZXldLFxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBnZW5lcmF0ZSgpO1xuICAgIH0pO1xuICB9KTtcbiAgcmV0dXJuIE9iamVjdC52YWx1ZXMoaW5kZXhlcyk7XG59XG4iLCJpbXBvcnQge1xuICB0eXBlIENvbnN0cnVjdG9yLFxuICBNb2RlbCxcbiAgTW9kZWxLZXlzLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5LCB1c2VzIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQge1xuICBDb250ZXh0LFxuICBlbmZvcmNlREJEZWNvcmF0b3JzLFxuICBPcGVyYXRpb25LZXlzLFxuICBWYWxpZGF0aW9uRXJyb3IsXG59IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgVHlwZU9STUZsYWdzLCBUeXBlT1JNUXVlcnkgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgVHlwZU9STUFkYXB0ZXIgfSBmcm9tIFwiLi9UeXBlT1JNQWRhcHRlclwiO1xuaW1wb3J0IHsgVHlwZU9STUZsYXZvdXIgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVwb3NpdG9yeSBpbXBsZW1lbnRhdGlvbiBiYWNrZWQgYnkgVHlwZU9STS5cbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIENSVUQgb3BlcmF0aW9ucyBmb3IgYSBnaXZlbiBNb2RlbCB1c2luZyB0aGUge0BsaW5rIFR5cGVPUk1BZGFwdGVyfSwgaW5jbHVkaW5nIGJ1bGsgb3BlcmF0aW9ucyBhbmQgcXVlcnkgYnVpbGRlciBhY2Nlc3Mgd2hpbGUgcHJlc2VydmluZyBEZWNhZi50cyByZXBvc2l0b3J5IHNlbWFudGljcy5cbiAqIEB0ZW1wbGF0ZSBNIFR5cGUgZXh0ZW5kaW5nIE1vZGVsIHRoYXQgdGhpcyByZXBvc2l0b3J5IHdpbGwgbWFuYWdlLlxuICogQHBhcmFtIHtUeXBlT1JNQWRhcHRlcn0gYWRhcHRlciBUaGUgYWRhcHRlciB1c2VkIHRvIGV4ZWN1dGUgcGVyc2lzdGVuY2Ugb3BlcmF0aW9ucy5cbiAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IG1vZGVsIFRoZSBNb2RlbCBjb25zdHJ1Y3RvciBhc3NvY2lhdGVkIHdpdGggdGhpcyByZXBvc2l0b3J5LlxuICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyBPcHRpb25hbCBhcmd1bWVudHMgZm9yd2FyZGVkIHRvIHRoZSBiYXNlIFJlcG9zaXRvcnkuXG4gKiBAY2xhc3MgVHlwZU9STVJlcG9zaXRvcnlcbiAqIEBleGFtcGxlXG4gKiAvLyBDcmVhdGluZyBhIHJlcG9zaXRvcnlcbiAqIGNvbnN0IHJlcG8gPSBuZXcgVHlwZU9STVJlcG9zaXRvcnk8VXNlcj4oYWRhcHRlciwgVXNlcik7XG4gKiBjb25zdCBjcmVhdGVkID0gYXdhaXQgcmVwby5jcmVhdGUobmV3IFVzZXIoeyBuYW1lOiBcIkFsaWNlXCIgfSkpO1xuICogY29uc3QgcmVhZCA9IGF3YWl0IHJlcG8ucmVhZChjcmVhdGVkLmlkKTtcbiAqXG4gKiAvLyBCdWxrIGNyZWF0ZVxuICogYXdhaXQgcmVwby5jcmVhdGVBbGwoW25ldyBVc2VyKHsgbmFtZTogXCJBXCIgfSksIG5ldyBVc2VyKHsgbmFtZTogXCJCXCIgfSldKTtcbiAqXG4gKiAvLyBVc2luZyB0aGUgcXVlcnkgYnVpbGRlclxuICogY29uc3QgcWIgPSByZXBvLnF1ZXJ5QnVpbGRlcigpO1xuICogY29uc3Qgcm93cyA9IGF3YWl0IHFiLndoZXJlKFwibmFtZSA9IDpuYW1lXCIsIHsgbmFtZTogXCJBbGljZVwiIH0pLmdldE1hbnkoKTtcbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEFwcFxuICogICBwYXJ0aWNpcGFudCBSZXBvIGFzIFR5cGVPUk1SZXBvc2l0b3J5XG4gKiAgIHBhcnRpY2lwYW50IEFkYXB0ZXIgYXMgVHlwZU9STUFkYXB0ZXJcbiAqICAgcGFydGljaXBhbnQgREIgYXMgVHlwZU9STS9EYXRhU291cmNlXG4gKlxuICogICBBcHAtPj5SZXBvOiBjcmVhdGUobW9kZWwpXG4gKiAgIFJlcG8tPj5BZGFwdGVyOiBwcmVwYXJlKG1vZGVsLCBwaylcbiAqICAgQWRhcHRlci0tPj5SZXBvOiB7IHJlY29yZCwgaWQsIHRyYW5zaWVudCB9XG4gKiAgIFJlcG8tPj5BZGFwdGVyOiBjcmVhdGUodGFibGUsIGlkLCBtb2RlbCwgLi4uYXJncylcbiAqICAgQWRhcHRlci0+PkRCOiBJTlNFUlQgLi4uXG4gKiAgIERCLS0+PkFkYXB0ZXI6IHJvd1xuICogICBBZGFwdGVyLS0+PlJlcG86IHJvd1xuICogICBSZXBvLT4+QWRhcHRlcjogcmV2ZXJ0KHJvdywgY2xhenosIHBrLCBpZClcbiAqICAgQWRhcHRlci0tPj5SZXBvOiBtb2RlbFxuICogICBSZXBvLS0+PkFwcDogbW9kZWxcbiAqL1xuQHVzZXMoVHlwZU9STUZsYXZvdXIpXG5leHBvcnQgY2xhc3MgVHlwZU9STVJlcG9zaXRvcnk8TSBleHRlbmRzIE1vZGVsPiBleHRlbmRzIFJlcG9zaXRvcnk8XG4gIE0sXG4gIFR5cGVPUk1RdWVyeTxNLCBhbnk+LFxuICBUeXBlT1JNQWRhcHRlcixcbiAgVHlwZU9STUZsYWdzLFxuICBDb250ZXh0PFR5cGVPUk1GbGFncz5cbj4ge1xuICBjb25zdHJ1Y3RvcihhZGFwdGVyOiBUeXBlT1JNQWRhcHRlciwgbW9kZWw6IENvbnN0cnVjdG9yPE0+LCAuLi5hcmdzOiBhbnlbXSkge1xuICAgIHN1cGVyKGFkYXB0ZXIsIG1vZGVsLCAuLi5hcmdzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIFR5cGVPUk0gcXVlcnkgYnVpbGRlciBmb3IgdGhlIHJlcG9zaXRvcnkgZW50aXR5LlxuICAgKiBAc3VtbWFyeSBSZXR1cm5zIGEgU2VsZWN0UXVlcnlCdWlsZGVyIGJvdW5kIHRvIHRoaXMgcmVwb3NpdG9yeSdzIGVudGl0eSBmb3IgYWR2YW5jZWQgcXVlcnlpbmcuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcInR5cGVvcm1cIikuU2VsZWN0UXVlcnlCdWlsZGVyPGFueT59IEEgVHlwZU9STSBTZWxlY3RRdWVyeUJ1aWxkZXIgaW5zdGFuY2UuXG4gICAqL1xuICBxdWVyeUJ1aWxkZXIoKSB7XG4gICAgY29uc3QgcmVwbyA9IHRoaXMuYWRhcHRlci5kYXRhU291cmNlLmdldFJlcG9zaXRvcnkoXG4gICAgICB0aGlzLmNsYXNzW01vZGVsS2V5cy5BTkNIT1IgYXMga2V5b2YgdHlwZW9mIHRoaXMuY2xhc3NdXG4gICAgKTtcbiAgICByZXR1cm4gcmVwby5jcmVhdGVRdWVyeUJ1aWxkZXIoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhbmQgcGVyc2lzdHMgYSBtb2RlbCBpbnN0YW5jZS5cbiAgICogQHN1bW1hcnkgUHJlcGFyZXMgdGhlIG1vZGVsLCBkZWxlZ2F0ZXMgaW5zZXJ0aW9uIHRvIHRoZSBhZGFwdGVyLCBhbmQgcmVoeWRyYXRlcyB0aGUgcGVyc2lzdGVkIHN0YXRlIGJhY2sgaW50byBhIE1vZGVsIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge019IG1vZGVsIFRoZSBtb2RlbCB0byBjcmVhdGUuXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgT3B0aW9uYWwgYXJndW1lbnRzL2NvbnRleHQuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IFRoZSBjcmVhdGVkIG1vZGVsIGluc3RhbmNlLlxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgY3JlYXRlKG1vZGVsOiBNLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TT4ge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBwcmVmZXItY29uc3RcbiAgICBsZXQgeyByZWNvcmQsIGlkLCB0cmFuc2llbnQgfSA9IHRoaXMuYWRhcHRlci5wcmVwYXJlKG1vZGVsLCB0aGlzLnBrKTtcbiAgICByZWNvcmQgPSBhd2FpdCB0aGlzLmFkYXB0ZXIuY3JlYXRlKFxuICAgICAgKHRoaXMuY2xhc3MgYXMgYW55KVtNb2RlbEtleXMuQU5DSE9SXSBhcyBhbnksXG4gICAgICBpZCxcbiAgICAgIG1vZGVsIGFzIGFueSxcbiAgICAgIC4uLmFyZ3NcbiAgICApO1xuICAgIGxldCBjOiBDb250ZXh0PFR5cGVPUk1GbGFncz4gfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gICAgaWYgKGFyZ3MubGVuZ3RoKSBjID0gYXJnc1thcmdzLmxlbmd0aCAtIDFdIGFzIENvbnRleHQ8VHlwZU9STUZsYWdzPjtcbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyLnJldmVydDxNPihcbiAgICAgIHJlY29yZCxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICB0aGlzLnBrLFxuICAgICAgaWQsXG4gICAgICBjICYmIGMuZ2V0KFwicmVidWlsZFdpdGhUcmFuc2llbnRcIikgPyB0cmFuc2llbnQgOiB1bmRlZmluZWRcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWFkcyBhIG1vZGVsIGZyb20gdGhlIGRhdGFiYXNlIGJ5IElELlxuICAgKiBAc3VtbWFyeSBSZXRyaWV2ZXMgYSBtb2RlbCBpbnN0YW5jZSBmcm9tIHRoZSBkYXRhYmFzZSB1c2luZyBpdHMgcHJpbWFyeSBrZXkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcnxiaWdpbnR9IGlkIC0gVGhlIHByaW1hcnkga2V5IG9mIHRoZSBtb2RlbCB0byByZWFkLlxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IFRoZSByZXRyaWV2ZWQgbW9kZWwgaW5zdGFuY2UuXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyByZWFkKFxuICAgIGlkOiBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQsXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8TT4ge1xuICAgIGNvbnN0IG0gPSBhd2FpdCB0aGlzLmFkYXB0ZXIucmVhZChcbiAgICAgICh0aGlzLmNsYXNzIGFzIGFueSlbTW9kZWxLZXlzLkFOQ0hPUl0gYXMgYW55LFxuICAgICAgaWQgYXMgc3RyaW5nLFxuICAgICAgdGhpcy5wayBhcyBzdHJpbmdcbiAgICApO1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmV2ZXJ0PE0+KG0sIHRoaXMuY2xhc3MsIHRoaXMucGssIGlkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVXBkYXRlcyBhbmQgcGVyc2lzdHMgYSBtb2RlbCBpbnN0YW5jZS5cbiAgICogQHN1bW1hcnkgUHJlcGFyZXMgdGhlIG1vZGVsLCBkZWxlZ2F0ZXMgdXBkYXRlIHRvIHRoZSBhZGFwdGVyLCBhbmQgcmVoeWRyYXRlcyB0aGUgcGVyc2lzdGVkIHN0YXRlIGJhY2sgaW50byBhIE1vZGVsIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge019IG1vZGVsIFRoZSBtb2RlbCB0byB1cGRhdGUuXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgT3B0aW9uYWwgYXJndW1lbnRzL2NvbnRleHQuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IFRoZSB1cGRhdGVkIG1vZGVsIGluc3RhbmNlLlxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgdXBkYXRlKG1vZGVsOiBNLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TT4ge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBwcmVmZXItY29uc3RcbiAgICBsZXQgeyByZWNvcmQsIGlkLCB0cmFuc2llbnQgfSA9IHRoaXMuYWRhcHRlci5wcmVwYXJlKG1vZGVsLCB0aGlzLnBrKTtcbiAgICByZWNvcmQgPSBhd2FpdCB0aGlzLmFkYXB0ZXIudXBkYXRlKFxuICAgICAgKHRoaXMuY2xhc3MgYXMgYW55KVtNb2RlbEtleXMuQU5DSE9SXSBhcyBhbnksXG4gICAgICBpZCxcbiAgICAgIG1vZGVsLFxuICAgICAgLi4uYXJnc1xuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5yZXZlcnQ8TT4ocmVjb3JkLCB0aGlzLmNsYXNzLCB0aGlzLnBrLCBpZCwgdHJhbnNpZW50KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRGVsZXRlcyBhIG1vZGVsIGZyb20gdGhlIGRhdGFiYXNlIGJ5IElELlxuICAgKiBAc3VtbWFyeSBSZW1vdmVzIGEgbW9kZWwgaW5zdGFuY2UgZnJvbSB0aGUgZGF0YWJhc2UgdXNpbmcgaXRzIHByaW1hcnkga2V5LlxuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ8YmlnaW50fSBpZCAtIFRoZSBwcmltYXJ5IGtleSBvZiB0aGUgbW9kZWwgdG8gZGVsZXRlLlxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IFRoZSBkZWxldGVkIG1vZGVsIGluc3RhbmNlLlxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgZGVsZXRlKFxuICAgIGlkOiBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQsXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxNPiB7XG4gICAgY29uc3QgbSA9IGF3YWl0IHRoaXMuYWRhcHRlci5kZWxldGUoXG4gICAgICAodGhpcy5jbGFzcyBhcyBhbnkpW01vZGVsS2V5cy5BTkNIT1JdIGFzIGFueSxcbiAgICAgIGlkIGFzIHN0cmluZyxcbiAgICAgIHRoaXMucGsgYXMgc3RyaW5nLFxuICAgICAgLi4uYXJnc1xuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5yZXZlcnQ8TT4obSwgdGhpcy5jbGFzcywgdGhpcy5waywgaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBWYWxpZGF0ZXMgYW5kIHByZXBhcmVzIG1vZGVscyBmb3IgYnVsayBjcmVhdGlvbi5cbiAgICogQHN1bW1hcnkgQXBwbGllcyBkZWNvcmF0b3ItYmFzZWQgdmFsaWRhdGlvbnMgYW5kIHJldHVybnMgdHJhbnNmb3JtZWQgbW9kZWxzIHdpdGggY29udGV4dCBhcmdzIGZvciBjcmVhdGVBbGwuXG4gICAqIEBwYXJhbSB7TVtdfSBtb2RlbHMgVGhlIG1vZGVscyB0byBiZSBjcmVhdGVkLlxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIE9wdGlvbmFsIGFyZ3VtZW50cy9jb250ZXh0LlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFtNW10sIC4uLmFueVtdXT59IFRoZSBwcmVwYXJlZCBtb2RlbHMgYW5kIGZvcndhcmRlZCBhcmdzIHR1cGxlLlxuICAgKi9cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFzeW5jIGNyZWF0ZUFsbFByZWZpeChtb2RlbHM6IE1bXSwgLi4uYXJnczogYW55W10pIHtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJncyhcbiAgICAgIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIGFyZ3MsXG4gICAgICB0aGlzLmFkYXB0ZXIsXG4gICAgICB0aGlzLl9vdmVycmlkZXMgfHwge31cbiAgICApO1xuICAgIGlmICghbW9kZWxzLmxlbmd0aCkgcmV0dXJuIFttb2RlbHMsIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuXG4gICAgbW9kZWxzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBtb2RlbHMubWFwKGFzeW5jIChtKSA9PiB7XG4gICAgICAgIG0gPSBuZXcgdGhpcy5jbGFzcyhtKTtcbiAgICAgICAgYXdhaXQgZW5mb3JjZURCRGVjb3JhdG9ycyhcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICAgICAgbSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLk9OXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBtO1xuICAgICAgfSlcbiAgICApO1xuICAgIGNvbnN0IGVycm9ycyA9IG1vZGVsc1xuICAgICAgLm1hcCgobSkgPT5cbiAgICAgICAgbS5oYXNFcnJvcnMoXG4gICAgICAgICAgLi4uKGNvbnRleHRBcmdzLmNvbnRleHQuZ2V0KFwiaWdub3JlZFZhbGlkYXRpb25Qcm9wZXJ0aWVzXCIpIHx8IFtdKVxuICAgICAgICApXG4gICAgICApXG4gICAgICAucmVkdWNlKChhY2N1bTogc3RyaW5nIHwgdW5kZWZpbmVkLCBlLCBpKSA9PiB7XG4gICAgICAgIGlmIChlKVxuICAgICAgICAgIGFjY3VtID1cbiAgICAgICAgICAgIHR5cGVvZiBhY2N1bSA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgICAgICA/IGFjY3VtICsgYFxcbiAtICR7aX06ICR7ZS50b1N0cmluZygpfWBcbiAgICAgICAgICAgICAgOiBgIC0gJHtpfTogJHtlLnRvU3RyaW5nKCl9YDtcbiAgICAgICAgcmV0dXJuIGFjY3VtO1xuICAgICAgfSwgdW5kZWZpbmVkKTtcbiAgICBpZiAoZXJyb3JzKSB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKGVycm9ycyk7XG4gICAgcmV0dXJuIFttb2RlbHMsIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIG11bHRpcGxlIG1vZGVscyBhdCBvbmNlLlxuICAgKiBAc3VtbWFyeSBQcmVwYXJlcywgcGVyc2lzdHMsIGFuZCByZWh5ZHJhdGVzIGEgYmF0Y2ggb2YgbW9kZWxzLlxuICAgKiBAcGFyYW0ge01bXX0gbW9kZWxzIFRoZSBtb2RlbHMgdG8gY3JlYXRlLlxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIE9wdGlvbmFsIGFyZ3VtZW50cy9jb250ZXh0LlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPE1bXT59IFRoZSBjcmVhdGVkIG1vZGVscy5cbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIGNyZWF0ZUFsbChtb2RlbHM6IE1bXSwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE1bXT4ge1xuICAgIGlmICghbW9kZWxzLmxlbmd0aCkgcmV0dXJuIG1vZGVscztcbiAgICBjb25zdCBwcmVwYXJlZCA9IG1vZGVscy5tYXAoKG0pID0+IHRoaXMuYWRhcHRlci5wcmVwYXJlKG0sIHRoaXMucGspKTtcbiAgICBjb25zdCBpZHMgPSBwcmVwYXJlZC5tYXAoKHApID0+IHAuaWQpO1xuICAgIGxldCByZWNvcmRzID0gcHJlcGFyZWQubWFwKChwKSA9PiBwLnJlY29yZCk7XG4gICAgcmVjb3JkcyA9IGF3YWl0IHRoaXMuYWRhcHRlci5jcmVhdGVBbGwoXG4gICAgICAodGhpcy5jbGFzcyBhcyBhbnkpW01vZGVsS2V5cy5BTkNIT1JdIGFzIGFueSxcbiAgICAgIGlkcyBhcyAoc3RyaW5nIHwgbnVtYmVyKVtdLFxuICAgICAgbW9kZWxzLFxuICAgICAgLi4uYXJnc1xuICAgICk7XG4gICAgcmV0dXJuIHJlY29yZHMubWFwKChyLCBpKSA9PlxuICAgICAgdGhpcy5hZGFwdGVyLnJldmVydChyLCB0aGlzLmNsYXNzLCB0aGlzLnBrLCBpZHNbaV0gYXMgc3RyaW5nIHwgbnVtYmVyKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlYWRzIG11bHRpcGxlIG1vZGVscyBieSB0aGVpciBwcmltYXJ5IGtleXMuXG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyBhIGxpc3Qgb2YgbW9kZWxzIGNvcnJlc3BvbmRpbmcgdG8gdGhlIHByb3ZpZGVkIGtleXMuXG4gICAqIEBwYXJhbSB7KHN0cmluZ1tdfG51bWJlcltdKX0ga2V5cyBUaGUgcHJpbWFyeSBrZXlzIHRvIHJlYWQuXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgT3B0aW9uYWwgYXJndW1lbnRzL2NvbnRleHQuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gVGhlIHJldHJpZXZlZCBtb2RlbHMuXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyByZWFkQWxsKFxuICAgIGtleXM6IHN0cmluZ1tdIHwgbnVtYmVyW10sXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxNW10+IHtcbiAgICBjb25zdCByZWNvcmRzID0gYXdhaXQgdGhpcy5hZGFwdGVyLnJlYWRBbGwoXG4gICAgICAodGhpcy5jbGFzcyBhcyBhbnkpW01vZGVsS2V5cy5BTkNIT1JdIGFzIGFueSxcbiAgICAgIGtleXMsXG4gICAgICB0aGlzLnBrIGFzIHN0cmluZyxcbiAgICAgIC4uLmFyZ3NcbiAgICApO1xuICAgIHJldHVybiByZWNvcmRzLm1hcCgocjogUmVjb3JkPHN0cmluZywgYW55PiwgaTogbnVtYmVyKSA9PlxuICAgICAgdGhpcy5hZGFwdGVyLnJldmVydChyLCB0aGlzLmNsYXNzLCB0aGlzLnBrLCBrZXlzW2ldKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgbXVsdGlwbGUgbW9kZWxzIGF0IG9uY2UuXG4gICAqIEBzdW1tYXJ5IFBlcnNpc3RzIGEgYmF0Y2ggb2YgbW9kZWwgdXBkYXRlcyBhbmQgcmV0dXJucyB0aGVpciByZWh5ZHJhdGVkIGluc3RhbmNlcy5cbiAgICogQHBhcmFtIHtNW119IG1vZGVscyBUaGUgbW9kZWxzIHRvIHVwZGF0ZS5cbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyBPcHRpb25hbCBhcmd1bWVudHMvY29udGV4dC5cbiAgICogQHJldHVybiB7UHJvbWlzZTxNW10+fSBUaGUgdXBkYXRlZCBtb2RlbHMuXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyB1cGRhdGVBbGwobW9kZWxzOiBNW10sIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxNW10+IHtcbiAgICBjb25zdCByZWNvcmRzID0gbW9kZWxzLm1hcCgobSkgPT4gdGhpcy5hZGFwdGVyLnByZXBhcmUobSwgdGhpcy5waykpO1xuICAgIGNvbnN0IHVwZGF0ZWQgPSBhd2FpdCB0aGlzLmFkYXB0ZXIudXBkYXRlQWxsKFxuICAgICAgKHRoaXMuY2xhc3MgYXMgYW55KVtNb2RlbEtleXMuQU5DSE9SXSBhcyBhbnksXG4gICAgICByZWNvcmRzLm1hcCgocikgPT4gci5pZCksXG4gICAgICBtb2RlbHMsXG4gICAgICB0aGlzLnBrIGFzIHN0cmluZyxcbiAgICAgIC4uLmFyZ3NcbiAgICApO1xuICAgIHJldHVybiB1cGRhdGVkLm1hcCgodTogUmVjb3JkPHN0cmluZywgYW55PiwgaTogbnVtYmVyKSA9PlxuICAgICAgdGhpcy5hZGFwdGVyLnJldmVydCh1LCB0aGlzLmNsYXNzLCB0aGlzLnBrLCByZWNvcmRzW2ldLmlkKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERlbGV0ZXMgbXVsdGlwbGUgbW9kZWxzIGF0IG9uY2UuXG4gICAqIEBzdW1tYXJ5IFJlbW92ZXMgYSBsaXN0IG9mIG1vZGVscyBieSB0aGVpciBwcmltYXJ5IGtleXMgYW5kIHJldHVybnMgdGhlaXIgbGFzdCBwZXJzaXN0ZWQgc3RhdGVzLlxuICAgKiBAcGFyYW0geyhzdHJpbmdbXXxudW1iZXJbXSl9IGtleXMgVGhlIHByaW1hcnkga2V5cyB0byBkZWxldGUuXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgT3B0aW9uYWwgYXJndW1lbnRzL2NvbnRleHQuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gVGhlIGRlbGV0ZWQgbW9kZWxzLlxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgZGVsZXRlQWxsKFxuICAgIGtleXM6IHN0cmluZ1tdIHwgbnVtYmVyW10sXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxNW10+IHtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgdGhpcy5hZGFwdGVyLmRlbGV0ZUFsbChcbiAgICAgICh0aGlzLmNsYXNzIGFzIGFueSlbTW9kZWxLZXlzLkFOQ0hPUl0gYXMgYW55LFxuICAgICAga2V5cyxcbiAgICAgIHRoaXMucGsgYXMgc3RyaW5nLFxuICAgICAgLi4uYXJnc1xuICAgICk7XG4gICAgcmV0dXJuIHJlc3VsdHMubWFwKChyOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBpOiBudW1iZXIpID0+XG4gICAgICB0aGlzLmFkYXB0ZXIucmV2ZXJ0KHIsIHRoaXMuY2xhc3MsIHRoaXMucGssIGtleXNbaV0pXG4gICAgKTtcbiAgfVxufVxuIiwiaW1wb3J0IHtcbiAgRW50aXR5U3Vic2NyaWJlckludGVyZmFjZSxcbiAgRXZlbnRTdWJzY3JpYmVyLFxuICBJbnNlcnRFdmVudCxcbiAgUmVtb3ZlRXZlbnQsXG4gIFVwZGF0ZUV2ZW50LFxufSBmcm9tIFwidHlwZW9ybVwiO1xuaW1wb3J0IHsgRXZlbnRJZHMsIFJlcG9zaXRvcnkgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IEludGVybmFsRXJyb3IsIE9wZXJhdGlvbktleXMgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBUeXBlT1JNIGV2ZW50IHN1YnNjcmliZXIgdGhhdCBmb3J3YXJkcyBlbnRpdHkgbGlmZWN5Y2xlIGV2ZW50cyB0byB0aGUgYWRhcHRlci5cbiAqIEBzdW1tYXJ5IExpc3RlbnMgZm9yIGluc2VydCwgdXBkYXRlLCBhbmQgcmVtb3ZlIGV2ZW50cyBlbWl0dGVkIGJ5IFR5cGVPUk0gYW5kIG5vdGlmaWVzIHRoZSBEZWNhZi50cyBhZGFwdGVyIHNvIHRoYXQgb2JzZXJ2ZXJzIGNhbiBiZSB1cGRhdGVkIGFjY29yZGluZ2x5LlxuICogQHBhcmFtIHtUeXBlT1JNQWRhcHRlcn0gYWRhcHRlciBUaGUgVHlwZU9STSBhZGFwdGVyIHVzZWQgdG8gcHJvcGFnYXRlIGV2ZW50cyBhbmQgbG9vayB1cCBtZXRhZGF0YS5cbiAqIEBjbGFzc1xuICogQGV4YW1wbGVcbiAqIC8vIFJlZ2lzdGVyaW5nIHRoZSBzdWJzY3JpYmVyIHdoZW4gY3JlYXRpbmcgYSBEYXRhU291cmNlXG4gKiAvLyBkYXRhU291cmNlT3B0aW9ucy5zdWJzY3JpYmVycyA9IFtuZXcgVHlwZU9STUV2ZW50U3Vic2NyaWJlcihhZGFwdGVyKV07XG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBUeXBlT1JNXG4gKiAgIHBhcnRpY2lwYW50IFN1YnNjcmliZXIgYXMgVHlwZU9STUV2ZW50U3Vic2NyaWJlclxuICogICBwYXJ0aWNpcGFudCBBZGFwdGVyIGFzIFR5cGVPUk1BZGFwdGVyXG4gKiAgIHBhcnRpY2lwYW50IE9ic2VydmVyc1xuICpcbiAqICAgVHlwZU9STS0+PlN1YnNjcmliZXI6IGFmdGVySW5zZXJ0KGVudGl0eSlcbiAqICAgU3Vic2NyaWJlci0+PkFkYXB0ZXI6IHVwZGF0ZU9ic2VydmVycyh0YWJsZSwgQ1JFQVRFLCBbaWRdKVxuICogICBBZGFwdGVyLT4+T2JzZXJ2ZXJzOiBub3RpZnkodGFibGUsIENSRUFURSwgW2lkXSlcbiAqXG4gKiAgIFR5cGVPUk0tPj5TdWJzY3JpYmVyOiBhZnRlclVwZGF0ZShldmVudClcbiAqICAgU3Vic2NyaWJlci0+PkFkYXB0ZXI6IHVwZGF0ZU9ic2VydmVycyh0YWJsZSwgVVBEQVRFLCBbaWRdKVxuICogICBBZGFwdGVyLT4+T2JzZXJ2ZXJzOiBub3RpZnkodGFibGUsIFVQREFURSwgW2lkXSlcbiAqXG4gKiAgIFR5cGVPUk0tPj5TdWJzY3JpYmVyOiBhZnRlclJlbW92ZShldmVudClcbiAqICAgU3Vic2NyaWJlci0+PkFkYXB0ZXI6IHVwZGF0ZU9ic2VydmVycyh0YWJsZSwgREVMRVRFLCBbaWRdKVxuICogICBBZGFwdGVyLT4+T2JzZXJ2ZXJzOiBub3RpZnkodGFibGUsIERFTEVURSwgW2lkXSlcbiAqL1xuQEV2ZW50U3Vic2NyaWJlcigpXG5leHBvcnQgY2xhc3MgVHlwZU9STUV2ZW50U3Vic2NyaWJlciBpbXBsZW1lbnRzIEVudGl0eVN1YnNjcmliZXJJbnRlcmZhY2Uge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgaGFuZGxlcjogKFxuICAgICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgICBvcGVyYXRpb246IE9wZXJhdGlvbktleXMsXG4gICAgICBpZHM6IEV2ZW50SWRzXG4gICAgKSA9PiB2b2lkXG4gICkge31cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEhhbmRsZXMgcG9zdC1pbnNlcnQgZXZlbnRzLlxuICAgKiBAc3VtbWFyeSBOb3RpZmllcyBvYnNlcnZlcnMgYWJvdXQgYSBjcmVhdGUgb3BlcmF0aW9uIGZvciB0aGUgaW5zZXJ0ZWQgZW50aXR5LlxuICAgKiBAcGFyYW0ge0luc2VydEV2ZW50PGFueT59IGV2ZW50IFRoZSBUeXBlT1JNIGluc2VydCBldmVudC5cbiAgICogQHJldHVybiB7UHJvbWlzZTxhbnk+fHZvaWR9IEEgcHJvbWlzZSB3aGVuIGFzeW5jIG9yIHZvaWQgb3RoZXJ3aXNlLlxuICAgKi9cbiAgYWZ0ZXJJbnNlcnQoZXZlbnQ6IEluc2VydEV2ZW50PGFueT4pOiBQcm9taXNlPGFueT4gfCB2b2lkIHtcbiAgICBjb25zdCBjb25zdHJ1Y3RvciA9IE1vZGVsLmdldChldmVudC5lbnRpdHkuY29uc3RydWN0b3IubmFtZSk7XG4gICAgaWYgKCFjb25zdHJ1Y3RvcilcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICBgTm8gcmVnaXN0ZXJlZCBtb2RlbCBmb3VuZCBmb3IgJHtldmVudC5lbnRpdHkuY29uc3RydWN0b3IubmFtZX1gXG4gICAgICApO1xuICAgIGNvbnN0IHRhYmxlTmFtZSA9IFJlcG9zaXRvcnkudGFibGUoY29uc3RydWN0b3IpO1xuXG4gICAgdGhpcy5oYW5kbGVyKHRhYmxlTmFtZSwgT3BlcmF0aW9uS2V5cy5DUkVBVEUsIFtldmVudC5lbnRpdHlJZCBhcyBhbnldKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBwb3N0LXJlbW92ZSBldmVudHMuXG4gICAqIEBzdW1tYXJ5IE5vdGlmaWVzIG9ic2VydmVycyBhYm91dCBhIGRlbGV0ZSBvcGVyYXRpb24gZm9yIHRoZSByZW1vdmVkIGVudGl0eS5cbiAgICogQHBhcmFtIHtSZW1vdmVFdmVudDxhbnk+fSBldmVudCBUaGUgVHlwZU9STSByZW1vdmUgZXZlbnQuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8YW55Pnx2b2lkfSBBIHByb21pc2Ugd2hlbiBhc3luYyBvciB2b2lkIG90aGVyd2lzZS5cbiAgICovXG4gIGFmdGVyUmVtb3ZlKGV2ZW50OiBSZW1vdmVFdmVudDxhbnk+KTogUHJvbWlzZTxhbnk+IHwgdm9pZCB7XG4gICAgY29uc3QgY29uc3RydWN0b3IgPSBNb2RlbC5nZXQoZXZlbnQuZW50aXR5LmNvbnN0cnVjdG9yLm5hbWUpO1xuICAgIGlmICghY29uc3RydWN0b3IpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgYE5vIHJlZ2lzdGVyZWQgbW9kZWwgZm91bmQgZm9yICR7ZXZlbnQuZW50aXR5LmNvbnN0cnVjdG9yLm5hbWV9YFxuICAgICAgKTtcbiAgICBjb25zdCB0YWJsZU5hbWUgPSBSZXBvc2l0b3J5LnRhYmxlKGNvbnN0cnVjdG9yKTtcblxuICAgIHRoaXMuaGFuZGxlcih0YWJsZU5hbWUsIE9wZXJhdGlvbktleXMuREVMRVRFLCBbZXZlbnQuZW50aXR5SWQgYXMgYW55XSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEhhbmRsZXMgcG9zdC11cGRhdGUgZXZlbnRzLlxuICAgKiBAc3VtbWFyeSBOb3RpZmllcyBvYnNlcnZlcnMgYWJvdXQgYW4gdXBkYXRlIG9wZXJhdGlvbiBmb3IgdGhlIG1vZGlmaWVkIGVudGl0eS5cbiAgICogQHBhcmFtIHtVcGRhdGVFdmVudDxhbnk+fSBldmVudCBUaGUgVHlwZU9STSB1cGRhdGUgZXZlbnQuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8YW55Pnx2b2lkfSBBIHByb21pc2Ugd2hlbiBhc3luYyBvciB2b2lkIG90aGVyd2lzZS5cbiAgICovXG4gIGFmdGVyVXBkYXRlKGV2ZW50OiBVcGRhdGVFdmVudDxhbnk+KTogUHJvbWlzZTxhbnk+IHwgdm9pZCB7XG4gICAgY29uc3QgY29uc3RydWN0b3IgPSBNb2RlbC5nZXQoZXZlbnQuZGF0YWJhc2VFbnRpdHkuY29uc3RydWN0b3IubmFtZSk7XG4gICAgaWYgKCFjb25zdHJ1Y3RvcilcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICBgTm8gcmVnaXN0ZXJlZCBtb2RlbCBmb3VuZCBmb3IgJHtldmVudC5kYXRhYmFzZUVudGl0eS5jb25zdHJ1Y3Rvci5uYW1lfWBcbiAgICAgICk7XG4gICAgY29uc3QgdGFibGVOYW1lID0gUmVwb3NpdG9yeS50YWJsZShjb25zdHJ1Y3Rvcik7XG5cbiAgICByZXR1cm4gdGhpcy5oYW5kbGVyKHRhYmxlTmFtZSwgT3BlcmF0aW9uS2V5cy5VUERBVEUsIFtcbiAgICAgIChldmVudC5lbnRpdHkgYXMgYW55KVtcImlkXCJdIGFzIGFueSxcbiAgICBdKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgRGlzcGF0Y2gsIEV2ZW50SWRzIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBJbnRlcm5hbEVycm9yLCBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBEYXRhU291cmNlT3B0aW9ucyB9IGZyb20gXCJ0eXBlb3JtL2RhdGEtc291cmNlL0RhdGFTb3VyY2VPcHRpb25zXCI7XG5pbXBvcnQgeyBUeXBlT1JNQWRhcHRlciB9IGZyb20gXCIuL1R5cGVPUk1BZGFwdGVyXCI7XG5pbXBvcnQgeyBUeXBlT1JNRXZlbnRTdWJzY3JpYmVyIH0gZnJvbSBcIi4vVHlwZU9STUV2ZW50U3Vic2NyaWJlclwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEaXNwYXRjaGVyIGZvciBUeXBlT1JNLWRyaXZlbiBjaGFuZ2UgZXZlbnRzLlxuICogQHN1bW1hcnkgU3Vic2NyaWJlcyBhIFR5cGVPUk0gRGF0YVNvdXJjZSB3aXRoIGEgY3VzdG9tIEVudGl0eVN1YnNjcmliZXIgdG8gbm90aWZ5IG9ic2VydmVycyB3aGVuIHJlY29yZHMgYXJlIGNyZWF0ZWQsIHVwZGF0ZWQsIG9yIGRlbGV0ZWQuXG4gKiBAcGFyYW0ge251bWJlcn0gW3RpbWVvdXQ9NTAwMF0gVGltZW91dCBpbiBtaWxsaXNlY29uZHMgZm9yIGluaXRpYWxpemF0aW9uIHJldHJpZXMuXG4gKiBAY2xhc3MgVHlwZU9STURpc3BhdGNoXG4gKiBAZXhhbXBsZVxuICogLy8gQ3JlYXRlIGEgZGlzcGF0Y2hlciBmb3IgYSBUeXBlT1JNIERhdGFTb3VyY2VcbiAqIGNvbnN0IGRpc3BhdGNoID0gbmV3IFR5cGVPUk1EaXNwYXRjaCgpO1xuICogYXdhaXQgZGlzcGF0Y2gub2JzZXJ2ZShhZGFwdGVyLCBhZGFwdGVyLmRhdGFTb3VyY2Uub3B0aW9ucyk7XG4gKlxuICogLy8gVGhlIGRpc3BhdGNoZXIgcmVnaXN0ZXJzIGEgVHlwZU9STUV2ZW50U3Vic2NyaWJlciBhbmQgbm90aWZpZXMgb2JzZXJ2ZXJzIHdoZW4gZW50aXRpZXMgY2hhbmdlLlxuICogQG1lcm1haWRcbiAqIGNsYXNzRGlhZ3JhbVxuICogICBjbGFzcyBEaXNwYXRjaCB7XG4gKiAgICAgK2luaXRpYWxpemUoKVxuICogICAgICt1cGRhdGVPYnNlcnZlcnMoKVxuICogICB9XG4gKiAgIGNsYXNzIFR5cGVPUk1EaXNwYXRjaCB7XG4gKiAgICAgLW9ic2VydmVyTGFzdFVwZGF0ZT86IHN0cmluZ1xuICogICAgIC1hdHRlbXB0Q291bnRlcjogbnVtYmVyXG4gKiAgICAgLXRpbWVvdXQ6IG51bWJlclxuICogICAgICtjb25zdHJ1Y3Rvcih0aW1lb3V0KVxuICogICAgICNub3RpZmljYXRpb25IYW5kbGVyKClcbiAqICAgICAjaW5pdGlhbGl6ZSgpXG4gKiAgIH1cbiAqICAgRGlzcGF0Y2ggPHwtLSBUeXBlT1JNRGlzcGF0Y2hcbiAqL1xuZXhwb3J0IGNsYXNzIFR5cGVPUk1EaXNwYXRjaCBleHRlbmRzIERpc3BhdGNoPERhdGFTb3VyY2VPcHRpb25zPiB7XG4gIHByaXZhdGUgb2JzZXJ2ZXJMYXN0VXBkYXRlPzogc3RyaW5nO1xuICBwcml2YXRlIGF0dGVtcHRDb3VudGVyOiBudW1iZXIgPSAwO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgdGltZW91dCA9IDUwMDApIHtcbiAgICBzdXBlcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcm9jZXNzZXMgVHlwZU9STSBub3RpZmljYXRpb24gZXZlbnRzLlxuICAgKiBAc3VtbWFyeSBIYW5kbGVzIGNoYW5nZSBub3RpZmljYXRpb25zICh0cmFuc2xhdGVkIGZyb20gVHlwZU9STSBldmVudHMpIGFuZCBub3RpZmllcyBvYnNlcnZlcnMgYWJvdXQgcmVjb3JkIGNoYW5nZXMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZSBUaGUgbm90aWZpY2F0aW9uIHBheWxvYWQuXG4gICAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5c30gb3BlcmF0aW9uIFRoZSBub3RpZmljYXRpb24gcGF5bG9hZC5cbiAgICogQHBhcmFtIHtFdmVudElkc30gaWRzIFRoZSBub3RpZmljYXRpb24gcGF5bG9hZC5cbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBhbGwgbm90aWZpY2F0aW9ucyBoYXZlIGJlZW4gcHJvY2Vzc2VkLlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBEIGFzIFBvc3RncmVTUUxEaXNwYXRjaFxuICAgKiAgIHBhcnRpY2lwYW50IEwgYXMgTG9nZ2VyXG4gICAqICAgcGFydGljaXBhbnQgTyBhcyBPYnNlcnZlcnNcbiAgICogICBOb3RlIG92ZXIgRDogUmVjZWl2ZSBub3RpZmljYXRpb24gZnJvbSBQb3N0Z3JlU1FMXG4gICAqICAgRC0+PkQ6IFBhcnNlIG5vdGlmaWNhdGlvbiBwYXlsb2FkXG4gICAqICAgRC0+PkQ6IEV4dHJhY3QgdGFibGUsIG9wZXJhdGlvbiwgYW5kIGlkc1xuICAgKiAgIEQtPj5POiB1cGRhdGVPYnNlcnZlcnModGFibGUsIG9wZXJhdGlvbiwgaWRzKVxuICAgKiAgIEQtPj5EOiBVcGRhdGUgb2JzZXJ2ZXJMYXN0VXBkYXRlXG4gICAqICAgRC0+Pkw6IExvZyBzdWNjZXNzZnVsIGRpc3BhdGNoXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgbm90aWZpY2F0aW9uSGFuZGxlcihcbiAgICB0YWJsZTogc3RyaW5nLFxuICAgIG9wZXJhdGlvbjogT3BlcmF0aW9uS2V5cyxcbiAgICBpZHM6IEV2ZW50SWRzXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLm5vdGlmaWNhdGlvbkhhbmRsZXIpO1xuICAgIHRyeSB7XG4gICAgICAvLyBOb3RpZnkgb2JzZXJ2ZXJzXG4gICAgICBhd2FpdCB0aGlzLnVwZGF0ZU9ic2VydmVycyh0YWJsZSwgb3BlcmF0aW9uLCBpZHMpO1xuICAgICAgdGhpcy5vYnNlcnZlckxhc3RVcGRhdGUgPSBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCk7XG4gICAgICBsb2cudmVyYm9zZShgT2JzZXJ2ZXIgcmVmcmVzaCBkaXNwYXRjaGVkIGJ5ICR7b3BlcmF0aW9ufSBmb3IgJHt0YWJsZX1gKTtcbiAgICAgIGxvZy5kZWJ1ZyhgcGtzOiAke2lkc31gKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICBsb2cuZXJyb3IoYEZhaWxlZCB0byBwcm9jZXNzIG5vdGlmaWNhdGlvbjogJHtlfWApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSW5pdGlhbGl6ZXMgdGhlIGRpc3BhdGNoZXIgYW5kIHN1YnNjcmliZXMgdG8gVHlwZU9STSBub3RpZmljYXRpb25zLlxuICAgKiBAc3VtbWFyeSBSZWdpc3RlcnMgdGhlIFR5cGVPUk1FdmVudFN1YnNjcmliZXIgb24gdGhlIERhdGFTb3VyY2UgYW5kIGxvZ3MgdGhlIHN1YnNjcmlwdGlvbiBsaWZlY3ljbGUuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIHN1YnNjcmlwdGlvbiBpcyBlc3RhYmxpc2hlZC5cbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgRCBhcyBUeXBlT1JNRGlzcGF0Y2hcbiAgICogICBwYXJ0aWNpcGFudCBTIGFzIHN1YnNjcmliZVRvVHlwZU9STVxuICAgKiAgIHBhcnRpY2lwYW50IERTIGFzIFR5cGVPUk0gRGF0YVNvdXJjZVxuICAgKiAgIHBhcnRpY2lwYW50IEwgYXMgTG9nZ2VyXG4gICAqICAgRC0+PlM6IENhbGwgc3Vic2NyaWJlVG9UeXBlT1JNXG4gICAqICAgUy0+PlM6IENoZWNrIGFkYXB0ZXIgYW5kIG5hdGl2ZVxuICAgKiAgIGFsdCBObyBhZGFwdGVyIG9yIG5hdGl2ZVxuICAgKiAgICAgUy0tPj5TOiB0aHJvdyBJbnRlcm5hbEVycm9yXG4gICAqICAgZW5kXG4gICAqICAgUy0+PkRTOiBpbml0aWFsaXplKClcbiAgICogICBTLT4+RFM6IHN1YnNjcmliZXJzLnB1c2goVHlwZU9STUV2ZW50U3Vic2NyaWJlcilcbiAgICogICBhbHQgU3VjY2Vzc1xuICAgKiAgICAgRFMtLT4+UzogU3Vic2NyaXB0aW9uIGVzdGFibGlzaGVkXG4gICAqICAgICBTLS0+PkQ6IFByb21pc2UgcmVzb2x2ZXNcbiAgICogICAgIEQtPj5MOiBMb2cgc3VjY2Vzc2Z1bCBzdWJzY3JpcHRpb25cbiAgICogICBlbHNlIEVycm9yXG4gICAqICAgICBEUy0tPj5TOiBFcnJvclxuICAgKiAgICAgUy0tPj5EOiBQcm9taXNlIHJlamVjdHNcbiAgICogICBlbmRcbiAgICovXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyBpbml0aWFsaXplKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGFzeW5jIGZ1bmN0aW9uIHN1YnNjcmliZVRvVHlwZU9STSh0aGlzOiBUeXBlT1JNRGlzcGF0Y2gpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGlmICghdGhpcy5hZGFwdGVyIHx8ICF0aGlzLm5hdGl2ZSkge1xuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgTm8gYWRhcHRlci9uYXRpdmUgb2JzZXJ2ZWQgZm9yIGRpc3BhdGNoYCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGFkYXB0ZXIgPSB0aGlzLmFkYXB0ZXIgYXMgVHlwZU9STUFkYXB0ZXI7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGlmICghYWRhcHRlci5kYXRhU291cmNlLmlzSW5pdGlhbGl6ZWQpXG4gICAgICAgICAgYXdhaXQgYWRhcHRlci5kYXRhU291cmNlLmluaXRpYWxpemUoKTtcblxuICAgICAgICBhZGFwdGVyLmRhdGFTb3VyY2Uuc3Vic2NyaWJlcnMucHVzaChcbiAgICAgICAgICBuZXcgVHlwZU9STUV2ZW50U3Vic2NyaWJlcih0aGlzLm5vdGlmaWNhdGlvbkhhbmRsZXIuYmluZCh0aGlzKSlcbiAgICAgICAgKTtcbiAgICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgc3Vic2NyaWJlVG9UeXBlT1JNXG4gICAgICAuY2FsbCh0aGlzKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLmxvZy5pbmZvKGBTdWJzY3JpYmVkIHRvIFR5cGVPUk0gbm90aWZpY2F0aW9uc2ApO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZTogdW5rbm93bikgPT4ge1xuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICBgRmFpbGVkIHRvIHN1YnNjcmliZSB0byBUeXBlT1JNIG5vdGlmaWNhdGlvbnM6ICR7ZX1gXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhbnVwIG1ldGhvZCB0byByZWxlYXNlIHJlc291cmNlcyB3aGVuIHRoZSBkaXNwYXRjaGVyIGlzIG5vIGxvbmdlciBuZWVkZWRcbiAgICovXG4gIHB1YmxpYyBjbGVhbnVwKCk6IHZvaWQge1xuICAgIC8vIGlmICh0aGlzLmFkYXB0ZXIpIHtcbiAgICAvL1xuICAgIC8vICAgY29uc3QgYWRhcHRlciA9IHRoaXMuYWRhcHRlciBhcyBUeXBlT1JNQWRhcHRlcjtcbiAgICAvLyAgIGF3YWl0IGFkYXB0ZXIuZGF0YVNvdXJjZS5kZXN0cm95KCk7XG4gICAgLy8gfVxuICB9XG59XG4iLCIvKipcbiAqIEBkZXNjcmlwdGlvbiBDb252ZXJ0cyBhIEphdmFTY3JpcHQgUmVnRXhwIHBhdHRlcm4gdG8gYSBQb3N0Z3JlU1FMIFBPU0lYIHBhdHRlcm4gc3RyaW5nLlxuICogQHN1bW1hcnkgQWNjZXB0cyBlaXRoZXIgYSBSZWdFeHAgb2JqZWN0IG9yIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uICgvcGF0dGVybi9mbGFncykgYW5kIHJldHVybnMgdGhlIHJhdyBwYXR0ZXJuIGNvbXBhdGlibGUgd2l0aCBQb3N0Z3JlU1FMJ3MgfiBhbmQgfiogb3BlcmF0b3JzLlxuICogQHBhcmFtIHtSZWdFeHB8c3RyaW5nfSBqc1JlZ2V4IEphdmFTY3JpcHQgUmVnRXhwIG9iamVjdCBvciBwYXR0ZXJuIHN0cmluZy5cbiAqIEByZXR1cm4ge3N0cmluZ30gUG9zdGdyZVNRTC1jb21wYXRpYmxlIHJlZ2V4IHBhdHRlcm4gc3RyaW5nLlxuICogQGZ1bmN0aW9uIGNvbnZlcnRKc1JlZ2V4VG9Qb3N0Z3Jlc1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBBcHBcbiAqICAgcGFydGljaXBhbnQgVXRpbHMgYXMgY29udmVydEpzUmVnZXhUb1Bvc3RncmVzXG4gKiAgIEFwcC0+PlV0aWxzOiBjb252ZXJ0SnNSZWdleFRvUG9zdGdyZXMoUmVnRXhwKFwiZm9vLipcIixcImlcIikpXG4gKiAgIFV0aWxzLT4+VXRpbHM6IFBhcnNlIHN0cmluZyBvciB1c2UgUmVnRXhwLnNvdXJjZVxuICogICBVdGlscy0tPj5BcHA6IFwiZm9vLipcIlxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItdHlwZW9ybVxuICovXG5leHBvcnQgZnVuY3Rpb24gY29udmVydEpzUmVnZXhUb1Bvc3RncmVzKGpzUmVnZXg6IFJlZ0V4cCB8IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHJ4cCA9IG5ldyBSZWdFeHAoL15cXC8oLispXFwvKFxcdyspJC9nKTtcbiAgaWYgKHR5cGVvZiBqc1JlZ2V4ID09PSBcInN0cmluZ1wiKSB7XG4gICAgY29uc3QgbWF0Y2ggPSByeHAuZXhlYyhqc1JlZ2V4KTtcbiAgICBpZiAobWF0Y2gpIHtcbiAgICAgIGNvbnN0IFssIHBdID0gbWF0Y2g7XG4gICAgICBqc1JlZ2V4ID0gcDtcbiAgICB9XG4gIH1cbiAgY29uc3QgcmVnZXggPSB0eXBlb2YganNSZWdleCA9PT0gXCJzdHJpbmdcIiA/IG5ldyBSZWdFeHAoanNSZWdleCkgOiBqc1JlZ2V4O1xuXG4gIGNvbnN0IHBhdHRlcm4gPSByZWdleC5zb3VyY2U7XG5cbiAgcmV0dXJuIHBhdHRlcm47XG59XG4iLCJpbXBvcnQgeyBDb2x1bW5NZXRhZGF0YUFyZ3MgfSBmcm9tIFwidHlwZW9ybS9tZXRhZGF0YS1hcmdzL0NvbHVtbk1ldGFkYXRhQXJnc1wiO1xuXG5leHBvcnQgZnVuY3Rpb24gYWdncmVnYXRlT3JOZXdDb2x1bW4oXG4gIHRhcmdldDogYW55LFxuICBwcm9wZXJ0eTogc3RyaW5nLFxuICBjb2x1bW5zOiBDb2x1bW5NZXRhZGF0YUFyZ3NbXSxcbiAgb3B0aW9uczogYW55ID0ge30sXG4gIG1vZGU6IHN0cmluZyA9IFwicmVndWxhclwiXG4pIHtcbiAgY29uc3QgY29scyA9IGNvbHVtbnMuZmlsdGVyKFxuICAgIChjOiBDb2x1bW5NZXRhZGF0YUFyZ3MpID0+XG4gICAgICBjLnRhcmdldCA9PT0gdGFyZ2V0ICYmIGMucHJvcGVydHlOYW1lID09PSBwcm9wZXJ0eVxuICApO1xuXG4gIGlmIChjb2xzLmxlbmd0aCA+IDEpXG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYE11bHRpcGxlIGNvbHVtbnMgZm9yICR7cHJvcGVydHl9IGZvdW5kIGZvciBnaXZlbiB0YXJnZXQ6ICR7Y29sdW1ucy5tYXAoKGMpID0+IGMucHJvcGVydHlOYW1lKS5qb2luKFwiLCBcIil9YFxuICAgICk7XG5cbiAgaWYgKGNvbHMubGVuZ3RoID09PSAwKSB7XG4gICAgY29sdW1ucy5wdXNoKHtcbiAgICAgIHRhcmdldDogdGFyZ2V0LFxuICAgICAgcHJvcGVydHlOYW1lOiBwcm9wZXJ0eSxcbiAgICAgIG1vZGU6IG1vZGUsXG4gICAgICBvcHRpb25zOiBvcHRpb25zLFxuICAgIH0gYXMgQ29sdW1uTWV0YWRhdGFBcmdzKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBjb2x1bW4gPSBjb2xzWzBdO1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoY29sdW1uLCBcIm9wdGlvbnNcIiwge1xuICAgIHZhbHVlOiB7IC4uLmNvbHVtbi5vcHRpb25zLCAuLi5vcHRpb25zIH0sXG4gICAgd3JpdGFibGU6IHRydWUsXG4gICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICBjb25maWd1cmFibGU6IHRydWUsXG4gIH0pO1xuXG4gIGlmIChtb2RlICE9PSBcInJlZ3VsYXJcIilcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoY29sdW1uLCBcIm1vZGVcIiwge1xuICAgICAgdmFsdWU6IG1vZGUsXG4gICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgfSk7XG59XG4iLCJpbXBvcnQgeyBHZW5lcmF0ZWRNZXRhZGF0YUFyZ3MgfSBmcm9tIFwidHlwZW9ybS9tZXRhZGF0YS1hcmdzL0dlbmVyYXRlZE1ldGFkYXRhQXJnc1wiO1xuaW1wb3J0IHtcbiAgQ29sdW1uT3B0aW9ucyxcbiAgQ29sdW1uVHlwZSxcbiAgQ29sdW1uVHlwZVVuZGVmaW5lZEVycm9yLFxuICBnZXRNZXRhZGF0YUFyZ3NTdG9yYWdlLFxufSBmcm9tIFwidHlwZW9ybVwiO1xuaW1wb3J0IHtcbiAgU2ltcGxlQ29sdW1uVHlwZSxcbiAgU3BhdGlhbENvbHVtblR5cGUsXG4gIFdpdGhMZW5ndGhDb2x1bW5UeXBlLFxuICBXaXRoUHJlY2lzaW9uQ29sdW1uVHlwZSxcbiAgV2l0aFdpZHRoQ29sdW1uVHlwZSxcbn0gZnJvbSBcInR5cGVvcm0vZHJpdmVyL3R5cGVzL0NvbHVtblR5cGVzXCI7XG5pbXBvcnQgeyBDb2x1bW5Db21tb25PcHRpb25zIH0gZnJvbSBcInR5cGVvcm0vZGVjb3JhdG9yL29wdGlvbnMvQ29sdW1uQ29tbW9uT3B0aW9uc1wiO1xuaW1wb3J0IHsgU3BhdGlhbENvbHVtbk9wdGlvbnMgfSBmcm9tIFwidHlwZW9ybS9kZWNvcmF0b3Ivb3B0aW9ucy9TcGF0aWFsQ29sdW1uT3B0aW9uc1wiO1xuaW1wb3J0IHsgQ29sdW1uV2l0aExlbmd0aE9wdGlvbnMgfSBmcm9tIFwidHlwZW9ybS9kZWNvcmF0b3Ivb3B0aW9ucy9Db2x1bW5XaXRoTGVuZ3RoT3B0aW9uc1wiO1xuaW1wb3J0IHsgQ29sdW1uV2l0aFdpZHRoT3B0aW9ucyB9IGZyb20gXCJ0eXBlb3JtL2RlY29yYXRvci9vcHRpb25zL0NvbHVtbldpdGhXaWR0aE9wdGlvbnNcIjtcbmltcG9ydCB7IENvbHVtbk51bWVyaWNPcHRpb25zIH0gZnJvbSBcInR5cGVvcm0vZGVjb3JhdG9yL29wdGlvbnMvQ29sdW1uTnVtZXJpY09wdGlvbnNcIjtcbmltcG9ydCB7IENvbHVtbkVudW1PcHRpb25zIH0gZnJvbSBcInR5cGVvcm0vZGVjb3JhdG9yL29wdGlvbnMvQ29sdW1uRW51bU9wdGlvbnNcIjtcbmltcG9ydCB7IENvbHVtbkhzdG9yZU9wdGlvbnMgfSBmcm9tIFwidHlwZW9ybS9kZWNvcmF0b3Ivb3B0aW9ucy9Db2x1bW5Ic3RvcmVPcHRpb25zXCI7XG5pbXBvcnQgeyBDb2x1bW5FbWJlZGRlZE9wdGlvbnMgfSBmcm9tIFwidHlwZW9ybS9kZWNvcmF0b3Ivb3B0aW9ucy9Db2x1bW5FbWJlZGRlZE9wdGlvbnNcIjtcbmltcG9ydCB7IEVtYmVkZGVkTWV0YWRhdGFBcmdzIH0gZnJvbSBcInR5cGVvcm0vbWV0YWRhdGEtYXJncy9FbWJlZGRlZE1ldGFkYXRhQXJnc1wiO1xuaW1wb3J0IHsgQ29sdW1uTWV0YWRhdGFBcmdzIH0gZnJvbSBcInR5cGVvcm0vbWV0YWRhdGEtYXJncy9Db2x1bW5NZXRhZGF0YUFyZ3NcIjtcbmltcG9ydCB7IGFnZ3JlZ2F0ZU9yTmV3Q29sdW1uIH0gZnJvbSBcIi4vdXRpbHNcIjtcblxuLyoqXG4gKiBDb2x1bW4gZGVjb3JhdG9yIGlzIHVzZWQgdG8gbWFyayBhIHNwZWNpZmljIGNsYXNzIHByb3BlcnR5IGFzIGEgdGFibGUgY29sdW1uLiBPbmx5IHByb3BlcnRpZXMgZGVjb3JhdGVkIHdpdGggdGhpc1xuICogZGVjb3JhdG9yIHdpbGwgYmUgcGVyc2lzdGVkIHRvIHRoZSBkYXRhYmFzZSB3aGVuIGVudGl0eSBiZSBzYXZlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENvbHVtbigpOiBQcm9wZXJ0eURlY29yYXRvcjtcblxuLyoqXG4gKiBDb2x1bW4gZGVjb3JhdG9yIGlzIHVzZWQgdG8gbWFyayBhIHNwZWNpZmljIGNsYXNzIHByb3BlcnR5IGFzIGEgdGFibGUgY29sdW1uLlxuICogT25seSBwcm9wZXJ0aWVzIGRlY29yYXRlZCB3aXRoIHRoaXMgZGVjb3JhdG9yIHdpbGwgYmUgcGVyc2lzdGVkIHRvIHRoZSBkYXRhYmFzZSB3aGVuIGVudGl0eSBiZSBzYXZlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENvbHVtbihvcHRpb25zOiBDb2x1bW5PcHRpb25zKTogUHJvcGVydHlEZWNvcmF0b3I7XG5cbi8qKlxuICogQ29sdW1uIGRlY29yYXRvciBpcyB1c2VkIHRvIG1hcmsgYSBzcGVjaWZpYyBjbGFzcyBwcm9wZXJ0eSBhcyBhIHRhYmxlIGNvbHVtbi5cbiAqIE9ubHkgcHJvcGVydGllcyBkZWNvcmF0ZWQgd2l0aCB0aGlzIGRlY29yYXRvciB3aWxsIGJlIHBlcnNpc3RlZCB0byB0aGUgZGF0YWJhc2Ugd2hlbiBlbnRpdHkgYmUgc2F2ZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBDb2x1bW4oXG4gIHR5cGU6IFNpbXBsZUNvbHVtblR5cGUsXG4gIG9wdGlvbnM/OiBDb2x1bW5Db21tb25PcHRpb25zXG4pOiBQcm9wZXJ0eURlY29yYXRvcjtcblxuLyoqXG4gKiBDb2x1bW4gZGVjb3JhdG9yIGlzIHVzZWQgdG8gbWFyayBhIHNwZWNpZmljIGNsYXNzIHByb3BlcnR5IGFzIGEgdGFibGUgY29sdW1uLlxuICogT25seSBwcm9wZXJ0aWVzIGRlY29yYXRlZCB3aXRoIHRoaXMgZGVjb3JhdG9yIHdpbGwgYmUgcGVyc2lzdGVkIHRvIHRoZSBkYXRhYmFzZSB3aGVuIGVudGl0eSBiZSBzYXZlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENvbHVtbihcbiAgdHlwZTogU3BhdGlhbENvbHVtblR5cGUsXG4gIG9wdGlvbnM/OiBDb2x1bW5Db21tb25PcHRpb25zICYgU3BhdGlhbENvbHVtbk9wdGlvbnNcbik6IFByb3BlcnR5RGVjb3JhdG9yO1xuXG4vKipcbiAqIENvbHVtbiBkZWNvcmF0b3IgaXMgdXNlZCB0byBtYXJrIGEgc3BlY2lmaWMgY2xhc3MgcHJvcGVydHkgYXMgYSB0YWJsZSBjb2x1bW4uXG4gKiBPbmx5IHByb3BlcnRpZXMgZGVjb3JhdGVkIHdpdGggdGhpcyBkZWNvcmF0b3Igd2lsbCBiZSBwZXJzaXN0ZWQgdG8gdGhlIGRhdGFiYXNlIHdoZW4gZW50aXR5IGJlIHNhdmVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQ29sdW1uKFxuICB0eXBlOiBXaXRoTGVuZ3RoQ29sdW1uVHlwZSxcbiAgb3B0aW9ucz86IENvbHVtbkNvbW1vbk9wdGlvbnMgJiBDb2x1bW5XaXRoTGVuZ3RoT3B0aW9uc1xuKTogUHJvcGVydHlEZWNvcmF0b3I7XG5cbi8qKlxuICogQ29sdW1uIGRlY29yYXRvciBpcyB1c2VkIHRvIG1hcmsgYSBzcGVjaWZpYyBjbGFzcyBwcm9wZXJ0eSBhcyBhIHRhYmxlIGNvbHVtbi5cbiAqIE9ubHkgcHJvcGVydGllcyBkZWNvcmF0ZWQgd2l0aCB0aGlzIGRlY29yYXRvciB3aWxsIGJlIHBlcnNpc3RlZCB0byB0aGUgZGF0YWJhc2Ugd2hlbiBlbnRpdHkgYmUgc2F2ZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBDb2x1bW4oXG4gIHR5cGU6IFdpdGhXaWR0aENvbHVtblR5cGUsXG4gIG9wdGlvbnM/OiBDb2x1bW5Db21tb25PcHRpb25zICYgQ29sdW1uV2l0aFdpZHRoT3B0aW9uc1xuKTogUHJvcGVydHlEZWNvcmF0b3I7XG5cbi8qKlxuICogQ29sdW1uIGRlY29yYXRvciBpcyB1c2VkIHRvIG1hcmsgYSBzcGVjaWZpYyBjbGFzcyBwcm9wZXJ0eSBhcyBhIHRhYmxlIGNvbHVtbi5cbiAqIE9ubHkgcHJvcGVydGllcyBkZWNvcmF0ZWQgd2l0aCB0aGlzIGRlY29yYXRvciB3aWxsIGJlIHBlcnNpc3RlZCB0byB0aGUgZGF0YWJhc2Ugd2hlbiBlbnRpdHkgYmUgc2F2ZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBDb2x1bW4oXG4gIHR5cGU6IFdpdGhQcmVjaXNpb25Db2x1bW5UeXBlLFxuICBvcHRpb25zPzogQ29sdW1uQ29tbW9uT3B0aW9ucyAmIENvbHVtbk51bWVyaWNPcHRpb25zXG4pOiBQcm9wZXJ0eURlY29yYXRvcjtcblxuLyoqXG4gKiBDb2x1bW4gZGVjb3JhdG9yIGlzIHVzZWQgdG8gbWFyayBhIHNwZWNpZmljIGNsYXNzIHByb3BlcnR5IGFzIGEgdGFibGUgY29sdW1uLlxuICogT25seSBwcm9wZXJ0aWVzIGRlY29yYXRlZCB3aXRoIHRoaXMgZGVjb3JhdG9yIHdpbGwgYmUgcGVyc2lzdGVkIHRvIHRoZSBkYXRhYmFzZSB3aGVuIGVudGl0eSBiZSBzYXZlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENvbHVtbihcbiAgdHlwZTogXCJlbnVtXCIsXG4gIG9wdGlvbnM/OiBDb2x1bW5Db21tb25PcHRpb25zICYgQ29sdW1uRW51bU9wdGlvbnNcbik6IFByb3BlcnR5RGVjb3JhdG9yO1xuXG4vKipcbiAqIENvbHVtbiBkZWNvcmF0b3IgaXMgdXNlZCB0byBtYXJrIGEgc3BlY2lmaWMgY2xhc3MgcHJvcGVydHkgYXMgYSB0YWJsZSBjb2x1bW4uXG4gKiBPbmx5IHByb3BlcnRpZXMgZGVjb3JhdGVkIHdpdGggdGhpcyBkZWNvcmF0b3Igd2lsbCBiZSBwZXJzaXN0ZWQgdG8gdGhlIGRhdGFiYXNlIHdoZW4gZW50aXR5IGJlIHNhdmVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQ29sdW1uKFxuICB0eXBlOiBcInNpbXBsZS1lbnVtXCIsXG4gIG9wdGlvbnM/OiBDb2x1bW5Db21tb25PcHRpb25zICYgQ29sdW1uRW51bU9wdGlvbnNcbik6IFByb3BlcnR5RGVjb3JhdG9yO1xuXG4vKipcbiAqIENvbHVtbiBkZWNvcmF0b3IgaXMgdXNlZCB0byBtYXJrIGEgc3BlY2lmaWMgY2xhc3MgcHJvcGVydHkgYXMgYSB0YWJsZSBjb2x1bW4uXG4gKiBPbmx5IHByb3BlcnRpZXMgZGVjb3JhdGVkIHdpdGggdGhpcyBkZWNvcmF0b3Igd2lsbCBiZSBwZXJzaXN0ZWQgdG8gdGhlIGRhdGFiYXNlIHdoZW4gZW50aXR5IGJlIHNhdmVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQ29sdW1uKFxuICB0eXBlOiBcInNldFwiLFxuICBvcHRpb25zPzogQ29sdW1uQ29tbW9uT3B0aW9ucyAmIENvbHVtbkVudW1PcHRpb25zXG4pOiBQcm9wZXJ0eURlY29yYXRvcjtcblxuLyoqXG4gKiBDb2x1bW4gZGVjb3JhdG9yIGlzIHVzZWQgdG8gbWFyayBhIHNwZWNpZmljIGNsYXNzIHByb3BlcnR5IGFzIGEgdGFibGUgY29sdW1uLlxuICogT25seSBwcm9wZXJ0aWVzIGRlY29yYXRlZCB3aXRoIHRoaXMgZGVjb3JhdG9yIHdpbGwgYmUgcGVyc2lzdGVkIHRvIHRoZSBkYXRhYmFzZSB3aGVuIGVudGl0eSBiZSBzYXZlZC5cbiAqL1xuLy8gQHRzLWV4cGVjdC1lcnJvciBzb21lIHR5cGVvcm0gdGhpbmdcbmV4cG9ydCBmdW5jdGlvbiBDb2x1bW4oXG4gIHR5cGU6IFwiaHN0b3JlXCIsXG4gIG9wdGlvbnM/OiBDb2x1bW5Db21tb25PcHRpb25zICYgQ29sdW1uSHN0b3JlT3B0aW9uc1xuKTogUHJvcGVydHlEZWNvcmF0b3I7XG5cbi8qKlxuICogQ29sdW1uIGRlY29yYXRvciBpcyB1c2VkIHRvIG1hcmsgYSBzcGVjaWZpYyBjbGFzcyBwcm9wZXJ0eSBhcyBhIHRhYmxlIGNvbHVtbi5cbiAqIE9ubHkgcHJvcGVydGllcyBkZWNvcmF0ZWQgd2l0aCB0aGlzIGRlY29yYXRvciB3aWxsIGJlIHBlcnNpc3RlZCB0byB0aGUgZGF0YWJhc2Ugd2hlbiBlbnRpdHkgYmUgc2F2ZWQuXG4gKlxuICogUHJvcGVydHkgaW4gZW50aXR5IGNhbiBiZSBtYXJrZWQgYXMgRW1iZWRkZWQsIGFuZCBvbiBwZXJzaXN0IGFsbCBjb2x1bW5zIGZyb20gdGhlIGVtYmVkZGVkIGFyZSBtYXBwZWQgdG8gdGhlXG4gKiBzaW5nbGUgdGFibGUgb2YgdGhlIGVudGl0eSB3aGVyZSBFbWJlZGRlZCBpcyB1c2VkLiBBbmQgb24gaHlkcmF0aW9uIGFsbCBjb2x1bW5zIHdoaWNoIHN1cHBvc2VkIHRvIGJlIGluIHRoZVxuICogZW1iZWRkZWQgd2lsbCBiZSBtYXBwZWQgdG8gaXQgZnJvbSB0aGUgc2luZ2xlIHRhYmxlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQ29sdW1uKFxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1mdW5jdGlvbi10eXBlXG4gIHR5cGU6ICh0eXBlPzogYW55KSA9PiBGdW5jdGlvbixcbiAgb3B0aW9ucz86IENvbHVtbkVtYmVkZGVkT3B0aW9uc1xuKTogUHJvcGVydHlEZWNvcmF0b3I7XG5cbi8qKlxuICogQ29sdW1uIGRlY29yYXRvciBpcyB1c2VkIHRvIG1hcmsgYSBzcGVjaWZpYyBjbGFzcyBwcm9wZXJ0eSBhcyBhIHRhYmxlIGNvbHVtbi5cbiAqIE9ubHkgcHJvcGVydGllcyBkZWNvcmF0ZWQgd2l0aCB0aGlzIGRlY29yYXRvciB3aWxsIGJlIHBlcnNpc3RlZCB0byB0aGUgZGF0YWJhc2Ugd2hlbiBlbnRpdHkgYmUgc2F2ZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBDb2x1bW4oXG4gIHR5cGVPck9wdGlvbnM/OiAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1mdW5jdGlvbi10eXBlXG4gIHwgKCh0eXBlPzogYW55KSA9PiBGdW5jdGlvbilcbiAgICB8IENvbHVtblR5cGVcbiAgICB8IChDb2x1bW5PcHRpb25zICYgQ29sdW1uRW1iZWRkZWRPcHRpb25zKSxcbiAgb3B0aW9ucz86IENvbHVtbk9wdGlvbnMgJiBDb2x1bW5FbWJlZGRlZE9wdGlvbnNcbik6IFByb3BlcnR5RGVjb3JhdG9yIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIChvYmplY3Q6IG9iamVjdCwgcHJvcGVydHlOYW1lOiBhbnkpIHtcbiAgICAvLyBub3JtYWxpemUgcGFyYW1ldGVyc1xuICAgIGxldCB0eXBlOiBDb2x1bW5UeXBlIHwgdW5kZWZpbmVkO1xuICAgIGlmIChcbiAgICAgIHR5cGVvZiB0eXBlT3JPcHRpb25zID09PSBcInN0cmluZ1wiIHx8XG4gICAgICB0eXBlb2YgdHlwZU9yT3B0aW9ucyA9PT0gXCJmdW5jdGlvblwiXG4gICAgKSB7XG4gICAgICB0eXBlID0gPENvbHVtblR5cGU+dHlwZU9yT3B0aW9ucztcbiAgICB9IGVsc2UgaWYgKHR5cGVPck9wdGlvbnMpIHtcbiAgICAgIG9wdGlvbnMgPSA8Q29sdW1uT3B0aW9ucz50eXBlT3JPcHRpb25zO1xuICAgICAgdHlwZSA9IHR5cGVPck9wdGlvbnMudHlwZTtcbiAgICB9XG4gICAgaWYgKCFvcHRpb25zKSBvcHRpb25zID0ge30gYXMgQ29sdW1uT3B0aW9ucztcblxuICAgIC8vIGlmIHR5cGUgaXMgbm90IGdpdmVuIGV4cGxpY2l0bHkgdGhlbiB0cnkgdG8gZ3Vlc3MgaXRcbiAgICBjb25zdCByZWZsZWN0TWV0YWRhdGFUeXBlID1cbiAgICAgIFJlZmxlY3QgJiYgKFJlZmxlY3QgYXMgYW55KS5nZXRNZXRhZGF0YVxuICAgICAgICA/IChSZWZsZWN0IGFzIGFueSkuZ2V0TWV0YWRhdGEoXCJkZXNpZ246dHlwZVwiLCBvYmplY3QsIHByb3BlcnR5TmFtZSlcbiAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgaWYgKCF0eXBlICYmIHJlZmxlY3RNZXRhZGF0YVR5cGUpXG4gICAgICAvLyBpZiB0eXBlIGlzIG5vdCBnaXZlbiBleHBsaWNpdGx5IHRoZW4gdHJ5IHRvIGd1ZXNzIGl0XG4gICAgICB0eXBlID0gcmVmbGVjdE1ldGFkYXRhVHlwZTtcblxuICAgIC8vIGNoZWNrIGlmIHRoZXJlIGlzIG5vIHR5cGUgaW4gY29sdW1uIG9wdGlvbnMgdGhlbiBzZXQgdHlwZSBmcm9tIGZpcnN0IGZ1bmN0aW9uIGFyZ3VtZW50LCBvciBndWVzc2VkIG9uZVxuICAgIGlmICghb3B0aW9ucy50eXBlICYmIHR5cGUpIG9wdGlvbnMudHlwZSA9IHR5cGU7XG5cbiAgICAvLyBzcGVjaWZ5IEhTVE9SRSB0eXBlIGlmIGNvbHVtbiBpcyBIU1RPUkVcbiAgICBpZiAob3B0aW9ucy50eXBlID09PSBcImhzdG9yZVwiICYmICFvcHRpb25zLmhzdG9yZVR5cGUpXG4gICAgICBvcHRpb25zLmhzdG9yZVR5cGUgPSByZWZsZWN0TWV0YWRhdGFUeXBlID09PSBPYmplY3QgPyBcIm9iamVjdFwiIDogXCJzdHJpbmdcIjtcblxuICAgIGlmICh0eXBlb2YgdHlwZU9yT3B0aW9ucyA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAvLyByZWdpc3RlciBhbiBlbWJlZGRlZFxuICAgICAgZ2V0TWV0YWRhdGFBcmdzU3RvcmFnZSgpLmVtYmVkZGVkcy5wdXNoKHtcbiAgICAgICAgdGFyZ2V0OiBvYmplY3QuY29uc3RydWN0b3IsXG4gICAgICAgIHByb3BlcnR5TmFtZTogcHJvcGVydHlOYW1lLFxuICAgICAgICBpc0FycmF5OiByZWZsZWN0TWV0YWRhdGFUeXBlID09PSBBcnJheSB8fCBvcHRpb25zLmFycmF5ID09PSB0cnVlLFxuICAgICAgICBwcmVmaXg6IG9wdGlvbnMucHJlZml4ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnByZWZpeCA6IHVuZGVmaW5lZCxcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtZnVuY3Rpb24tdHlwZVxuICAgICAgICB0eXBlOiB0eXBlT3JPcHRpb25zIGFzICh0eXBlPzogYW55KSA9PiBGdW5jdGlvbixcbiAgICAgIH0gYXMgRW1iZWRkZWRNZXRhZGF0YUFyZ3MpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyByZWdpc3RlciBhIHJlZ3VsYXIgY29sdW1uXG5cbiAgICAgIC8vIGlmIHdlIHN0aWxsIGRvbid0IGhhdmUgYSB0eXBlIHRoZW4gd2UgbmVlZCB0byBnaXZlIGVycm9yIHRvIHVzZXIgdGhhdCB0eXBlIGlzIHJlcXVpcmVkXG4gICAgICBpZiAoIW9wdGlvbnMudHlwZSlcbiAgICAgICAgdGhyb3cgbmV3IENvbHVtblR5cGVVbmRlZmluZWRFcnJvcihvYmplY3QsIHByb3BlcnR5TmFtZSk7XG5cbiAgICAgIC8vIGNyZWF0ZSB1bmlxdWVcbiAgICAgIGlmIChvcHRpb25zLnVuaXF1ZSA9PT0gdHJ1ZSlcbiAgICAgICAgZ2V0TWV0YWRhdGFBcmdzU3RvcmFnZSgpLnVuaXF1ZXMucHVzaCh7XG4gICAgICAgICAgdGFyZ2V0OiBvYmplY3QuY29uc3RydWN0b3IsXG4gICAgICAgICAgY29sdW1uczogW3Byb3BlcnR5TmFtZV0sXG4gICAgICAgIH0pO1xuXG4gICAgICBjb25zdCBjb2x1bW5zID0gZ2V0TWV0YWRhdGFBcmdzU3RvcmFnZSgpLmNvbHVtbnM7XG4gICAgICBhZ2dyZWdhdGVPck5ld0NvbHVtbihvYmplY3QuY29uc3RydWN0b3IsIHByb3BlcnR5TmFtZSwgY29sdW1ucywgb3B0aW9ucyk7XG5cbiAgICAgIGlmIChvcHRpb25zLmdlbmVyYXRlZCkge1xuICAgICAgICBnZXRNZXRhZGF0YUFyZ3NTdG9yYWdlKCkuZ2VuZXJhdGlvbnMucHVzaCh7XG4gICAgICAgICAgdGFyZ2V0OiBvYmplY3QuY29uc3RydWN0b3IsXG4gICAgICAgICAgcHJvcGVydHlOYW1lOiBwcm9wZXJ0eU5hbWUsXG4gICAgICAgICAgc3RyYXRlZ3k6XG4gICAgICAgICAgICB0eXBlb2Ygb3B0aW9ucy5nZW5lcmF0ZWQgPT09IFwic3RyaW5nXCJcbiAgICAgICAgICAgICAgPyBvcHRpb25zLmdlbmVyYXRlZFxuICAgICAgICAgICAgICA6IFwiaW5jcmVtZW50XCIsXG4gICAgICAgIH0gYXMgR2VuZXJhdGVkTWV0YWRhdGFBcmdzKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG59XG4iLCJpbXBvcnQgeyBDb2x1bW5PcHRpb25zLCBnZXRNZXRhZGF0YUFyZ3NTdG9yYWdlIH0gZnJvbSBcInR5cGVvcm1cIjtcbmltcG9ydCB7IGFnZ3JlZ2F0ZU9yTmV3Q29sdW1uIH0gZnJvbSBcIi4vdXRpbHNcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIFVwZGF0ZURhdGVDb2x1bW4ob3B0aW9ucz86IENvbHVtbk9wdGlvbnMpOiBQcm9wZXJ0eURlY29yYXRvciB7XG4gIHJldHVybiBmdW5jdGlvbiAob2JqZWN0OiBhbnksIHByb3BlcnR5TmFtZTogYW55KSB7XG4gICAgY29uc3QgY29sdW1ucyA9IGdldE1ldGFkYXRhQXJnc1N0b3JhZ2UoKS5jb2x1bW5zO1xuICAgIGFnZ3JlZ2F0ZU9yTmV3Q29sdW1uKFxuICAgICAgb2JqZWN0LmNvbnN0cnVjdG9yLFxuICAgICAgcHJvcGVydHlOYW1lLFxuICAgICAgY29sdW1ucyxcbiAgICAgIG9wdGlvbnMgfHwge30sXG4gICAgICBcInVwZGF0ZURhdGVcIlxuICAgICk7XG4gIH07XG59XG4iLCJpbXBvcnQgeyBDb2x1bW5PcHRpb25zLCBnZXRNZXRhZGF0YUFyZ3NTdG9yYWdlIH0gZnJvbSBcInR5cGVvcm1cIjtcbmltcG9ydCB7IGFnZ3JlZ2F0ZU9yTmV3Q29sdW1uIH0gZnJvbSBcIi4vdXRpbHNcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIENyZWF0ZURhdGVDb2x1bW4ob3B0aW9ucz86IENvbHVtbk9wdGlvbnMpOiBQcm9wZXJ0eURlY29yYXRvciB7XG4gIHJldHVybiBmdW5jdGlvbiAob2JqZWN0OiBhbnksIHByb3BlcnR5TmFtZTogYW55KSB7XG4gICAgY29uc3QgY29sdW1ucyA9IGdldE1ldGFkYXRhQXJnc1N0b3JhZ2UoKS5jb2x1bW5zO1xuICAgIGFnZ3JlZ2F0ZU9yTmV3Q29sdW1uKFxuICAgICAgb2JqZWN0LmNvbnN0cnVjdG9yLFxuICAgICAgcHJvcGVydHlOYW1lLFxuICAgICAgY29sdW1ucyxcbiAgICAgIG9wdGlvbnMgfHwge30sXG4gICAgICBcImNyZWF0ZURhdGVcIlxuICAgICk7XG4gIH07XG59XG4iLCJpbXBvcnQgeyBPYmplY3RVdGlscyB9IGZyb20gXCJ0eXBlb3JtL3V0aWwvT2JqZWN0VXRpbHNcIjtcbmltcG9ydCB7IFByaW1hcnlHZW5lcmF0ZWRDb2x1bW5OdW1lcmljT3B0aW9ucyB9IGZyb20gXCJ0eXBlb3JtL2RlY29yYXRvci9vcHRpb25zL1ByaW1hcnlHZW5lcmF0ZWRDb2x1bW5OdW1lcmljT3B0aW9uc1wiO1xuaW1wb3J0IHsgUHJpbWFyeUdlbmVyYXRlZENvbHVtblVVSURPcHRpb25zIH0gZnJvbSBcInR5cGVvcm0vZGVjb3JhdG9yL29wdGlvbnMvUHJpbWFyeUdlbmVyYXRlZENvbHVtblVVSURPcHRpb25zXCI7XG5pbXBvcnQgeyBQcmltYXJ5R2VuZXJhdGVkQ29sdW1uSWRlbnRpdHlPcHRpb25zIH0gZnJvbSBcInR5cGVvcm0vZGVjb3JhdG9yL29wdGlvbnMvUHJpbWFyeUdlbmVyYXRlZENvbHVtbklkZW50aXR5T3B0aW9uc1wiO1xuaW1wb3J0IHsgQ29sdW1uT3B0aW9ucywgZ2V0TWV0YWRhdGFBcmdzU3RvcmFnZSB9IGZyb20gXCJ0eXBlb3JtXCI7XG5pbXBvcnQgeyBHZW5lcmF0ZWRNZXRhZGF0YUFyZ3MgfSBmcm9tIFwidHlwZW9ybS9tZXRhZGF0YS1hcmdzL0dlbmVyYXRlZE1ldGFkYXRhQXJnc1wiO1xuaW1wb3J0IHsgYWdncmVnYXRlT3JOZXdDb2x1bW4gfSBmcm9tIFwiLi91dGlsc1wiO1xuXG4vKipcbiAqIENvbHVtbiBkZWNvcmF0b3IgaXMgdXNlZCB0byBtYXJrIGEgc3BlY2lmaWMgY2xhc3MgcHJvcGVydHkgYXMgYSB0YWJsZSBjb2x1bW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBQcmltYXJ5R2VuZXJhdGVkQ29sdW1uKCk6IFByb3BlcnR5RGVjb3JhdG9yO1xuXG4vKipcbiAqIENvbHVtbiBkZWNvcmF0b3IgaXMgdXNlZCB0byBtYXJrIGEgc3BlY2lmaWMgY2xhc3MgcHJvcGVydHkgYXMgYSB0YWJsZSBjb2x1bW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBQcmltYXJ5R2VuZXJhdGVkQ29sdW1uKFxuICBvcHRpb25zOiBQcmltYXJ5R2VuZXJhdGVkQ29sdW1uTnVtZXJpY09wdGlvbnNcbik6IFByb3BlcnR5RGVjb3JhdG9yO1xuXG4vKipcbiAqIENvbHVtbiBkZWNvcmF0b3IgaXMgdXNlZCB0byBtYXJrIGEgc3BlY2lmaWMgY2xhc3MgcHJvcGVydHkgYXMgYSB0YWJsZSBjb2x1bW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBQcmltYXJ5R2VuZXJhdGVkQ29sdW1uKFxuICBzdHJhdGVneTogXCJpbmNyZW1lbnRcIixcbiAgb3B0aW9ucz86IFByaW1hcnlHZW5lcmF0ZWRDb2x1bW5OdW1lcmljT3B0aW9uc1xuKTogUHJvcGVydHlEZWNvcmF0b3I7XG5cbi8qKlxuICogQ29sdW1uIGRlY29yYXRvciBpcyB1c2VkIHRvIG1hcmsgYSBzcGVjaWZpYyBjbGFzcyBwcm9wZXJ0eSBhcyBhIHRhYmxlIGNvbHVtbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFByaW1hcnlHZW5lcmF0ZWRDb2x1bW4oXG4gIHN0cmF0ZWd5OiBcInV1aWRcIixcbiAgb3B0aW9ucz86IFByaW1hcnlHZW5lcmF0ZWRDb2x1bW5VVUlET3B0aW9uc1xuKTogUHJvcGVydHlEZWNvcmF0b3I7XG5cbi8qKlxuICogQ29sdW1uIGRlY29yYXRvciBpcyB1c2VkIHRvIG1hcmsgYSBzcGVjaWZpYyBjbGFzcyBwcm9wZXJ0eSBhcyBhIHRhYmxlIGNvbHVtbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFByaW1hcnlHZW5lcmF0ZWRDb2x1bW4oXG4gIHN0cmF0ZWd5OiBcInJvd2lkXCIsXG4gIG9wdGlvbnM/OiBQcmltYXJ5R2VuZXJhdGVkQ29sdW1uVVVJRE9wdGlvbnNcbik6IFByb3BlcnR5RGVjb3JhdG9yO1xuXG5leHBvcnQgZnVuY3Rpb24gUHJpbWFyeUdlbmVyYXRlZENvbHVtbihcbiAgc3RyYXRlZ3k6IFwiaWRlbnRpdHlcIixcbiAgb3B0aW9ucz86IFByaW1hcnlHZW5lcmF0ZWRDb2x1bW5JZGVudGl0eU9wdGlvbnNcbik6IFByb3BlcnR5RGVjb3JhdG9yO1xuXG4vKipcbiAqIENvbHVtbiBkZWNvcmF0b3IgaXMgdXNlZCB0byBtYXJrIGEgc3BlY2lmaWMgY2xhc3MgcHJvcGVydHkgYXMgYSB0YWJsZSBjb2x1bW4uXG4gKiBPbmx5IHByb3BlcnRpZXMgZGVjb3JhdGVkIHdpdGggdGhpcyBkZWNvcmF0b3Igd2lsbCBiZSBwZXJzaXN0ZWQgdG8gdGhlIGRhdGFiYXNlIHdoZW4gZW50aXR5IGJlIHNhdmVkLlxuICogVGhpcyBjb2x1bW4gY3JlYXRlcyBhbiBpbnRlZ2VyIFBSSU1BUlkgQ09MVU1OIHdpdGggZ2VuZXJhdGVkIHNldCB0byB0cnVlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gUHJpbWFyeUdlbmVyYXRlZENvbHVtbihcbiAgc3RyYXRlZ3lPck9wdGlvbnM/OlxuICAgIHwgXCJpbmNyZW1lbnRcIlxuICAgIHwgXCJ1dWlkXCJcbiAgICB8IFwicm93aWRcIlxuICAgIHwgXCJpZGVudGl0eVwiXG4gICAgfCBQcmltYXJ5R2VuZXJhdGVkQ29sdW1uTnVtZXJpY09wdGlvbnNcbiAgICB8IFByaW1hcnlHZW5lcmF0ZWRDb2x1bW5VVUlET3B0aW9uc1xuICAgIHwgUHJpbWFyeUdlbmVyYXRlZENvbHVtbklkZW50aXR5T3B0aW9ucyxcbiAgbWF5YmVPcHRpb25zPzpcbiAgICB8IFByaW1hcnlHZW5lcmF0ZWRDb2x1bW5OdW1lcmljT3B0aW9uc1xuICAgIHwgUHJpbWFyeUdlbmVyYXRlZENvbHVtblVVSURPcHRpb25zXG4gICAgfCBQcmltYXJ5R2VuZXJhdGVkQ29sdW1uSWRlbnRpdHlPcHRpb25zXG4pOiBQcm9wZXJ0eURlY29yYXRvciB7XG4gIC8vIG5vcm1hbGl6ZSBwYXJhbWV0ZXJzXG4gIGNvbnN0IG9wdGlvbnM6IENvbHVtbk9wdGlvbnMgPSB7fTtcbiAgbGV0IHN0cmF0ZWd5OiBcImluY3JlbWVudFwiIHwgXCJ1dWlkXCIgfCBcInJvd2lkXCIgfCBcImlkZW50aXR5XCI7XG4gIGlmIChzdHJhdGVneU9yT3B0aW9ucykge1xuICAgIGlmICh0eXBlb2Ygc3RyYXRlZ3lPck9wdGlvbnMgPT09IFwic3RyaW5nXCIpXG4gICAgICBzdHJhdGVneSA9IHN0cmF0ZWd5T3JPcHRpb25zIGFzXG4gICAgICAgIHwgXCJpbmNyZW1lbnRcIlxuICAgICAgICB8IFwidXVpZFwiXG4gICAgICAgIHwgXCJyb3dpZFwiXG4gICAgICAgIHwgXCJpZGVudGl0eVwiO1xuXG4gICAgaWYgKE9iamVjdFV0aWxzLmlzT2JqZWN0KHN0cmF0ZWd5T3JPcHRpb25zKSkge1xuICAgICAgc3RyYXRlZ3kgPSBcImluY3JlbWVudFwiO1xuICAgICAgT2JqZWN0LmFzc2lnbihvcHRpb25zLCBzdHJhdGVneU9yT3B0aW9ucyk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHN0cmF0ZWd5ID0gXCJpbmNyZW1lbnRcIjtcbiAgfVxuICBpZiAoT2JqZWN0VXRpbHMuaXNPYmplY3QobWF5YmVPcHRpb25zKSkgT2JqZWN0LmFzc2lnbihvcHRpb25zLCBtYXliZU9wdGlvbnMpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAob2JqZWN0OiBhbnksIHByb3BlcnR5TmFtZTogYW55KSB7XG4gICAgLy8gaWYgY29sdW1uIHR5cGUgaXMgbm90IGV4cGxpY2l0bHkgc2V0IHRoZW4gZGV0ZXJtaW5lIGl0IGJhc2VkIG9uIGdlbmVyYXRpb24gc3RyYXRlZ3lcbiAgICBpZiAoIW9wdGlvbnMudHlwZSkge1xuICAgICAgaWYgKHN0cmF0ZWd5ID09PSBcImluY3JlbWVudFwiIHx8IHN0cmF0ZWd5ID09PSBcImlkZW50aXR5XCIpIHtcbiAgICAgICAgb3B0aW9ucy50eXBlID0gTnVtYmVyO1xuICAgICAgfSBlbHNlIGlmIChzdHJhdGVneSA9PT0gXCJ1dWlkXCIpIHtcbiAgICAgICAgb3B0aW9ucy50eXBlID0gXCJ1dWlkXCI7XG4gICAgICB9IGVsc2UgaWYgKHN0cmF0ZWd5ID09PSBcInJvd2lkXCIpIHtcbiAgICAgICAgb3B0aW9ucy50eXBlID0gXCJpbnRcIjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBleHBsaWNpdGx5IHNldCBhIHByaW1hcnkgYW5kIGdlbmVyYXRlZCB0byBjb2x1bW4gb3B0aW9uc1xuICAgIG9wdGlvbnMucHJpbWFyeSA9IHRydWU7XG5cbiAgICBjb25zdCBjb2x1bW5zID0gZ2V0TWV0YWRhdGFBcmdzU3RvcmFnZSgpLmNvbHVtbnM7XG4gICAgYWdncmVnYXRlT3JOZXdDb2x1bW4ob2JqZWN0LmNvbnN0cnVjdG9yLCBwcm9wZXJ0eU5hbWUsIGNvbHVtbnMsIG9wdGlvbnMpO1xuICAgIC8vIHJlZ2lzdGVyIGdlbmVyYXRlZCBtZXRhZGF0YSBhcmdzXG4gICAgZ2V0TWV0YWRhdGFBcmdzU3RvcmFnZSgpLmdlbmVyYXRpb25zLnB1c2goe1xuICAgICAgdGFyZ2V0OiBvYmplY3QuY29uc3RydWN0b3IsXG4gICAgICBwcm9wZXJ0eU5hbWU6IHByb3BlcnR5TmFtZSxcbiAgICAgIHN0cmF0ZWd5OiBzdHJhdGVneSxcbiAgICB9IGFzIEdlbmVyYXRlZE1ldGFkYXRhQXJncyk7XG4gIH07XG59XG4iLCJpbXBvcnQge1xuICBDb2x1bW5PcHRpb25zLFxuICBDb2x1bW5UeXBlLFxuICBDb2x1bW5UeXBlVW5kZWZpbmVkRXJyb3IsXG4gIGdldE1ldGFkYXRhQXJnc1N0b3JhZ2UsXG4gIFByaW1hcnlDb2x1bW5DYW5ub3RCZU51bGxhYmxlRXJyb3IsXG59IGZyb20gXCJ0eXBlb3JtXCI7XG5pbXBvcnQgeyBDb2x1bW5NZXRhZGF0YUFyZ3MgfSBmcm9tIFwidHlwZW9ybS9tZXRhZGF0YS1hcmdzL0NvbHVtbk1ldGFkYXRhQXJnc1wiO1xuaW1wb3J0IHsgR2VuZXJhdGVkTWV0YWRhdGFBcmdzIH0gZnJvbSBcInR5cGVvcm0vbWV0YWRhdGEtYXJncy9HZW5lcmF0ZWRNZXRhZGF0YUFyZ3NcIjtcbmltcG9ydCB7IGFnZ3JlZ2F0ZU9yTmV3Q29sdW1uIH0gZnJvbSBcIi4vdXRpbHNcIjtcblxuLyoqXG4gKiBEZXNjcmliZXMgYWxsIHByaW1hcnkga2V5IGNvbHVtbidzIG9wdGlvbnMuXG4gKiBJZiBzcGVjaWZpZWQsIHRoZSBudWxsYWJsZSBmaWVsZCBtdXN0IGJlIHNldCB0byBmYWxzZS5cbiAqL1xuZXhwb3J0IHR5cGUgUHJpbWFyeUNvbHVtbk9wdGlvbnMgPSBDb2x1bW5PcHRpb25zICYgeyBudWxsYWJsZT86IGZhbHNlIH07XG5cbi8qKlxuICogQ29sdW1uIGRlY29yYXRvciBpcyB1c2VkIHRvIG1hcmsgYSBzcGVjaWZpYyBjbGFzcyBwcm9wZXJ0eSBhcyBhIHRhYmxlIGNvbHVtbi5cbiAqIE9ubHkgcHJvcGVydGllcyBkZWNvcmF0ZWQgd2l0aCB0aGlzIGRlY29yYXRvciB3aWxsIGJlIHBlcnNpc3RlZCB0byB0aGUgZGF0YWJhc2Ugd2hlbiBlbnRpdHkgYmUgc2F2ZWQuXG4gKiBQcmltYXJ5IGNvbHVtbnMgYWxzbyBjcmVhdGVzIGEgUFJJTUFSWSBLRVkgZm9yIHRoaXMgY29sdW1uIGluIGEgZGIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBQcmltYXJ5Q29sdW1uKFxuICBvcHRpb25zPzogUHJpbWFyeUNvbHVtbk9wdGlvbnNcbik6IFByb3BlcnR5RGVjb3JhdG9yO1xuXG4vKipcbiAqIENvbHVtbiBkZWNvcmF0b3IgaXMgdXNlZCB0byBtYXJrIGEgc3BlY2lmaWMgY2xhc3MgcHJvcGVydHkgYXMgYSB0YWJsZSBjb2x1bW4uXG4gKiBPbmx5IHByb3BlcnRpZXMgZGVjb3JhdGVkIHdpdGggdGhpcyBkZWNvcmF0b3Igd2lsbCBiZSBwZXJzaXN0ZWQgdG8gdGhlIGRhdGFiYXNlIHdoZW4gZW50aXR5IGJlIHNhdmVkLlxuICogUHJpbWFyeSBjb2x1bW5zIGFsc28gY3JlYXRlcyBhIFBSSU1BUlkgS0VZIGZvciB0aGlzIGNvbHVtbiBpbiBhIGRiLlxuICovXG5leHBvcnQgZnVuY3Rpb24gUHJpbWFyeUNvbHVtbihcbiAgdHlwZT86IENvbHVtblR5cGUsXG4gIG9wdGlvbnM/OiBQcmltYXJ5Q29sdW1uT3B0aW9uc1xuKTogUHJvcGVydHlEZWNvcmF0b3I7XG5cbi8qKlxuICogQ29sdW1uIGRlY29yYXRvciBpcyB1c2VkIHRvIG1hcmsgYSBzcGVjaWZpYyBjbGFzcyBwcm9wZXJ0eSBhcyBhIHRhYmxlIGNvbHVtbi5cbiAqIE9ubHkgcHJvcGVydGllcyBkZWNvcmF0ZWQgd2l0aCB0aGlzIGRlY29yYXRvciB3aWxsIGJlIHBlcnNpc3RlZCB0byB0aGUgZGF0YWJhc2Ugd2hlbiBlbnRpdHkgYmUgc2F2ZWQuXG4gKiBQcmltYXJ5IGNvbHVtbnMgYWxzbyBjcmVhdGVzIGEgUFJJTUFSWSBLRVkgZm9yIHRoaXMgY29sdW1uIGluIGEgZGIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBQcmltYXJ5Q29sdW1uKFxuICB0eXBlT3JPcHRpb25zPzogQ29sdW1uVHlwZSB8IFByaW1hcnlDb2x1bW5PcHRpb25zLFxuICBvcHRpb25zPzogUHJpbWFyeUNvbHVtbk9wdGlvbnNcbik6IFByb3BlcnR5RGVjb3JhdG9yIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIChvYmplY3Q6IGFueSwgcHJvcGVydHlOYW1lOiBhbnkpIHtcbiAgICAvLyBub3JtYWxpemUgcGFyYW1ldGVyc1xuICAgIGxldCB0eXBlOiBDb2x1bW5UeXBlIHwgdW5kZWZpbmVkO1xuICAgIGlmIChcbiAgICAgIHR5cGVvZiB0eXBlT3JPcHRpb25zID09PSBcInN0cmluZ1wiIHx8XG4gICAgICB0eXBlT3JPcHRpb25zID09PSBTdHJpbmcgfHxcbiAgICAgIHR5cGVPck9wdGlvbnMgPT09IEJvb2xlYW4gfHxcbiAgICAgIHR5cGVPck9wdGlvbnMgPT09IE51bWJlclxuICAgICkge1xuICAgICAgdHlwZSA9IHR5cGVPck9wdGlvbnMgYXMgQ29sdW1uVHlwZTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oe30sIDxQcmltYXJ5Q29sdW1uT3B0aW9ucz50eXBlT3JPcHRpb25zKTtcbiAgICB9XG4gICAgaWYgKCFvcHRpb25zKSBvcHRpb25zID0ge30gYXMgUHJpbWFyeUNvbHVtbk9wdGlvbnM7XG5cbiAgICAvLyBpZiB0eXBlIGlzIG5vdCBnaXZlbiBleHBsaWNpdGx5IHRoZW4gdHJ5IHRvIGd1ZXNzIGl0XG4gICAgY29uc3QgcmVmbGVjdE1ldGFkYXRhVHlwZSA9XG4gICAgICBSZWZsZWN0ICYmIChSZWZsZWN0IGFzIGFueSkuZ2V0TWV0YWRhdGFcbiAgICAgICAgPyAoUmVmbGVjdCBhcyBhbnkpLmdldE1ldGFkYXRhKFwiZGVzaWduOnR5cGVcIiwgb2JqZWN0LCBwcm9wZXJ0eU5hbWUpXG4gICAgICAgIDogdW5kZWZpbmVkO1xuICAgIGlmICghdHlwZSAmJiByZWZsZWN0TWV0YWRhdGFUeXBlKSB0eXBlID0gcmVmbGVjdE1ldGFkYXRhVHlwZTtcblxuICAgIC8vIGNoZWNrIGlmIHRoZXJlIGlzIG5vIHR5cGUgaW4gY29sdW1uIG9wdGlvbnMgdGhlbiBzZXQgdHlwZSBmcm9tIGZpcnN0IGZ1bmN0aW9uIGFyZ3VtZW50LCBvciBndWVzc2VkIG9uZVxuICAgIGlmICghb3B0aW9ucy50eXBlICYmIHR5cGUpIG9wdGlvbnMudHlwZSA9IHR5cGU7XG5cbiAgICAvLyBpZiB3ZSBzdGlsbCBkb24ndCBoYXZlIGEgdHlwZSB0aGVuIHdlIG5lZWQgdG8gZ2l2ZSBlcnJvciB0byB1c2VyIHRoYXQgdHlwZSBpcyByZXF1aXJlZFxuICAgIGlmICghb3B0aW9ucy50eXBlKSB0aHJvdyBuZXcgQ29sdW1uVHlwZVVuZGVmaW5lZEVycm9yKG9iamVjdCwgcHJvcGVydHlOYW1lKTtcblxuICAgIC8vIGNoZWNrIGlmIGNvbHVtbiBpcyBub3QgbnVsbGFibGUsIGJlY2F1c2Ugd2UgY2Fubm90IGFsbG93IGEgcHJpbWFyeSBrZXkgdG8gYmUgbnVsbGFibGVcbiAgICBpZiAob3B0aW9ucy5udWxsYWJsZSlcbiAgICAgIHRocm93IG5ldyBQcmltYXJ5Q29sdW1uQ2Fubm90QmVOdWxsYWJsZUVycm9yKG9iamVjdCwgcHJvcGVydHlOYW1lKTtcblxuICAgIC8vIGV4cGxpY2l0bHkgc2V0IGEgcHJpbWFyeSB0byBjb2x1bW4gb3B0aW9uc1xuICAgIG9wdGlvbnMucHJpbWFyeSA9IHRydWU7XG5cbiAgICBjb25zdCBjb2x1bW5zID0gZ2V0TWV0YWRhdGFBcmdzU3RvcmFnZSgpLmNvbHVtbnM7XG4gICAgYWdncmVnYXRlT3JOZXdDb2x1bW4ob2JqZWN0LmNvbnN0cnVjdG9yLCBwcm9wZXJ0eU5hbWUsIGNvbHVtbnMsIG9wdGlvbnMpO1xuXG4gICAgaWYgKG9wdGlvbnMuZ2VuZXJhdGVkKSB7XG4gICAgICBnZXRNZXRhZGF0YUFyZ3NTdG9yYWdlKCkuZ2VuZXJhdGlvbnMucHVzaCh7XG4gICAgICAgIHRhcmdldDogb2JqZWN0LmNvbnN0cnVjdG9yLFxuICAgICAgICBwcm9wZXJ0eU5hbWU6IHByb3BlcnR5TmFtZSxcbiAgICAgICAgc3RyYXRlZ3k6XG4gICAgICAgICAgdHlwZW9mIG9wdGlvbnMuZ2VuZXJhdGVkID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICA/IG9wdGlvbnMuZ2VuZXJhdGVkXG4gICAgICAgICAgICA6IFwiaW5jcmVtZW50XCIsXG4gICAgICB9IGFzIEdlbmVyYXRlZE1ldGFkYXRhQXJncyk7XG4gICAgfVxuICB9O1xufVxuIiwiaW1wb3J0IHsgRW50aXR5T3B0aW9ucywgZ2V0TWV0YWRhdGFBcmdzU3RvcmFnZSB9IGZyb20gXCJ0eXBlb3JtXCI7XG5pbXBvcnQgeyBPYmplY3RVdGlscyB9IGZyb20gXCJ0eXBlb3JtL3V0aWwvT2JqZWN0VXRpbHNcIjtcbmltcG9ydCB7IFRhYmxlTWV0YWRhdGFBcmdzIH0gZnJvbSBcInR5cGVvcm0vbWV0YWRhdGEtYXJncy9UYWJsZU1ldGFkYXRhQXJnc1wiO1xuXG4vKipcbiAqIFRoaXMgZGVjb3JhdG9yIGlzIHVzZWQgdG8gbWFyayBjbGFzc2VzIHRoYXQgd2lsbCBiZSBhbiBlbnRpdHkgKHRhYmxlIG9yIGRvY3VtZW50IGRlcGVuZCBvbiBkYXRhYmFzZSB0eXBlKS5cbiAqIERhdGFiYXNlIHNjaGVtYSB3aWxsIGJlIGNyZWF0ZWQgZm9yIGFsbCBjbGFzc2VzIGRlY29yYXRlZCB3aXRoIGl0LCBhbmQgUmVwb3NpdG9yeSBjYW4gYmUgcmV0cmlldmVkIGFuZCB1c2VkIGZvciBpdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEVudGl0eShvcHRpb25zPzogRW50aXR5T3B0aW9ucyk6IENsYXNzRGVjb3JhdG9yO1xuXG4vKipcbiAqIFRoaXMgZGVjb3JhdG9yIGlzIHVzZWQgdG8gbWFyayBjbGFzc2VzIHRoYXQgd2lsbCBiZSBhbiBlbnRpdHkgKHRhYmxlIG9yIGRvY3VtZW50IGRlcGVuZCBvbiBkYXRhYmFzZSB0eXBlKS5cbiAqIERhdGFiYXNlIHNjaGVtYSB3aWxsIGJlIGNyZWF0ZWQgZm9yIGFsbCBjbGFzc2VzIGRlY29yYXRlZCB3aXRoIGl0LCBhbmQgUmVwb3NpdG9yeSBjYW4gYmUgcmV0cmlldmVkIGFuZCB1c2VkIGZvciBpdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEVudGl0eShuYW1lPzogc3RyaW5nLCBvcHRpb25zPzogRW50aXR5T3B0aW9ucyk6IENsYXNzRGVjb3JhdG9yO1xuXG4vKipcbiAqIFRoaXMgZGVjb3JhdG9yIGlzIHVzZWQgdG8gbWFyayBjbGFzc2VzIHRoYXQgd2lsbCBiZSBhbiBlbnRpdHkgKHRhYmxlIG9yIGRvY3VtZW50IGRlcGVuZCBvbiBkYXRhYmFzZSB0eXBlKS5cbiAqIERhdGFiYXNlIHNjaGVtYSB3aWxsIGJlIGNyZWF0ZWQgZm9yIGFsbCBjbGFzc2VzIGRlY29yYXRlZCB3aXRoIGl0LCBhbmQgUmVwb3NpdG9yeSBjYW4gYmUgcmV0cmlldmVkIGFuZCB1c2VkIGZvciBpdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEVudGl0eShcbiAgbmFtZU9yT3B0aW9ucz86IHN0cmluZyB8IEVudGl0eU9wdGlvbnMsXG4gIG1heWJlT3B0aW9ucz86IEVudGl0eU9wdGlvbnNcbik6IENsYXNzRGVjb3JhdG9yIHtcbiAgY29uc3Qgb3B0aW9ucyA9XG4gICAgKE9iamVjdFV0aWxzLmlzT2JqZWN0KG5hbWVPck9wdGlvbnMpXG4gICAgICA/IChuYW1lT3JPcHRpb25zIGFzIEVudGl0eU9wdGlvbnMpXG4gICAgICA6IG1heWJlT3B0aW9ucykgfHwge307XG4gIGNvbnN0IG5hbWUgPSB0eXBlb2YgbmFtZU9yT3B0aW9ucyA9PT0gXCJzdHJpbmdcIiA/IG5hbWVPck9wdGlvbnMgOiBvcHRpb25zLm5hbWU7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQpIHtcbiAgICBjb25zdCB0YWJsZXMgPSBnZXRNZXRhZGF0YUFyZ3NTdG9yYWdlKCkudGFibGVzO1xuICAgIHRhYmxlcy5wdXNoKHtcbiAgICAgIHRhcmdldDogdGFyZ2V0LFxuICAgICAgbmFtZTogbmFtZSxcbiAgICAgIHR5cGU6IFwicmVndWxhclwiLFxuICAgICAgb3JkZXJCeTogb3B0aW9ucy5vcmRlckJ5ID8gb3B0aW9ucy5vcmRlckJ5IDogdW5kZWZpbmVkLFxuICAgICAgZW5naW5lOiBvcHRpb25zLmVuZ2luZSA/IG9wdGlvbnMuZW5naW5lIDogdW5kZWZpbmVkLFxuICAgICAgZGF0YWJhc2U6IG9wdGlvbnMuZGF0YWJhc2UgPyBvcHRpb25zLmRhdGFiYXNlIDogdW5kZWZpbmVkLFxuICAgICAgc2NoZW1hOiBvcHRpb25zLnNjaGVtYSA/IG9wdGlvbnMuc2NoZW1hIDogdW5kZWZpbmVkLFxuICAgICAgc3luY2hyb25pemU6IG9wdGlvbnMuc3luY2hyb25pemUsXG4gICAgICB3aXRob3V0Um93aWQ6IG9wdGlvbnMud2l0aG91dFJvd2lkLFxuICAgICAgY29tbWVudDogb3B0aW9ucy5jb21tZW50ID8gb3B0aW9ucy5jb21tZW50IDogdW5kZWZpbmVkLFxuICAgIH0gYXMgVGFibGVNZXRhZGF0YUFyZ3MpO1xuICB9O1xufVxuIiwiaW1wb3J0IHtcbiAgQWRhcHRlcixcbiAgQ2FzY2FkZSxcbiAgQ2FzY2FkZU1ldGFkYXRhLFxuICBDb25uZWN0aW9uRXJyb3IsXG4gIGZpbmFsLFxuICBQZXJzaXN0ZW5jZUtleXMsXG4gIFJlbGF0aW9uc01ldGFkYXRhLFxuICBSZXBvc2l0b3J5LFxuICBTZXF1ZW5jZSxcbiAgdHlwZSBTZXF1ZW5jZU9wdGlvbnMsXG59IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgcmVzZXJ2ZWRBdHRyaWJ1dGVzLCBUeXBlT1JNRmxhdm91ciB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHtcbiAgQmFzZUVycm9yLFxuICBDb25mbGljdEVycm9yLFxuICBDb250ZXh0LFxuICBEQktleXMsXG4gIERFRkFVTFRfRVJST1JfTUVTU0FHRVMgYXMgREJfREVGQVVMVF9FUlJPUl9NRVNTQUdFUyxcbiAgZmluZFByaW1hcnlLZXksXG4gIEludGVybmFsRXJyb3IsXG4gIE5vdEZvdW5kRXJyb3IsXG4gIE9wZXJhdGlvbktleXMsXG4gIHJlYWRvbmx5LFxuICBVcGRhdGVWYWxpZGF0aW9uS2V5cyxcbn0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgXCJyZWZsZWN0LW1ldGFkYXRhXCI7XG5pbXBvcnQge1xuICB0eXBlIENvbnN0cnVjdG9yLFxuICBkYXRlLFxuICBEZWNvcmF0aW9uLFxuICBERUZBVUxUX0VSUk9SX01FU1NBR0VTLFxuICBsaXN0LFxuICBNYXhMZW5ndGhWYWxpZGF0b3JPcHRpb25zLFxuICBNYXhWYWxpZGF0b3JPcHRpb25zLFxuICBNaW5MZW5ndGhWYWxpZGF0b3JPcHRpb25zLFxuICBNaW5WYWxpZGF0b3JPcHRpb25zLFxuICBNb2RlbCxcbiAgTW9kZWxLZXlzLFxuICBQYXR0ZXJuVmFsaWRhdG9yT3B0aW9ucyxcbiAgcHJvcCxcbiAgcHJvcE1ldGFkYXRhLFxuICByZXF1aXJlZCxcbiAgdHlwZSxcbiAgVHlwZU1ldGFkYXRhLFxuICBWYWxpZGF0aW9uLFxuICBWYWxpZGF0aW9uS2V5cyxcbiAgVmFsaWRhdG9yT3B0aW9ucyxcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgSW5kZXhFcnJvciB9IGZyb20gXCIuL2Vycm9yc1wiO1xuaW1wb3J0IHsgVHlwZU9STVN0YXRlbWVudCB9IGZyb20gXCIuL3F1ZXJ5XCI7XG5pbXBvcnQgeyBUeXBlT1JNU2VxdWVuY2UgfSBmcm9tIFwiLi9zZXF1ZW5jZXNcIjtcbmltcG9ydCB7IGdlbmVyYXRlSW5kZXhlcyB9IGZyb20gXCIuL2luZGV4ZXNcIjtcbmltcG9ydCB7IFR5cGVPUk1GbGFncywgVHlwZU9STVF1ZXJ5LCBUeXBlT1JNVGFibGVTcGVjIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IGFwcGx5LCBSZWZsZWN0aW9uIH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5pbXBvcnQgeyBUeXBlT1JNUmVwb3NpdG9yeSB9IGZyb20gXCIuL1R5cGVPUk1SZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBMb2dnaW5nIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5pbXBvcnQgeyBUeXBlT1JNRGlzcGF0Y2ggfSBmcm9tIFwiLi9UeXBlT1JNRGlzcGF0Y2hcIjtcbmltcG9ydCB7IGNvbnZlcnRKc1JlZ2V4VG9Qb3N0Z3JlcyB9IGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQge1xuICBEYXRhU291cmNlLFxuICBGaW5kT25lT3B0aW9ucyxcbiAgSW4sXG4gIEluc2VydFJlc3VsdCxcbiAgUmVsYXRpb25PcHRpb25zLFxuICBPbmVUb09uZSxcbiAgSm9pbkNvbHVtbixcbiAgTWFueVRvTWFueSxcbiAgU2VsZWN0UXVlcnlCdWlsZGVyLFxuICBWZXJzaW9uQ29sdW1uLFxuICBPbmVUb01hbnksXG4gIE1hbnlUb09uZSxcbiAgSm9pblRhYmxlLFxufSBmcm9tIFwidHlwZW9ybVwiO1xuaW1wb3J0IHsgRGF0YVNvdXJjZU9wdGlvbnMgfSBmcm9tIFwidHlwZW9ybS9kYXRhLXNvdXJjZS9EYXRhU291cmNlT3B0aW9uc1wiO1xuaW1wb3J0IHsgQ29sdW1uIH0gZnJvbSBcIi4vb3ZlcnJpZGVzL0NvbHVtblwiO1xuaW1wb3J0IHsgVXBkYXRlRGF0ZUNvbHVtbiB9IGZyb20gXCIuL292ZXJyaWRlcy9VcGRhdGVEYXRlQ29sdW1uXCI7XG5pbXBvcnQgeyBDcmVhdGVEYXRlQ29sdW1uIH0gZnJvbSBcIi4vb3ZlcnJpZGVzL0NyZWF0ZURhdGVDb2x1bW5cIjtcbmltcG9ydCB7IFByaW1hcnlHZW5lcmF0ZWRDb2x1bW4gfSBmcm9tIFwiLi9vdmVycmlkZXMvUHJpbWFyeUdlbmVyYXRlZENvbHVtblwiO1xuaW1wb3J0IHsgUHJpbWFyeUNvbHVtbiB9IGZyb20gXCIuL292ZXJyaWRlcy9QcmltYXJ5Q29sdW1uXCI7XG5pbXBvcnQgeyBFbnRpdHkgfSBmcm9tIFwiLi9vdmVycmlkZXMvRW50aXR5XCI7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjcmVhdGVkQnlPblBvc3RncmVzQ3JlYXRlVXBkYXRlPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFIgZXh0ZW5kcyBUeXBlT1JNUmVwb3NpdG9yeTxNPixcbiAgViBleHRlbmRzIFJlbGF0aW9uc01ldGFkYXRhLFxuPihcbiAgdGhpczogUixcbiAgY29udGV4dDogQ29udGV4dDxUeXBlT1JNRmxhZ3M+LFxuICBkYXRhOiBWLFxuICBrZXk6IGtleW9mIE0sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCB1c2VyID0gY29udGV4dC5nZXQoXCJ1c2VyXCIpO1xuICAgIG1vZGVsW2tleV0gPSB1c2VyIGFzIE1bdHlwZW9mIGtleV07XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBcIk5vIFVzZXIgZm91bmQgaW4gY29udGV4dC4gUGxlYXNlIHByb3ZpZGUgYSB1c2VyIGluIHRoZSBjb250ZXh0XCJcbiAgICApO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEFkYXB0ZXIgZm9yIFR5cGVPUk0tYmFja2VkIHBlcnNpc3RlbmNlIG9wZXJhdGlvbnMuXG4gKiBAc3VtbWFyeSBJbXBsZW1lbnRzIHRoZSBEZWNhZi50cyBBZGFwdGVyIG92ZXIgYSBUeXBlT1JNIERhdGFTb3VyY2UsIHByb3ZpZGluZyBDUlVEIG9wZXJhdGlvbnMsIHF1ZXJ5L3N0YXRlbWVudCBmYWN0b3JpZXMsIHNlcXVlbmNlIG1hbmFnZW1lbnQsIGVycm9yIHBhcnNpbmcsIGFuZCBkZWNvcmF0aW9uIGhlbHBlcnMuXG4gKiBAdGVtcGxhdGUgWSBUaGUgbmF0aXZlIGNvbmZpZ3VyYXRpb24gdHlwZSAoVHlwZU9STSBEYXRhU291cmNlT3B0aW9ucykuXG4gKiBAdGVtcGxhdGUgRiBUaGUgcmVwb3NpdG9yeSBmbGFncyB0eXBlLlxuICogQHRlbXBsYXRlIEMgVGhlIGNvbnRleHQgdHlwZS5cbiAqIEBwYXJhbSB7RGF0YVNvdXJjZU9wdGlvbnN9IHNjb3BlIFRoZSBEYXRhU291cmNlIG9wdGlvbnMgZm9yIHRoZSBhZGFwdGVyLlxuICogQHBhcmFtIHtzdHJpbmd9IGZsYXZvdXIgVGhlIGZsYXZvdXIgb2YgdGhlIGFkYXB0ZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30gW2FsaWFzXSBPcHRpb25hbCBhbGlhcyBmb3IgdGhlIGFkYXB0ZXIuXG4gKiBAY2xhc3MgVHlwZU9STUFkYXB0ZXJcbiAqIEBleGFtcGxlXG4gKiBjb25zdCBhZGFwdGVyID0gbmV3IFR5cGVPUk1BZGFwdGVyKHsgdHlwZTogJ3Bvc3RncmVzJywgLyogLi4uICpcXC8gfSk7XG4gKiBhd2FpdCBhZGFwdGVyLmluaXRpYWxpemUoKTtcbiAqIGNvbnN0IHJlcG8gPSBuZXcgKGFkYXB0ZXIucmVwb3NpdG9yeTxVc2VyPigpKShhZGFwdGVyLCBVc2VyKTtcbiAqIGNvbnN0IGNyZWF0ZWQgPSBhd2FpdCByZXBvLmNyZWF0ZShuZXcgVXNlcih7IG5hbWU6ICdBbGljZScgfSkpO1xuICpcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQXBwXG4gKiAgIHBhcnRpY2lwYW50IEFkYXB0ZXIgYXMgVHlwZU9STUFkYXB0ZXJcbiAqICAgcGFydGljaXBhbnQgUmVwbyBhcyBUeXBlT1JNUmVwb3NpdG9yeVxuICogICBwYXJ0aWNpcGFudCBEUyBhcyBUeXBlT1JNIERhdGFTb3VyY2VcbiAqXG4gKiAgIEFwcC0+PkFkYXB0ZXI6IG5ldyBUeXBlT1JNQWRhcHRlcihvcHRzKVxuICogICBBZGFwdGVyLT4+RFM6IGluaXRpYWxpemUoKVxuICogICBBcHAtPj5BZGFwdGVyOiByZXBvc2l0b3J5KClcbiAqICAgQWRhcHRlci0tPj5BcHA6IFR5cGVPUk1SZXBvc2l0b3J5XG4gKiAgIEFwcC0+PlJlcG86IGNyZWF0ZShtb2RlbClcbiAqICAgUmVwby0+PkFkYXB0ZXI6IHByZXBhcmUvY3JlYXRlL3JldmVydFxuICogICBBZGFwdGVyLS0+PlJlcG86IE1vZGVsXG4gKiAgIFJlcG8tLT4+QXBwOiBNb2RlbFxuICovXG5leHBvcnQgY2xhc3MgVHlwZU9STUFkYXB0ZXIgZXh0ZW5kcyBBZGFwdGVyPFxuICBEYXRhU291cmNlT3B0aW9ucyxcbiAgVHlwZU9STVF1ZXJ5LFxuICBUeXBlT1JNRmxhZ3MsXG4gIENvbnRleHQ8VHlwZU9STUZsYWdzPlxuPiB7XG4gIHByaXZhdGUgX2RhdGFTb3VyY2U/OiBEYXRhU291cmNlO1xuXG4gIGdldCBkYXRhU291cmNlKCk6IERhdGFTb3VyY2Uge1xuICAgIGlmICghdGhpcy5fZGF0YVNvdXJjZSkge1xuICAgICAgY29uc3QgbW9kZWxzID0gQWRhcHRlci5tb2RlbHModGhpcy5mbGF2b3VyKTtcbiAgICAgIHRoaXMuX2RhdGFTb3VyY2UgPSBuZXcgRGF0YVNvdXJjZShcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLm5hdGl2ZSwge1xuICAgICAgICAgIGVudGl0aWVzOiBtb2RlbHMubWFwKChjKSA9PiBjW01vZGVsS2V5cy5BTkNIT1IgYXMga2V5b2YgdHlwZW9mIGNdKSxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9kYXRhU291cmNlO1xuICB9XG4gIC8vIHByb3RlY3RlZCBkYXRhU291XG5cbiAgY29uc3RydWN0b3Iob3B0aW9uczogRGF0YVNvdXJjZU9wdGlvbnMsIGFsaWFzPzogc3RyaW5nKSB7XG4gICAgc3VwZXIob3B0aW9ucywgVHlwZU9STUZsYXZvdXIsIGFsaWFzKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyBmbGFnczxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG9wZXJhdGlvbjogT3BlcmF0aW9uS2V5cyxcbiAgICBtb2RlbDogQ29uc3RydWN0b3I8TT4sXG4gICAgZmxhZ3M6IFBhcnRpYWw8VHlwZU9STUZsYWdzPlxuICApOiBQcm9taXNlPFR5cGVPUk1GbGFncz4ge1xuICAgIGNvbnN0IGYgPSBhd2FpdCBzdXBlci5mbGFncyhvcGVyYXRpb24sIG1vZGVsLCBmbGFncyk7XG4gICAgY29uc3QgbmV3T2JqOiBhbnkgPSB7XG4gICAgICB1c2VyOiAoYXdhaXQgVHlwZU9STUFkYXB0ZXIuZ2V0Q3VycmVudFVzZXIodGhpcy5kYXRhU291cmNlKSkgYXMgc3RyaW5nLFxuICAgIH07XG4gICAgY29uc3QgbSA9IG5ldyBtb2RlbCgpO1xuXG4gICAgY29uc3QgZXhjZXB0aW9uczogc3RyaW5nW10gPSBbXTtcbiAgICBpZiAob3BlcmF0aW9uID09PSBPcGVyYXRpb25LZXlzLkNSRUFURSkge1xuICAgICAgY29uc3QgcGsgPSBmaW5kUHJpbWFyeUtleShtKS5pZDtcbiAgICAgIGV4Y2VwdGlvbnMucHVzaChwayBhcyBzdHJpbmcpO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIG9wZXJhdGlvbiA9PT0gT3BlcmF0aW9uS2V5cy5DUkVBVEUgfHxcbiAgICAgIG9wZXJhdGlvbiA9PT0gT3BlcmF0aW9uS2V5cy5VUERBVEVcbiAgICApIHtcbiAgICAgIGNvbnN0IGRlY3MgPSBPYmplY3Qua2V5cyhtKS5yZWR1Y2UoKGFjY3VtOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBrZXkpID0+IHtcbiAgICAgICAgY29uc3QgZGVjcyA9IFJlZmxlY3Rpb24uZ2V0UHJvcGVydHlEZWNvcmF0b3JzKFxuICAgICAgICAgIFZhbGlkYXRpb25LZXlzLlJFRkxFQ1QsXG4gICAgICAgICAgbSxcbiAgICAgICAgICBrZXksXG4gICAgICAgICAgdHJ1ZVxuICAgICAgICApO1xuICAgICAgICBjb25zdCBkZWMgPSBkZWNzLmRlY29yYXRvcnMuZmluZChcbiAgICAgICAgICAoZGVjOiBhbnkpID0+XG4gICAgICAgICAgICBkZWMua2V5ID09PSBEQktleXMuVElNRVNUQU1QICYmXG4gICAgICAgICAgICBkZWMucHJvcHMub3BlcmF0aW9uLmluZGV4T2Yob3BlcmF0aW9uKSAhPT0gLTFcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGRlYykge1xuICAgICAgICAgIGFjY3VtW2tleV0gPSBkZWMucHJvcHM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFjY3VtO1xuICAgICAgfSwge30pO1xuXG4gICAgICBleGNlcHRpb25zLnB1c2goLi4uT2JqZWN0LmtleXMoZGVjcykpO1xuICAgIH1cblxuICAgIG5ld09iai5pZ25vcmVkVmFsaWRhdGlvblByb3BlcnRpZXMgPSAoXG4gICAgICBmLmlnbm9yZWRWYWxpZGF0aW9uUHJvcGVydGllcyA/IGYuaWdub3JlZFZhbGlkYXRpb25Qcm9wZXJ0aWVzIDogW11cbiAgICApLmNvbmNhdCguLi5leGNlcHRpb25zKTtcbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihmLCBuZXdPYmopIGFzIFR5cGVPUk1GbGFncztcbiAgfVxuXG4gIEBmaW5hbCgpXG4gIHByb3RlY3RlZCBvdmVycmlkZSBEaXNwYXRjaCgpOiBUeXBlT1JNRGlzcGF0Y2gge1xuICAgIHJldHVybiBuZXcgVHlwZU9STURpc3BhdGNoKCk7XG4gIH1cblxuICBAZmluYWwoKVxuICBvdmVycmlkZSByZXBvc2l0b3J5PE0gZXh0ZW5kcyBNb2RlbD4oKTogQ29uc3RydWN0b3I8VHlwZU9STVJlcG9zaXRvcnk8TT4+IHtcbiAgICByZXR1cm4gVHlwZU9STVJlcG9zaXRvcnk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgUG9zdGdyZXMgc3RhdGVtZW50IGZvciBxdWVyeWluZ1xuICAgKiBAc3VtbWFyeSBGYWN0b3J5IG1ldGhvZCB0aGF0IGNyZWF0ZXMgYSBuZXcgUG9zdGdyZXNTdGF0ZW1lbnQgaW5zdGFuY2UgZm9yIGJ1aWxkaW5nIHF1ZXJpZXNcbiAgICogQHRlbXBsYXRlIE0gLSBUaGUgbW9kZWwgdHlwZVxuICAgKiBAcmV0dXJuIHtUeXBlT1JNU3RhdGVtZW50PE0sIGFueT59IEEgbmV3IFBvc3RncmVzU3RhdGVtZW50IGluc3RhbmNlXG4gICAqL1xuICBAZmluYWwoKVxuICBTdGF0ZW1lbnQ8TSBleHRlbmRzIE1vZGVsPigpOiBUeXBlT1JNU3RhdGVtZW50PE0sIGFueT4ge1xuICAgIHJldHVybiBuZXcgVHlwZU9STVN0YXRlbWVudCh0aGlzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG5ldyBQb3N0Z3JlU1FMIHNlcXVlbmNlXG4gICAqIEBzdW1tYXJ5IEZhY3RvcnkgbWV0aG9kIHRoYXQgY3JlYXRlcyBhIG5ldyBQb3N0Z3JlU1FMU2VxdWVuY2UgaW5zdGFuY2UgZm9yIG1hbmFnaW5nIHNlcXVlbmNlc1xuICAgKiBAcGFyYW0ge1NlcXVlbmNlT3B0aW9uc30gb3B0aW9ucyAtIFRoZSBvcHRpb25zIGZvciB0aGUgc2VxdWVuY2VcbiAgICogQHJldHVybiB7UHJvbWlzZTxTZXF1ZW5jZT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgbmV3IFNlcXVlbmNlIGluc3RhbmNlXG4gICAqL1xuICBAZmluYWwoKVxuICBhc3luYyBTZXF1ZW5jZShvcHRpb25zOiBTZXF1ZW5jZU9wdGlvbnMpOiBQcm9taXNlPFNlcXVlbmNlPiB7XG4gICAgcmV0dXJuIG5ldyBUeXBlT1JNU2VxdWVuY2Uob3B0aW9ucywgdGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemVzIHRoZSBhZGFwdGVyIGJ5IGNyZWF0aW5nIGluZGV4ZXMgZm9yIGFsbCBtYW5hZ2VkIG1vZGVsc1xuICAgKiBAc3VtbWFyeSBTZXRzIHVwIHRoZSBuZWNlc3NhcnkgZGF0YWJhc2UgaW5kZXhlcyBmb3IgYWxsIG1vZGVscyBtYW5hZ2VkIGJ5IHRoaXMgYWRhcHRlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGluaXRpYWxpemF0aW9uIGlzIGNvbXBsZXRlXG4gICAqL1xuICBhc3luYyBpbml0aWFsaXplKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGRzID0gdGhpcy5kYXRhU291cmNlO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBkcy5pbml0aWFsaXplKCk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUgYXMgRXJyb3IpO1xuICAgIH1cbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5pbml0aWFsaXplKTtcbiAgICBsb2cudmVyYm9zZShgJHt0aGlzLmZsYXZvdXJ9IGFkYXB0ZXIgaW5pdGlhbGl6ZWRgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBpbmRleGVzIGZvciB0aGUgZ2l2ZW4gbW9kZWxzXG4gICAqIEBzdW1tYXJ5IEFic3RyYWN0IG1ldGhvZCB0aGF0IG11c3QgYmUgaW1wbGVtZW50ZWQgdG8gY3JlYXRlIGRhdGFiYXNlIGluZGV4ZXMgZm9yIHRoZSBzcGVjaWZpZWQgbW9kZWxzXG4gICAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGVcbiAgICogQHBhcmFtIHsuLi5Db25zdHJ1Y3RvcjxNPn0gbW9kZWxzIC0gVGhlIG1vZGVsIGNvbnN0cnVjdG9ycyB0byBjcmVhdGUgaW5kZXhlcyBmb3JcbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBhbGwgaW5kZXhlcyBhcmUgY3JlYXRlZFxuICAgKi9cbiAgQGZpbmFsKClcbiAgcHJvdGVjdGVkIGFzeW5jIGluZGV4PE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgLi4ubW9kZWxzOiBDb25zdHJ1Y3RvcjxNPltdXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGluZGV4ZXM6IFR5cGVPUk1RdWVyeVtdID0gZ2VuZXJhdGVJbmRleGVzKG1vZGVscyk7XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5kYXRhU291cmNlLnF1ZXJ5KFwiQkVHSU5cIik7XG5cbiAgICAgIGZvciAoY29uc3QgaW5kZXggb2YgaW5kZXhlcykge1xuICAgICAgICBhd2FpdCB0aGlzLmRhdGFTb3VyY2UucXVlcnkoaW5kZXgucXVlcnksIGluZGV4LnZhbHVlcyk7XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IHRoaXMuZGF0YVNvdXJjZS5xdWVyeShcIkNPTU1JVFwiKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICBhd2FpdCB0aGlzLmRhdGFTb3VyY2UucXVlcnkoXCJST0xMQkFDS1wiKTtcbiAgICAgIHRocm93IHRoaXMucGFyc2VFcnJvcihlIGFzIEVycm9yKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEV4ZWN1dGVzIGEgcmF3IFNRTCBxdWVyeSBhZ2FpbnN0IHRoZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBBYnN0cmFjdCBtZXRob2QgdGhhdCBtdXN0IGJlIGltcGxlbWVudGVkIHRvIGV4ZWN1dGUgcmF3IFNRTCBxdWVyaWVzXG4gICAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHJlc3VsdCB0eXBlXG4gICAqIEBwYXJhbSB7VHlwZU9STVF1ZXJ5fSBxIC0gVGhlIHF1ZXJ5IHRvIGV4ZWN1dGVcbiAgICogQHJldHVybiB7UHJvbWlzZTxSPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHF1ZXJ5IHJlc3VsdFxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgcmF3PFI+KHE6IFR5cGVPUk1RdWVyeSk6IFByb21pc2U8Uj4ge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLnJhdyk7XG4gICAgdHJ5IHtcbiAgICAgIGlmICghdGhpcy5kYXRhU291cmNlLmlzSW5pdGlhbGl6ZWQpIGF3YWl0IHRoaXMuZGF0YVNvdXJjZS5pbml0aWFsaXplKCk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUgYXMgRXJyb3IpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgY29uc3QgeyBxdWVyeSwgdmFsdWVzIH0gPSBxO1xuICAgICAgbG9nLmRlYnVnKFxuICAgICAgICBgZXhlY3V0aW5nIHF1ZXJ5OiAkeyhxdWVyeSBhcyB1bmtub3duIGFzIFNlbGVjdFF1ZXJ5QnVpbGRlcjxhbnk+KS5nZXRTcWwoKX1gXG4gICAgICApO1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmRhdGFTb3VyY2UucXVlcnkocXVlcnksIHZhbHVlcyk7XG4gICAgICByZXR1cm4gcmVzcG9uc2UgYXMgUjtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgb3ZlcnJpZGUgcHJlcGFyZTxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG1vZGVsOiBNLFxuICAgIHBrOiBrZXlvZiBNLFxuICAgIGNoaWxkID0gZmFsc2VcbiAgKToge1xuICAgIHJlY29yZDogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgICBpZDogc3RyaW5nO1xuICAgIHRyYW5zaWVudD86IFJlY29yZDxzdHJpbmcsIGFueT47XG4gIH0ge1xuICAgIGNvbnN0IHByZXBhcmVkID0gc3VwZXIucHJlcGFyZShtb2RlbCwgcGspO1xuXG4gICAgcHJlcGFyZWQucmVjb3JkID0gT2JqZWN0LmVudHJpZXMocHJlcGFyZWQucmVjb3JkKS5yZWR1Y2UoXG4gICAgICAoYWNjdW06IFJlY29yZDxzdHJpbmcsIGFueT4sIFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgICBpZiAoa2V5ID09PSBQZXJzaXN0ZW5jZUtleXMuTUVUQURBVEEgfHwgdGhpcy5pc1Jlc2VydmVkKGtleSkpXG4gICAgICAgICAgcmV0dXJuIGFjY3VtO1xuICAgICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHJldHVybiBhY2N1bTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgICB2YWx1ZSA9IG5ldyBEYXRlKHZhbHVlLmdldFRpbWUoKSk7XG4gICAgICAgIH0gZWxzZSBpZiAoTW9kZWwuaXNNb2RlbCh2YWx1ZSkpIHtcbiAgICAgICAgICB2YWx1ZSA9IHRoaXMucHJlcGFyZSh2YWx1ZSwgZmluZFByaW1hcnlLZXkodmFsdWUpLmlkLCB0cnVlKS5yZWNvcmQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc3dpdGNoICh0eXBlb2YgdmFsdWUpIHtcbiAgICAgICAgICAgIGNhc2UgXCJzdHJpbmdcIjpcbiAgICAgICAgICAgICAgdmFsdWUgPSBgJHt2YWx1ZX1gO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAvL2RvIG5vdGhpbmc7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGFjY3VtW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgcmV0dXJuIGFjY3VtO1xuICAgICAgfSxcbiAgICAgIHt9XG4gICAgKTtcbiAgICBjb25zdCBjb25zdHI6IENvbnN0cnVjdG9yPGFueT4gfCB1bmRlZmluZWQgPSBNb2RlbC5nZXQoXG4gICAgICBtb2RlbC5jb25zdHJ1Y3Rvci5uYW1lXG4gICAgKTtcbiAgICBpZiAoIWNvbnN0cilcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICBgTW9kZWwgJHttb2RlbC5jb25zdHJ1Y3Rvci5uYW1lfSBub3QgZm91bmQgaW4gcmVnaXN0cnlgXG4gICAgICApO1xuICAgIGNvbnN0IHJlc3VsdCA9IGNoaWxkXG4gICAgICA/IG5ldyAoY29uc3RyIGFzIGFueSlbTW9kZWxLZXlzLkFOQ0hPUiBhcyBrZXlvZiB0eXBlb2YgY29uc3RyXSgpXG4gICAgICA6IG5ldyBjb25zdHIoKTtcbiAgICBpZiAoY2hpbGQpXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkocmVzdWx0LCBcImNvbnN0cnVjdG9yXCIsIHtcbiAgICAgICAgY29uZmlndXJhYmxlOiBmYWxzZSxcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHZhbHVlOiAoY29uc3RyIGFzIGFueSlbTW9kZWxLZXlzLkFOQ0hPUiBhcyBrZXlvZiB0eXBlb2YgY29uc3RyXSxcbiAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgfSk7XG4gICAgT2JqZWN0LmVudHJpZXMocHJlcGFyZWQucmVjb3JkKS5mb3JFYWNoKFxuICAgICAgKFtrZXksIHZhbF0pID0+IChyZXN1bHRba2V5IGFzIGtleW9mIHR5cGVvZiByZXN1bHRdID0gdmFsKVxuICAgICk7XG4gICAgcHJlcGFyZWQucmVjb3JkID0gcmVzdWx0O1xuICAgIHJldHVybiBwcmVwYXJlZDtcbiAgfVxuXG4gIG92ZXJyaWRlIHJldmVydDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG9iajogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICBjbGF6ejogc3RyaW5nIHwgQ29uc3RydWN0b3I8TT4sXG4gICAgcGs6IGtleW9mIE0sXG4gICAgaWQ6IHN0cmluZyB8IG51bWJlciB8IGJpZ2ludCxcbiAgICB0cmFuc2llbnQ/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+XG4gICk6IE0ge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLnJldmVydCk7XG4gICAgaWYgKHRyYW5zaWVudCkge1xuICAgICAgbG9nLnZlcmJvc2UoXG4gICAgICAgIGByZS1hZGRpbmcgdHJhbnNpZW50IHByb3BlcnRpZXM6ICR7T2JqZWN0LmtleXModHJhbnNpZW50KS5qb2luKFwiLCBcIil9YFxuICAgICAgKTtcbiAgICAgIE9iamVjdC5lbnRyaWVzKHRyYW5zaWVudCkuZm9yRWFjaCgoW2tleSwgdmFsXSkgPT4ge1xuICAgICAgICBpZiAoa2V5IGluIG9iailcbiAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICAgIGBUcmFuc2llbnQgcHJvcGVydHkgJHtrZXl9IGFscmVhZHkgZXhpc3RzIG9uIG1vZGVsICR7dHlwZW9mIGNsYXp6ID09PSBcInN0cmluZ1wiID8gY2xhenogOiBjbGF6ei5uYW1lfS4gc2hvdWxkIGJlIGltcG9zc2libGVgXG4gICAgICAgICAgKTtcbiAgICAgICAgKG9iaiBhcyBNKVtrZXkgYXMga2V5b2YgTV0gPSB2YWw7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IChjbGF6eiBhcyBDb25zdHJ1Y3RvcjxNPikob2JqKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG5ldyByZWNvcmQgaW4gdGhlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IEFic3RyYWN0IG1ldGhvZCB0aGF0IG11c3QgYmUgaW1wbGVtZW50ZWQgdG8gY3JlYXRlIGEgbmV3IHJlY29yZFxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlXG4gICAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gaWQgLSBUaGUgSUQgb2YgdGhlIHJlY29yZFxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IG1vZGVsIC0gVGhlIG1vZGVsIHRvIGNyZWF0ZVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIGNyZWF0ZWQgcmVjb3JkXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyBjcmVhdGUoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IHN0cmluZyB8IG51bWJlcixcbiAgICBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gICAgY29uc3QgbTogQ29uc3RydWN0b3I8TW9kZWw+ID0gdGFibGVOYW1lIGFzIHVua25vd24gYXMgQ29uc3RydWN0b3I8TW9kZWw+O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXBvID0gdGhpcy5kYXRhU291cmNlLmdldFJlcG9zaXRvcnkobSk7XG4gICAgICByZXR1cm4gYXdhaXQgcmVwby5zYXZlKG1vZGVsKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWFkcyBhIHJlY29yZCBmcm9tIHRoZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBBYnN0cmFjdCBtZXRob2QgdGhhdCBtdXN0IGJlIGltcGxlbWVudGVkIHRvIHJlYWQgYSByZWNvcmRcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZVxuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIC0gVGhlIElEIG9mIHRoZSByZWNvcmRcbiAgICogQHBhcmFtIHtzdHJpbmd9IHBrIC0gcHJpbWFyeSBrZXkgY29sdW1cbiAgICogQHJldHVybiB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHJlYWQgcmVjb3JkXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyByZWFkKFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIGlkOiBzdHJpbmcgfCBudW1iZXIsXG4gICAgcGs6IHN0cmluZ1xuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+IHtcbiAgICBjb25zdCBtOiBDb25zdHJ1Y3RvcjxNb2RlbD4gPSB0YWJsZU5hbWUgYXMgdW5rbm93biBhcyBDb25zdHJ1Y3RvcjxNb2RlbD47XG4gICAgbGV0IHJlc3VsdDogYW55O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXBvID0gdGhpcy5kYXRhU291cmNlLmdldFJlcG9zaXRvcnkobSk7XG4gICAgICBjb25zdCBxOiBGaW5kT25lT3B0aW9ucyA9IHtcbiAgICAgICAgd2hlcmU6IHtcbiAgICAgICAgICBbcGtdOiBpZCxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgICByZXN1bHQgPSAoYXdhaXQgcmVwby5maW5kT25lKHEpKSBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IHRoaXMucGFyc2VFcnJvcihlIGFzIEVycm9yKTtcbiAgICB9XG4gICAgaWYgKCFyZXN1bHQpXG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFcnJvcihcbiAgICAgICAgYFJlY29yZCB3aXRoIGlkOiAke2lkfSBub3QgZm91bmQgaW4gdGFibGUgJHt0eXBlb2YgdGFibGVOYW1lID09PSBcInN0cmluZ1wiID8gdGFibGVOYW1lIDogUmVwb3NpdG9yeS50YWJsZSh0YWJsZU5hbWUpfWBcbiAgICAgICk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVXBkYXRlcyBhIHJlY29yZCBpbiB0aGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgQWJzdHJhY3QgbWV0aG9kIHRoYXQgbXVzdCBiZSBpbXBsZW1lbnRlZCB0byB1cGRhdGUgYSByZWNvcmRcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZVxuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIC0gVGhlIElEIG9mIHRoZSByZWNvcmRcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBtb2RlbCAtIFRoZSBtb2RlbCB0byB1cGRhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHBrIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgdXBkYXRlZCByZWNvcmRcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIHVwZGF0ZShcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZDogc3RyaW5nIHwgbnVtYmVyLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+IHtcbiAgICBjb25zdCBtOiBDb25zdHJ1Y3RvcjxNb2RlbD4gPSB0YWJsZU5hbWUgYXMgdW5rbm93biBhcyBDb25zdHJ1Y3RvcjxNb2RlbD47XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcG8gPSB0aGlzLmRhdGFTb3VyY2UuZ2V0UmVwb3NpdG9yeShtKTtcbiAgICAgIHJldHVybiByZXBvLnNhdmUobW9kZWwpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IHRoaXMucGFyc2VFcnJvcihlIGFzIEVycm9yKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERlbGV0ZXMgYSByZWNvcmQgZnJvbSB0aGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgQWJzdHJhY3QgbWV0aG9kIHRoYXQgbXVzdCBiZSBpbXBsZW1lbnRlZCB0byBkZWxldGUgYSByZWNvcmRcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZVxuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIC0gVGhlIElEIG9mIHRoZSByZWNvcmRcbiAgICogQHBhcmFtIHtzdHJpbmd9IHBrIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgZGVsZXRlZCByZWNvcmRcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIGRlbGV0ZShcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZDogc3RyaW5nIHwgbnVtYmVyLFxuICAgIHBrOiBzdHJpbmcsXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj4ge1xuICAgIGNvbnN0IG06IENvbnN0cnVjdG9yPE1vZGVsPiA9IHRhYmxlTmFtZSBhcyB1bmtub3duIGFzIENvbnN0cnVjdG9yPE1vZGVsPjtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVwbyA9IHRoaXMuZGF0YVNvdXJjZS5nZXRSZXBvc2l0b3J5KG0pO1xuICAgICAgY29uc3QgbW9kZWwgPSBhd2FpdCB0aGlzLnJlYWQodGFibGVOYW1lLCBpZCwgcGspO1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgcmVwby5kZWxldGUoaWQpO1xuICAgICAgcmV0dXJuIG1vZGVsO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IHRoaXMucGFyc2VFcnJvcihlIGFzIEVycm9yKTtcbiAgICB9XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBjcmVhdGVBbGwoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IChzdHJpbmcgfCBudW1iZXIpW10sXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT5bXSxcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+W10+IHtcbiAgICBjb25zdCBtOiBDb25zdHJ1Y3RvcjxNb2RlbD4gPSB0YWJsZU5hbWUgYXMgdW5rbm93biBhcyBDb25zdHJ1Y3RvcjxNb2RlbD47XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcG8gPSB0aGlzLmRhdGFTb3VyY2UuZ2V0UmVwb3NpdG9yeShtKTtcbiAgICAgIGNvbnN0IHJlc3VsdDogSW5zZXJ0UmVzdWx0ID0gYXdhaXQgcmVwby5pbnNlcnQobW9kZWwpO1xuICAgICAgcmV0dXJuIHRoaXMucmVhZEFsbChcbiAgICAgICAgdGFibGVOYW1lLFxuICAgICAgICByZXN1bHQuaWRlbnRpZmllcnMubWFwKChpZCkgPT4gaWQuaWQpLFxuICAgICAgICBcImlkXCJcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUgYXMgRXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIHJlYWRBbGwoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IChzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQpW10sXG4gICAgcGs6IHN0cmluZyxcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+W10+IHtcbiAgICBpZiAoIWlkLmxlbmd0aCkgcmV0dXJuIFtdO1xuXG4gICAgY29uc3QgbTogQ29uc3RydWN0b3I8TW9kZWw+ID0gdGFibGVOYW1lIGFzIHVua25vd24gYXMgQ29uc3RydWN0b3I8TW9kZWw+O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXBvID0gdGhpcy5kYXRhU291cmNlLmdldFJlcG9zaXRvcnkobSk7XG4gICAgICByZXR1cm4gcmVwby5maW5kQnkoeyBbcGtdOiBJbihpZCkgfSk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUgYXMgRXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIHVwZGF0ZUFsbChcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZHM6IHN0cmluZ1tdIHwgbnVtYmVyW10sXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT5bXSxcbiAgICBwazogc3RyaW5nLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55PltdPiB7XG4gICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgZm9yIChjb25zdCBtIG9mIG1vZGVsKSB7XG4gICAgICByZXN1bHQucHVzaChhd2FpdCB0aGlzLnVwZGF0ZSh0YWJsZU5hbWUsIG1bcGtdLCBtLCAuLi5hcmdzKSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBkZWxldGVBbGwoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWRzOiAoc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50KVtdLFxuICAgIHBrOiBzdHJpbmcsXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55PltdPiB7XG4gICAgaWYgKCFpZHMubGVuZ3RoKSByZXR1cm4gW107XG4gICAgY29uc3QgbTogQ29uc3RydWN0b3I8TW9kZWw+ID0gdGFibGVOYW1lIGFzIHVua25vd24gYXMgQ29uc3RydWN0b3I8TW9kZWw+O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXBvID0gdGhpcy5kYXRhU291cmNlLmdldFJlcG9zaXRvcnkobSk7XG4gICAgICBjb25zdCBtb2RlbHMgPSBhd2FpdCB0aGlzLnJlYWRBbGwodGFibGVOYW1lLCBpZHMsIHBrKTtcbiAgICAgIGF3YWl0IHJlcG8uZGVsZXRlKGlkcyk7XG4gICAgICByZXR1cm4gbW9kZWxzO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IHRoaXMucGFyc2VFcnJvcihlIGFzIEVycm9yKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFBhcnNlcyBhbiBlcnJvciBhbmQgY29udmVydHMgaXQgdG8gYSBCYXNlRXJyb3JcbiAgICogQHN1bW1hcnkgQ29udmVydHMgdmFyaW91cyBlcnJvciB0eXBlcyB0byBhcHByb3ByaWF0ZSBCYXNlRXJyb3Igc3VidHlwZXNcbiAgICogQHBhcmFtIHtFcnJvcnxzdHJpbmd9IGVyciAtIFRoZSBlcnJvciB0byBwYXJzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3JlYXNvbl0gLSBPcHRpb25hbCByZWFzb24gZm9yIHRoZSBlcnJvclxuICAgKiBAcmV0dXJuIHtCYXNlRXJyb3J9IFRoZSBwYXJzZWQgZXJyb3IgYXMgYSBCYXNlRXJyb3JcbiAgICovXG4gIHBhcnNlRXJyb3IoZXJyOiBFcnJvciB8IHN0cmluZywgcmVhc29uPzogc3RyaW5nKTogQmFzZUVycm9yIHtcbiAgICByZXR1cm4gVHlwZU9STUFkYXB0ZXIucGFyc2VFcnJvcihlcnIsIHJlYXNvbik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENoZWNrcyBpZiBhbiBhdHRyaWJ1dGUgaXMgcmVzZXJ2ZWRcbiAgICogQHN1bW1hcnkgRGV0ZXJtaW5lcyBpZiBhbiBhdHRyaWJ1dGUgbmFtZSBpcyByZXNlcnZlZCBpbiBQb3N0Z3JlU1FMXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhdHRyIC0gVGhlIGF0dHJpYnV0ZSBuYW1lIHRvIGNoZWNrXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgdGhlIGF0dHJpYnV0ZSBpcyByZXNlcnZlZCwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAqL1xuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgaXNSZXNlcnZlZChhdHRyOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISFhdHRyLm1hdGNoKHJlc2VydmVkQXR0cmlidXRlcyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFN0YXRpYyBtZXRob2QgdG8gcGFyc2UgYW4gZXJyb3IgYW5kIGNvbnZlcnQgaXQgdG8gYSBCYXNlRXJyb3JcbiAgICogQHN1bW1hcnkgQ29udmVydHMgdmFyaW91cyBlcnJvciB0eXBlcyB0byBhcHByb3ByaWF0ZSBCYXNlRXJyb3Igc3VidHlwZXMgYmFzZWQgb24gUG9zdGdyZVNRTCBlcnJvciBjb2RlcyBhbmQgbWVzc2FnZXNcbiAgICogQHBhcmFtIHtFcnJvcnxzdHJpbmd9IGVyciAtIFRoZSBlcnJvciB0byBwYXJzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3JlYXNvbl0gLSBPcHRpb25hbCByZWFzb24gZm9yIHRoZSBlcnJvclxuICAgKiBAcmV0dXJuIHtCYXNlRXJyb3J9IFRoZSBwYXJzZWQgZXJyb3IgYXMgYSBCYXNlRXJyb3JcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gICAqICAgcGFydGljaXBhbnQgcGFyc2VFcnJvclxuICAgKiAgIHBhcnRpY2lwYW50IEVycm9yVHlwZXNcbiAgICpcbiAgICogICBDYWxsZXItPj5wYXJzZUVycm9yOiBlcnIsIHJlYXNvblxuICAgKiAgIE5vdGUgb3ZlciBwYXJzZUVycm9yOiBDaGVjayBpZiBlcnIgaXMgYWxyZWFkeSBhIEJhc2VFcnJvclxuICAgKiAgIGFsdCBlcnIgaXMgQmFzZUVycm9yXG4gICAqICAgICBwYXJzZUVycm9yLS0+PkNhbGxlcjogcmV0dXJuIGVyclxuICAgKiAgIGVsc2UgZXJyIGlzIHN0cmluZ1xuICAgKiAgICAgTm90ZSBvdmVyIHBhcnNlRXJyb3I6IEV4dHJhY3QgY29kZSBmcm9tIHN0cmluZ1xuICAgKiAgICAgYWx0IGNvZGUgbWF0Y2hlcyBcImR1cGxpY2F0ZSBrZXl8YWxyZWFkeSBleGlzdHNcIlxuICAgKiAgICAgICBwYXJzZUVycm9yLT4+RXJyb3JUeXBlczogbmV3IENvbmZsaWN0RXJyb3IoY29kZSlcbiAgICogICAgICAgRXJyb3JUeXBlcy0tPj5DYWxsZXI6IENvbmZsaWN0RXJyb3JcbiAgICogICAgIGVsc2UgY29kZSBtYXRjaGVzIFwiZG9lcyBub3QgZXhpc3R8bm90IGZvdW5kXCJcbiAgICogICAgICAgcGFyc2VFcnJvci0+PkVycm9yVHlwZXM6IG5ldyBOb3RGb3VuZEVycm9yKGNvZGUpXG4gICAqICAgICAgIEVycm9yVHlwZXMtLT4+Q2FsbGVyOiBOb3RGb3VuZEVycm9yXG4gICAqICAgICBlbmRcbiAgICogICBlbHNlIGVyciBoYXMgY29kZSBwcm9wZXJ0eVxuICAgKiAgICAgTm90ZSBvdmVyIHBhcnNlRXJyb3I6IEV4dHJhY3QgY29kZSBhbmQgcmVhc29uXG4gICAqICAgZWxzZVxuICAgKiAgICAgTm90ZSBvdmVyIHBhcnNlRXJyb3I6IFVzZSBlcnIubWVzc2FnZSBhcyBjb2RlXG4gICAqICAgZW5kXG4gICAqXG4gICAqICAgTm90ZSBvdmVyIHBhcnNlRXJyb3I6IFN3aXRjaCBvbiBQb3N0Z3JlU1FMIGVycm9yIGNvZGVcbiAgICogICBhbHQgY29kZSBpcyAyMzUwNSAodW5pcXVlX3Zpb2xhdGlvbilcbiAgICogICAgIHBhcnNlRXJyb3ItPj5FcnJvclR5cGVzOiBuZXcgQ29uZmxpY3RFcnJvcihyZWFzb24pXG4gICAqICAgICBFcnJvclR5cGVzLS0+PkNhbGxlcjogQ29uZmxpY3RFcnJvclxuICAgKiAgIGVsc2UgY29kZSBpcyAyMzUwMyAoZm9yZWlnbl9rZXlfdmlvbGF0aW9uKVxuICAgKiAgICAgcGFyc2VFcnJvci0+PkVycm9yVHlwZXM6IG5ldyBDb25mbGljdEVycm9yKHJlYXNvbilcbiAgICogICAgIEVycm9yVHlwZXMtLT4+Q2FsbGVyOiBDb25mbGljdEVycm9yXG4gICAqICAgZWxzZSBjb2RlIGlzIDQyUDAxICh1bmRlZmluZWRfdGFibGUpXG4gICAqICAgICBwYXJzZUVycm9yLT4+RXJyb3JUeXBlczogbmV3IE5vdEZvdW5kRXJyb3IocmVhc29uKVxuICAgKiAgICAgRXJyb3JUeXBlcy0tPj5DYWxsZXI6IE5vdEZvdW5kRXJyb3JcbiAgICogICBlbHNlIGNvZGUgaXMgNDI3MDMgKHVuZGVmaW5lZF9jb2x1bW4pXG4gICAqICAgICBwYXJzZUVycm9yLT4+RXJyb3JUeXBlczogbmV3IE5vdEZvdW5kRXJyb3IocmVhc29uKVxuICAgKiAgICAgRXJyb3JUeXBlcy0tPj5DYWxsZXI6IE5vdEZvdW5kRXJyb3JcbiAgICogICBlbHNlIGNvZGUgaXMgNDJQMDcgKGR1cGxpY2F0ZV90YWJsZSlcbiAgICogICAgIHBhcnNlRXJyb3ItPj5FcnJvclR5cGVzOiBuZXcgQ29uZmxpY3RFcnJvcihyZWFzb24pXG4gICAqICAgICBFcnJvclR5cGVzLS0+PkNhbGxlcjogQ29uZmxpY3RFcnJvclxuICAgKiAgIGVsc2UgY29kZSBpcyA0MlAxNiAoaW52YWxpZF90YWJsZV9kZWZpbml0aW9uKVxuICAgKiAgICAgcGFyc2VFcnJvci0+PkVycm9yVHlwZXM6IG5ldyBJbmRleEVycm9yKGVycilcbiAgICogICAgIEVycm9yVHlwZXMtLT4+Q2FsbGVyOiBJbmRleEVycm9yXG4gICAqICAgZWxzZSBjb2RlIG1hdGNoZXMgXCJFQ09OTlJFRlVTRURcIlxuICAgKiAgICAgcGFyc2VFcnJvci0+PkVycm9yVHlwZXM6IG5ldyBDb25uZWN0aW9uRXJyb3IoZXJyKVxuICAgKiAgICAgRXJyb3JUeXBlcy0tPj5DYWxsZXI6IENvbm5lY3Rpb25FcnJvclxuICAgKiAgIGVsc2VcbiAgICogICAgIHBhcnNlRXJyb3ItPj5FcnJvclR5cGVzOiBuZXcgSW50ZXJuYWxFcnJvcihlcnIpXG4gICAqICAgICBFcnJvclR5cGVzLS0+PkNhbGxlcjogSW50ZXJuYWxFcnJvclxuICAgKiAgIGVuZFxuICAgKi9cbiAgcHJvdGVjdGVkIHN0YXRpYyBwYXJzZUVycm9yKGVycjogRXJyb3IgfCBzdHJpbmcsIHJlYXNvbj86IHN0cmluZyk6IEJhc2VFcnJvciB7XG4gICAgaWYgKGVyciBpbnN0YW5jZW9mIEJhc2VFcnJvcikgcmV0dXJuIGVyciBhcyBhbnk7XG4gICAgY29uc3QgY29kZTogc3RyaW5nID0gdHlwZW9mIGVyciA9PT0gXCJzdHJpbmdcIiA/IGVyciA6IGVyci5tZXNzYWdlO1xuXG4gICAgaWYgKGNvZGUubWF0Y2goL2R1cGxpY2F0ZSBrZXl8YWxyZWFkeSBleGlzdHMvZykpXG4gICAgICByZXR1cm4gbmV3IENvbmZsaWN0RXJyb3IoY29kZSk7XG4gICAgaWYgKGNvZGUubWF0Y2goL2RvZXMgbm90IGV4aXN0fG5vdCBmb3VuZC9nKSkgcmV0dXJuIG5ldyBOb3RGb3VuZEVycm9yKGNvZGUpO1xuXG4gICAgLy8gUG9zdGdyZVNRTCBlcnJvciBjb2RlczogaHR0cHM6Ly93d3cucG9zdGdyZXNxbC5vcmcvZG9jcy9jdXJyZW50L2VycmNvZGVzLWFwcGVuZGl4Lmh0bWxcbiAgICBzd2l0Y2ggKGNvZGUudG9TdHJpbmcoKSkge1xuICAgICAgLy8gSW50ZWdyaXR5IGNvbnN0cmFpbnQgdmlvbGF0aW9uc1xuICAgICAgY2FzZSBcIjIzNTA1XCI6IC8vIHVuaXF1ZV92aW9sYXRpb25cbiAgICAgIGNhc2UgXCIyMzUwM1wiOiAvLyBmb3JlaWduX2tleV92aW9sYXRpb25cbiAgICAgIGNhc2UgXCI0MlAwN1wiOiAvLyBkdXBsaWNhdGVfdGFibGVcbiAgICAgICAgcmV0dXJuIG5ldyBDb25mbGljdEVycm9yKHJlYXNvbiBhcyBzdHJpbmcpO1xuXG4gICAgICAvLyBPYmplY3Qgbm90IGZvdW5kIGVycm9yc1xuICAgICAgY2FzZSBcIjQyUDAxXCI6IC8vIHVuZGVmaW5lZF90YWJsZVxuICAgICAgY2FzZSBcIjQyNzAzXCI6IC8vIHVuZGVmaW5lZF9jb2x1bW5cbiAgICAgICAgcmV0dXJuIG5ldyBOb3RGb3VuZEVycm9yKHJlYXNvbiBhcyBzdHJpbmcpO1xuXG4gICAgICAvLyBJbnZhbGlkIG9iamVjdCBkZWZpbml0aW9uXG4gICAgICBjYXNlIFwiNDJQMTZcIjogLy8gaW52YWxpZF90YWJsZV9kZWZpbml0aW9uXG4gICAgICAgIHJldHVybiBuZXcgSW5kZXhFcnJvcihlcnIpO1xuXG4gICAgICAvLyBDb25uZWN0aW9uIGVycm9yc1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGNvZGUudG9TdHJpbmcoKS5tYXRjaCgvRUNPTk5SRUZVU0VEL2cpKVxuICAgICAgICAgIHJldHVybiBuZXcgQ29ubmVjdGlvbkVycm9yKGVycik7XG4gICAgICAgIHJldHVybiBuZXcgSW50ZXJuYWxFcnJvcihlcnIpO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBhc3luYyBjb25uZWN0KGNvbmZpZzogRGF0YVNvdXJjZU9wdGlvbnMpOiBQcm9taXNlPERhdGFTb3VyY2U+IHtcbiAgICBjb25zdCBjb24gPSBuZXcgRGF0YVNvdXJjZShjb25maWcpO1xuICAgIGlmICghY29uLmlzSW5pdGlhbGl6ZWQpIGF3YWl0IGNvbi5pbml0aWFsaXplKCk7XG4gICAgcmV0dXJuIGNvbjtcbiAgfVxuXG4gIHN0YXRpYyBhc3luYyBjcmVhdGVEYXRhYmFzZShcbiAgICBkYXRhU291cmNlOiBEYXRhU291cmNlLFxuICAgIGRiTmFtZTogc3RyaW5nXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGxvZyA9IExvZ2dpbmcuZm9yKHRoaXMuY3JlYXRlRGF0YWJhc2UpO1xuICAgIGxvZy52ZXJib3NlKGBDcmVhdGluZyBkYXRhYmFzZSAke2RiTmFtZX1gKTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgZGF0YVNvdXJjZS5xdWVyeShgQ1JFQVRFIERBVEFCQVNFICR7ZGJOYW1lfWApO1xuICAgICAgbG9nLmluZm8oYENyZWF0ZWQgZGF0YWJhc2UgJHtkYk5hbWV9YCk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUgYXMgRXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBhc3luYyBjcmVhdGVOb3RpZnlGdW5jdGlvbihcbiAgICBkYXRhU291cmNlOiBEYXRhU291cmNlLFxuICAgIHVzZXI6IHN0cmluZ1xuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBsb2cgPSBMb2dnaW5nLmZvcih0aGlzLmNyZWF0ZU5vdGlmeUZ1bmN0aW9uKTtcbiAgICBsb2cudmVyYm9zZShgQ3JlYXRpbmcgbm90aWZ5IGZ1bmN0aW9uYCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGRhdGFTb3VyY2UucXVlcnkoXG4gICAgICAgIGBDUkVBVEUgT1IgUkVQTEFDRSBGVU5DVElPTiBub3RpZnlfdGFibGVfY2hhbmdlcygpXG5SRVRVUk5TIHRyaWdnZXIgQVMgJCRcbkJFR0lOXG4gICAgUEVSRk9STSBwZ19ub3RpZnkoXG4gICAgICAgICd0YWJsZV9jaGFuZ2VzJyxcbiAgICAgICAganNvbl9idWlsZF9vYmplY3QoXG4gICAgICAgICAgICAndGFibGUnLCBUR19UQUJMRV9OQU1FLFxuICAgICAgICAgICAgJ2FjdGlvbicsIFRHX09QLFxuICAgICAgICAgICAgJ2RhdGEnLCByb3dfdG9fanNvbihORVcpLFxuICAgICAgICAgICAgJ29sZF9kYXRhJywgcm93X3RvX2pzb24oT0xEKVxuICAgICAgICApOjp0ZXh0XG4gICAgKTtcbiAgICBSRVRVUk4gTkVXO1xuRU5EO1xuJCQgTEFOR1VBR0UgcGxwZ3NxbCBTRUNVUklUWSBERUZJTkVSXG47YFxuICAgICAgKTtcbiAgICAgIGF3YWl0IGRhdGFTb3VyY2UucXVlcnkoXG4gICAgICAgIGBBTFRFUiBGVU5DVElPTiBub3RpZnlfdGFibGVfY2hhbmdlcygpIE9XTkVSIFRPICR7dXNlcn07YFxuICAgICAgKTtcbiAgICAgIGF3YWl0IGRhdGFTb3VyY2UucXVlcnkoYFxuICAgICAgICAgICAgR1JBTlQgRVhFQ1VURSBPTiBGVU5DVElPTiBub3RpZnlfdGFibGVfY2hhbmdlcygpIFRPIHB1YmxpYztcbiAgICAgICAgYCk7XG4gICAgICBsb2cuaW5mbyhgQ3JlYXRlZCBub3RpZnkgZnVuY3Rpb25gKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGFzeW5jIGRlbGV0ZURhdGFiYXNlKFxuICAgIGRhdGFTb3VyY2U6IERhdGFTb3VyY2UsXG4gICAgZGJOYW1lOiBzdHJpbmcsXG4gICAgdXNlcj86IHN0cmluZ1xuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgaWYgKHVzZXIpIGF3YWl0IGRhdGFTb3VyY2UucXVlcnkoYERST1AgT1dORUQgQlkgJHt1c2VyfSBDQVNDQURFO2ApO1xuICAgICAgYXdhaXQgZGF0YVNvdXJjZS5xdWVyeShgRFJPUCBEQVRBQkFTRSAke2RiTmFtZX1gKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGFzeW5jIGNyZWF0ZVVzZXIoXG4gICAgZGF0YVNvdXJjZTogRGF0YVNvdXJjZSxcbiAgICBkYk5hbWU6IHN0cmluZyxcbiAgICB1c2VyOiBzdHJpbmcsXG4gICAgcGFzc3dvcmQ6IHN0cmluZ1xuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgZGF0YVNvdXJjZS5xdWVyeShgQ1JFQVRFIFVTRVIgJHt1c2VyfSBXSVRIIFBBU1NXT1JEICcke3Bhc3N3b3JkfSdgKTtcbiAgICAgIGF3YWl0IGRhdGFTb3VyY2UucXVlcnkoYEdSQU5UIENPTk5FQ1QgT04gREFUQUJBU0UgJHtkYk5hbWV9IFRPICR7dXNlcn1gKTtcblxuICAgICAgYXdhaXQgZGF0YVNvdXJjZS5xdWVyeShgR1JBTlQgVVNBR0UgT04gU0NIRU1BIHB1YmxpYyBUTyAke3VzZXJ9YCk7XG4gICAgICBhd2FpdCBkYXRhU291cmNlLnF1ZXJ5KGBHUkFOVCBDUkVBVEUgT04gU0NIRU1BIHB1YmxpYyBUTyAke3VzZXJ9YCk7XG4gICAgICBhd2FpdCBkYXRhU291cmNlLnF1ZXJ5KFxuICAgICAgICBgR1JBTlQgQUxMIFBSSVZJTEVHRVMgT04gQUxMIFRBQkxFUyBJTiBTQ0hFTUEgcHVibGljIFRPICR7dXNlcn1gXG4gICAgICApO1xuICAgICAgYXdhaXQgZGF0YVNvdXJjZS5xdWVyeShcbiAgICAgICAgYEdSQU5UIEFMTCBQUklWSUxFR0VTIE9OIEFMTCBTRVFVRU5DRVMgSU4gU0NIRU1BIHB1YmxpYyBUTyAke3VzZXJ9YFxuICAgICAgKTtcbiAgICAgIGF3YWl0IGRhdGFTb3VyY2UucXVlcnkoXG4gICAgICAgIGBHUkFOVCBBTEwgUFJJVklMRUdFUyBPTiBBTEwgRlVOQ1RJT05TIElOIFNDSEVNQSBwdWJsaWMgVE8gJHt1c2VyfWBcbiAgICAgICk7XG4gICAgICBhd2FpdCBkYXRhU291cmNlLnF1ZXJ5KFxuICAgICAgICBgQUxURVIgREVGQVVMVCBQUklWSUxFR0VTIElOIFNDSEVNQSBwdWJsaWMgR1JBTlQgQUxMIFBSSVZJTEVHRVMgT04gVEFCTEVTIFRPICR7dXNlcn1gXG4gICAgICApO1xuICAgICAgYXdhaXQgZGF0YVNvdXJjZS5xdWVyeShcbiAgICAgICAgYEFMVEVSIERFRkFVTFQgUFJJVklMRUdFUyBJTiBTQ0hFTUEgcHVibGljIEdSQU5UIEFMTCBQUklWSUxFR0VTIE9OIFNFUVVFTkNFUyBUTyAke3VzZXJ9YFxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGFzeW5jIGRlbGV0ZVVzZXIoXG4gICAgY2xpZW50OiBEYXRhU291cmNlLFxuICAgIHVzZXI6IHN0cmluZyxcbiAgICBhZG1pbjogc3RyaW5nXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBjbGllbnQucXVlcnkoYFJFQVNTSUdOIE9XTkVEIEJZICR7dXNlcn0gVE8gJHthZG1pbn1gKTtcbiAgICAgIGF3YWl0IGNsaWVudC5xdWVyeShcbiAgICAgICAgYFJFVk9LRSBBTEwgT04gQUxMIFRBQkxFUyBJTiBTQ0hFTUEgcHVibGljIEZST00gJHt1c2VyfWBcbiAgICAgICk7XG4gICAgICBhd2FpdCBjbGllbnQucXVlcnkoYFJFVk9LRSBBTEwgT04gU0NIRU1BIHB1YmxpYyBGUk9NICR7dXNlcn1gKTtcbiAgICAgIGF3YWl0IGNsaWVudC5xdWVyeShcbiAgICAgICAgYFJFVk9LRSBBTEwgUFJJVklMRUdFUyBPTiBBTEwgU0VRVUVOQ0VTIElOIFNDSEVNQSBwdWJsaWMgRlJPTSAke3VzZXJ9YFxuICAgICAgKTtcbiAgICAgIGF3YWl0IGNsaWVudC5xdWVyeShcbiAgICAgICAgYFJFVk9LRSBBTEwgUFJJVklMRUdFUyBPTiBBTEwgRlVOQ1RJT05TIElOIFNDSEVNQSBwdWJsaWMgRlJPTSAke3VzZXJ9YFxuICAgICAgKTtcbiAgICAgIGF3YWl0IGNsaWVudC5xdWVyeShcbiAgICAgICAgYEFMVEVSIERFRkFVTFQgUFJJVklMRUdFUyBGT1IgUk9MRSAke2FkbWlufSBJTiBTQ0hFTUEgcHVibGljIFJFVk9LRSBBTEwgT04gVEFCTEVTIEZST00gJHt1c2VyfWBcbiAgICAgICk7XG4gICAgICBhd2FpdCBjbGllbnQucXVlcnkoXG4gICAgICAgIGBBTFRFUiBERUZBVUxUIFBSSVZJTEVHRVMgRk9SIFJPTEUgJHthZG1pbn0gSU4gU0NIRU1BIHB1YmxpYyBSRVZPS0UgQUxMIE9OIFNFUVVFTkNFUyBGUk9NICR7dXNlcn07YFxuICAgICAgKTtcbiAgICAgIGF3YWl0IGNsaWVudC5xdWVyeShcbiAgICAgICAgYEFMVEVSIERFRkFVTFQgUFJJVklMRUdFUyBGT1IgUk9MRSAke2FkbWlufSBJTiBTQ0hFTUEgcHVibGljIFJFVk9LRSBBTEwgT04gRlVOQ1RJT05TIEZST00gJHt1c2VyfWBcbiAgICAgICk7XG4gICAgICBhd2FpdCBjbGllbnQucXVlcnkoYERST1AgT1dORUQgQlkgJHt1c2VyfSBDQVNDQURFYCk7XG4gICAgICBhd2FpdCBjbGllbnQucXVlcnkoYERST1AgVVNFUiBJRiBFWElTVFMgXCIke3VzZXJ9XCJgKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgcGFyc2VUeXBlVG9Qb3N0Z3JlcyhcbiAgICB0eXBlOiBzdHJpbmcsXG4gICAgaXNQazogYm9vbGVhbixcbiAgICBpc0ZrID0gZmFsc2VcbiAgKSB7XG4gICAgc3dpdGNoICh0eXBlLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgIGNhc2UgXCJzdHJpbmdcIjpcbiAgICAgICAgcmV0dXJuIGlzUGsgPyBcIlRFWFQgUFJJTUFSWSBLRVlcIiA6IGlzRmsgPyBcIlRFWFRcIiA6IFwiVkFSQ0hBUlwiO1xuICAgICAgY2FzZSBcIm51bWJlclwiOlxuICAgICAgICByZXR1cm4gaXNQayA/IFwiU0VSSUFMIFBSSU1BUlkgS0VZXCIgOiBcIklOVEVHRVJcIjtcbiAgICAgIGNhc2UgXCJib29sZWFuXCI6XG4gICAgICAgIHJldHVybiBcIkJPT0xFQU5cIjtcbiAgICAgIGNhc2UgXCJkYXRlXCI6XG4gICAgICAgIHJldHVybiBcIlRJTUVTVEFNUFwiO1xuICAgICAgY2FzZSBcImJpZ2ludFwiOlxuICAgICAgICByZXR1cm4gaXNQayA/IFwiQklHSU5UIFBSSU1BUlkgS0VZXCIgOiBcIkJJR0lOVFwiO1xuICAgICAgZGVmYXVsdDoge1xuICAgICAgICBjb25zdCBtID0gTW9kZWwuZ2V0KHR5cGUpO1xuICAgICAgICBpZiAobSkge1xuICAgICAgICAgIGNvbnN0IG1tID0gbmV3IG0oKTtcbiAgICAgICAgICBjb25zdCB0eXBlID0gUmVmbGVjdGlvbi5nZXRUeXBlRnJvbURlY29yYXRvcihcbiAgICAgICAgICAgIG1tLFxuICAgICAgICAgICAgZmluZFByaW1hcnlLZXkobW0pLmlkXG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbW9kZWw6IG0sXG4gICAgICAgICAgICBwa1R5cGU6IHR5cGUsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgVW5zdXBwb3J0ZWQgdHlwZTogJHt0eXBlfWApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIHBhcnNlVmFsaWRhdGlvblRvUG9zdGdyZXMoXG4gICAgcHJvcDogc3RyaW5nLFxuICAgIHR5cGU6IHN0cmluZyxcbiAgICBpc1BrOiBib29sZWFuLFxuICAgIGtleTogc3RyaW5nLFxuICAgIG9wdGlvbnM6IFZhbGlkYXRvck9wdGlvbnNcbiAgKSB7XG4gICAgc3dpdGNoIChrZXkpIHtcbiAgICAgIGNhc2UgVmFsaWRhdGlvbktleXMuUkVRVUlSRUQ6XG4gICAgICAgIHJldHVybiBcIk5PVCBOVUxMXCI7XG4gICAgICBjYXNlIFZhbGlkYXRpb25LZXlzLk1BWF9MRU5HVEg6XG4gICAgICAgIGlmIChpc1BrIHx8ICFvcHRpb25zIHx8IHR5cGUudG9Mb3dlckNhc2UoKSAhPT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgIHJldHVybiBcIlwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBgKCR7KG9wdGlvbnMgYXMgTWF4TGVuZ3RoVmFsaWRhdG9yT3B0aW9ucylbVmFsaWRhdGlvbktleXMuTUFYX0xFTkdUSF19KWA7XG4gICAgICBjYXNlIFZhbGlkYXRpb25LZXlzLk1JTl9MRU5HVEg6XG4gICAgICAgIHJldHVybiBgQ09OU1RSQUlOVCAke3Byb3B9X21pbl9sZW5ndGhfY2hlY2sgQ0hFQ0sgKExFTkdUSCgke3Byb3B9KSA+PSAkeyhvcHRpb25zIGFzIE1pbkxlbmd0aFZhbGlkYXRvck9wdGlvbnMpW1ZhbGlkYXRpb25LZXlzLk1JTl9MRU5HVEhdfSlgO1xuICAgICAgY2FzZSBWYWxpZGF0aW9uS2V5cy5QQVRURVJOOlxuICAgICAgY2FzZSBWYWxpZGF0aW9uS2V5cy5VUkw6XG4gICAgICBjYXNlIFZhbGlkYXRpb25LZXlzLkVNQUlMOlxuICAgICAgICByZXR1cm4gYENPTlNUUkFJTlQgJHtwcm9wfV9wYXR0ZXJuX2NoZWNrIENIRUNLICgke3Byb3B9IH4gJyR7Y29udmVydEpzUmVnZXhUb1Bvc3RncmVzKChvcHRpb25zIGFzIFBhdHRlcm5WYWxpZGF0b3JPcHRpb25zKVtWYWxpZGF0aW9uS2V5cy5QQVRURVJOXSBhcyBzdHJpbmcpfScpYDtcbiAgICAgIGNhc2UgVmFsaWRhdGlvbktleXMuVFlQRTpcbiAgICAgIGNhc2UgVmFsaWRhdGlvbktleXMuREFURTpcbiAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICBjYXNlIFZhbGlkYXRpb25LZXlzLk1JTjpcbiAgICAgICAgcmV0dXJuIGBDT05TVFJBSU5UICR7cHJvcH1fJHtrZXl9X2NoZWNrIENIRUNLICgke3Byb3B9ID49ICR7KG9wdGlvbnMgYXMgTWluVmFsaWRhdG9yT3B0aW9ucylbVmFsaWRhdGlvbktleXMuTUlOXX0pYDtcbiAgICAgIGNhc2UgVmFsaWRhdGlvbktleXMuTUFYOlxuICAgICAgICByZXR1cm4gYENPTlNUUkFJTlQgJHtwcm9wfV8ke2tleX1fY2hlY2sgQ0hFQ0sgKCR7cHJvcH0gPD0gJHsob3B0aW9ucyBhcyBNYXhWYWxpZGF0b3JPcHRpb25zKVtWYWxpZGF0aW9uS2V5cy5NQVhdfSlgO1xuICAgICAgY2FzZSBWYWxpZGF0aW9uS2V5cy5QQVNTV09SRDpcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGBVbnN1cHBvcnRlZCB0eXBlOiAke2tleX1gKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBwYXJzZVJlbGF0aW9uc1RvUG9zdGdyZXMoXG4gICAgcHJvcDogc3RyaW5nLFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNb2RlbD4sXG4gICAgcGs6IHN0cmluZyxcbiAgICBrZXk6IFBlcnNpc3RlbmNlS2V5cyxcbiAgICBvcHRpb25zOiBSZWxhdGlvbnNNZXRhZGF0YVxuICApIHtcbiAgICBjb25zdCB0YWJsZU5hbWUgPSBSZXBvc2l0b3J5LnRhYmxlKGNsYXp6KTtcbiAgICBjb25zdCB7IGNhc2NhZGUgfSA9IG9wdGlvbnM7XG4gICAgY29uc3QgY2FzY2FkZVN0ciA9IGAke2Nhc2NhZGUudXBkYXRlID8gXCIgT04gVVBEQVRFIENBU0NBREVcIiA6IFwiXCJ9JHtjYXNjYWRlLmRlbGV0ZSA/IFwiIE9OIERFTEVURSBDQVNDQURFXCIgOiBcIlwifWA7XG4gICAgc3dpdGNoIChgcmVsYXRpb25zJHtrZXl9YCkge1xuICAgICAgY2FzZSBQZXJzaXN0ZW5jZUtleXMuT05FX1RPX09ORTpcbiAgICAgICAgcmV0dXJuIGBGT1JFSUdOIEtFWSAoJHtwcm9wfSkgUkVGRVJFTkNFUyAke3RhYmxlTmFtZX0oJHtwa30pJHtjYXNjYWRlU3RyfWA7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgVW5zdXBwb3J0ZWQgb3BlcmF0aW9uOiAke2tleX1gKTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgYXN5bmMgY3JlYXRlVGFibGU8TSBleHRlbmRzIE1vZGVsPihcbiAgICBjbGllbnQ6IERhdGFTb3VyY2UsXG4gICAgbW9kZWw6IENvbnN0cnVjdG9yPE0+XG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgVHlwZU9STVRhYmxlU3BlYz4+IHtcbiAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIFR5cGVPUk1UYWJsZVNwZWM+ID0ge307XG4gICAgY29uc3QgbSA9IG5ldyBtb2RlbCh7fSk7XG4gICAgY29uc3QgdGFibGVOYW1lID0gUmVwb3NpdG9yeS50YWJsZShtb2RlbCk7XG4gICAgY29uc3QgeyBpZCB9ID0gZmluZFByaW1hcnlLZXkobSk7XG5cbiAgICBsZXQgaXNQazogYm9vbGVhbiwgY29sdW1uOiBzdHJpbmc7XG4gICAgY29uc3QgcHJvcGVydGllcyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKG0pIGFzIChrZXlvZiBNKVtdO1xuICAgIGZvciAoY29uc3QgcHJvcCBvZiBwcm9wZXJ0aWVzKSB7XG4gICAgICBpZiAoXG4gICAgICAgIHR5cGVvZiAodGhpcyBhcyBhbnkpW3Byb3BdID09PSBcImZ1bmN0aW9uXCIgfHxcbiAgICAgICAgcHJvcC50b1N0cmluZygpLnN0YXJ0c1dpdGgoXCJfXCIpIHx8XG4gICAgICAgIHByb3AgPT09IFwiY29uc3RydWN0b3JcIlxuICAgICAgKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpc1BrID0gcHJvcCA9PT0gaWQ7XG4gICAgICBjb2x1bW4gPSBSZXBvc2l0b3J5LmNvbHVtbihtLCBwcm9wLnRvU3RyaW5nKCkpO1xuXG4gICAgICBjb25zdCBhbGxEZWNzID0gUmVmbGVjdGlvbi5nZXRQcm9wZXJ0eURlY29yYXRvcnMoXG4gICAgICAgIFZhbGlkYXRpb25LZXlzLlJFRkxFQ1QsXG4gICAgICAgIG0sXG4gICAgICAgIHByb3AudG9TdHJpbmcoKSxcbiAgICAgICAgZmFsc2UsXG4gICAgICAgIHRydWVcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IGRlY29yYXRvckRhdGEgPSBhbGxEZWNzLmRlY29yYXRvcnMucmVkdWNlKFxuICAgICAgICAoYWNjdW06IFJlY29yZDxzdHJpbmcsIGFueT4sIGVsKSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBrZXksIHByb3BzIH0gPSBlbDtcbiAgICAgICAgICBpZiAoa2V5ID09PSBNb2RlbEtleXMuVFlQRSAmJiAhYWNjdW1bVmFsaWRhdGlvbktleXMuVFlQRV0pIHtcbiAgICAgICAgICAgIGFjY3VtW1ZhbGlkYXRpb25LZXlzLlRZUEVdID0ge1xuICAgICAgICAgICAgICBjdXN0b21UeXBlczogW3Byb3BzLm5hbWUgYXMgc3RyaW5nXSxcbiAgICAgICAgICAgICAgbWVzc2FnZTogREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5UWVBFLFxuICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogXCJkZWZpbmVzIHRoZSBhY2NlcHRlZCB0eXBlcyBmb3IgdGhlIGF0dHJpYnV0ZVwiLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGtleSAhPT0gVmFsaWRhdGlvbktleXMuVFlQRSkge1xuICAgICAgICAgICAgLy8gZG8gbm90aGluZy4gd2UgY2FuIG9ubHkgc3VwcG9ydCBiYXNpcyBjdHlwZXMgYXQgdGhpcyB0aW1lXG4gICAgICAgICAgICBhY2N1bVtrZXldID0gcHJvcHM7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBhY2N1bTtcbiAgICAgICAgfSxcbiAgICAgICAge31cbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IGRiRGVjcyA9IFJlZmxlY3Rpb24uZ2V0UHJvcGVydHlEZWNvcmF0b3JzKFxuICAgICAgICBSZXBvc2l0b3J5LmtleShcInJlbGF0aW9uc1wiKSxcbiAgICAgICAgbSxcbiAgICAgICAgcHJvcC50b1N0cmluZygpLFxuICAgICAgICB0cnVlLFxuICAgICAgICB0cnVlXG4gICAgICApO1xuXG4gICAgICBjb25zdCBxdWVyeTogc3RyaW5nW10gPSBbXTtcbiAgICAgIGNvbnN0IGNvbnN0cmFpbnRzOiBzdHJpbmdbXSA9IFtdO1xuICAgICAgY29uc3QgZm9yZWlnbktleXM6IHN0cmluZ1tdID0gW107XG4gICAgICBsZXQgdHlwZURhdGE6IFR5cGVNZXRhZGF0YSB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgICAgIGxldCBjaGlsZENsYXNzOiBDb25zdHJ1Y3RvcjxNb2RlbD4gfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gICAgICBsZXQgY2hpbGRQazogYW55O1xuXG4gICAgICBpZiAoT2JqZWN0LmtleXMoZGVjb3JhdG9yRGF0YSkubGVuZ3RoKSB7XG4gICAgICAgIHR5cGVEYXRhID0gZGVjb3JhdG9yRGF0YVtWYWxpZGF0aW9uS2V5cy5UWVBFXSBhcyBUeXBlTWV0YWRhdGE7XG5cbiAgICAgICAgaWYgKCF0eXBlRGF0YSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgTWlzc2luZyB0eXBlIGluZm9ybWF0aW9uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcGFyc2VkVHlwZTpcbiAgICAgICAgICB8IHN0cmluZ1xuICAgICAgICAgIHwgeyBtb2RlbDogQ29uc3RydWN0b3I8TW9kZWw+IHwgc3RyaW5nOyBwa1R5cGU/OiBzdHJpbmcgfSA9XG4gICAgICAgICAgdGhpcy5wYXJzZVR5cGVUb1Bvc3RncmVzKFxuICAgICAgICAgICAgdHlwZW9mICh0eXBlRGF0YS5jdXN0b21UeXBlcyBhcyBhbnlbXSlbMF0gPT09IFwiZnVuY3Rpb25cIlxuICAgICAgICAgICAgICA/ICh0eXBlRGF0YS5jdXN0b21UeXBlcyBhcyBhbnkpWzBdKClcbiAgICAgICAgICAgICAgOiAodHlwZURhdGEuY3VzdG9tVHlwZXMgYXMgYW55KVswXSxcbiAgICAgICAgICAgIGlzUGtcbiAgICAgICAgICApO1xuICAgICAgICBpZiAodHlwZW9mIHBhcnNlZFR5cGUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICBwYXJzZWRUeXBlID0geyBtb2RlbDogcGFyc2VkVHlwZSB9O1xuICAgICAgICB9XG4gICAgICAgIGxldCB0eXBlU3RyOlxuICAgICAgICAgIHwgc3RyaW5nXG4gICAgICAgICAgfCB7IG1vZGVsOiBDb25zdHJ1Y3RvcjxNb2RlbD4gfCBzdHJpbmc7IHBrVHlwZT86IHN0cmluZyB9ID1cbiAgICAgICAgICBwYXJzZWRUeXBlLm1vZGVsIGFzXG4gICAgICAgICAgICB8IHN0cmluZ1xuICAgICAgICAgICAgfCB7IG1vZGVsOiBDb25zdHJ1Y3RvcjxNb2RlbD4gfCBzdHJpbmc7IHBrVHlwZT86IHN0cmluZyB9O1xuXG4gICAgICAgIGlmICh0eXBlb2YgdHlwZVN0ciAhPT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHR5cGVTdHIpKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyh0eXBlU3RyKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBjb250aW51ZTtcbiAgICAgICAgICAvLyBjb25zdCByZXM6IFJlY29yZDxzdHJpbmcsIFBvc3RncmVzVGFibGVTcGVjPiA9IGF3YWl0IHRoaXMuY3JlYXRlVGFibGUocG9vbCwgdHlwZVN0cik7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNoaWxkQ2xhc3MgPSBwYXJzZWRUeXBlLm1vZGVsIGFzIENvbnN0cnVjdG9yPE1vZGVsPjtcbiAgICAgICAgICAgIGNvbnN0IG0gPSBuZXcgY2hpbGRDbGFzcygpO1xuICAgICAgICAgICAgY2hpbGRQayA9IGZpbmRQcmltYXJ5S2V5KG0pO1xuICAgICAgICAgICAgdHlwZVN0ciA9IHRoaXMucGFyc2VUeXBlVG9Qb3N0Z3JlcyhcbiAgICAgICAgICAgICAgcGFyc2VkVHlwZS5wa1R5cGUgYXMgc3RyaW5nLFxuICAgICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgICAgdHJ1ZVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY3JlYXRlVGFibGUoY2xpZW50LCBjaGlsZENsYXNzKTtcbiAgICAgICAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgQ29uZmxpY3RFcnJvcikpIHRocm93IGU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHRwID0gQXJyYXkuaXNBcnJheSh0eXBlRGF0YS5jdXN0b21UeXBlcylcbiAgICAgICAgICA/IHR5cGVEYXRhLmN1c3RvbVR5cGVzWzBdXG4gICAgICAgICAgOiB0eXBlRGF0YS5jdXN0b21UeXBlcztcbiAgICAgICAgdHAgPSB0eXBlb2YgdHAgPT09IFwiZnVuY3Rpb25cIiAmJiAhdHAubmFtZSA/IHRwKCkgOiB0cDtcbiAgICAgICAgY29uc3QgdmFsaWRhdGlvblN0ciA9IHRoaXMucGFyc2VWYWxpZGF0aW9uVG9Qb3N0Z3JlcyhcbiAgICAgICAgICBjb2x1bW4sXG4gICAgICAgICAgdHAgYXMgYW55LFxuICAgICAgICAgIGlzUGssXG4gICAgICAgICAgVmFsaWRhdGlvbktleXMuTUFYX0xFTkdUSCxcbiAgICAgICAgICAoZGVjb3JhdG9yRGF0YVtcbiAgICAgICAgICAgIFZhbGlkYXRpb25LZXlzLk1BWF9MRU5HVEhcbiAgICAgICAgICBdIGFzIE1heExlbmd0aFZhbGlkYXRvck9wdGlvbnMpIHx8IHtcbiAgICAgICAgICAgIFtWYWxpZGF0aW9uS2V5cy5NQVhfTEVOR1RIXTogMjU1LFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBxID0gYCR7Y29sdW1ufSAke3R5cGVTdHJ9JHt2YWxpZGF0aW9uU3RyfWA7XG5cbiAgICAgICAgaWYgKGlzUGspIHtcbiAgICAgICAgICBxdWVyeS51bnNoaWZ0KHEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHF1ZXJ5LnB1c2gocSk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGNvbnN0IFtrZXksIHByb3BzXSBvZiBPYmplY3QuZW50cmllcyhkZWNvcmF0b3JEYXRhKS5maWx0ZXIoXG4gICAgICAgICAgKFtrXSkgPT5cbiAgICAgICAgICAgICFbVmFsaWRhdGlvbktleXMuVFlQRSwgVmFsaWRhdGlvbktleXMuTUFYX0xFTkdUSF0uaW5jbHVkZXMoayBhcyBhbnkpXG4gICAgICAgICkpIHtcbiAgICAgICAgICBjb25zdCB2YWxpZGF0aW9uID0gdGhpcy5wYXJzZVZhbGlkYXRpb25Ub1Bvc3RncmVzKFxuICAgICAgICAgICAgY29sdW1uLFxuICAgICAgICAgICAgdHAgYXMgYW55LFxuICAgICAgICAgICAgaXNQayxcbiAgICAgICAgICAgIGtleSxcbiAgICAgICAgICAgIHByb3BzXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAodmFsaWRhdGlvbi5zdGFydHNXaXRoKFwiQ09OU1RSQUlOVFwiKSkge1xuICAgICAgICAgICAgY29uc3RyYWludHMucHVzaCh2YWxpZGF0aW9uKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHZhbGlkYXRpb24pIHtcbiAgICAgICAgICAgICAgcXVlcnkucHVzaCh2YWxpZGF0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gVE9ETyBpZ25vcmUgZm9yIG5vdy4gdGhpcyBsZWF2ZXMgZm9yZWlnbiBrZXlzIG91dFxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnN0YW50LWJpbmFyeS1leHByZXNzaW9uXG4gICAgICBpZiAoZmFsc2UgfHwgKGRiRGVjcyAmJiBkYkRlY3MuZGVjb3JhdG9ycy5sZW5ndGgpKSB7XG4gICAgICAgIGlmICghdHlwZURhdGEpIHRocm93IG5ldyBFcnJvcihgTWlzc2luZyB0eXBlIGluZm9ybWF0aW9uYCk7XG4gICAgICAgIGZvciAoY29uc3QgZGVjb3JhdG9yIG9mIGRiRGVjcy5kZWNvcmF0b3JzKSB7XG4gICAgICAgICAgY29uc3QgeyBrZXksIHByb3BzIH0gPSBkZWNvcmF0b3I7XG4gICAgICAgICAgY29uc3QgdmFsaWRhdGlvbiA9IHRoaXMucGFyc2VSZWxhdGlvbnNUb1Bvc3RncmVzKFxuICAgICAgICAgICAgY29sdW1uLFxuICAgICAgICAgICAgY2hpbGRDbGFzcyBhcyBDb25zdHJ1Y3RvcjxNb2RlbD4sXG4gICAgICAgICAgICBjaGlsZFBrLmlkLFxuICAgICAgICAgICAga2V5IGFzIFBlcnNpc3RlbmNlS2V5cyxcbiAgICAgICAgICAgIHByb3BzIGFzIHVua25vd24gYXMgUmVsYXRpb25zTWV0YWRhdGFcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmICh2YWxpZGF0aW9uLnN0YXJ0c1dpdGgoXCJGT1JFSUdOXCIpKSB7XG4gICAgICAgICAgICBmb3JlaWduS2V5cy5wdXNoKHZhbGlkYXRpb24pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgVW5zdXBwb3J0ZWQgcmVsYXRpb246ICR7a2V5fWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXN1bHRbcHJvcC50b1N0cmluZygpXSA9IHtcbiAgICAgICAgcXVlcnk6IHF1ZXJ5LmpvaW4oXCIgXCIpLFxuICAgICAgICB2YWx1ZXM6IFtdLFxuICAgICAgICBwcmltYXJ5S2V5OiBpc1BrLFxuICAgICAgICBjb25zdHJhaW50czogY29uc3RyYWludHMsXG4gICAgICAgIGZvcmVpZ25LZXlzOiBmb3JlaWduS2V5cyxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgdmFsdWVzID0gT2JqZWN0LnZhbHVlcyhyZXN1bHQpO1xuICAgIGNvbnN0IHF1ZXJ5ID0gdmFsdWVzLm1hcCgocikgPT4gci5xdWVyeSkuam9pbihcIixcXG5cIik7XG4gICAgY29uc3QgY29uc3RyYWludHMgPSB2YWx1ZXNcbiAgICAgIC5maWx0ZXIoKGMpID0+ICEhYy5jb25zdHJhaW50cy5sZW5ndGgpXG4gICAgICAubWFwKChyKSA9PiByLmNvbnN0cmFpbnRzKVxuICAgICAgLmpvaW4oXCIsXFxuXCIpO1xuICAgIGNvbnN0IGZvcmVpZ25LZXlzID0gdmFsdWVzXG4gICAgICAuZmlsdGVyKChjKSA9PiAhIWMuZm9yZWlnbktleXMubGVuZ3RoKVxuICAgICAgLm1hcCgocikgPT4gci5mb3JlaWduS2V5cylcbiAgICAgIC5qb2luKFwiLFxcblwiKTtcbiAgICBjb25zdCB2YWxzID0gW3F1ZXJ5LCBjb25zdHJhaW50c107XG4gICAgaWYgKGZvcmVpZ25LZXlzKSB7XG4gICAgICB2YWxzLnB1c2goZm9yZWlnbktleXMpO1xuICAgIH1cbiAgICBjb25zdCBxdWVyeVN0cmluZyA9IGBDUkVBVEUgVEFCTEUgJHt0YWJsZU5hbWV9ICgke3ZhbHMuZmlsdGVyKCh2KSA9PiAhIXYpLmpvaW4oXCIsXFxuXCIpfSlgO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBjbGllbnQucXVlcnkocXVlcnlTdHJpbmcpO1xuICAgICAgYXdhaXQgY2xpZW50LnF1ZXJ5KFxuICAgICAgICBgQ1JFQVRFIFRSSUdHRVIgbm90aWZ5X2NoYW5nZXNfJHt0YWJsZU5hbWV9XG5BRlRFUiBJTlNFUlQgT1IgVVBEQVRFIE9SIERFTEVURSBPTiAke3RhYmxlTmFtZX1cbiAgICBGT1IgRUFDSCBST1dcbiAgICBFWEVDVVRFIEZVTkNUSU9OIG5vdGlmeV90YWJsZV9jaGFuZ2VzKCk7YFxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBzdGF0aWMgYXN5bmMgZ2V0Q3VycmVudFVzZXIoY2xpZW50OiBEYXRhU291cmNlKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBxdWVyeVN0cmluZyA9IGBTRUxFQ1QgQ1VSUkVOVF9VU0VSO2A7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNsaWVudC5xdWVyeShxdWVyeVN0cmluZyk7XG4gICAgICByZXR1cm4gcmVzdWx0WzBdLmN1cnJlbnRfdXNlcjtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGRlY29yYXRpb24oKSB7XG4gICAgLy8gQHRhYmxlKCkgPT4gQEVudGl0eSgpXG4gICAgY29uc3QgdGFibGVLZXkgPSBBZGFwdGVyLmtleShQZXJzaXN0ZW5jZUtleXMuVEFCTEUpO1xuICAgIERlY29yYXRpb24uZmxhdm91cmVkQXMoVHlwZU9STUZsYXZvdXIpXG4gICAgICAuZm9yKHRhYmxlS2V5KVxuICAgICAgLmV4dGVuZCgob3JpZ2luYWw6IGFueSkgPT5cbiAgICAgICAgRW50aXR5KCkob3JpZ2luYWxbTW9kZWxLZXlzLkFOQ0hPUl0gfHwgb3JpZ2luYWwpXG4gICAgICApXG4gICAgICAuYXBwbHkoKTtcblxuICAgIC8vIEBwaygpID0+IEBQcmltYXJ5R2VuZXJhdGVkQ29sdW1uKCkgfCBAUHJpbWFyeUNvbHVtbigpXG4gICAgY29uc3QgcGtLZXkgPSBSZXBvc2l0b3J5LmtleShEQktleXMuSUQpO1xuXG4gICAgZnVuY3Rpb24gcGtEZWMob3B0aW9uczogU2VxdWVuY2VPcHRpb25zKSB7XG4gICAgICBjb25zdCBkZWNvcmF0b3JzOiBhbnlbXSA9IFtcbiAgICAgICAgcmVxdWlyZWQoKSxcbiAgICAgICAgcmVhZG9ubHkoKSxcbiAgICAgICAgcHJvcE1ldGFkYXRhKHBrS2V5LCBvcHRpb25zKSxcbiAgICAgIF07XG4gICAgICBpZiAob3B0aW9ucy50eXBlKSBkZWNvcmF0b3JzLnB1c2goUHJpbWFyeUdlbmVyYXRlZENvbHVtbigpKTtcbiAgICAgIGVsc2UgZGVjb3JhdG9ycy5wdXNoKFByaW1hcnlDb2x1bW4oeyB1bmlxdWU6IHRydWUgfSkpO1xuICAgICAgcmV0dXJuIGFwcGx5KC4uLmRlY29yYXRvcnMpO1xuICAgIH1cblxuICAgIERlY29yYXRpb24uZmxhdm91cmVkQXMoVHlwZU9STUZsYXZvdXIpXG4gICAgICAuZm9yKHBrS2V5KVxuICAgICAgLmRlZmluZSh7XG4gICAgICAgIGRlY29yYXRvcjogcGtEZWMsXG4gICAgICB9KVxuICAgICAgLmFwcGx5KCk7XG5cbiAgICAvLyBAY29sdW1uKFwiY29sdW1uTmFtZVwiKSA9PiBAQ29sdW1uKHtuYW1lOiBcImNvbHVtbk5hbWVcIn0pXG4gICAgY29uc3QgY29sdW1uS2V5ID0gQWRhcHRlci5rZXkoUGVyc2lzdGVuY2VLZXlzLkNPTFVNTik7XG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyZWRBcyhUeXBlT1JNRmxhdm91cilcbiAgICAgIC5mb3IoY29sdW1uS2V5KVxuICAgICAgLmV4dGVuZCh7XG4gICAgICAgIGRlY29yYXRvcjogZnVuY3Rpb24gY29sdW1tKG5hbWU6IHN0cmluZykge1xuICAgICAgICAgIHJldHVybiBmdW5jdGlvbiBjb2x1bW4ob2JqOiBhbnksIHByb3A6IGFueSkge1xuICAgICAgICAgICAgcmV0dXJuIENvbHVtbih7XG4gICAgICAgICAgICAgIG5hbWU6IG5hbWUgfHwgcHJvcCxcbiAgICAgICAgICAgICAgbnVsbGFibGU6IHRydWUsXG4gICAgICAgICAgICB9KShvYmosIHByb3ApO1xuICAgICAgICAgIH07XG4gICAgICAgIH0sXG4gICAgICAgIHRyYW5zZm9ybTogKGFyZ3M6IGFueVtdKSA9PiB7XG4gICAgICAgICAgY29uc3QgY29sdW1uTmFtZSA9IGFyZ3NbMV07XG4gICAgICAgICAgcmV0dXJuIFtjb2x1bW5OYW1lXTtcbiAgICAgICAgfSxcbiAgICAgIH0pXG4gICAgICAuYXBwbHkoKTtcblxuICAgIC8vIEB1bmlxdWUgPT4gQENvbHVtbih7dW5pcXVlOiB0cnVlfSlcbiAgICBjb25zdCB1bmlxdWVLZXkgPSBBZGFwdGVyLmtleShQZXJzaXN0ZW5jZUtleXMuVU5JUVVFKTtcbiAgICBEZWNvcmF0aW9uLmZsYXZvdXJlZEFzKFR5cGVPUk1GbGF2b3VyKVxuICAgICAgLmZvcih1bmlxdWVLZXkpXG4gICAgICAuZGVmaW5lKHByb3BNZXRhZGF0YSh1bmlxdWVLZXksIHt9KSlcbiAgICAgIC5leHRlbmQoQ29sdW1uKHsgdW5pcXVlOiB0cnVlIH0pKVxuICAgICAgLmFwcGx5KCk7XG5cbiAgICAvLyBAcmVxdWlyZWQgPT4gQENvbHVtbih7IG51bGxhYmxlOiBmYWxzZSB9KVxuICAgIGNvbnN0IHJlcXVpcmVkS2V5ID0gVmFsaWRhdGlvbi5rZXkoVmFsaWRhdGlvbktleXMuUkVRVUlSRUQpO1xuICAgIERlY29yYXRpb24uZmxhdm91cmVkQXMoVHlwZU9STUZsYXZvdXIpXG4gICAgICAuZm9yKHJlcXVpcmVkS2V5KVxuICAgICAgLmV4dGVuZChDb2x1bW4oeyBudWxsYWJsZTogZmFsc2UgfSkpXG4gICAgICAuYXBwbHkoKTtcblxuICAgIC8vIEB2ZXJzaW9uID0+IEBWZXJzaW9uQ29sdW1uKClcbiAgICBjb25zdCB2ZXJzaW9uS2V5ID0gUmVwb3NpdG9yeS5rZXkoREJLZXlzLlZFUlNJT04pO1xuICAgIERlY29yYXRpb24uZmxhdm91cmVkQXMoVHlwZU9STUZsYXZvdXIpXG4gICAgICAuZm9yKHZlcnNpb25LZXkpXG4gICAgICAuZGVmaW5lKHR5cGUoTnVtYmVyLm5hbWUpLCBWZXJzaW9uQ29sdW1uKCkpXG4gICAgICAuYXBwbHkoKTtcblxuICAgIGZ1bmN0aW9uIFZhbGlkYXRpb25VcGRhdGVLZXkoa2V5OiBzdHJpbmcpIHtcbiAgICAgIHJldHVybiBVcGRhdGVWYWxpZGF0aW9uS2V5cy5SRUZMRUNUICsga2V5O1xuICAgIH1cblxuICAgIC8vIEB0aW1lc3RhbXAob3ApID0+IEBDcmVhdGVEYXRlQ29sdW1uKCkgfHwgQFVwZGF0ZURhdGVDb2x1bW4oKVxuICAgIGNvbnN0IHRpbWVzdGFtcEtleSA9IFZhbGlkYXRpb25VcGRhdGVLZXkoREJLZXlzLlRJTUVTVEFNUCk7XG5cbiAgICBmdW5jdGlvbiB0cyhvcGVyYXRpb246IE9wZXJhdGlvbktleXNbXSwgZm9ybWF0OiBzdHJpbmcpIHtcbiAgICAgIGNvbnN0IGRlY29yYXRvcnM6IGFueVtdID0gW1xuICAgICAgICBkYXRlKGZvcm1hdCwgREJfREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5USU1FU1RBTVAuREFURSksXG4gICAgICAgIHJlcXVpcmVkKERCX0RFRkFVTFRfRVJST1JfTUVTU0FHRVMuVElNRVNUQU1QLlJFUVVJUkVEKSxcbiAgICAgICAgcHJvcE1ldGFkYXRhKFZhbGlkYXRpb24ua2V5KERCS2V5cy5USU1FU1RBTVApLCB7XG4gICAgICAgICAgb3BlcmF0aW9uOiBvcGVyYXRpb24sXG4gICAgICAgICAgZm9ybWF0OiBmb3JtYXQsXG4gICAgICAgIH0pLFxuICAgICAgXTtcbiAgICAgIGlmIChvcGVyYXRpb24uaW5kZXhPZihPcGVyYXRpb25LZXlzLlVQREFURSkgIT09IC0xKVxuICAgICAgICBkZWNvcmF0b3JzLnB1c2goXG4gICAgICAgICAgcHJvcE1ldGFkYXRhKHRpbWVzdGFtcEtleSwge1xuICAgICAgICAgICAgbWVzc2FnZTogREJfREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5USU1FU1RBTVAuSU5WQUxJRCxcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgZWxzZSBkZWNvcmF0b3JzLnB1c2gocmVhZG9ubHkoKSk7XG4gICAgICByZXR1cm4gYXBwbHkoLi4uZGVjb3JhdG9ycyk7XG4gICAgfVxuXG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyZWRBcyhUeXBlT1JNRmxhdm91cilcbiAgICAgIC5mb3IodGltZXN0YW1wS2V5KVxuICAgICAgLmRlZmluZSh7XG4gICAgICAgIGRlY29yYXRvcjogdHMsXG4gICAgICB9KVxuICAgICAgLmV4dGVuZCh7XG4gICAgICAgIGRlY29yYXRvcjogZnVuY3Rpb24gdGltZXN0YW1wKC4uLm9wczogT3BlcmF0aW9uS2V5c1tdKSB7XG4gICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIHRpbWVzdGFtcChvYmo6IGFueSwgcHJvcDogYW55KSB7XG4gICAgICAgICAgICBpZiAob3BzLmluZGV4T2YoT3BlcmF0aW9uS2V5cy5VUERBVEUpICE9PSAtMSlcbiAgICAgICAgICAgICAgcmV0dXJuIFVwZGF0ZURhdGVDb2x1bW4oKShvYmosIHByb3ApO1xuICAgICAgICAgICAgcmV0dXJuIENyZWF0ZURhdGVDb2x1bW4oKShvYmosIHByb3ApO1xuICAgICAgICAgIH07XG4gICAgICAgIH0sXG4gICAgICAgIHRyYW5zZm9ybTogKGFyZ3M6IGFueVtdKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGFyZ3NbMF07XG4gICAgICAgIH0sXG4gICAgICB9KVxuICAgICAgLmFwcGx5KCk7XG5cbiAgICAvLyBAb25lVG9PbmUoY2xhenopID0+IEBPbmVUb09uZSgoKSA9PiBjbGF6eilcbiAgICBjb25zdCBvbmVUb09uZUtleSA9IFJlcG9zaXRvcnkua2V5KFBlcnNpc3RlbmNlS2V5cy5PTkVfVE9fT05FKTtcbiAgICBEZWNvcmF0aW9uLmZsYXZvdXJlZEFzKFR5cGVPUk1GbGF2b3VyKVxuICAgICAgLmZvcihvbmVUb09uZUtleSlcbiAgICAgIC5kZWZpbmUoe1xuICAgICAgICBkZWNvcmF0b3I6IGZ1bmN0aW9uIG9uZVRvT25lKFxuICAgICAgICAgIGNsYXp6OiBDb25zdHJ1Y3Rvcjxhbnk+IHwgKCgpID0+IENvbnN0cnVjdG9yPGFueT4pLFxuICAgICAgICAgIGNhc2NhZGU6IENhc2NhZGVNZXRhZGF0YSxcbiAgICAgICAgICBwb3B1bGF0ZTogYm9vbGVhblxuICAgICAgICApIHtcbiAgICAgICAgICBjb25zdCBtZXRhZGF0YTogUmVsYXRpb25zTWV0YWRhdGEgPSB7XG4gICAgICAgICAgICBjbGFzczogKGNsYXp6Lm5hbWUgPyBjbGF6ei5uYW1lIDogY2xhenopIGFzIHN0cmluZyxcbiAgICAgICAgICAgIGNhc2NhZGU6IGNhc2NhZGUsXG4gICAgICAgICAgICBwb3B1bGF0ZTogcG9wdWxhdGUsXG4gICAgICAgICAgfTtcbiAgICAgICAgICBjb25zdCBvcm1NZXRhOiBSZWxhdGlvbk9wdGlvbnMgPSB7XG4gICAgICAgICAgICBjYXNjYWRlOlxuICAgICAgICAgICAgICBjYXNjYWRlLnVwZGF0ZSA9PT0gQ2FzY2FkZS5DQVNDQURFIHx8XG4gICAgICAgICAgICAgIGNhc2NhZGUuZGVsZXRlID09PSBDYXNjYWRlLkNBU0NBREUsXG4gICAgICAgICAgICBvbkRlbGV0ZTogY2FzY2FkZS5kZWxldGUgPyBcIkNBU0NBREVcIiA6IFwiREVGQVVMVFwiLFxuICAgICAgICAgICAgb25VcGRhdGU6IGNhc2NhZGUudXBkYXRlID8gXCJDQVNDQURFXCIgOiBcIkRFRkFVTFRcIixcbiAgICAgICAgICAgIG51bGxhYmxlOiB0cnVlLFxuICAgICAgICAgICAgZWFnZXI6IHBvcHVsYXRlLFxuICAgICAgICAgIH07XG4gICAgICAgICAgcmV0dXJuIGFwcGx5KFxuICAgICAgICAgICAgcHJvcChQZXJzaXN0ZW5jZUtleXMuUkVMQVRJT05TKSxcbiAgICAgICAgICAgIHR5cGUoW1xuICAgICAgICAgICAgICAodHlwZW9mIGNsYXp6ID09PSBcImZ1bmN0aW9uXCIgJiYgIWNsYXp6Lm5hbWVcbiAgICAgICAgICAgICAgICA/IGNsYXp6XG4gICAgICAgICAgICAgICAgOiBjbGF6ei5uYW1lKSBhcyBhbnksXG4gICAgICAgICAgICAgIFN0cmluZy5uYW1lLFxuICAgICAgICAgICAgICBOdW1iZXIubmFtZSxcbiAgICAgICAgICAgICAgQmlnSW50Lm5hbWUsXG4gICAgICAgICAgICBdKSxcbiAgICAgICAgICAgIHByb3BNZXRhZGF0YShvbmVUb09uZUtleSwgbWV0YWRhdGEpLFxuICAgICAgICAgICAgT25lVG9PbmUoXG4gICAgICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoIWNsYXp6Lm5hbWUpIGNsYXp6ID0gKGNsYXp6IGFzIGFueSkoKTtcbiAgICAgICAgICAgICAgICBpZiAoIWNsYXp6W01vZGVsS2V5cy5BTkNIT1IgYXMga2V5b2YgdHlwZW9mIGNsYXp6XSlcbiAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICAgICAgICAgICAgICBcIk9yaWdpbmFsIE1vZGVsIG5vdCBmb3VuZCBpbiBjb25zdHJ1Y3RvclwiXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHJldHVybiBjbGF6eltNb2RlbEtleXMuQU5DSE9SIGFzIGtleW9mIHR5cGVvZiBjbGF6el07XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIChtb2RlbDogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGsgPSBmaW5kUHJpbWFyeUtleShuZXcgKGNsYXp6IGFzIENvbnN0cnVjdG9yPGFueT4pKCkpLmlkO1xuICAgICAgICAgICAgICAgIHJldHVybiBtb2RlbFtwa107XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIG9ybU1ldGFcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBKb2luQ29sdW1uKClcbiAgICAgICAgICApO1xuICAgICAgICB9LFxuICAgICAgfSlcbiAgICAgIC5hcHBseSgpO1xuXG4gICAgLy8gQG9uZVRvTWFueShjbGF6eikgPT4gQE9uZVRvTWFueSgoKSA9PiBjbGF6eilcbiAgICBjb25zdCBvbmVUb01hbnlLZXkgPSBSZXBvc2l0b3J5LmtleShQZXJzaXN0ZW5jZUtleXMuT05FX1RPX01BTlkpO1xuICAgIERlY29yYXRpb24uZmxhdm91cmVkQXMoVHlwZU9STUZsYXZvdXIpXG4gICAgICAuZm9yKG9uZVRvTWFueUtleSlcbiAgICAgIC5kZWZpbmUoe1xuICAgICAgICBkZWNvcmF0b3I6IGZ1bmN0aW9uIG9uZVRvTWFueShcbiAgICAgICAgICBjbGF6ejogQ29uc3RydWN0b3I8YW55PiB8ICgoKSA9PiBDb25zdHJ1Y3Rvcjxhbnk+KSxcbiAgICAgICAgICBjYXNjYWRlOiBDYXNjYWRlTWV0YWRhdGEsXG4gICAgICAgICAgcG9wdWxhdGU6IGJvb2xlYW5cbiAgICAgICAgKSB7XG4gICAgICAgICAgY29uc3QgbWV0YWRhdGE6IFJlbGF0aW9uc01ldGFkYXRhID0ge1xuICAgICAgICAgICAgY2xhc3M6IChjbGF6ei5uYW1lID8gY2xhenoubmFtZSA6IGNsYXp6KSBhcyBzdHJpbmcsXG4gICAgICAgICAgICBjYXNjYWRlOiBjYXNjYWRlLFxuICAgICAgICAgICAgcG9wdWxhdGU6IHBvcHVsYXRlLFxuICAgICAgICAgIH07XG4gICAgICAgICAgcmV0dXJuIGFwcGx5KFxuICAgICAgICAgICAgcHJvcChQZXJzaXN0ZW5jZUtleXMuUkVMQVRJT05TKSxcbiAgICAgICAgICAgIGxpc3QoY2xhenopLFxuICAgICAgICAgICAgcHJvcE1ldGFkYXRhKG9uZVRvTWFueUtleSwgbWV0YWRhdGEpLFxuICAgICAgICAgICAgZnVuY3Rpb24gT25lVG9NYW55V3JhcHBlcihvYmo6IGFueSwgcHJvcDogYW55KTogYW55IHtcbiAgICAgICAgICAgICAgY29uc3Qgb3JtTWV0YTogUmVsYXRpb25PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIGNhc2NhZGU6XG4gICAgICAgICAgICAgICAgICBjYXNjYWRlLnVwZGF0ZSA9PT0gQ2FzY2FkZS5DQVNDQURFIHx8XG4gICAgICAgICAgICAgICAgICBjYXNjYWRlLmRlbGV0ZSA9PT0gQ2FzY2FkZS5DQVNDQURFLFxuICAgICAgICAgICAgICAgIG9uRGVsZXRlOiBjYXNjYWRlLmRlbGV0ZSA/IFwiQ0FTQ0FERVwiIDogXCJERUZBVUxUXCIsXG4gICAgICAgICAgICAgICAgb25VcGRhdGU6IGNhc2NhZGUudXBkYXRlID8gXCJDQVNDQURFXCIgOiBcIkRFRkFVTFRcIixcbiAgICAgICAgICAgICAgICBudWxsYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBlYWdlcjogcG9wdWxhdGUsXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgIHJldHVybiBPbmVUb01hbnkoXG4gICAgICAgICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKCFjbGF6ei5uYW1lKSBjbGF6eiA9IChjbGF6eiBhcyBhbnkpKCk7XG4gICAgICAgICAgICAgICAgICBpZiAoIWNsYXp6W01vZGVsS2V5cy5BTkNIT1IgYXMga2V5b2YgdHlwZW9mIGNsYXp6XSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgXCJPcmlnaW5hbCBNb2RlbCBub3QgZm91bmQgaW4gY29uc3RydWN0b3JcIlxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIGNsYXp6W01vZGVsS2V5cy5BTkNIT1IgYXMga2V5b2YgdHlwZW9mIGNsYXp6XTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIChtb2RlbDogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoIWNsYXp6Lm5hbWUpIGNsYXp6ID0gKGNsYXp6IGFzIGFueSkoKTtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IG0gPSBuZXcgKGNsYXp6IGFzIENvbnN0cnVjdG9yPGFueT4pKCk7XG4gICAgICAgICAgICAgICAgICBjb25zdCBjcm9zc1JlbGF0aW9uS2V5ID0gT2JqZWN0LmtleXMobSkuZmluZCgoaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBkZWNzID0gUmVmbGVjdGlvbi5nZXRQcm9wZXJ0eURlY29yYXRvcnMoXG4gICAgICAgICAgICAgICAgICAgICAgUmVwb3NpdG9yeS5rZXkoUGVyc2lzdGVuY2VLZXlzLk1BTllfVE9fT05FKSxcbiAgICAgICAgICAgICAgICAgICAgICBtLFxuICAgICAgICAgICAgICAgICAgICAgIGssXG4gICAgICAgICAgICAgICAgICAgICAgdHJ1ZVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWRlY3MgfHwgIWRlY3MuZGVjb3JhdG9ycyB8fCAhZGVjcy5kZWNvcmF0b3JzLmxlbmd0aClcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlc2lnblR5cGUgPSBSZWZsZWN0LmdldE1ldGFkYXRhKFxuICAgICAgICAgICAgICAgICAgICAgIE1vZGVsS2V5cy5UWVBFLFxuICAgICAgICAgICAgICAgICAgICAgIG0sXG4gICAgICAgICAgICAgICAgICAgICAga1xuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2lnblR5cGUpXG4gICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICBgTm8gVHlwZSBEZWZpbml0aW9uIGZvdW5kIGZvciAke2t9IGluICR7bS5jb25zdHJ1Y3Rvci5uYW1lfWBcbiAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGVzaWduVHlwZS5uYW1lID09PSBvYmouY29uc3RydWN0b3IubmFtZTtcbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgaWYgKCFjcm9zc1JlbGF0aW9uS2V5KVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICBgQ3Jvc3MgcmVsYXRpb24gbm90IGZvdW5kLiBEaWQgeW91IHVzZSBAbWFueVRvT25lIG9uIHRoZSAke2NsYXp6Lm5hbWV9P2BcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBtb2RlbFtjcm9zc1JlbGF0aW9uS2V5XTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9ybU1ldGFcbiAgICAgICAgICAgICAgKShvYmosIHByb3ApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICk7XG4gICAgICAgIH0sXG4gICAgICB9KVxuICAgICAgLmFwcGx5KCk7XG5cbiAgICAvLyBAbWFueVRvT25lKGNsYXp6KSA9PiBATWFueVRvT25lKCgpID0+IGNsYXp6KVxuICAgIGNvbnN0IG1hbnlUb09uZUtleSA9IFJlcG9zaXRvcnkua2V5KFBlcnNpc3RlbmNlS2V5cy5NQU5ZX1RPX09ORSk7XG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyZWRBcyhUeXBlT1JNRmxhdm91cilcbiAgICAgIC5mb3IobWFueVRvT25lS2V5KVxuICAgICAgLmRlZmluZSh7XG4gICAgICAgIGRlY29yYXRvcjogZnVuY3Rpb24gbWFueVRvT25lKFxuICAgICAgICAgIGNsYXp6OiBDb25zdHJ1Y3Rvcjxhbnk+IHwgKCgpID0+IENvbnN0cnVjdG9yPGFueT4pLFxuICAgICAgICAgIGNhc2NhZGU6IENhc2NhZGVNZXRhZGF0YSxcbiAgICAgICAgICBwb3B1bGF0ZTogYm9vbGVhblxuICAgICAgICApIHtcbiAgICAgICAgICBjb25zdCBtZXRhZGF0YTogUmVsYXRpb25zTWV0YWRhdGEgPSB7XG4gICAgICAgICAgICBjbGFzczogKGNsYXp6Lm5hbWUgPyBjbGF6ei5uYW1lIDogY2xhenopIGFzIHN0cmluZyxcbiAgICAgICAgICAgIGNhc2NhZGU6IGNhc2NhZGUsXG4gICAgICAgICAgICBwb3B1bGF0ZTogcG9wdWxhdGUsXG4gICAgICAgICAgfTtcbiAgICAgICAgICBjb25zdCBvcm1NZXRhOiBSZWxhdGlvbk9wdGlvbnMgPSB7XG4gICAgICAgICAgICBjYXNjYWRlOlxuICAgICAgICAgICAgICBjYXNjYWRlLnVwZGF0ZSA9PT0gQ2FzY2FkZS5DQVNDQURFIHx8XG4gICAgICAgICAgICAgIGNhc2NhZGUuZGVsZXRlID09PSBDYXNjYWRlLkNBU0NBREUsXG4gICAgICAgICAgICBvbkRlbGV0ZTogY2FzY2FkZS5kZWxldGUgPyBcIkNBU0NBREVcIiA6IFwiREVGQVVMVFwiLFxuICAgICAgICAgICAgb25VcGRhdGU6IGNhc2NhZGUudXBkYXRlID8gXCJDQVNDQURFXCIgOiBcIkRFRkFVTFRcIixcbiAgICAgICAgICAgIG51bGxhYmxlOiB0cnVlLFxuICAgICAgICAgICAgZWFnZXI6IHBvcHVsYXRlLFxuICAgICAgICAgIH07XG4gICAgICAgICAgcmV0dXJuIGFwcGx5KFxuICAgICAgICAgICAgcHJvcChQZXJzaXN0ZW5jZUtleXMuUkVMQVRJT05TKSxcbiAgICAgICAgICAgIHR5cGUoW1xuICAgICAgICAgICAgICAodHlwZW9mIGNsYXp6ID09PSBcImZ1bmN0aW9uXCIgJiYgIWNsYXp6Lm5hbWVcbiAgICAgICAgICAgICAgICA/IGNsYXp6XG4gICAgICAgICAgICAgICAgOiBjbGF6ei5uYW1lKSBhcyBhbnksXG4gICAgICAgICAgICAgIFN0cmluZy5uYW1lLFxuICAgICAgICAgICAgICBOdW1iZXIubmFtZSxcbiAgICAgICAgICAgICAgQmlnSW50Lm5hbWUsXG4gICAgICAgICAgICBdKSxcbiAgICAgICAgICAgIHByb3BNZXRhZGF0YShtYW55VG9PbmVLZXksIG1ldGFkYXRhKSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIE1hbnlUb09uZVdyYXBwZXIob2JqOiBhbnksIHByb3A6IGFueSk6IGFueSB7XG4gICAgICAgICAgICAgIHJldHVybiBNYW55VG9PbmUoXG4gICAgICAgICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKCFjbGF6ei5uYW1lKSBjbGF6eiA9IChjbGF6eiBhcyBhbnkpKCk7XG4gICAgICAgICAgICAgICAgICBpZiAoIWNsYXp6W01vZGVsS2V5cy5BTkNIT1IgYXMga2V5b2YgdHlwZW9mIGNsYXp6XSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgXCJPcmlnaW5hbCBNb2RlbCBub3QgZm91bmQgaW4gY29uc3RydWN0b3JcIlxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIGNsYXp6W01vZGVsS2V5cy5BTkNIT1IgYXMga2V5b2YgdHlwZW9mIGNsYXp6XTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIChtb2RlbDogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoIWNsYXp6Lm5hbWUpIGNsYXp6ID0gKGNsYXp6IGFzIGFueSkoKTtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IG0gPSBuZXcgKGNsYXp6IGFzIENvbnN0cnVjdG9yPGFueT4pKCk7XG4gICAgICAgICAgICAgICAgICBjb25zdCBjcm9zc1JlbGF0aW9uS2V5ID0gT2JqZWN0LmtleXMobSkuZmluZCgoaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBkZWNzID0gUmVmbGVjdGlvbi5nZXRQcm9wZXJ0eURlY29yYXRvcnMoXG4gICAgICAgICAgICAgICAgICAgICAgUmVwb3NpdG9yeS5rZXkoUGVyc2lzdGVuY2VLZXlzLk9ORV9UT19NQU5ZKSxcbiAgICAgICAgICAgICAgICAgICAgICBtLFxuICAgICAgICAgICAgICAgICAgICAgIGssXG4gICAgICAgICAgICAgICAgICAgICAgdHJ1ZVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWRlY3MgfHwgIWRlY3MuZGVjb3JhdG9ycyB8fCAhZGVjcy5kZWNvcmF0b3JzLmxlbmd0aClcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGxpc3REZWMgPSBSZWZsZWN0LmdldE1ldGFkYXRhKFxuICAgICAgICAgICAgICAgICAgICAgIFZhbGlkYXRpb24ua2V5KFZhbGlkYXRpb25LZXlzLkxJU1QpLFxuICAgICAgICAgICAgICAgICAgICAgIG0sXG4gICAgICAgICAgICAgICAgICAgICAga1xuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWxpc3REZWMpXG4gICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICBgTm8gVHlwZSBEZWZpbml0aW9uIGZvdW5kIGZvciAke2t9IGluICR7bS5jb25zdHJ1Y3Rvci5uYW1lfWBcbiAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBuYW1lID0gbGlzdERlYy5jbGF6elswXSgpLm5hbWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuYW1lID09PSBvYmouY29uc3RydWN0b3IubmFtZTtcbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgaWYgKCFjcm9zc1JlbGF0aW9uS2V5KVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICBgQ3Jvc3MgcmVsYXRpb24gbm90IGZvdW5kLiBEaWQgeW91IHVzZSBAbWFueVRvT25lIG9uIHRoZSAke2NsYXp6Lm5hbWV9P2BcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBtb2RlbFtjcm9zc1JlbGF0aW9uS2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICkob2JqLCBwcm9wKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICB9LFxuICAgICAgfSlcbiAgICAgIC5hcHBseSgpO1xuXG4gICAgLy8gQG1hbnlUb01hbnkoY2xhenopID0+IEBNYW55VG9NYW55KCgpID0+IGNsYXp6KVxuICAgIGNvbnN0IG1hbnlUb01hbnlLZXkgPSBSZXBvc2l0b3J5LmtleShQZXJzaXN0ZW5jZUtleXMuTUFOWV9UT19NQU5ZKTtcbiAgICBEZWNvcmF0aW9uLmZsYXZvdXJlZEFzKFR5cGVPUk1GbGF2b3VyKVxuICAgICAgLmZvcihtYW55VG9NYW55S2V5KVxuICAgICAgLmRlZmluZSh7XG4gICAgICAgIGRlY29yYXRvcjogZnVuY3Rpb24gbWFueVRvTWFueShcbiAgICAgICAgICBjbGF6ejogQ29uc3RydWN0b3I8YW55PiB8ICgoKSA9PiBDb25zdHJ1Y3Rvcjxhbnk+KSxcbiAgICAgICAgICBjYXNjYWRlOiBDYXNjYWRlTWV0YWRhdGEsXG4gICAgICAgICAgcG9wdWxhdGU6IGJvb2xlYW5cbiAgICAgICAgKSB7XG4gICAgICAgICAgY29uc3QgbWV0YWRhdGE6IFJlbGF0aW9uc01ldGFkYXRhID0ge1xuICAgICAgICAgICAgY2xhc3M6IGNsYXp6Lm5hbWUsXG4gICAgICAgICAgICBjYXNjYWRlOiBjYXNjYWRlLFxuICAgICAgICAgICAgcG9wdWxhdGU6IHBvcHVsYXRlLFxuICAgICAgICAgIH07XG4gICAgICAgICAgY29uc3Qgb3JtTWV0YTogUmVsYXRpb25PcHRpb25zID0ge1xuICAgICAgICAgICAgY2FzY2FkZTpcbiAgICAgICAgICAgICAgY2FzY2FkZS51cGRhdGUgPT09IENhc2NhZGUuQ0FTQ0FERSB8fFxuICAgICAgICAgICAgICBjYXNjYWRlLmRlbGV0ZSA9PT0gQ2FzY2FkZS5DQVNDQURFLFxuICAgICAgICAgICAgb25EZWxldGU6IGNhc2NhZGUuZGVsZXRlID8gXCJDQVNDQURFXCIgOiBcIkRFRkFVTFRcIixcbiAgICAgICAgICAgIG9uVXBkYXRlOiBjYXNjYWRlLnVwZGF0ZSA/IFwiQ0FTQ0FERVwiIDogXCJERUZBVUxUXCIsXG4gICAgICAgICAgICBudWxsYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGVhZ2VyOiBwb3B1bGF0ZSxcbiAgICAgICAgICB9O1xuICAgICAgICAgIHJldHVybiBhcHBseShcbiAgICAgICAgICAgIHByb3AoUGVyc2lzdGVuY2VLZXlzLlJFTEFUSU9OUyksXG4gICAgICAgICAgICBsaXN0KGNsYXp6KSxcbiAgICAgICAgICAgIHByb3BNZXRhZGF0YShtYW55VG9NYW55S2V5LCBtZXRhZGF0YSksXG4gICAgICAgICAgICBNYW55VG9NYW55KFxuICAgICAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFjbGF6ei5uYW1lKSBjbGF6eiA9IChjbGF6eiBhcyBhbnkpKCk7XG4gICAgICAgICAgICAgICAgaWYgKCFjbGF6eltNb2RlbEtleXMuQU5DSE9SIGFzIGtleW9mIHR5cGVvZiBjbGF6el0pXG4gICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgXCJPcmlnaW5hbCBNb2RlbCBub3QgZm91bmQgaW4gY29uc3RydWN0b3JcIlxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2xhenpbTW9kZWxLZXlzLkFOQ0hPUiBhcyBrZXlvZiB0eXBlb2YgY2xhenpdO1xuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAobW9kZWw6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghY2xhenoubmFtZSkgY2xhenogPSAoY2xhenogYXMgYW55KSgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHBrID0gZmluZFByaW1hcnlLZXkobmV3IChjbGF6eiBhcyBDb25zdHJ1Y3Rvcjxhbnk+KSgpKS5pZDtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9kZWxbcGtdO1xuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBvcm1NZXRhXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgSm9pblRhYmxlKClcbiAgICAgICAgICApO1xuICAgICAgICB9LFxuICAgICAgfSlcbiAgICAgIC5hcHBseSgpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBUeXBlT1JNQWRhcHRlciB9IGZyb20gXCIuL1R5cGVPUk1BZGFwdGVyXCI7XG5cblR5cGVPUk1BZGFwdGVyLmRlY29yYXRpb24oKTtcblxuZXhwb3J0ICogZnJvbSBcIi4vaW5kZXhlc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vcXVlcnlcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3NlcXVlbmNlc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vVHlwZU9STUFkYXB0ZXJcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vZXJyb3JzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9UeXBlT1JNRGlzcGF0Y2hcIjtcbmV4cG9ydCAqIGZyb20gXCIuL1R5cGVPUk1SZXBvc2l0b3J5XCI7XG5leHBvcnQgKiBmcm9tIFwiLi90eXBlc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vdXRpbHNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gVHlwZU9STSBpbnRlZ3JhdGlvbiBmb3IgRGVjYWYudHMuXG4gKiBAc3VtbWFyeSBQcm92aWRlcyB0aGUgVHlwZU9STS1iYWNrZWQgaW1wbGVtZW50YXRpb24gb2YgdGhlIERlY2FmLnRzIGRhdGEgYWNjZXNzIGFic3RyYWN0aW9ucywgaW5jbHVkaW5nIHRoZSBhZGFwdGVyLCByZXBvc2l0b3J5LCBzdGF0ZW1lbnQgYnVpbGRlciwgcGFnaW5hdGlvbiB1dGlsaXRpZXMsIGluZGV4IGhlbHBlcnMsIGFuZCB0eXBlIGRlZmluaXRpb25zLiBLZXkgZXhwb3J0cyBpbmNsdWRlIHtAbGluayBUeXBlT1JNQWRhcHRlcn0sIHtAbGluayBUeXBlT1JNUmVwb3NpdG9yeX0sIHtAbGluayBUeXBlT1JNU3RhdGVtZW50fSwge0BsaW5rIFR5cGVPUk1QYWdpbmF0b3J9LCBhbmQgaW5kZXggZ2VuZXJhdGlvbiB1dGlsaXRpZXMuXG4gKiBAbW9kdWxlIGZvci10eXBlb3JtXG4gKi9cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU3RvcmVzIHRoZSBjdXJyZW50IHBhY2thZ2UgdmVyc2lvbi5cbiAqIEBzdW1tYXJ5IFRoZSB2ZXJzaW9uIHN0cmluZyBvZiB0aGUgZm9yLXR5cGVvcm0gcGFja2FnZS5cbiAqIEBjb25zdCBWRVJTSU9OXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci10eXBlb3JtXG4gKi9cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gXCIjI1ZFUlNJT04jI1wiO1xuIl0sIm5hbWVzIjpbIkRCX0RFRkFVTFRfRVJST1JfTUVTU0FHRVMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQTs7Ozs7QUFLRztBQUNJLE1BQU0sa0JBQWtCLEdBQzdCO0FBRUssTUFBTSxjQUFjLEdBQUc7QUFFOUI7Ozs7Ozs7Ozs7Ozs7QUFhRztBQUNIOzs7Ozs7QUFNRztBQUNJLE1BQU0s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