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