@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.
- package/LICENSE.md +21 -0
- package/README.md +93 -0
- package/dist/for-typeorm.cjs +2553 -0
- package/dist/for-typeorm.esm.cjs +2538 -0
- package/lib/TypeORMAdapter.cjs +1129 -0
- package/lib/TypeORMAdapter.d.ts +221 -0
- package/lib/TypeORMDispatch.cjs +134 -0
- package/lib/TypeORMDispatch.d.ts +87 -0
- package/lib/TypeORMEventSubscriber.cjs +96 -0
- package/lib/TypeORMEventSubscriber.d.ts +56 -0
- package/lib/TypeORMRepository.cjs +209 -0
- package/lib/TypeORMRepository.d.ts +125 -0
- package/lib/constants.cjs +43 -0
- package/lib/constants.d.ts +39 -0
- package/lib/errors.cjs +28 -0
- package/lib/errors.d.ts +21 -0
- package/lib/esm/TypeORMAdapter.d.ts +221 -0
- package/lib/esm/TypeORMAdapter.js +1124 -0
- package/lib/esm/TypeORMDispatch.d.ts +87 -0
- package/lib/esm/TypeORMDispatch.js +130 -0
- package/lib/esm/TypeORMEventSubscriber.d.ts +56 -0
- package/lib/esm/TypeORMEventSubscriber.js +93 -0
- package/lib/esm/TypeORMRepository.d.ts +125 -0
- package/lib/esm/TypeORMRepository.js +206 -0
- package/lib/esm/constants.d.ts +39 -0
- package/lib/esm/constants.js +40 -0
- package/lib/esm/errors.d.ts +21 -0
- package/lib/esm/errors.js +24 -0
- package/lib/esm/index.d.ts +22 -0
- package/lib/esm/index.js +25 -0
- package/lib/esm/indexes/generator.d.ts +50 -0
- package/lib/esm/indexes/generator.js +95 -0
- package/lib/esm/indexes/index.d.ts +1 -0
- package/lib/esm/indexes/index.js +2 -0
- package/lib/esm/overrides/Column.d.ts +74 -0
- package/lib/esm/overrides/Column.js +70 -0
- package/lib/esm/overrides/CreateDateColumn.d.ts +2 -0
- package/lib/esm/overrides/CreateDateColumn.js +9 -0
- package/lib/esm/overrides/Entity.d.ts +11 -0
- package/lib/esm/overrides/Entity.js +28 -0
- package/lib/esm/overrides/PrimaryColumn.d.ts +20 -0
- package/lib/esm/overrides/PrimaryColumn.js +53 -0
- package/lib/esm/overrides/PrimaryGeneratedColumn.d.ts +24 -0
- package/lib/esm/overrides/PrimaryGeneratedColumn.js +51 -0
- package/lib/esm/overrides/UpdateDateColumn.d.ts +2 -0
- package/lib/esm/overrides/UpdateDateColumn.js +9 -0
- package/lib/esm/overrides/utils.d.ts +2 -0
- package/lib/esm/overrides/utils.js +29 -0
- package/lib/esm/query/Paginator.d.ts +86 -0
- package/lib/esm/query/Paginator.js +124 -0
- package/lib/esm/query/Statement.d.ts +131 -0
- package/lib/esm/query/Statement.js +242 -0
- package/lib/esm/query/constants.d.ts +52 -0
- package/lib/esm/query/constants.js +74 -0
- package/lib/esm/query/index.d.ts +4 -0
- package/lib/esm/query/index.js +5 -0
- package/lib/esm/query/translate.d.ts +34 -0
- package/lib/esm/query/translate.js +42 -0
- package/lib/esm/raw/postgres.d.ts +36 -0
- package/lib/esm/raw/postgres.js +2 -0
- package/lib/esm/sequences/Sequence.d.ts +67 -0
- package/lib/esm/sequences/Sequence.js +117 -0
- package/lib/esm/sequences/index.d.ts +1 -0
- package/lib/esm/sequences/index.js +2 -0
- package/lib/esm/types.d.ts +67 -0
- package/lib/esm/types.js +28 -0
- package/lib/esm/utils.d.ts +16 -0
- package/lib/esm/utils.js +29 -0
- package/lib/index.cjs +42 -0
- package/lib/index.d.ts +22 -0
- package/lib/indexes/generator.cjs +98 -0
- package/lib/indexes/generator.d.ts +50 -0
- package/lib/indexes/index.cjs +18 -0
- package/lib/indexes/index.d.ts +1 -0
- package/lib/overrides/Column.cjs +73 -0
- package/lib/overrides/Column.d.ts +74 -0
- package/lib/overrides/CreateDateColumn.cjs +12 -0
- package/lib/overrides/CreateDateColumn.d.ts +2 -0
- package/lib/overrides/Entity.cjs +31 -0
- package/lib/overrides/Entity.d.ts +11 -0
- package/lib/overrides/PrimaryColumn.cjs +56 -0
- package/lib/overrides/PrimaryColumn.d.ts +20 -0
- package/lib/overrides/PrimaryGeneratedColumn.cjs +54 -0
- package/lib/overrides/PrimaryGeneratedColumn.d.ts +24 -0
- package/lib/overrides/UpdateDateColumn.cjs +12 -0
- package/lib/overrides/UpdateDateColumn.d.ts +2 -0
- package/lib/overrides/utils.cjs +32 -0
- package/lib/overrides/utils.d.ts +2 -0
- package/lib/query/Paginator.cjs +128 -0
- package/lib/query/Paginator.d.ts +86 -0
- package/lib/query/Statement.cjs +246 -0
- package/lib/query/Statement.d.ts +131 -0
- package/lib/query/constants.cjs +77 -0
- package/lib/query/constants.d.ts +52 -0
- package/lib/query/index.cjs +21 -0
- package/lib/query/index.d.ts +4 -0
- package/lib/query/translate.cjs +45 -0
- package/lib/query/translate.d.ts +34 -0
- package/lib/raw/postgres.cjs +3 -0
- package/lib/raw/postgres.d.ts +36 -0
- package/lib/sequences/Sequence.cjs +121 -0
- package/lib/sequences/Sequence.d.ts +67 -0
- package/lib/sequences/index.cjs +18 -0
- package/lib/sequences/index.d.ts +1 -0
- package/lib/types.cjs +31 -0
- package/lib/types.d.ts +67 -0
- package/lib/utils.cjs +32 -0
- package/lib/utils.d.ts +16 -0
- package/package.json +128 -0
|
@@ -0,0 +1,1129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.TypeORMAdapter = void 0;
|
|
13
|
+
exports.createdByOnPostgresCreateUpdate = createdByOnPostgresCreateUpdate;
|
|
14
|
+
const core_1 = require("@decaf-ts/core");
|
|
15
|
+
const constants_1 = require("./constants.cjs");
|
|
16
|
+
const db_decorators_1 = require("@decaf-ts/db-decorators");
|
|
17
|
+
require("reflect-metadata");
|
|
18
|
+
const decorator_validation_1 = require("@decaf-ts/decorator-validation");
|
|
19
|
+
const errors_1 = require("./errors.cjs");
|
|
20
|
+
const query_1 = require("./query/index.cjs");
|
|
21
|
+
const sequences_1 = require("./sequences/index.cjs");
|
|
22
|
+
const indexes_1 = require("./indexes/index.cjs");
|
|
23
|
+
const reflection_1 = require("@decaf-ts/reflection");
|
|
24
|
+
const TypeORMRepository_1 = require("./TypeORMRepository.cjs");
|
|
25
|
+
const logging_1 = require("@decaf-ts/logging");
|
|
26
|
+
const TypeORMDispatch_1 = require("./TypeORMDispatch.cjs");
|
|
27
|
+
const utils_1 = require("./utils.cjs");
|
|
28
|
+
const typeorm_1 = require("typeorm");
|
|
29
|
+
const Column_1 = require("./overrides/Column.cjs");
|
|
30
|
+
const UpdateDateColumn_1 = require("./overrides/UpdateDateColumn.cjs");
|
|
31
|
+
const CreateDateColumn_1 = require("./overrides/CreateDateColumn.cjs");
|
|
32
|
+
const PrimaryGeneratedColumn_1 = require("./overrides/PrimaryGeneratedColumn.cjs");
|
|
33
|
+
const PrimaryColumn_1 = require("./overrides/PrimaryColumn.cjs");
|
|
34
|
+
const Entity_1 = require("./overrides/Entity.cjs");
|
|
35
|
+
async function createdByOnPostgresCreateUpdate(context, data, key, model) {
|
|
36
|
+
try {
|
|
37
|
+
const user = context.get("user");
|
|
38
|
+
model[key] = user;
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
throw new db_decorators_1.InternalError("No User found in context. Please provide a user in the context");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* @description Adapter for TypeORM-backed persistence operations.
|
|
47
|
+
* @summary Implements the Decaf.ts Adapter over a TypeORM DataSource, providing CRUD operations, query/statement factories, sequence management, error parsing, and decoration helpers.
|
|
48
|
+
* @template Y The native configuration type (TypeORM DataSourceOptions).
|
|
49
|
+
* @template F The repository flags type.
|
|
50
|
+
* @template C The context type.
|
|
51
|
+
* @param {DataSourceOptions} scope The DataSource options for the adapter.
|
|
52
|
+
* @param {string} flavour The flavour of the adapter.
|
|
53
|
+
* @param {string} [alias] Optional alias for the adapter.
|
|
54
|
+
* @class TypeORMAdapter
|
|
55
|
+
* @example
|
|
56
|
+
* const adapter = new TypeORMAdapter({ type: 'postgres', /* ... *\/ });
|
|
57
|
+
* await adapter.initialize();
|
|
58
|
+
* const repo = new (adapter.repository<User>())(adapter, User);
|
|
59
|
+
* const created = await repo.create(new User({ name: 'Alice' }));
|
|
60
|
+
*
|
|
61
|
+
* @mermaid
|
|
62
|
+
* sequenceDiagram
|
|
63
|
+
* participant App
|
|
64
|
+
* participant Adapter as TypeORMAdapter
|
|
65
|
+
* participant Repo as TypeORMRepository
|
|
66
|
+
* participant DS as TypeORM DataSource
|
|
67
|
+
*
|
|
68
|
+
* App->>Adapter: new TypeORMAdapter(opts)
|
|
69
|
+
* Adapter->>DS: initialize()
|
|
70
|
+
* App->>Adapter: repository()
|
|
71
|
+
* Adapter-->>App: TypeORMRepository
|
|
72
|
+
* App->>Repo: create(model)
|
|
73
|
+
* Repo->>Adapter: prepare/create/revert
|
|
74
|
+
* Adapter-->>Repo: Model
|
|
75
|
+
* Repo-->>App: Model
|
|
76
|
+
*/
|
|
77
|
+
class TypeORMAdapter extends core_1.Adapter {
|
|
78
|
+
get dataSource() {
|
|
79
|
+
if (!this._dataSource) {
|
|
80
|
+
const models = core_1.Adapter.models(this.flavour);
|
|
81
|
+
this._dataSource = new typeorm_1.DataSource(Object.assign(this.native, {
|
|
82
|
+
entities: models.map((c) => c[decorator_validation_1.ModelKeys.ANCHOR]),
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
return this._dataSource;
|
|
86
|
+
}
|
|
87
|
+
// protected dataSou
|
|
88
|
+
constructor(options, alias) {
|
|
89
|
+
super(options, constants_1.TypeORMFlavour, alias);
|
|
90
|
+
}
|
|
91
|
+
async flags(operation, model, flags) {
|
|
92
|
+
const f = await super.flags(operation, model, flags);
|
|
93
|
+
const newObj = {
|
|
94
|
+
user: (await TypeORMAdapter.getCurrentUser(this.dataSource)),
|
|
95
|
+
};
|
|
96
|
+
const m = new model();
|
|
97
|
+
const exceptions = [];
|
|
98
|
+
if (operation === db_decorators_1.OperationKeys.CREATE) {
|
|
99
|
+
const pk = (0, db_decorators_1.findPrimaryKey)(m).id;
|
|
100
|
+
exceptions.push(pk);
|
|
101
|
+
}
|
|
102
|
+
if (operation === db_decorators_1.OperationKeys.CREATE ||
|
|
103
|
+
operation === db_decorators_1.OperationKeys.UPDATE) {
|
|
104
|
+
const decs = Object.keys(m).reduce((accum, key) => {
|
|
105
|
+
const decs = reflection_1.Reflection.getPropertyDecorators(decorator_validation_1.ValidationKeys.REFLECT, m, key, true);
|
|
106
|
+
const dec = decs.decorators.find((dec) => dec.key === db_decorators_1.DBKeys.TIMESTAMP &&
|
|
107
|
+
dec.props.operation.indexOf(operation) !== -1);
|
|
108
|
+
if (dec) {
|
|
109
|
+
accum[key] = dec.props;
|
|
110
|
+
}
|
|
111
|
+
return accum;
|
|
112
|
+
}, {});
|
|
113
|
+
exceptions.push(...Object.keys(decs));
|
|
114
|
+
}
|
|
115
|
+
newObj.ignoredValidationProperties = (f.ignoredValidationProperties ? f.ignoredValidationProperties : []).concat(...exceptions);
|
|
116
|
+
return Object.assign(f, newObj);
|
|
117
|
+
}
|
|
118
|
+
Dispatch() {
|
|
119
|
+
return new TypeORMDispatch_1.TypeORMDispatch();
|
|
120
|
+
}
|
|
121
|
+
repository() {
|
|
122
|
+
return TypeORMRepository_1.TypeORMRepository;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* @description Creates a new Postgres statement for querying
|
|
126
|
+
* @summary Factory method that creates a new PostgresStatement instance for building queries
|
|
127
|
+
* @template M - The model type
|
|
128
|
+
* @return {TypeORMStatement<M, any>} A new PostgresStatement instance
|
|
129
|
+
*/
|
|
130
|
+
Statement() {
|
|
131
|
+
return new query_1.TypeORMStatement(this);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* @description Creates a new PostgreSQL sequence
|
|
135
|
+
* @summary Factory method that creates a new PostgreSQLSequence instance for managing sequences
|
|
136
|
+
* @param {SequenceOptions} options - The options for the sequence
|
|
137
|
+
* @return {Promise<Sequence>} A promise that resolves to a new Sequence instance
|
|
138
|
+
*/
|
|
139
|
+
async Sequence(options) {
|
|
140
|
+
return new sequences_1.TypeORMSequence(options, this);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* @description Initializes the adapter by creating indexes for all managed models
|
|
144
|
+
* @summary Sets up the necessary database indexes for all models managed by this adapter
|
|
145
|
+
* @return {Promise<void>} A promise that resolves when initialization is complete
|
|
146
|
+
*/
|
|
147
|
+
async initialize() {
|
|
148
|
+
const ds = this.dataSource;
|
|
149
|
+
try {
|
|
150
|
+
await ds.initialize();
|
|
151
|
+
}
|
|
152
|
+
catch (e) {
|
|
153
|
+
throw this.parseError(e);
|
|
154
|
+
}
|
|
155
|
+
const log = this.log.for(this.initialize);
|
|
156
|
+
log.verbose(`${this.flavour} adapter initialized`);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* @description Creates indexes for the given models
|
|
160
|
+
* @summary Abstract method that must be implemented to create database indexes for the specified models
|
|
161
|
+
* @template M - The model type
|
|
162
|
+
* @param {...Constructor<M>} models - The model constructors to create indexes for
|
|
163
|
+
* @return {Promise<void>} A promise that resolves when all indexes are created
|
|
164
|
+
*/
|
|
165
|
+
async index(...models) {
|
|
166
|
+
const indexes = (0, indexes_1.generateIndexes)(models);
|
|
167
|
+
try {
|
|
168
|
+
await this.dataSource.query("BEGIN");
|
|
169
|
+
for (const index of indexes) {
|
|
170
|
+
await this.dataSource.query(index.query, index.values);
|
|
171
|
+
}
|
|
172
|
+
await this.dataSource.query("COMMIT");
|
|
173
|
+
}
|
|
174
|
+
catch (e) {
|
|
175
|
+
await this.dataSource.query("ROLLBACK");
|
|
176
|
+
throw this.parseError(e);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* @description Executes a raw SQL query against the database
|
|
181
|
+
* @summary Abstract method that must be implemented to execute raw SQL queries
|
|
182
|
+
* @template R - The result type
|
|
183
|
+
* @param {TypeORMQuery} q - The query to execute
|
|
184
|
+
* @return {Promise<R>} A promise that resolves to the query result
|
|
185
|
+
*/
|
|
186
|
+
async raw(q) {
|
|
187
|
+
const log = this.log.for(this.raw);
|
|
188
|
+
try {
|
|
189
|
+
if (!this.dataSource.isInitialized)
|
|
190
|
+
await this.dataSource.initialize();
|
|
191
|
+
}
|
|
192
|
+
catch (e) {
|
|
193
|
+
throw this.parseError(e);
|
|
194
|
+
}
|
|
195
|
+
try {
|
|
196
|
+
const { query, values } = q;
|
|
197
|
+
log.debug(`executing query: ${query.getSql()}`);
|
|
198
|
+
const response = await this.dataSource.query(query, values);
|
|
199
|
+
return response;
|
|
200
|
+
}
|
|
201
|
+
catch (e) {
|
|
202
|
+
throw this.parseError(e);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
prepare(model, pk, child = false) {
|
|
206
|
+
const prepared = super.prepare(model, pk);
|
|
207
|
+
prepared.record = Object.entries(prepared.record).reduce((accum, [key, value]) => {
|
|
208
|
+
if (key === core_1.PersistenceKeys.METADATA || this.isReserved(key))
|
|
209
|
+
return accum;
|
|
210
|
+
if (value === undefined) {
|
|
211
|
+
return accum;
|
|
212
|
+
}
|
|
213
|
+
if (value instanceof Date) {
|
|
214
|
+
value = new Date(value.getTime());
|
|
215
|
+
}
|
|
216
|
+
else if (decorator_validation_1.Model.isModel(value)) {
|
|
217
|
+
value = this.prepare(value, (0, db_decorators_1.findPrimaryKey)(value).id, true).record;
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
switch (typeof value) {
|
|
221
|
+
case "string":
|
|
222
|
+
value = `${value}`;
|
|
223
|
+
break;
|
|
224
|
+
default:
|
|
225
|
+
//do nothing;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
accum[key] = value;
|
|
229
|
+
return accum;
|
|
230
|
+
}, {});
|
|
231
|
+
const constr = decorator_validation_1.Model.get(model.constructor.name);
|
|
232
|
+
if (!constr)
|
|
233
|
+
throw new db_decorators_1.InternalError(`Model ${model.constructor.name} not found in registry`);
|
|
234
|
+
const result = child
|
|
235
|
+
? new constr[decorator_validation_1.ModelKeys.ANCHOR]()
|
|
236
|
+
: new constr();
|
|
237
|
+
if (child)
|
|
238
|
+
Object.defineProperty(result, "constructor", {
|
|
239
|
+
configurable: false,
|
|
240
|
+
enumerable: false,
|
|
241
|
+
value: constr[decorator_validation_1.ModelKeys.ANCHOR],
|
|
242
|
+
writable: false,
|
|
243
|
+
});
|
|
244
|
+
Object.entries(prepared.record).forEach(([key, val]) => (result[key] = val));
|
|
245
|
+
prepared.record = result;
|
|
246
|
+
return prepared;
|
|
247
|
+
}
|
|
248
|
+
revert(obj, clazz, pk, id, transient) {
|
|
249
|
+
const log = this.log.for(this.revert);
|
|
250
|
+
if (transient) {
|
|
251
|
+
log.verbose(`re-adding transient properties: ${Object.keys(transient).join(", ")}`);
|
|
252
|
+
Object.entries(transient).forEach(([key, val]) => {
|
|
253
|
+
if (key in obj)
|
|
254
|
+
throw new db_decorators_1.InternalError(`Transient property ${key} already exists on model ${typeof clazz === "string" ? clazz : clazz.name}. should be impossible`);
|
|
255
|
+
obj[key] = val;
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
return new clazz(obj);
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* @description Creates a new record in the database
|
|
262
|
+
* @summary Abstract method that must be implemented to create a new record
|
|
263
|
+
* @param {string} tableName - The name of the table
|
|
264
|
+
* @param {string|number} id - The ID of the record
|
|
265
|
+
* @param {Record<string, any>} model - The model to create
|
|
266
|
+
* @param {...any[]} args - Additional arguments
|
|
267
|
+
* @return {Promise<Record<string, any>>} A promise that resolves to the created record
|
|
268
|
+
*/
|
|
269
|
+
async create(tableName, id, model,
|
|
270
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
271
|
+
...args) {
|
|
272
|
+
const m = tableName;
|
|
273
|
+
try {
|
|
274
|
+
const repo = this.dataSource.getRepository(m);
|
|
275
|
+
return await repo.save(model);
|
|
276
|
+
}
|
|
277
|
+
catch (e) {
|
|
278
|
+
throw this.parseError(e);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* @description Reads a record from the database
|
|
283
|
+
* @summary Abstract method that must be implemented to read a record
|
|
284
|
+
* @param {string} tableName - The name of the table
|
|
285
|
+
* @param {string|number} id - The ID of the record
|
|
286
|
+
* @param {string} pk - primary key colum
|
|
287
|
+
* @return {Promise<Record<string, any>>} A promise that resolves to the read record
|
|
288
|
+
*/
|
|
289
|
+
async read(tableName, id, pk) {
|
|
290
|
+
const m = tableName;
|
|
291
|
+
let result;
|
|
292
|
+
try {
|
|
293
|
+
const repo = this.dataSource.getRepository(m);
|
|
294
|
+
const q = {
|
|
295
|
+
where: {
|
|
296
|
+
[pk]: id,
|
|
297
|
+
},
|
|
298
|
+
};
|
|
299
|
+
result = (await repo.findOne(q));
|
|
300
|
+
}
|
|
301
|
+
catch (e) {
|
|
302
|
+
throw this.parseError(e);
|
|
303
|
+
}
|
|
304
|
+
if (!result)
|
|
305
|
+
throw new db_decorators_1.NotFoundError(`Record with id: ${id} not found in table ${typeof tableName === "string" ? tableName : core_1.Repository.table(tableName)}`);
|
|
306
|
+
return result;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* @description Updates a record in the database
|
|
310
|
+
* @summary Abstract method that must be implemented to update a record
|
|
311
|
+
* @param {string} tableName - The name of the table
|
|
312
|
+
* @param {string|number} id - The ID of the record
|
|
313
|
+
* @param {Record<string, any>} model - The model to update
|
|
314
|
+
* @param {string} pk - Additional arguments
|
|
315
|
+
* @return A promise that resolves to the updated record
|
|
316
|
+
*/
|
|
317
|
+
async update(tableName, id, model,
|
|
318
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
319
|
+
...args) {
|
|
320
|
+
const m = tableName;
|
|
321
|
+
try {
|
|
322
|
+
const repo = this.dataSource.getRepository(m);
|
|
323
|
+
return repo.save(model);
|
|
324
|
+
}
|
|
325
|
+
catch (e) {
|
|
326
|
+
throw this.parseError(e);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* @description Deletes a record from the database
|
|
331
|
+
* @summary Abstract method that must be implemented to delete a record
|
|
332
|
+
* @param {string} tableName - The name of the table
|
|
333
|
+
* @param {string|number} id - The ID of the record
|
|
334
|
+
* @param {string} pk - Additional arguments
|
|
335
|
+
* @return A promise that resolves to the deleted record
|
|
336
|
+
*/
|
|
337
|
+
async delete(tableName, id, pk,
|
|
338
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
339
|
+
...args) {
|
|
340
|
+
const m = tableName;
|
|
341
|
+
try {
|
|
342
|
+
const repo = this.dataSource.getRepository(m);
|
|
343
|
+
const model = await this.read(tableName, id, pk);
|
|
344
|
+
const res = await repo.delete(id);
|
|
345
|
+
return model;
|
|
346
|
+
}
|
|
347
|
+
catch (e) {
|
|
348
|
+
throw this.parseError(e);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
async createAll(tableName, id, model,
|
|
352
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
353
|
+
...args) {
|
|
354
|
+
const m = tableName;
|
|
355
|
+
try {
|
|
356
|
+
const repo = this.dataSource.getRepository(m);
|
|
357
|
+
const result = await repo.insert(model);
|
|
358
|
+
return this.readAll(tableName, result.identifiers.map((id) => id.id), "id");
|
|
359
|
+
}
|
|
360
|
+
catch (e) {
|
|
361
|
+
throw this.parseError(e);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
async readAll(tableName, id, pk,
|
|
365
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
366
|
+
...args) {
|
|
367
|
+
if (!id.length)
|
|
368
|
+
return [];
|
|
369
|
+
const m = tableName;
|
|
370
|
+
try {
|
|
371
|
+
const repo = this.dataSource.getRepository(m);
|
|
372
|
+
return repo.findBy({ [pk]: (0, typeorm_1.In)(id) });
|
|
373
|
+
}
|
|
374
|
+
catch (e) {
|
|
375
|
+
throw this.parseError(e);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
async updateAll(tableName, ids, model, pk, ...args) {
|
|
379
|
+
const result = [];
|
|
380
|
+
for (const m of model) {
|
|
381
|
+
result.push(await this.update(tableName, m[pk], m, ...args));
|
|
382
|
+
}
|
|
383
|
+
return result;
|
|
384
|
+
}
|
|
385
|
+
async deleteAll(tableName, ids, pk,
|
|
386
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
387
|
+
...args) {
|
|
388
|
+
if (!ids.length)
|
|
389
|
+
return [];
|
|
390
|
+
const m = tableName;
|
|
391
|
+
try {
|
|
392
|
+
const repo = this.dataSource.getRepository(m);
|
|
393
|
+
const models = await this.readAll(tableName, ids, pk);
|
|
394
|
+
await repo.delete(ids);
|
|
395
|
+
return models;
|
|
396
|
+
}
|
|
397
|
+
catch (e) {
|
|
398
|
+
throw this.parseError(e);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* @description Parses an error and converts it to a BaseError
|
|
403
|
+
* @summary Converts various error types to appropriate BaseError subtypes
|
|
404
|
+
* @param {Error|string} err - The error to parse
|
|
405
|
+
* @param {string} [reason] - Optional reason for the error
|
|
406
|
+
* @return {BaseError} The parsed error as a BaseError
|
|
407
|
+
*/
|
|
408
|
+
parseError(err, reason) {
|
|
409
|
+
return TypeORMAdapter.parseError(err, reason);
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* @description Checks if an attribute is reserved
|
|
413
|
+
* @summary Determines if an attribute name is reserved in PostgreSQL
|
|
414
|
+
* @param {string} attr - The attribute name to check
|
|
415
|
+
* @return {boolean} True if the attribute is reserved, false otherwise
|
|
416
|
+
*/
|
|
417
|
+
isReserved(attr) {
|
|
418
|
+
return !!attr.match(constants_1.reservedAttributes);
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* @description Static method to parse an error and convert it to a BaseError
|
|
422
|
+
* @summary Converts various error types to appropriate BaseError subtypes based on PostgreSQL error codes and messages
|
|
423
|
+
* @param {Error|string} err - The error to parse
|
|
424
|
+
* @param {string} [reason] - Optional reason for the error
|
|
425
|
+
* @return {BaseError} The parsed error as a BaseError
|
|
426
|
+
* @mermaid
|
|
427
|
+
* sequenceDiagram
|
|
428
|
+
* participant Caller
|
|
429
|
+
* participant parseError
|
|
430
|
+
* participant ErrorTypes
|
|
431
|
+
*
|
|
432
|
+
* Caller->>parseError: err, reason
|
|
433
|
+
* Note over parseError: Check if err is already a BaseError
|
|
434
|
+
* alt err is BaseError
|
|
435
|
+
* parseError-->>Caller: return err
|
|
436
|
+
* else err is string
|
|
437
|
+
* Note over parseError: Extract code from string
|
|
438
|
+
* alt code matches "duplicate key|already exists"
|
|
439
|
+
* parseError->>ErrorTypes: new ConflictError(code)
|
|
440
|
+
* ErrorTypes-->>Caller: ConflictError
|
|
441
|
+
* else code matches "does not exist|not found"
|
|
442
|
+
* parseError->>ErrorTypes: new NotFoundError(code)
|
|
443
|
+
* ErrorTypes-->>Caller: NotFoundError
|
|
444
|
+
* end
|
|
445
|
+
* else err has code property
|
|
446
|
+
* Note over parseError: Extract code and reason
|
|
447
|
+
* else
|
|
448
|
+
* Note over parseError: Use err.message as code
|
|
449
|
+
* end
|
|
450
|
+
*
|
|
451
|
+
* Note over parseError: Switch on PostgreSQL error code
|
|
452
|
+
* alt code is 23505 (unique_violation)
|
|
453
|
+
* parseError->>ErrorTypes: new ConflictError(reason)
|
|
454
|
+
* ErrorTypes-->>Caller: ConflictError
|
|
455
|
+
* else code is 23503 (foreign_key_violation)
|
|
456
|
+
* parseError->>ErrorTypes: new ConflictError(reason)
|
|
457
|
+
* ErrorTypes-->>Caller: ConflictError
|
|
458
|
+
* else code is 42P01 (undefined_table)
|
|
459
|
+
* parseError->>ErrorTypes: new NotFoundError(reason)
|
|
460
|
+
* ErrorTypes-->>Caller: NotFoundError
|
|
461
|
+
* else code is 42703 (undefined_column)
|
|
462
|
+
* parseError->>ErrorTypes: new NotFoundError(reason)
|
|
463
|
+
* ErrorTypes-->>Caller: NotFoundError
|
|
464
|
+
* else code is 42P07 (duplicate_table)
|
|
465
|
+
* parseError->>ErrorTypes: new ConflictError(reason)
|
|
466
|
+
* ErrorTypes-->>Caller: ConflictError
|
|
467
|
+
* else code is 42P16 (invalid_table_definition)
|
|
468
|
+
* parseError->>ErrorTypes: new IndexError(err)
|
|
469
|
+
* ErrorTypes-->>Caller: IndexError
|
|
470
|
+
* else code matches "ECONNREFUSED"
|
|
471
|
+
* parseError->>ErrorTypes: new ConnectionError(err)
|
|
472
|
+
* ErrorTypes-->>Caller: ConnectionError
|
|
473
|
+
* else
|
|
474
|
+
* parseError->>ErrorTypes: new InternalError(err)
|
|
475
|
+
* ErrorTypes-->>Caller: InternalError
|
|
476
|
+
* end
|
|
477
|
+
*/
|
|
478
|
+
static parseError(err, reason) {
|
|
479
|
+
if (err instanceof db_decorators_1.BaseError)
|
|
480
|
+
return err;
|
|
481
|
+
const code = typeof err === "string" ? err : err.message;
|
|
482
|
+
if (code.match(/duplicate key|already exists/g))
|
|
483
|
+
return new db_decorators_1.ConflictError(code);
|
|
484
|
+
if (code.match(/does not exist|not found/g))
|
|
485
|
+
return new db_decorators_1.NotFoundError(code);
|
|
486
|
+
// PostgreSQL error codes: https://www.postgresql.org/docs/current/errcodes-appendix.html
|
|
487
|
+
switch (code.toString()) {
|
|
488
|
+
// Integrity constraint violations
|
|
489
|
+
case "23505": // unique_violation
|
|
490
|
+
case "23503": // foreign_key_violation
|
|
491
|
+
case "42P07": // duplicate_table
|
|
492
|
+
return new db_decorators_1.ConflictError(reason);
|
|
493
|
+
// Object not found errors
|
|
494
|
+
case "42P01": // undefined_table
|
|
495
|
+
case "42703": // undefined_column
|
|
496
|
+
return new db_decorators_1.NotFoundError(reason);
|
|
497
|
+
// Invalid object definition
|
|
498
|
+
case "42P16": // invalid_table_definition
|
|
499
|
+
return new errors_1.IndexError(err);
|
|
500
|
+
// Connection errors
|
|
501
|
+
default:
|
|
502
|
+
if (code.toString().match(/ECONNREFUSED/g))
|
|
503
|
+
return new core_1.ConnectionError(err);
|
|
504
|
+
return new db_decorators_1.InternalError(err);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
static async connect(config) {
|
|
508
|
+
const con = new typeorm_1.DataSource(config);
|
|
509
|
+
if (!con.isInitialized)
|
|
510
|
+
await con.initialize();
|
|
511
|
+
return con;
|
|
512
|
+
}
|
|
513
|
+
static async createDatabase(dataSource, dbName) {
|
|
514
|
+
const log = logging_1.Logging.for(this.createDatabase);
|
|
515
|
+
log.verbose(`Creating database ${dbName}`);
|
|
516
|
+
try {
|
|
517
|
+
await dataSource.query(`CREATE DATABASE ${dbName}`);
|
|
518
|
+
log.info(`Created database ${dbName}`);
|
|
519
|
+
}
|
|
520
|
+
catch (e) {
|
|
521
|
+
throw this.parseError(e);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
static async createNotifyFunction(dataSource, user) {
|
|
525
|
+
const log = logging_1.Logging.for(this.createNotifyFunction);
|
|
526
|
+
log.verbose(`Creating notify function`);
|
|
527
|
+
try {
|
|
528
|
+
await dataSource.query(`CREATE OR REPLACE FUNCTION notify_table_changes()
|
|
529
|
+
RETURNS trigger AS $$
|
|
530
|
+
BEGIN
|
|
531
|
+
PERFORM pg_notify(
|
|
532
|
+
'table_changes',
|
|
533
|
+
json_build_object(
|
|
534
|
+
'table', TG_TABLE_NAME,
|
|
535
|
+
'action', TG_OP,
|
|
536
|
+
'data', row_to_json(NEW),
|
|
537
|
+
'old_data', row_to_json(OLD)
|
|
538
|
+
)::text
|
|
539
|
+
);
|
|
540
|
+
RETURN NEW;
|
|
541
|
+
END;
|
|
542
|
+
$$ LANGUAGE plpgsql SECURITY DEFINER
|
|
543
|
+
;`);
|
|
544
|
+
await dataSource.query(`ALTER FUNCTION notify_table_changes() OWNER TO ${user};`);
|
|
545
|
+
await dataSource.query(`
|
|
546
|
+
GRANT EXECUTE ON FUNCTION notify_table_changes() TO public;
|
|
547
|
+
`);
|
|
548
|
+
log.info(`Created notify function`);
|
|
549
|
+
}
|
|
550
|
+
catch (e) {
|
|
551
|
+
throw this.parseError(e);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
static async deleteDatabase(dataSource, dbName, user) {
|
|
555
|
+
try {
|
|
556
|
+
if (user)
|
|
557
|
+
await dataSource.query(`DROP OWNED BY ${user} CASCADE;`);
|
|
558
|
+
await dataSource.query(`DROP DATABASE ${dbName}`);
|
|
559
|
+
}
|
|
560
|
+
catch (e) {
|
|
561
|
+
throw this.parseError(e);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
static async createUser(dataSource, dbName, user, password) {
|
|
565
|
+
try {
|
|
566
|
+
await dataSource.query(`CREATE USER ${user} WITH PASSWORD '${password}'`);
|
|
567
|
+
await dataSource.query(`GRANT CONNECT ON DATABASE ${dbName} TO ${user}`);
|
|
568
|
+
await dataSource.query(`GRANT USAGE ON SCHEMA public TO ${user}`);
|
|
569
|
+
await dataSource.query(`GRANT CREATE ON SCHEMA public TO ${user}`);
|
|
570
|
+
await dataSource.query(`GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO ${user}`);
|
|
571
|
+
await dataSource.query(`GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO ${user}`);
|
|
572
|
+
await dataSource.query(`GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO ${user}`);
|
|
573
|
+
await dataSource.query(`ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO ${user}`);
|
|
574
|
+
await dataSource.query(`ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON SEQUENCES TO ${user}`);
|
|
575
|
+
}
|
|
576
|
+
catch (e) {
|
|
577
|
+
throw this.parseError(e);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
static async deleteUser(client, user, admin) {
|
|
581
|
+
try {
|
|
582
|
+
await client.query(`REASSIGN OWNED BY ${user} TO ${admin}`);
|
|
583
|
+
await client.query(`REVOKE ALL ON ALL TABLES IN SCHEMA public FROM ${user}`);
|
|
584
|
+
await client.query(`REVOKE ALL ON SCHEMA public FROM ${user}`);
|
|
585
|
+
await client.query(`REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM ${user}`);
|
|
586
|
+
await client.query(`REVOKE ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public FROM ${user}`);
|
|
587
|
+
await client.query(`ALTER DEFAULT PRIVILEGES FOR ROLE ${admin} IN SCHEMA public REVOKE ALL ON TABLES FROM ${user}`);
|
|
588
|
+
await client.query(`ALTER DEFAULT PRIVILEGES FOR ROLE ${admin} IN SCHEMA public REVOKE ALL ON SEQUENCES FROM ${user};`);
|
|
589
|
+
await client.query(`ALTER DEFAULT PRIVILEGES FOR ROLE ${admin} IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM ${user}`);
|
|
590
|
+
await client.query(`DROP OWNED BY ${user} CASCADE`);
|
|
591
|
+
await client.query(`DROP USER IF EXISTS "${user}"`);
|
|
592
|
+
}
|
|
593
|
+
catch (e) {
|
|
594
|
+
throw this.parseError(e);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
static parseTypeToPostgres(type, isPk, isFk = false) {
|
|
598
|
+
switch (type.toLowerCase()) {
|
|
599
|
+
case "string":
|
|
600
|
+
return isPk ? "TEXT PRIMARY KEY" : isFk ? "TEXT" : "VARCHAR";
|
|
601
|
+
case "number":
|
|
602
|
+
return isPk ? "SERIAL PRIMARY KEY" : "INTEGER";
|
|
603
|
+
case "boolean":
|
|
604
|
+
return "BOOLEAN";
|
|
605
|
+
case "date":
|
|
606
|
+
return "TIMESTAMP";
|
|
607
|
+
case "bigint":
|
|
608
|
+
return isPk ? "BIGINT PRIMARY KEY" : "BIGINT";
|
|
609
|
+
default: {
|
|
610
|
+
const m = decorator_validation_1.Model.get(type);
|
|
611
|
+
if (m) {
|
|
612
|
+
const mm = new m();
|
|
613
|
+
const type = reflection_1.Reflection.getTypeFromDecorator(mm, (0, db_decorators_1.findPrimaryKey)(mm).id);
|
|
614
|
+
return {
|
|
615
|
+
model: m,
|
|
616
|
+
pkType: type,
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
throw new db_decorators_1.InternalError(`Unsupported type: ${type}`);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
static parseValidationToPostgres(prop, type, isPk, key, options) {
|
|
624
|
+
switch (key) {
|
|
625
|
+
case decorator_validation_1.ValidationKeys.REQUIRED:
|
|
626
|
+
return "NOT NULL";
|
|
627
|
+
case decorator_validation_1.ValidationKeys.MAX_LENGTH:
|
|
628
|
+
if (isPk || !options || type.toLowerCase() !== "string") {
|
|
629
|
+
return "";
|
|
630
|
+
}
|
|
631
|
+
return `(${options[decorator_validation_1.ValidationKeys.MAX_LENGTH]})`;
|
|
632
|
+
case decorator_validation_1.ValidationKeys.MIN_LENGTH:
|
|
633
|
+
return `CONSTRAINT ${prop}_min_length_check CHECK (LENGTH(${prop}) >= ${options[decorator_validation_1.ValidationKeys.MIN_LENGTH]})`;
|
|
634
|
+
case decorator_validation_1.ValidationKeys.PATTERN:
|
|
635
|
+
case decorator_validation_1.ValidationKeys.URL:
|
|
636
|
+
case decorator_validation_1.ValidationKeys.EMAIL:
|
|
637
|
+
return `CONSTRAINT ${prop}_pattern_check CHECK (${prop} ~ '${(0, utils_1.convertJsRegexToPostgres)(options[decorator_validation_1.ValidationKeys.PATTERN])}')`;
|
|
638
|
+
case decorator_validation_1.ValidationKeys.TYPE:
|
|
639
|
+
case decorator_validation_1.ValidationKeys.DATE:
|
|
640
|
+
return "";
|
|
641
|
+
case decorator_validation_1.ValidationKeys.MIN:
|
|
642
|
+
return `CONSTRAINT ${prop}_${key}_check CHECK (${prop} >= ${options[decorator_validation_1.ValidationKeys.MIN]})`;
|
|
643
|
+
case decorator_validation_1.ValidationKeys.MAX:
|
|
644
|
+
return `CONSTRAINT ${prop}_${key}_check CHECK (${prop} <= ${options[decorator_validation_1.ValidationKeys.MAX]})`;
|
|
645
|
+
case decorator_validation_1.ValidationKeys.PASSWORD:
|
|
646
|
+
default:
|
|
647
|
+
throw new db_decorators_1.InternalError(`Unsupported type: ${key}`);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
static parseRelationsToPostgres(prop, clazz, pk, key, options) {
|
|
651
|
+
const tableName = core_1.Repository.table(clazz);
|
|
652
|
+
const { cascade } = options;
|
|
653
|
+
const cascadeStr = `${cascade.update ? " ON UPDATE CASCADE" : ""}${cascade.delete ? " ON DELETE CASCADE" : ""}`;
|
|
654
|
+
switch (`relations${key}`) {
|
|
655
|
+
case core_1.PersistenceKeys.ONE_TO_ONE:
|
|
656
|
+
return `FOREIGN KEY (${prop}) REFERENCES ${tableName}(${pk})${cascadeStr}`;
|
|
657
|
+
default:
|
|
658
|
+
throw new db_decorators_1.InternalError(`Unsupported operation: ${key}`);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
static async createTable(client, model) {
|
|
662
|
+
const result = {};
|
|
663
|
+
const m = new model({});
|
|
664
|
+
const tableName = core_1.Repository.table(model);
|
|
665
|
+
const { id } = (0, db_decorators_1.findPrimaryKey)(m);
|
|
666
|
+
let isPk, column;
|
|
667
|
+
const properties = Object.getOwnPropertyNames(m);
|
|
668
|
+
for (const prop of properties) {
|
|
669
|
+
if (typeof this[prop] === "function" ||
|
|
670
|
+
prop.toString().startsWith("_") ||
|
|
671
|
+
prop === "constructor") {
|
|
672
|
+
continue;
|
|
673
|
+
}
|
|
674
|
+
isPk = prop === id;
|
|
675
|
+
column = core_1.Repository.column(m, prop.toString());
|
|
676
|
+
const allDecs = reflection_1.Reflection.getPropertyDecorators(decorator_validation_1.ValidationKeys.REFLECT, m, prop.toString(), false, true);
|
|
677
|
+
const decoratorData = allDecs.decorators.reduce((accum, el) => {
|
|
678
|
+
const { key, props } = el;
|
|
679
|
+
if (key === decorator_validation_1.ModelKeys.TYPE && !accum[decorator_validation_1.ValidationKeys.TYPE]) {
|
|
680
|
+
accum[decorator_validation_1.ValidationKeys.TYPE] = {
|
|
681
|
+
customTypes: [props.name],
|
|
682
|
+
message: decorator_validation_1.DEFAULT_ERROR_MESSAGES.TYPE,
|
|
683
|
+
description: "defines the accepted types for the attribute",
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
else if (key !== decorator_validation_1.ValidationKeys.TYPE) {
|
|
687
|
+
// do nothing. we can only support basis ctypes at this time
|
|
688
|
+
accum[key] = props;
|
|
689
|
+
}
|
|
690
|
+
return accum;
|
|
691
|
+
}, {});
|
|
692
|
+
const dbDecs = reflection_1.Reflection.getPropertyDecorators(core_1.Repository.key("relations"), m, prop.toString(), true, true);
|
|
693
|
+
const query = [];
|
|
694
|
+
const constraints = [];
|
|
695
|
+
const foreignKeys = [];
|
|
696
|
+
let typeData = undefined;
|
|
697
|
+
let childClass = undefined;
|
|
698
|
+
let childPk;
|
|
699
|
+
if (Object.keys(decoratorData).length) {
|
|
700
|
+
typeData = decoratorData[decorator_validation_1.ValidationKeys.TYPE];
|
|
701
|
+
if (!typeData) {
|
|
702
|
+
throw new Error(`Missing type information`);
|
|
703
|
+
}
|
|
704
|
+
let parsedType = this.parseTypeToPostgres(typeof typeData.customTypes[0] === "function"
|
|
705
|
+
? typeData.customTypes[0]()
|
|
706
|
+
: typeData.customTypes[0], isPk);
|
|
707
|
+
if (typeof parsedType === "string") {
|
|
708
|
+
parsedType = { model: parsedType };
|
|
709
|
+
}
|
|
710
|
+
let typeStr = parsedType.model;
|
|
711
|
+
if (typeof typeStr !== "string") {
|
|
712
|
+
if (Array.isArray(typeStr)) {
|
|
713
|
+
console.log(typeStr);
|
|
714
|
+
}
|
|
715
|
+
// continue;
|
|
716
|
+
// const res: Record<string, PostgresTableSpec> = await this.createTable(pool, typeStr);
|
|
717
|
+
try {
|
|
718
|
+
childClass = parsedType.model;
|
|
719
|
+
const m = new childClass();
|
|
720
|
+
childPk = (0, db_decorators_1.findPrimaryKey)(m);
|
|
721
|
+
typeStr = this.parseTypeToPostgres(parsedType.pkType, false, true);
|
|
722
|
+
await this.createTable(client, childClass);
|
|
723
|
+
}
|
|
724
|
+
catch (e) {
|
|
725
|
+
if (!(e instanceof db_decorators_1.ConflictError))
|
|
726
|
+
throw e;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
let tp = Array.isArray(typeData.customTypes)
|
|
730
|
+
? typeData.customTypes[0]
|
|
731
|
+
: typeData.customTypes;
|
|
732
|
+
tp = typeof tp === "function" && !tp.name ? tp() : tp;
|
|
733
|
+
const validationStr = this.parseValidationToPostgres(column, tp, isPk, decorator_validation_1.ValidationKeys.MAX_LENGTH, decoratorData[decorator_validation_1.ValidationKeys.MAX_LENGTH] || {
|
|
734
|
+
[decorator_validation_1.ValidationKeys.MAX_LENGTH]: 255,
|
|
735
|
+
});
|
|
736
|
+
const q = `${column} ${typeStr}${validationStr}`;
|
|
737
|
+
if (isPk) {
|
|
738
|
+
query.unshift(q);
|
|
739
|
+
}
|
|
740
|
+
else {
|
|
741
|
+
query.push(q);
|
|
742
|
+
}
|
|
743
|
+
for (const [key, props] of Object.entries(decoratorData).filter(([k]) => ![decorator_validation_1.ValidationKeys.TYPE, decorator_validation_1.ValidationKeys.MAX_LENGTH].includes(k))) {
|
|
744
|
+
const validation = this.parseValidationToPostgres(column, tp, isPk, key, props);
|
|
745
|
+
if (validation.startsWith("CONSTRAINT")) {
|
|
746
|
+
constraints.push(validation);
|
|
747
|
+
}
|
|
748
|
+
else {
|
|
749
|
+
if (validation) {
|
|
750
|
+
query.push(validation);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
// TODO ignore for now. this leaves foreign keys out
|
|
756
|
+
// eslint-disable-next-line no-constant-binary-expression
|
|
757
|
+
if (false || (dbDecs && dbDecs.decorators.length)) {
|
|
758
|
+
if (!typeData)
|
|
759
|
+
throw new Error(`Missing type information`);
|
|
760
|
+
for (const decorator of dbDecs.decorators) {
|
|
761
|
+
const { key, props } = decorator;
|
|
762
|
+
const validation = this.parseRelationsToPostgres(column, childClass, childPk.id, key, props);
|
|
763
|
+
if (validation.startsWith("FOREIGN")) {
|
|
764
|
+
foreignKeys.push(validation);
|
|
765
|
+
}
|
|
766
|
+
else {
|
|
767
|
+
throw new db_decorators_1.InternalError(`Unsupported relation: ${key}`);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
result[prop.toString()] = {
|
|
772
|
+
query: query.join(" "),
|
|
773
|
+
values: [],
|
|
774
|
+
primaryKey: isPk,
|
|
775
|
+
constraints: constraints,
|
|
776
|
+
foreignKeys: foreignKeys,
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
const values = Object.values(result);
|
|
780
|
+
const query = values.map((r) => r.query).join(",\n");
|
|
781
|
+
const constraints = values
|
|
782
|
+
.filter((c) => !!c.constraints.length)
|
|
783
|
+
.map((r) => r.constraints)
|
|
784
|
+
.join(",\n");
|
|
785
|
+
const foreignKeys = values
|
|
786
|
+
.filter((c) => !!c.foreignKeys.length)
|
|
787
|
+
.map((r) => r.foreignKeys)
|
|
788
|
+
.join(",\n");
|
|
789
|
+
const vals = [query, constraints];
|
|
790
|
+
if (foreignKeys) {
|
|
791
|
+
vals.push(foreignKeys);
|
|
792
|
+
}
|
|
793
|
+
const queryString = `CREATE TABLE ${tableName} (${vals.filter((v) => !!v).join(",\n")})`;
|
|
794
|
+
try {
|
|
795
|
+
await client.query(queryString);
|
|
796
|
+
await client.query(`CREATE TRIGGER notify_changes_${tableName}
|
|
797
|
+
AFTER INSERT OR UPDATE OR DELETE ON ${tableName}
|
|
798
|
+
FOR EACH ROW
|
|
799
|
+
EXECUTE FUNCTION notify_table_changes();`);
|
|
800
|
+
}
|
|
801
|
+
catch (e) {
|
|
802
|
+
throw this.parseError(e);
|
|
803
|
+
}
|
|
804
|
+
return result;
|
|
805
|
+
}
|
|
806
|
+
static async getCurrentUser(client) {
|
|
807
|
+
const queryString = `SELECT CURRENT_USER;`;
|
|
808
|
+
try {
|
|
809
|
+
const result = await client.query(queryString);
|
|
810
|
+
return result[0].current_user;
|
|
811
|
+
}
|
|
812
|
+
catch (e) {
|
|
813
|
+
throw this.parseError(e);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
static decoration() {
|
|
817
|
+
// @table() => @Entity()
|
|
818
|
+
const tableKey = core_1.Adapter.key(core_1.PersistenceKeys.TABLE);
|
|
819
|
+
decorator_validation_1.Decoration.flavouredAs(constants_1.TypeORMFlavour)
|
|
820
|
+
.for(tableKey)
|
|
821
|
+
.extend((original) => (0, Entity_1.Entity)()(original[decorator_validation_1.ModelKeys.ANCHOR] || original))
|
|
822
|
+
.apply();
|
|
823
|
+
// @pk() => @PrimaryGeneratedColumn() | @PrimaryColumn()
|
|
824
|
+
const pkKey = core_1.Repository.key(db_decorators_1.DBKeys.ID);
|
|
825
|
+
function pkDec(options) {
|
|
826
|
+
const decorators = [
|
|
827
|
+
(0, decorator_validation_1.required)(),
|
|
828
|
+
(0, db_decorators_1.readonly)(),
|
|
829
|
+
(0, decorator_validation_1.propMetadata)(pkKey, options),
|
|
830
|
+
];
|
|
831
|
+
if (options.type)
|
|
832
|
+
decorators.push((0, PrimaryGeneratedColumn_1.PrimaryGeneratedColumn)());
|
|
833
|
+
else
|
|
834
|
+
decorators.push((0, PrimaryColumn_1.PrimaryColumn)({ unique: true }));
|
|
835
|
+
return (0, reflection_1.apply)(...decorators);
|
|
836
|
+
}
|
|
837
|
+
decorator_validation_1.Decoration.flavouredAs(constants_1.TypeORMFlavour)
|
|
838
|
+
.for(pkKey)
|
|
839
|
+
.define({
|
|
840
|
+
decorator: pkDec,
|
|
841
|
+
})
|
|
842
|
+
.apply();
|
|
843
|
+
// @column("columnName") => @Column({name: "columnName"})
|
|
844
|
+
const columnKey = core_1.Adapter.key(core_1.PersistenceKeys.COLUMN);
|
|
845
|
+
decorator_validation_1.Decoration.flavouredAs(constants_1.TypeORMFlavour)
|
|
846
|
+
.for(columnKey)
|
|
847
|
+
.extend({
|
|
848
|
+
decorator: function columm(name) {
|
|
849
|
+
return function column(obj, prop) {
|
|
850
|
+
return (0, Column_1.Column)({
|
|
851
|
+
name: name || prop,
|
|
852
|
+
nullable: true,
|
|
853
|
+
})(obj, prop);
|
|
854
|
+
};
|
|
855
|
+
},
|
|
856
|
+
transform: (args) => {
|
|
857
|
+
const columnName = args[1];
|
|
858
|
+
return [columnName];
|
|
859
|
+
},
|
|
860
|
+
})
|
|
861
|
+
.apply();
|
|
862
|
+
// @unique => @Column({unique: true})
|
|
863
|
+
const uniqueKey = core_1.Adapter.key(core_1.PersistenceKeys.UNIQUE);
|
|
864
|
+
decorator_validation_1.Decoration.flavouredAs(constants_1.TypeORMFlavour)
|
|
865
|
+
.for(uniqueKey)
|
|
866
|
+
.define((0, decorator_validation_1.propMetadata)(uniqueKey, {}))
|
|
867
|
+
.extend((0, Column_1.Column)({ unique: true }))
|
|
868
|
+
.apply();
|
|
869
|
+
// @required => @Column({ nullable: false })
|
|
870
|
+
const requiredKey = decorator_validation_1.Validation.key(decorator_validation_1.ValidationKeys.REQUIRED);
|
|
871
|
+
decorator_validation_1.Decoration.flavouredAs(constants_1.TypeORMFlavour)
|
|
872
|
+
.for(requiredKey)
|
|
873
|
+
.extend((0, Column_1.Column)({ nullable: false }))
|
|
874
|
+
.apply();
|
|
875
|
+
// @version => @VersionColumn()
|
|
876
|
+
const versionKey = core_1.Repository.key(db_decorators_1.DBKeys.VERSION);
|
|
877
|
+
decorator_validation_1.Decoration.flavouredAs(constants_1.TypeORMFlavour)
|
|
878
|
+
.for(versionKey)
|
|
879
|
+
.define((0, decorator_validation_1.type)(Number.name), (0, typeorm_1.VersionColumn)())
|
|
880
|
+
.apply();
|
|
881
|
+
function ValidationUpdateKey(key) {
|
|
882
|
+
return db_decorators_1.UpdateValidationKeys.REFLECT + key;
|
|
883
|
+
}
|
|
884
|
+
// @timestamp(op) => @CreateDateColumn() || @UpdateDateColumn()
|
|
885
|
+
const timestampKey = ValidationUpdateKey(db_decorators_1.DBKeys.TIMESTAMP);
|
|
886
|
+
function ts(operation, format) {
|
|
887
|
+
const decorators = [
|
|
888
|
+
(0, decorator_validation_1.date)(format, db_decorators_1.DEFAULT_ERROR_MESSAGES.TIMESTAMP.DATE),
|
|
889
|
+
(0, decorator_validation_1.required)(db_decorators_1.DEFAULT_ERROR_MESSAGES.TIMESTAMP.REQUIRED),
|
|
890
|
+
(0, decorator_validation_1.propMetadata)(decorator_validation_1.Validation.key(db_decorators_1.DBKeys.TIMESTAMP), {
|
|
891
|
+
operation: operation,
|
|
892
|
+
format: format,
|
|
893
|
+
}),
|
|
894
|
+
];
|
|
895
|
+
if (operation.indexOf(db_decorators_1.OperationKeys.UPDATE) !== -1)
|
|
896
|
+
decorators.push((0, decorator_validation_1.propMetadata)(timestampKey, {
|
|
897
|
+
message: db_decorators_1.DEFAULT_ERROR_MESSAGES.TIMESTAMP.INVALID,
|
|
898
|
+
}));
|
|
899
|
+
else
|
|
900
|
+
decorators.push((0, db_decorators_1.readonly)());
|
|
901
|
+
return (0, reflection_1.apply)(...decorators);
|
|
902
|
+
}
|
|
903
|
+
decorator_validation_1.Decoration.flavouredAs(constants_1.TypeORMFlavour)
|
|
904
|
+
.for(timestampKey)
|
|
905
|
+
.define({
|
|
906
|
+
decorator: ts,
|
|
907
|
+
})
|
|
908
|
+
.extend({
|
|
909
|
+
decorator: function timestamp(...ops) {
|
|
910
|
+
return function timestamp(obj, prop) {
|
|
911
|
+
if (ops.indexOf(db_decorators_1.OperationKeys.UPDATE) !== -1)
|
|
912
|
+
return (0, UpdateDateColumn_1.UpdateDateColumn)()(obj, prop);
|
|
913
|
+
return (0, CreateDateColumn_1.CreateDateColumn)()(obj, prop);
|
|
914
|
+
};
|
|
915
|
+
},
|
|
916
|
+
transform: (args) => {
|
|
917
|
+
return args[0];
|
|
918
|
+
},
|
|
919
|
+
})
|
|
920
|
+
.apply();
|
|
921
|
+
// @oneToOne(clazz) => @OneToOne(() => clazz)
|
|
922
|
+
const oneToOneKey = core_1.Repository.key(core_1.PersistenceKeys.ONE_TO_ONE);
|
|
923
|
+
decorator_validation_1.Decoration.flavouredAs(constants_1.TypeORMFlavour)
|
|
924
|
+
.for(oneToOneKey)
|
|
925
|
+
.define({
|
|
926
|
+
decorator: function oneToOne(clazz, cascade, populate) {
|
|
927
|
+
const metadata = {
|
|
928
|
+
class: (clazz.name ? clazz.name : clazz),
|
|
929
|
+
cascade: cascade,
|
|
930
|
+
populate: populate,
|
|
931
|
+
};
|
|
932
|
+
const ormMeta = {
|
|
933
|
+
cascade: cascade.update === core_1.Cascade.CASCADE ||
|
|
934
|
+
cascade.delete === core_1.Cascade.CASCADE,
|
|
935
|
+
onDelete: cascade.delete ? "CASCADE" : "DEFAULT",
|
|
936
|
+
onUpdate: cascade.update ? "CASCADE" : "DEFAULT",
|
|
937
|
+
nullable: true,
|
|
938
|
+
eager: populate,
|
|
939
|
+
};
|
|
940
|
+
return (0, reflection_1.apply)((0, decorator_validation_1.prop)(core_1.PersistenceKeys.RELATIONS), (0, decorator_validation_1.type)([
|
|
941
|
+
(typeof clazz === "function" && !clazz.name
|
|
942
|
+
? clazz
|
|
943
|
+
: clazz.name),
|
|
944
|
+
String.name,
|
|
945
|
+
Number.name,
|
|
946
|
+
BigInt.name,
|
|
947
|
+
]), (0, decorator_validation_1.propMetadata)(oneToOneKey, metadata), (0, typeorm_1.OneToOne)(() => {
|
|
948
|
+
if (!clazz.name)
|
|
949
|
+
clazz = clazz();
|
|
950
|
+
if (!clazz[decorator_validation_1.ModelKeys.ANCHOR])
|
|
951
|
+
throw new db_decorators_1.InternalError("Original Model not found in constructor");
|
|
952
|
+
return clazz[decorator_validation_1.ModelKeys.ANCHOR];
|
|
953
|
+
}, (model) => {
|
|
954
|
+
const pk = (0, db_decorators_1.findPrimaryKey)(new clazz()).id;
|
|
955
|
+
return model[pk];
|
|
956
|
+
}, ormMeta), (0, typeorm_1.JoinColumn)());
|
|
957
|
+
},
|
|
958
|
+
})
|
|
959
|
+
.apply();
|
|
960
|
+
// @oneToMany(clazz) => @OneToMany(() => clazz)
|
|
961
|
+
const oneToManyKey = core_1.Repository.key(core_1.PersistenceKeys.ONE_TO_MANY);
|
|
962
|
+
decorator_validation_1.Decoration.flavouredAs(constants_1.TypeORMFlavour)
|
|
963
|
+
.for(oneToManyKey)
|
|
964
|
+
.define({
|
|
965
|
+
decorator: function oneToMany(clazz, cascade, populate) {
|
|
966
|
+
const metadata = {
|
|
967
|
+
class: (clazz.name ? clazz.name : clazz),
|
|
968
|
+
cascade: cascade,
|
|
969
|
+
populate: populate,
|
|
970
|
+
};
|
|
971
|
+
return (0, reflection_1.apply)((0, decorator_validation_1.prop)(core_1.PersistenceKeys.RELATIONS), (0, decorator_validation_1.list)(clazz), (0, decorator_validation_1.propMetadata)(oneToManyKey, metadata), function OneToManyWrapper(obj, prop) {
|
|
972
|
+
const ormMeta = {
|
|
973
|
+
cascade: cascade.update === core_1.Cascade.CASCADE ||
|
|
974
|
+
cascade.delete === core_1.Cascade.CASCADE,
|
|
975
|
+
onDelete: cascade.delete ? "CASCADE" : "DEFAULT",
|
|
976
|
+
onUpdate: cascade.update ? "CASCADE" : "DEFAULT",
|
|
977
|
+
nullable: true,
|
|
978
|
+
eager: populate,
|
|
979
|
+
};
|
|
980
|
+
return (0, typeorm_1.OneToMany)(() => {
|
|
981
|
+
if (!clazz.name)
|
|
982
|
+
clazz = clazz();
|
|
983
|
+
if (!clazz[decorator_validation_1.ModelKeys.ANCHOR])
|
|
984
|
+
throw new db_decorators_1.InternalError("Original Model not found in constructor");
|
|
985
|
+
return clazz[decorator_validation_1.ModelKeys.ANCHOR];
|
|
986
|
+
}, (model) => {
|
|
987
|
+
if (!clazz.name)
|
|
988
|
+
clazz = clazz();
|
|
989
|
+
const m = new clazz();
|
|
990
|
+
const crossRelationKey = Object.keys(m).find((k) => {
|
|
991
|
+
const decs = reflection_1.Reflection.getPropertyDecorators(core_1.Repository.key(core_1.PersistenceKeys.MANY_TO_ONE), m, k, true);
|
|
992
|
+
if (!decs || !decs.decorators || !decs.decorators.length)
|
|
993
|
+
return false;
|
|
994
|
+
const designType = Reflect.getMetadata(decorator_validation_1.ModelKeys.TYPE, m, k);
|
|
995
|
+
if (!designType)
|
|
996
|
+
throw new db_decorators_1.InternalError(`No Type Definition found for ${k} in ${m.constructor.name}`);
|
|
997
|
+
return designType.name === obj.constructor.name;
|
|
998
|
+
});
|
|
999
|
+
if (!crossRelationKey)
|
|
1000
|
+
throw new db_decorators_1.InternalError(`Cross relation not found. Did you use @manyToOne on the ${clazz.name}?`);
|
|
1001
|
+
return model[crossRelationKey];
|
|
1002
|
+
}, ormMeta)(obj, prop);
|
|
1003
|
+
});
|
|
1004
|
+
},
|
|
1005
|
+
})
|
|
1006
|
+
.apply();
|
|
1007
|
+
// @manyToOne(clazz) => @ManyToOne(() => clazz)
|
|
1008
|
+
const manyToOneKey = core_1.Repository.key(core_1.PersistenceKeys.MANY_TO_ONE);
|
|
1009
|
+
decorator_validation_1.Decoration.flavouredAs(constants_1.TypeORMFlavour)
|
|
1010
|
+
.for(manyToOneKey)
|
|
1011
|
+
.define({
|
|
1012
|
+
decorator: function manyToOne(clazz, cascade, populate) {
|
|
1013
|
+
const metadata = {
|
|
1014
|
+
class: (clazz.name ? clazz.name : clazz),
|
|
1015
|
+
cascade: cascade,
|
|
1016
|
+
populate: populate,
|
|
1017
|
+
};
|
|
1018
|
+
const ormMeta = {
|
|
1019
|
+
cascade: cascade.update === core_1.Cascade.CASCADE ||
|
|
1020
|
+
cascade.delete === core_1.Cascade.CASCADE,
|
|
1021
|
+
onDelete: cascade.delete ? "CASCADE" : "DEFAULT",
|
|
1022
|
+
onUpdate: cascade.update ? "CASCADE" : "DEFAULT",
|
|
1023
|
+
nullable: true,
|
|
1024
|
+
eager: populate,
|
|
1025
|
+
};
|
|
1026
|
+
return (0, reflection_1.apply)((0, decorator_validation_1.prop)(core_1.PersistenceKeys.RELATIONS), (0, decorator_validation_1.type)([
|
|
1027
|
+
(typeof clazz === "function" && !clazz.name
|
|
1028
|
+
? clazz
|
|
1029
|
+
: clazz.name),
|
|
1030
|
+
String.name,
|
|
1031
|
+
Number.name,
|
|
1032
|
+
BigInt.name,
|
|
1033
|
+
]), (0, decorator_validation_1.propMetadata)(manyToOneKey, metadata), function ManyToOneWrapper(obj, prop) {
|
|
1034
|
+
return (0, typeorm_1.ManyToOne)(() => {
|
|
1035
|
+
if (!clazz.name)
|
|
1036
|
+
clazz = clazz();
|
|
1037
|
+
if (!clazz[decorator_validation_1.ModelKeys.ANCHOR])
|
|
1038
|
+
throw new db_decorators_1.InternalError("Original Model not found in constructor");
|
|
1039
|
+
return clazz[decorator_validation_1.ModelKeys.ANCHOR];
|
|
1040
|
+
}, (model) => {
|
|
1041
|
+
if (!clazz.name)
|
|
1042
|
+
clazz = clazz();
|
|
1043
|
+
const m = new clazz();
|
|
1044
|
+
const crossRelationKey = Object.keys(m).find((k) => {
|
|
1045
|
+
const decs = reflection_1.Reflection.getPropertyDecorators(core_1.Repository.key(core_1.PersistenceKeys.ONE_TO_MANY), m, k, true);
|
|
1046
|
+
if (!decs || !decs.decorators || !decs.decorators.length)
|
|
1047
|
+
return false;
|
|
1048
|
+
const listDec = Reflect.getMetadata(decorator_validation_1.Validation.key(decorator_validation_1.ValidationKeys.LIST), m, k);
|
|
1049
|
+
if (!listDec)
|
|
1050
|
+
throw new db_decorators_1.InternalError(`No Type Definition found for ${k} in ${m.constructor.name}`);
|
|
1051
|
+
const name = listDec.clazz[0]().name;
|
|
1052
|
+
return name === obj.constructor.name;
|
|
1053
|
+
});
|
|
1054
|
+
if (!crossRelationKey)
|
|
1055
|
+
throw new db_decorators_1.InternalError(`Cross relation not found. Did you use @manyToOne on the ${clazz.name}?`);
|
|
1056
|
+
return model[crossRelationKey];
|
|
1057
|
+
})(obj, prop);
|
|
1058
|
+
});
|
|
1059
|
+
},
|
|
1060
|
+
})
|
|
1061
|
+
.apply();
|
|
1062
|
+
// @manyToMany(clazz) => @ManyToMany(() => clazz)
|
|
1063
|
+
const manyToManyKey = core_1.Repository.key(core_1.PersistenceKeys.MANY_TO_MANY);
|
|
1064
|
+
decorator_validation_1.Decoration.flavouredAs(constants_1.TypeORMFlavour)
|
|
1065
|
+
.for(manyToManyKey)
|
|
1066
|
+
.define({
|
|
1067
|
+
decorator: function manyToMany(clazz, cascade, populate) {
|
|
1068
|
+
const metadata = {
|
|
1069
|
+
class: clazz.name,
|
|
1070
|
+
cascade: cascade,
|
|
1071
|
+
populate: populate,
|
|
1072
|
+
};
|
|
1073
|
+
const ormMeta = {
|
|
1074
|
+
cascade: cascade.update === core_1.Cascade.CASCADE ||
|
|
1075
|
+
cascade.delete === core_1.Cascade.CASCADE,
|
|
1076
|
+
onDelete: cascade.delete ? "CASCADE" : "DEFAULT",
|
|
1077
|
+
onUpdate: cascade.update ? "CASCADE" : "DEFAULT",
|
|
1078
|
+
nullable: true,
|
|
1079
|
+
eager: populate,
|
|
1080
|
+
};
|
|
1081
|
+
return (0, reflection_1.apply)((0, decorator_validation_1.prop)(core_1.PersistenceKeys.RELATIONS), (0, decorator_validation_1.list)(clazz), (0, decorator_validation_1.propMetadata)(manyToManyKey, metadata), (0, typeorm_1.ManyToMany)(() => {
|
|
1082
|
+
if (!clazz.name)
|
|
1083
|
+
clazz = clazz();
|
|
1084
|
+
if (!clazz[decorator_validation_1.ModelKeys.ANCHOR])
|
|
1085
|
+
throw new db_decorators_1.InternalError("Original Model not found in constructor");
|
|
1086
|
+
return clazz[decorator_validation_1.ModelKeys.ANCHOR];
|
|
1087
|
+
}, (model) => {
|
|
1088
|
+
if (!clazz.name)
|
|
1089
|
+
clazz = clazz();
|
|
1090
|
+
const pk = (0, db_decorators_1.findPrimaryKey)(new clazz()).id;
|
|
1091
|
+
return model[pk];
|
|
1092
|
+
}, ormMeta), (0, typeorm_1.JoinTable)());
|
|
1093
|
+
},
|
|
1094
|
+
})
|
|
1095
|
+
.apply();
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
exports.TypeORMAdapter = TypeORMAdapter;
|
|
1099
|
+
__decorate([
|
|
1100
|
+
(0, core_1.final)(),
|
|
1101
|
+
__metadata("design:type", Function),
|
|
1102
|
+
__metadata("design:paramtypes", []),
|
|
1103
|
+
__metadata("design:returntype", TypeORMDispatch_1.TypeORMDispatch)
|
|
1104
|
+
], TypeORMAdapter.prototype, "Dispatch", null);
|
|
1105
|
+
__decorate([
|
|
1106
|
+
(0, core_1.final)(),
|
|
1107
|
+
__metadata("design:type", Function),
|
|
1108
|
+
__metadata("design:paramtypes", []),
|
|
1109
|
+
__metadata("design:returntype", Object)
|
|
1110
|
+
], TypeORMAdapter.prototype, "repository", null);
|
|
1111
|
+
__decorate([
|
|
1112
|
+
(0, core_1.final)(),
|
|
1113
|
+
__metadata("design:type", Function),
|
|
1114
|
+
__metadata("design:paramtypes", []),
|
|
1115
|
+
__metadata("design:returntype", query_1.TypeORMStatement)
|
|
1116
|
+
], TypeORMAdapter.prototype, "Statement", null);
|
|
1117
|
+
__decorate([
|
|
1118
|
+
(0, core_1.final)(),
|
|
1119
|
+
__metadata("design:type", Function),
|
|
1120
|
+
__metadata("design:paramtypes", [Object]),
|
|
1121
|
+
__metadata("design:returntype", Promise)
|
|
1122
|
+
], TypeORMAdapter.prototype, "Sequence", null);
|
|
1123
|
+
__decorate([
|
|
1124
|
+
(0, core_1.final)(),
|
|
1125
|
+
__metadata("design:type", Function),
|
|
1126
|
+
__metadata("design:paramtypes", [Object]),
|
|
1127
|
+
__metadata("design:returntype", Promise)
|
|
1128
|
+
], TypeORMAdapter.prototype, "index", null);
|
|
1129
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVHlwZU9STUFkYXB0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvVHlwZU9STUFkYXB0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBa0ZBLDBFQW9CQztBQXRHRCx5Q0FXd0I7QUFDeEIsK0NBQWlFO0FBQ2pFLDJEQVlpQztBQUNqQyw0QkFBMEI7QUFDMUIseUVBcUJ3QztBQUN4Qyx5Q0FBc0M7QUFDdEMsNkNBQTJDO0FBQzNDLHFEQUE4QztBQUM5QyxpREFBNEM7QUFFNUMscURBQXlEO0FBQ3pELCtEQUF3RDtBQUN4RCwrQ0FBNEM7QUFDNUMsMkRBQW9EO0FBQ3BELHVDQUFtRDtBQUNuRCxxQ0FjaUI7QUFFakIsbURBQTRDO0FBQzVDLHVFQUFnRTtBQUNoRSx1RUFBZ0U7QUFDaEUsbUZBQTRFO0FBQzVFLGlFQUEwRDtBQUMxRCxtREFBNEM7QUFFckMsS0FBSyxVQUFVLCtCQUErQixDQU1uRCxPQUE4QixFQUM5QixJQUFPLEVBQ1AsR0FBWSxFQUNaLEtBQVE7SUFFUixJQUFJLENBQUM7UUFDSCxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2pDLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFxQixDQUFDO1FBQ25DLDZEQUE2RDtJQUMvRCxDQUFDO0lBQUMsT0FBTyxDQUFVLEVBQUUsQ0FBQztRQUNwQixNQUFNLElBQUksNkJBQWEsQ0FDckIsZ0VBQWdFLENBQ2pFLENBQUM7SUFDSixDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBK0JHO0FBQ0gsTUFBYSxjQUFlLFNBQVEsY0FLbkM7SUFHQyxJQUFJLFVBQVU7UUFDWixJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3RCLE1BQU0sTUFBTSxHQUFHLGNBQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lB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RGYsSUFBQSxZQUFLLEdBQUU7Ozs7MkNBa0JQIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQWRhcHRlcixcbiAgQ2FzY2FkZSxcbiAgQ2FzY2FkZU1ldGFkYXRhLFxuICBDb25uZWN0aW9uRXJyb3IsXG4gIGZpbmFsLFxuICBQZXJzaXN0ZW5jZUtleXMsXG4gIFJlbGF0aW9uc01ldGFkYXRhLFxuICBSZXBvc2l0b3J5LFxuICBTZXF1ZW5jZSxcbiAgdHlwZSBTZXF1ZW5jZU9wdGlvbnMsXG59IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgcmVzZXJ2ZWRBdHRyaWJ1dGVzLCBUeXBlT1JNRmxhdm91ciB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHtcbiAgQmFzZUVycm9yLFxuICBDb25mbGljdEVycm9yLFxuICBDb250ZXh0LFxuICBEQktleXMsXG4gIERFRkFVTFRfRVJST1JfTUVTU0FHRVMgYXMgREJfREVGQVVMVF9FUlJPUl9NRVNTQUdFUyxcbiAgZmluZFByaW1hcnlLZXksXG4gIEludGVybmFsRXJyb3IsXG4gIE5vdEZvdW5kRXJyb3IsXG4gIE9wZXJhdGlvbktleXMsXG4gIHJlYWRvbmx5LFxuICBVcGRhdGVWYWxpZGF0aW9uS2V5cyxcbn0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgXCJyZWZsZWN0LW1ldGFkYXRhXCI7XG5pbXBvcnQge1xuICB0eXBlIENvbnN0cnVjdG9yLFxuICBkYXRlLFxuICBEZWNvcmF0aW9uLFxuICBERUZBVUxUX0VSUk9SX01FU1NBR0VTLFxuICBsaXN0LFxuICBNYXhMZW5ndGhWYWxpZGF0b3JPcHRpb25zLFxuICBNYXhWYWxpZGF0b3JPcHRpb25zLFxuICBNaW5MZW5ndGhWYWxpZGF0b3JPcHRpb25zLFxuICBNaW5WYWxpZGF0b3JPcHRpb25zLFxuICBNb2RlbCxcbiAgTW9kZWxLZXlzLFxuICBQYXR0ZXJuVmFsaWRhdG9yT3B0aW9ucyxcbiAgcHJvcCxcbiAgcHJvcE1ldGFkYXRhLFxuICByZXF1aXJlZCxcbiAgdHlwZSxcbiAgVHlwZU1ldGFkYXRhLFxuICBWYWxpZGF0aW9uLFxuICBWYWxpZGF0aW9uS2V5cyxcbiAgVmFsaWRhdG9yT3B0aW9ucyxcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgSW5kZXhFcnJvciB9IGZyb20gXCIuL2Vycm9yc1wiO1xuaW1wb3J0IHsgVHlwZU9STVN0YXRlbWVudCB9IGZyb20gXCIuL3F1ZXJ5XCI7XG5pbXBvcnQgeyBUeXBlT1JNU2VxdWVuY2UgfSBmcm9tIFwiLi9zZXF1ZW5jZXNcIjtcbmltcG9ydCB7IGdlbmVyYXRlSW5kZXhlcyB9IGZyb20gXCIuL2luZGV4ZXNcIjtcbmltcG9ydCB7IFR5cGVPUk1GbGFncywgVHlwZU9STVF1ZXJ5LCBUeXBlT1JNVGFibGVTcGVjIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IGFwcGx5LCBSZWZsZWN0aW9uIH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5pbXBvcnQgeyBUeXBlT1JNUmVwb3NpdG9yeSB9IGZyb20gXCIuL1R5cGVPUk1SZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBMb2dnaW5nIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5pbXBvcnQgeyBUeXBlT1JNRGlzcGF0Y2ggfSBmcm9tIFwiLi9UeXBlT1JNRGlzcGF0Y2hcIjtcbmltcG9ydCB7IGNvbnZlcnRKc1JlZ2V4VG9Qb3N0Z3JlcyB9IGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQge1xuICBEYXRhU291cmNlLFxuICBGaW5kT25lT3B0aW9ucyxcbiAgSW4sXG4gIEluc2VydFJlc3VsdCxcbiAgUmVsYXRpb25PcHRpb25zLFxuICBPbmVUb09uZSxcbiAgSm9pbkNvbHVtbixcbiAgTWFueVRvTWFueSxcbiAgU2VsZWN0UXVlcnlCdWlsZGVyLFxuICBWZXJzaW9uQ29sdW1uLFxuICBPbmVUb01hbnksXG4gIE1hbnlUb09uZSxcbiAgSm9pblRhYmxlLFxufSBmcm9tIFwidHlwZW9ybVwiO1xuaW1wb3J0IHsgRGF0YVNvdXJjZU9wdGlvbnMgfSBmcm9tIFwidHlwZW9ybS9kYXRhLXNvdXJjZS9EYXRhU291cmNlT3B0aW9uc1wiO1xuaW1wb3J0IHsgQ29sdW1uIH0gZnJvbSBcIi4vb3ZlcnJpZGVzL0NvbHVtblwiO1xuaW1wb3J0IHsgVXBkYXRlRGF0ZUNvbHVtbiB9IGZyb20gXCIuL292ZXJyaWRlcy9VcGRhdGVEYXRlQ29sdW1uXCI7XG5pbXBvcnQgeyBDcmVhdGVEYXRlQ29sdW1uIH0gZnJvbSBcIi4vb3ZlcnJpZGVzL0NyZWF0ZURhdGVDb2x1bW5cIjtcbmltcG9ydCB7IFByaW1hcnlHZW5lcmF0ZWRDb2x1bW4gfSBmcm9tIFwiLi9vdmVycmlkZXMvUHJpbWFyeUdlbmVyYXRlZENvbHVtblwiO1xuaW1wb3J0IHsgUHJpbWFyeUNvbHVtbiB9IGZyb20gXCIuL292ZXJyaWRlcy9QcmltYXJ5Q29sdW1uXCI7XG5pbXBvcnQgeyBFbnRpdHkgfSBmcm9tIFwiLi9vdmVycmlkZXMvRW50aXR5XCI7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjcmVhdGVkQnlPblBvc3RncmVzQ3JlYXRlVXBkYXRlPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFIgZXh0ZW5kcyBUeXBlT1JNUmVwb3NpdG9yeTxNPixcbiAgViBleHRlbmRzIFJlbGF0aW9uc01ldGFkYXRhLFxuPihcbiAgdGhpczogUixcbiAgY29udGV4dDogQ29udGV4dDxUeXBlT1JNRmxhZ3M+LFxuICBkYXRhOiBWLFxuICBrZXk6IGtleW9mIE0sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCB1c2VyID0gY29udGV4dC5nZXQoXCJ1c2VyXCIpO1xuICAgIG1vZGVsW2tleV0gPSB1c2VyIGFzIE1bdHlwZW9mIGtleV07XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBcIk5vIFVzZXIgZm91bmQgaW4gY29udGV4dC4gUGxlYXNlIHByb3ZpZGUgYSB1c2VyIGluIHRoZSBjb250ZXh0XCJcbiAgICApO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEFkYXB0ZXIgZm9yIFR5cGVPUk0tYmFja2VkIHBlcnNpc3RlbmNlIG9wZXJhdGlvbnMuXG4gKiBAc3VtbWFyeSBJbXBsZW1lbnRzIHRoZSBEZWNhZi50cyBBZGFwdGVyIG92ZXIgYSBUeXBlT1JNIERhdGFTb3VyY2UsIHByb3ZpZGluZyBDUlVEIG9wZXJhdGlvbnMsIHF1ZXJ5L3N0YXRlbWVudCBmYWN0b3JpZXMsIHNlcXVlbmNlIG1hbmFnZW1lbnQsIGVycm9yIHBhcnNpbmcsIGFuZCBkZWNvcmF0aW9uIGhlbHBlcnMuXG4gKiBAdGVtcGxhdGUgWSBUaGUgbmF0aXZlIGNvbmZpZ3VyYXRpb24gdHlwZSAoVHlwZU9STSBEYXRhU291cmNlT3B0aW9ucykuXG4gKiBAdGVtcGxhdGUgRiBUaGUgcmVwb3NpdG9yeSBmbGFncyB0eXBlLlxuICogQHRlbXBsYXRlIEMgVGhlIGNvbnRleHQgdHlwZS5cbiAqIEBwYXJhbSB7RGF0YVNvdXJjZU9wdGlvbnN9IHNjb3BlIFRoZSBEYXRhU291cmNlIG9wdGlvbnMgZm9yIHRoZSBhZGFwdGVyLlxuICogQHBhcmFtIHtzdHJpbmd9IGZsYXZvdXIgVGhlIGZsYXZvdXIgb2YgdGhlIGFkYXB0ZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30gW2FsaWFzXSBPcHRpb25hbCBhbGlhcyBmb3IgdGhlIGFkYXB0ZXIuXG4gKiBAY2xhc3MgVHlwZU9STUFkYXB0ZXJcbiAqIEBleGFtcGxlXG4gKiBjb25zdCBhZGFwdGVyID0gbmV3IFR5cGVPUk1BZGFwdGVyKHsgdHlwZTogJ3Bvc3RncmVzJywgLyogLi4uICpcXC8gfSk7XG4gKiBhd2FpdCBhZGFwdGVyLmluaXRpYWxpemUoKTtcbiAqIGNvbnN0IHJlcG8gPSBuZXcgKGFkYXB0ZXIucmVwb3NpdG9yeTxVc2VyPigpKShhZGFwdGVyLCBVc2VyKTtcbiAqIGNvbnN0IGNyZWF0ZWQgPSBhd2FpdCByZXBvLmNyZWF0ZShuZXcgVXNlcih7IG5hbWU6ICdBbGljZScgfSkpO1xuICpcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQXBwXG4gKiAgIHBhcnRpY2lwYW50IEFkYXB0ZXIgYXMgVHlwZU9STUFkYXB0ZXJcbiAqICAgcGFydGljaXBhbnQgUmVwbyBhcyBUeXBlT1JNUmVwb3NpdG9yeVxuICogICBwYXJ0aWNpcGFudCBEUyBhcyBUeXBlT1JNIERhdGFTb3VyY2VcbiAqXG4gKiAgIEFwcC0+PkFkYXB0ZXI6IG5ldyBUeXBlT1JNQWRhcHRlcihvcHRzKVxuICogICBBZGFwdGVyLT4+RFM6IGluaXRpYWxpemUoKVxuICogICBBcHAtPj5BZGFwdGVyOiByZXBvc2l0b3J5KClcbiAqICAgQWRhcHRlci0tPj5BcHA6IFR5cGVPUk1SZXBvc2l0b3J5XG4gKiAgIEFwcC0+PlJlcG86IGNyZWF0ZShtb2RlbClcbiAqICAgUmVwby0+PkFkYXB0ZXI6IHByZXBhcmUvY3JlYXRlL3JldmVydFxuICogICBBZGFwdGVyLS0+PlJlcG86IE1vZGVsXG4gKiAgIFJlcG8tLT4+QXBwOiBNb2RlbFxuICovXG5leHBvcnQgY2xhc3MgVHlwZU9STUFkYXB0ZXIgZXh0ZW5kcyBBZGFwdGVyPFxuICBEYXRhU291cmNlT3B0aW9ucyxcbiAgVHlwZU9STVF1ZXJ5LFxuICBUeXBlT1JNRmxhZ3MsXG4gIENvbnRleHQ8VHlwZU9STUZsYWdzPlxuPiB7XG4gIHByaXZhdGUgX2RhdGFTb3VyY2U/OiBEYXRhU291cmNlO1xuXG4gIGdldCBkYXRhU291cmNlKCk6IERhdGFTb3VyY2Uge1xuICAgIGlmICghdGhpcy5fZGF0YVNvdXJjZSkge1xuICAgICAgY29uc3QgbW9kZWxzID0gQWRhcHRlci5tb2RlbHModGhpcy5mbGF2b3VyKTtcbiAgICAgIHRoaXMuX2RhdGFTb3VyY2UgPSBuZXcgRGF0YVNvdXJjZShcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLm5hdGl2ZSwge1xuICAgICAgICAgIGVudGl0aWVzOiBtb2RlbHMubWFwKChjKSA9PiBjW01vZGVsS2V5cy5BTkNIT1IgYXMga2V5b2YgdHlwZW9mIGNdKSxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9kYXRhU291cmNlO1xuICB9XG4gIC8vIHByb3RlY3RlZCBkYXRhU291XG5cbiAgY29uc3RydWN0b3Iob3B0aW9uczogRGF0YVNvdXJjZU9wdGlvbnMsIGFsaWFzPzogc3RyaW5nKSB7XG4gICAgc3VwZXIob3B0aW9ucywgVHlwZU9STUZsYXZvdXIsIGFsaWFzKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyBmbGFnczxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG9wZXJhdGlvbjogT3BlcmF0aW9uS2V5cyxcbiAgICBtb2RlbDogQ29uc3RydWN0b3I8TT4sXG4gICAgZmxhZ3M6IFBhcnRpYWw8VHlwZU9STUZsYWdzPlxuICApOiBQcm9taXNlPFR5cGVPUk1GbGFncz4ge1xuICAgIGNvbnN0IGYgPSBhd2FpdCBzdXBlci5mbGFncyhvcGVyYXRpb24sIG1vZGVsLCBmbGFncyk7XG4gICAgY29uc3QgbmV3T2JqOiBhbnkgPSB7XG4gICAgICB1c2VyOiAoYXdhaXQgVHlwZU9STUFkYXB0ZXIuZ2V0Q3VycmVudFVzZXIodGhpcy5kYXRhU291cmNlKSkgYXMgc3RyaW5nLFxuICAgIH07XG4gICAgY29uc3QgbSA9IG5ldyBtb2RlbCgpO1xuXG4gICAgY29uc3QgZXhjZXB0aW9uczogc3RyaW5nW10gPSBbXTtcbiAgICBpZiAob3BlcmF0aW9uID09PSBPcGVyYXRpb25LZXlzLkNSRUFURSkge1xuICAgICAgY29uc3QgcGsgPSBmaW5kUHJpbWFyeUtleShtKS5pZDtcbiAgICAgIGV4Y2VwdGlvbnMucHVzaChwayBhcyBzdHJpbmcpO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIG9wZXJhdGlvbiA9PT0gT3BlcmF0aW9uS2V5cy5DUkVBVEUgfHxcbiAgICAgIG9wZXJhdGlvbiA9PT0gT3BlcmF0aW9uS2V5cy5VUERBVEVcbiAgICApIHtcbiAgICAgIGNvbnN0IGRlY3MgPSBPYmplY3Qua2V5cyhtKS5yZWR1Y2UoKGFjY3VtOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBrZXkpID0+IHtcbiAgICAgICAgY29uc3QgZGVjcyA9IFJlZmxlY3Rpb24uZ2V0UHJvcGVydHlEZWNvcmF0b3JzKFxuICAgICAgICAgIFZhbGlkYXRpb25LZXlzLlJFRkxFQ1QsXG4gICAgICAgICAgbSxcbiAgICAgICAgICBrZXksXG4gICAgICAgICAgdHJ1ZVxuICAgICAgICApO1xuICAgICAgICBjb25zdCBkZWMgPSBkZWNzLmRlY29yYXRvcnMuZmluZChcbiAgICAgICAgICAoZGVjOiBhbnkpID0+XG4gICAgICAgICAgICBkZWMua2V5ID09PSBEQktleXMuVElNRVNUQU1QICYmXG4gICAgICAgICAgICBkZWMucHJvcHMub3BlcmF0aW9uLmluZGV4T2Yob3BlcmF0aW9uKSAhPT0gLTFcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGRlYykge1xuICAgICAgICAgIGFjY3VtW2tleV0gPSBkZWMucHJvcHM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFjY3VtO1xuICAgICAgfSwge30pO1xuXG4gICAgICBleGNlcHRpb25zLnB1c2goLi4uT2JqZWN0LmtleXMoZGVjcykpO1xuICAgIH1cblxuICAgIG5ld09iai5pZ25vcmVkVmFsaWRhdGlvblByb3BlcnRpZXMgPSAoXG4gICAgICBmLmlnbm9yZWRWYWxpZGF0aW9uUHJvcGVydGllcyA/IGYuaWdub3JlZFZhbGlkYXRpb25Qcm9wZXJ0aWVzIDogW11cbiAgICApLmNvbmNhdCguLi5leGNlcHRpb25zKTtcbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihmLCBuZXdPYmopIGFzIFR5cGVPUk1GbGFncztcbiAgfVxuXG4gIEBmaW5hbCgpXG4gIHByb3RlY3RlZCBvdmVycmlkZSBEaXNwYXRjaCgpOiBUeXBlT1JNRGlzcGF0Y2gge1xuICAgIHJldHVybiBuZXcgVHlwZU9STURpc3BhdGNoKCk7XG4gIH1cblxuICBAZmluYWwoKVxuICBvdmVycmlkZSByZXBvc2l0b3J5PE0gZXh0ZW5kcyBNb2RlbD4oKTogQ29uc3RydWN0b3I8VHlwZU9STVJlcG9zaXRvcnk8TT4+IHtcbiAgICByZXR1cm4gVHlwZU9STVJlcG9zaXRvcnk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgUG9zdGdyZXMgc3RhdGVtZW50IGZvciBxdWVyeWluZ1xuICAgKiBAc3VtbWFyeSBGYWN0b3J5IG1ldGhvZCB0aGF0IGNyZWF0ZXMgYSBuZXcgUG9zdGdyZXNTdGF0ZW1lbnQgaW5zdGFuY2UgZm9yIGJ1aWxkaW5nIHF1ZXJpZXNcbiAgICogQHRlbXBsYXRlIE0gLSBUaGUgbW9kZWwgdHlwZVxuICAgKiBAcmV0dXJuIHtUeXBlT1JNU3RhdGVtZW50PE0sIGFueT59IEEgbmV3IFBvc3RncmVzU3RhdGVtZW50IGluc3RhbmNlXG4gICAqL1xuICBAZmluYWwoKVxuICBTdGF0ZW1lbnQ8TSBleHRlbmRzIE1vZGVsPigpOiBUeXBlT1JNU3RhdGVtZW50PE0sIGFueT4ge1xuICAgIHJldHVybiBuZXcgVHlwZU9STVN0YXRlbWVudCh0aGlzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG5ldyBQb3N0Z3JlU1FMIHNlcXVlbmNlXG4gICAqIEBzdW1tYXJ5IEZhY3RvcnkgbWV0aG9kIHRoYXQgY3JlYXRlcyBhIG5ldyBQb3N0Z3JlU1FMU2VxdWVuY2UgaW5zdGFuY2UgZm9yIG1hbmFnaW5nIHNlcXVlbmNlc1xuICAgKiBAcGFyYW0ge1NlcXVlbmNlT3B0aW9uc30gb3B0aW9ucyAtIFRoZSBvcHRpb25zIGZvciB0aGUgc2VxdWVuY2VcbiAgICogQHJldHVybiB7UHJvbWlzZTxTZXF1ZW5jZT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgbmV3IFNlcXVlbmNlIGluc3RhbmNlXG4gICAqL1xuICBAZmluYWwoKVxuICBhc3luYyBTZXF1ZW5jZShvcHRpb25zOiBTZXF1ZW5jZU9wdGlvbnMpOiBQcm9taXNlPFNlcXVlbmNlPiB7XG4gICAgcmV0dXJuIG5ldyBUeXBlT1JNU2VxdWVuY2Uob3B0aW9ucywgdGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemVzIHRoZSBhZGFwdGVyIGJ5IGNyZWF0aW5nIGluZGV4ZXMgZm9yIGFsbCBtYW5hZ2VkIG1vZGVsc1xuICAgKiBAc3VtbWFyeSBTZXRzIHVwIHRoZSBuZWNlc3NhcnkgZGF0YWJhc2UgaW5kZXhlcyBmb3IgYWxsIG1vZGVscyBtYW5hZ2VkIGJ5IHRoaXMgYWRhcHRlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGluaXRpYWxpemF0aW9uIGlzIGNvbXBsZXRlXG4gICAqL1xuICBhc3luYyBpbml0aWFsaXplKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGRzID0gdGhpcy5kYXRhU291cmNlO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBkcy5pbml0aWFsaXplKCk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUgYXMgRXJyb3IpO1xuICAgIH1cbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5pbml0aWFsaXplKTtcbiAgICBsb2cudmVyYm9zZShgJHt0aGlzLmZsYXZvdXJ9IGFkYXB0ZXIgaW5pdGlhbGl6ZWRgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBpbmRleGVzIGZvciB0aGUgZ2l2ZW4gbW9kZWxzXG4gICAqIEBzdW1tYXJ5IEFic3RyYWN0IG1ldGhvZCB0aGF0IG11c3QgYmUgaW1wbGVtZW50ZWQgdG8gY3JlYXRlIGRhdGFiYXNlIGluZGV4ZXMgZm9yIHRoZSBzcGVjaWZpZWQgbW9kZWxzXG4gICAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGVcbiAgICogQHBhcmFtIHsuLi5Db25zdHJ1Y3RvcjxNPn0gbW9kZWxzIC0gVGhlIG1vZGVsIGNvbnN0cnVjdG9ycyB0byBjcmVhdGUgaW5kZXhlcyBmb3JcbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBhbGwgaW5kZXhlcyBhcmUgY3JlYXRlZFxuICAgKi9cbiAgQGZpbmFsKClcbiAgcHJvdGVjdGVkIGFzeW5jIGluZGV4PE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgLi4ubW9kZWxzOiBDb25zdHJ1Y3RvcjxNPltdXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGluZGV4ZXM6IFR5cGVPUk1RdWVyeVtdID0gZ2VuZXJhdGVJbmRleGVzKG1vZGVscyk7XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5kYXRhU291cmNlLnF1ZXJ5KFwiQkVHSU5cIik7XG5cbiAgICAgIGZvciAoY29uc3QgaW5kZXggb2YgaW5kZXhlcykge1xuICAgICAgICBhd2FpdCB0aGlzLmRhdGFTb3VyY2UucXVlcnkoaW5kZXgucXVlcnksIGluZGV4LnZhbHVlcyk7XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IHRoaXMuZGF0YVNvdXJjZS5xdWVyeShcIkNPTU1JVFwiKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICBhd2FpdCB0aGlzLmRhdGFTb3VyY2UucXVlcnkoXCJST0xMQkFDS1wiKTtcbiAgICAgIHRocm93IHRoaXMucGFyc2VFcnJvcihlIGFzIEVycm9yKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEV4ZWN1dGVzIGEgcmF3IFNRTCBxdWVyeSBhZ2FpbnN0IHRoZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBBYnN0cmFjdCBtZXRob2QgdGhhdCBtdXN0IGJlIGltcGxlbWVudGVkIHRvIGV4ZWN1dGUgcmF3IFNRTCBxdWVyaWVzXG4gICAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHJlc3VsdCB0eXBlXG4gICAqIEBwYXJhbSB7VHlwZU9STVF1ZXJ5fSBxIC0gVGhlIHF1ZXJ5IHRvIGV4ZWN1dGVcbiAgICogQHJldHVybiB7UHJvbWlzZTxSPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHF1ZXJ5IHJlc3VsdFxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgcmF3PFI+KHE6IFR5cGVPUk1RdWVyeSk6IFByb21pc2U8Uj4ge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLnJhdyk7XG4gICAgdHJ5IHtcbiAgICAgIGlmICghdGhpcy5kYXRhU291cmNlLmlzSW5pdGlhbGl6ZWQpIGF3YWl0IHRoaXMuZGF0YVNvdXJjZS5pbml0aWFsaXplKCk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUgYXMgRXJyb3IpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgY29uc3QgeyBxdWVyeSwgdmFsdWVzIH0gPSBxO1xuICAgICAgbG9nLmRlYnVnKFxuICAgICAgICBgZXhlY3V0aW5nIHF1ZXJ5OiAkeyhxdWVyeSBhcyB1bmtub3duIGFzIFNlbGVjdFF1ZXJ5QnVpbGRlcjxhbnk+KS5nZXRTcWwoKX1gXG4gICAgICApO1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmRhdGFTb3VyY2UucXVlcnkocXVlcnksIHZhbHVlcyk7XG4gICAgICByZXR1cm4gcmVzcG9uc2UgYXMgUjtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgb3ZlcnJpZGUgcHJlcGFyZTxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG1vZGVsOiBNLFxuICAgIHBrOiBrZXlvZiBNLFxuICAgIGNoaWxkID0gZmFsc2VcbiAgKToge1xuICAgIHJlY29yZDogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgICBpZDogc3RyaW5nO1xuICAgIHRyYW5zaWVudD86IFJlY29yZDxzdHJpbmcsIGFueT47XG4gIH0ge1xuICAgIGNvbnN0IHByZXBhcmVkID0gc3VwZXIucHJlcGFyZShtb2RlbCwgcGspO1xuXG4gICAgcHJlcGFyZWQucmVjb3JkID0gT2JqZWN0LmVudHJpZXMocHJlcGFyZWQucmVjb3JkKS5yZWR1Y2UoXG4gICAgICAoYWNjdW06IFJlY29yZDxzdHJpbmcsIGFueT4sIFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgICBpZiAoa2V5ID09PSBQZXJzaXN0ZW5jZUtleXMuTUVUQURBVEEgfHwgdGhpcy5pc1Jlc2VydmVkKGtleSkpXG4gICAgICAgICAgcmV0dXJuIGFjY3VtO1xuICAgICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHJldHVybiBhY2N1bTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgICB2YWx1ZSA9IG5ldyBEYXRlKHZhbHVlLmdldFRpbWUoKSk7XG4gICAgICAgIH0gZWxzZSBpZiAoTW9kZWwuaXNNb2RlbCh2YWx1ZSkpIHtcbiAgICAgICAgICB2YWx1ZSA9IHRoaXMucHJlcGFyZSh2YWx1ZSwgZmluZFByaW1hcnlLZXkodmFsdWUpLmlkLCB0cnVlKS5yZWNvcmQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc3dpdGNoICh0eXBlb2YgdmFsdWUpIHtcbiAgICAgICAgICAgIGNhc2UgXCJzdHJpbmdcIjpcbiAgICAgICAgICAgICAgdmFsdWUgPSBgJHt2YWx1ZX1gO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAvL2RvIG5vdGhpbmc7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGFjY3VtW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgcmV0dXJuIGFjY3VtO1xuICAgICAgfSxcbiAgICAgIHt9XG4gICAgKTtcbiAgICBjb25zdCBjb25zdHI6IENvbnN0cnVjdG9yPGFueT4gfCB1bmRlZmluZWQgPSBNb2RlbC5nZXQoXG4gICAgICBtb2RlbC5jb25zdHJ1Y3Rvci5uYW1lXG4gICAgKTtcbiAgICBpZiAoIWNvbnN0cilcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICBgTW9kZWwgJHttb2RlbC5jb25zdHJ1Y3Rvci5uYW1lfSBub3QgZm91bmQgaW4gcmVnaXN0cnlgXG4gICAgICApO1xuICAgIGNvbnN0IHJlc3VsdCA9IGNoaWxkXG4gICAgICA/IG5ldyAoY29uc3RyIGFzIGFueSlbTW9kZWxLZXlzLkFOQ0hPUiBhcyBrZXlvZiB0eXBlb2YgY29uc3RyXSgpXG4gICAgICA6IG5ldyBjb25zdHIoKTtcbiAgICBpZiAoY2hpbGQpXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkocmVzdWx0LCBcImNvbnN0cnVjdG9yXCIsIHtcbiAgICAgICAgY29uZmlndXJhYmxlOiBmYWxzZSxcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHZhbHVlOiAoY29uc3RyIGFzIGFueSlbTW9kZWxLZXlzLkFOQ0hPUiBhcyBrZXlvZiB0eXBlb2YgY29uc3RyXSxcbiAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgfSk7XG4gICAgT2JqZWN0LmVudHJpZXMocHJlcGFyZWQucmVjb3JkKS5mb3JFYWNoKFxuICAgICAgKFtrZXksIHZhbF0pID0+IChyZXN1bHRba2V5IGFzIGtleW9mIHR5cGVvZiByZXN1bHRdID0gdmFsKVxuICAgICk7XG4gICAgcHJlcGFyZWQucmVjb3JkID0gcmVzdWx0O1xuICAgIHJldHVybiBwcmVwYXJlZDtcbiAgfVxuXG4gIG92ZXJyaWRlIHJldmVydDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG9iajogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICBjbGF6ejogc3RyaW5nIHwgQ29uc3RydWN0b3I8TT4sXG4gICAgcGs6IGtleW9mIE0sXG4gICAgaWQ6IHN0cmluZyB8IG51bWJlciB8IGJpZ2ludCxcbiAgICB0cmFuc2llbnQ/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+XG4gICk6IE0ge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLnJldmVydCk7XG4gICAgaWYgKHRyYW5zaWVudCkge1xuICAgICAgbG9nLnZlcmJvc2UoXG4gICAgICAgIGByZS1hZGRpbmcgdHJhbnNpZW50IHByb3BlcnRpZXM6ICR7T2JqZWN0LmtleXModHJhbnNpZW50KS5qb2luKFwiLCBcIil9YFxuICAgICAgKTtcbiAgICAgIE9iamVjdC5lbnRyaWVzKHRyYW5zaWVudCkuZm9yRWFjaCgoW2tleSwgdmFsXSkgPT4ge1xuICAgICAgICBpZiAoa2V5IGluIG9iailcbiAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICAgIGBUcmFuc2llbnQgcHJvcGVydHkgJHtrZXl9IGFscmVhZHkgZXhpc3RzIG9uIG1vZGVsICR7dHlwZW9mIGNsYXp6ID09PSBcInN0cmluZ1wiID8gY2xhenogOiBjbGF6ei5uYW1lfS4gc2hvdWxkIGJlIGltcG9zc2libGVgXG4gICAgICAgICAgKTtcbiAgICAgICAgKG9iaiBhcyBNKVtrZXkgYXMga2V5b2YgTV0gPSB2YWw7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IChjbGF6eiBhcyBDb25zdHJ1Y3RvcjxNPikob2JqKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG5ldyByZWNvcmQgaW4gdGhlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IEFic3RyYWN0IG1ldGhvZCB0aGF0IG11c3QgYmUgaW1wbGVtZW50ZWQgdG8gY3JlYXRlIGEgbmV3IHJlY29yZFxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlXG4gICAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gaWQgLSBUaGUgSUQgb2YgdGhlIHJlY29yZFxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IG1vZGVsIC0gVGhlIG1vZGVsIHRvIGNyZWF0ZVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIGNyZWF0ZWQgcmVjb3JkXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyBjcmVhdGUoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IHN0cmluZyB8IG51bWJlcixcbiAgICBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gICAgY29uc3QgbTogQ29uc3RydWN0b3I8TW9kZWw+ID0gdGFibGVOYW1lIGFzIHVua25vd24gYXMgQ29uc3RydWN0b3I8TW9kZWw+O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXBvID0gdGhpcy5kYXRhU291cmNlLmdldFJlcG9zaXRvcnkobSk7XG4gICAgICByZXR1cm4gYXdhaXQgcmVwby5zYXZlKG1vZGVsKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWFkcyBhIHJlY29yZCBmcm9tIHRoZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBBYnN0cmFjdCBtZXRob2QgdGhhdCBtdXN0IGJlIGltcGxlbWVudGVkIHRvIHJlYWQgYSByZWNvcmRcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZVxuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIC0gVGhlIElEIG9mIHRoZSByZWNvcmRcbiAgICogQHBhcmFtIHtzdHJpbmd9IHBrIC0gcHJpbWFyeSBrZXkgY29sdW1cbiAgICogQHJldHVybiB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHJlYWQgcmVjb3JkXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyByZWFkKFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIGlkOiBzdHJpbmcgfCBudW1iZXIsXG4gICAgcGs6IHN0cmluZ1xuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+IHtcbiAgICBjb25zdCBtOiBDb25zdHJ1Y3RvcjxNb2RlbD4gPSB0YWJsZU5hbWUgYXMgdW5rbm93biBhcyBDb25zdHJ1Y3RvcjxNb2RlbD47XG4gICAgbGV0IHJlc3VsdDogYW55O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXBvID0gdGhpcy5kYXRhU291cmNlLmdldFJlcG9zaXRvcnkobSk7XG4gICAgICBjb25zdCBxOiBGaW5kT25lT3B0aW9ucyA9IHtcbiAgICAgICAgd2hlcmU6IHtcbiAgICAgICAgICBbcGtdOiBpZCxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgICByZXN1bHQgPSAoYXdhaXQgcmVwby5maW5kT25lKHEpKSBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IHRoaXMucGFyc2VFcnJvcihlIGFzIEVycm9yKTtcbiAgICB9XG4gICAgaWYgKCFyZXN1bHQpXG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFcnJvcihcbiAgICAgICAgYFJlY29yZCB3aXRoIGlkOiAke2lkfSBub3QgZm91bmQgaW4gdGFibGUgJHt0eXBlb2YgdGFibGVOYW1lID09PSBcInN0cmluZ1wiID8gdGFibGVOYW1lIDogUmVwb3NpdG9yeS50YWJsZSh0YWJsZU5hbWUpfWBcbiAgICAgICk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVXBkYXRlcyBhIHJlY29yZCBpbiB0aGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgQWJzdHJhY3QgbWV0aG9kIHRoYXQgbXVzdCBiZSBpbXBsZW1lbnRlZCB0byB1cGRhdGUgYSByZWNvcmRcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZVxuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIC0gVGhlIElEIG9mIHRoZSByZWNvcmRcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBtb2RlbCAtIFRoZSBtb2RlbCB0byB1cGRhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHBrIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgdXBkYXRlZCByZWNvcmRcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIHVwZGF0ZShcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZDogc3RyaW5nIHwgbnVtYmVyLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+IHtcbiAgICBjb25zdCBtOiBDb25zdHJ1Y3RvcjxNb2RlbD4gPSB0YWJsZU5hbWUgYXMgdW5rbm93biBhcyBDb25zdHJ1Y3RvcjxNb2RlbD47XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcG8gPSB0aGlzLmRhdGFTb3VyY2UuZ2V0UmVwb3NpdG9yeShtKTtcbiAgICAgIHJldHVybiByZXBvLnNhdmUobW9kZWwpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IHRoaXMucGFyc2VFcnJvcihlIGFzIEVycm9yKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERlbGV0ZXMgYSByZWNvcmQgZnJvbSB0aGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgQWJzdHJhY3QgbWV0aG9kIHRoYXQgbXVzdCBiZSBpbXBsZW1lbnRlZCB0byBkZWxldGUgYSByZWNvcmRcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZVxuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIC0gVGhlIElEIG9mIHRoZSByZWNvcmRcbiAgICogQHBhcmFtIHtzdHJpbmd9IHBrIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgZGVsZXRlZCByZWNvcmRcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIGRlbGV0ZShcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZDogc3RyaW5nIHwgbnVtYmVyLFxuICAgIHBrOiBzdHJpbmcsXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj4ge1xuICAgIGNvbnN0IG06IENvbnN0cnVjdG9yPE1vZGVsPiA9IHRhYmxlTmFtZSBhcyB1bmtub3duIGFzIENvbnN0cnVjdG9yPE1vZGVsPjtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVwbyA9IHRoaXMuZGF0YVNvdXJjZS5nZXRSZXBvc2l0b3J5KG0pO1xuICAgICAgY29uc3QgbW9kZWwgPSBhd2FpdCB0aGlzLnJlYWQodGFibGVOYW1lLCBpZCwgcGspO1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgcmVwby5kZWxldGUoaWQpO1xuICAgICAgcmV0dXJuIG1vZGVsO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IHRoaXMucGFyc2VFcnJvcihlIGFzIEVycm9yKTtcbiAgICB9XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBjcmVhdGVBbGwoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IChzdHJpbmcgfCBudW1iZXIpW10sXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT5bXSxcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+W10+IHtcbiAgICBjb25zdCBtOiBDb25zdHJ1Y3RvcjxNb2RlbD4gPSB0YWJsZU5hbWUgYXMgdW5rbm93biBhcyBDb25zdHJ1Y3RvcjxNb2RlbD47XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcG8gPSB0aGlzLmRhdGFTb3VyY2UuZ2V0UmVwb3NpdG9yeShtKTtcbiAgICAgIGNvbnN0IHJlc3VsdDogSW5zZXJ0UmVzdWx0ID0gYXdhaXQgcmVwby5pbnNlcnQobW9kZWwpO1xuICAgICAgcmV0dXJuIHRoaXMucmVhZEFsbChcbiAgICAgICAgdGFibGVOYW1lLFxuICAgICAgICByZXN1bHQuaWRlbnRpZmllcnMubWFwKChpZCkgPT4gaWQuaWQpLFxuICAgICAgICBcImlkXCJcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUgYXMgRXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIHJlYWRBbGwoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IChzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQpW10sXG4gICAgcGs6IHN0cmluZyxcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+W10+IHtcbiAgICBpZiAoIWlkLmxlbmd0aCkgcmV0dXJuIFtdO1xuXG4gICAgY29uc3QgbTogQ29uc3RydWN0b3I8TW9kZWw+ID0gdGFibGVOYW1lIGFzIHVua25vd24gYXMgQ29uc3RydWN0b3I8TW9kZWw+O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXBvID0gdGhpcy5kYXRhU291cmNlLmdldFJlcG9zaXRvcnkobSk7XG4gICAgICByZXR1cm4gcmVwby5maW5kQnkoeyBbcGtdOiBJbihpZCkgfSk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUgYXMgRXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIHVwZGF0ZUFsbChcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZHM6IHN0cmluZ1tdIHwgbnVtYmVyW10sXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT5bXSxcbiAgICBwazogc3RyaW5nLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55PltdPiB7XG4gICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgZm9yIChjb25zdCBtIG9mIG1vZGVsKSB7XG4gICAgICByZXN1bHQucHVzaChhd2FpdCB0aGlzLnVwZGF0ZSh0YWJsZU5hbWUsIG1bcGtdLCBtLCAuLi5hcmdzKSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBkZWxldGVBbGwoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWRzOiAoc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50KVtdLFxuICAgIHBrOiBzdHJpbmcsXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55PltdPiB7XG4gICAgaWYgKCFpZHMubGVuZ3RoKSByZXR1cm4gW107XG4gICAgY29uc3QgbTogQ29uc3RydWN0b3I8TW9kZWw+ID0gdGFibGVOYW1lIGFzIHVua25vd24gYXMgQ29uc3RydWN0b3I8TW9kZWw+O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXBvID0gdGhpcy5kYXRhU291cmNlLmdldFJlcG9zaXRvcnkobSk7XG4gICAgICBjb25zdCBtb2RlbHMgPSBhd2FpdCB0aGlzLnJlYWRBbGwodGFibGVOYW1lLCBpZHMsIHBrKTtcbiAgICAgIGF3YWl0IHJlcG8uZGVsZXRlKGlkcyk7XG4gICAgICByZXR1cm4gbW9kZWxzO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IHRoaXMucGFyc2VFcnJvcihlIGFzIEVycm9yKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFBhcnNlcyBhbiBlcnJvciBhbmQgY29udmVydHMgaXQgdG8gYSBCYXNlRXJyb3JcbiAgICogQHN1bW1hcnkgQ29udmVydHMgdmFyaW91cyBlcnJvciB0eXBlcyB0byBhcHByb3ByaWF0ZSBCYXNlRXJyb3Igc3VidHlwZXNcbiAgICogQHBhcmFtIHtFcnJvcnxzdHJpbmd9IGVyciAtIFRoZSBlcnJvciB0byBwYXJzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3JlYXNvbl0gLSBPcHRpb25hbCByZWFzb24gZm9yIHRoZSBlcnJvclxuICAgKiBAcmV0dXJuIHtCYXNlRXJyb3J9IFRoZSBwYXJzZWQgZXJyb3IgYXMgYSBCYXNlRXJyb3JcbiAgICovXG4gIHBhcnNlRXJyb3IoZXJyOiBFcnJvciB8IHN0cmluZywgcmVhc29uPzogc3RyaW5nKTogQmFzZUVycm9yIHtcbiAgICByZXR1cm4gVHlwZU9STUFkYXB0ZXIucGFyc2VFcnJvcihlcnIsIHJlYXNvbik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENoZWNrcyBpZiBhbiBhdHRyaWJ1dGUgaXMgcmVzZXJ2ZWRcbiAgICogQHN1bW1hcnkgRGV0ZXJtaW5lcyBpZiBhbiBhdHRyaWJ1dGUgbmFtZSBpcyByZXNlcnZlZCBpbiBQb3N0Z3JlU1FMXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhdHRyIC0gVGhlIGF0dHJpYnV0ZSBuYW1lIHRvIGNoZWNrXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgdGhlIGF0dHJpYnV0ZSBpcyByZXNlcnZlZCwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAqL1xuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgaXNSZXNlcnZlZChhdHRyOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISFhdHRyLm1hdGNoKHJlc2VydmVkQXR0cmlidXRlcyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFN0YXRpYyBtZXRob2QgdG8gcGFyc2UgYW4gZXJyb3IgYW5kIGNvbnZlcnQgaXQgdG8gYSBCYXNlRXJyb3JcbiAgICogQHN1bW1hcnkgQ29udmVydHMgdmFyaW91cyBlcnJvciB0eXBlcyB0byBhcHByb3ByaWF0ZSBCYXNlRXJyb3Igc3VidHlwZXMgYmFzZWQgb24gUG9zdGdyZVNRTCBlcnJvciBjb2RlcyBhbmQgbWVzc2FnZXNcbiAgICogQHBhcmFtIHtFcnJvcnxzdHJpbmd9IGVyciAtIFRoZSBlcnJvciB0byBwYXJzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3JlYXNvbl0gLSBPcHRpb25hbCByZWFzb24gZm9yIHRoZSBlcnJvclxuICAgKiBAcmV0dXJuIHtCYXNlRXJyb3J9IFRoZSBwYXJzZWQgZXJyb3IgYXMgYSBCYXNlRXJyb3JcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gICAqICAgcGFydGljaXBhbnQgcGFyc2VFcnJvclxuICAgKiAgIHBhcnRpY2lwYW50IEVycm9yVHlwZXNcbiAgICpcbiAgICogICBDYWxsZXItPj5wYXJzZUVycm9yOiBlcnIsIHJlYXNvblxuICAgKiAgIE5vdGUgb3ZlciBwYXJzZUVycm9yOiBDaGVjayBpZiBlcnIgaXMgYWxyZWFkeSBhIEJhc2VFcnJvclxuICAgKiAgIGFsdCBlcnIgaXMgQmFzZUVycm9yXG4gICAqICAgICBwYXJzZUVycm9yLS0+PkNhbGxlcjogcmV0dXJuIGVyclxuICAgKiAgIGVsc2UgZXJyIGlzIHN0cmluZ1xuICAgKiAgICAgTm90ZSBvdmVyIHBhcnNlRXJyb3I6IEV4dHJhY3QgY29kZSBmcm9tIHN0cmluZ1xuICAgKiAgICAgYWx0IGNvZGUgbWF0Y2hlcyBcImR1cGxpY2F0ZSBrZXl8YWxyZWFkeSBleGlzdHNcIlxuICAgKiAgICAgICBwYXJzZUVycm9yLT4+RXJyb3JUeXBlczogbmV3IENvbmZsaWN0RXJyb3IoY29kZSlcbiAgICogICAgICAgRXJyb3JUeXBlcy0tPj5DYWxsZXI6IENvbmZsaWN0RXJyb3JcbiAgICogICAgIGVsc2UgY29kZSBtYXRjaGVzIFwiZG9lcyBub3QgZXhpc3R8bm90IGZvdW5kXCJcbiAgICogICAgICAgcGFyc2VFcnJvci0+PkVycm9yVHlwZXM6IG5ldyBOb3RGb3VuZEVycm9yKGNvZGUpXG4gICAqICAgICAgIEVycm9yVHlwZXMtLT4+Q2FsbGVyOiBOb3RGb3VuZEVycm9yXG4gICAqICAgICBlbmRcbiAgICogICBlbHNlIGVyciBoYXMgY29kZSBwcm9wZXJ0eVxuICAgKiAgICAgTm90ZSBvdmVyIHBhcnNlRXJyb3I6IEV4dHJhY3QgY29kZSBhbmQgcmVhc29uXG4gICAqICAgZWxzZVxuICAgKiAgICAgTm90ZSBvdmVyIHBhcnNlRXJyb3I6IFVzZSBlcnIubWVzc2FnZSBhcyBjb2RlXG4gICAqICAgZW5kXG4gICAqXG4gICAqICAgTm90ZSBvdmVyIHBhcnNlRXJyb3I6IFN3aXRjaCBvbiBQb3N0Z3JlU1FMIGVycm9yIGNvZGVcbiAgICogICBhbHQgY29kZSBpcyAyMzUwNSAodW5pcXVlX3Zpb2xhdGlvbilcbiAgICogICAgIHBhcnNlRXJyb3ItPj5FcnJvclR5cGVzOiBuZXcgQ29uZmxpY3RFcnJvcihyZWFzb24pXG4gICAqICAgICBFcnJvclR5cGVzLS0+PkNhbGxlcjogQ29uZmxpY3RFcnJvclxuICAgKiAgIGVsc2UgY29kZSBpcyAyMzUwMyAoZm9yZWlnbl9rZXlfdmlvbGF0aW9uKVxuICAgKiAgICAgcGFyc2VFcnJvci0+PkVycm9yVHlwZXM6IG5ldyBDb25mbGljdEVycm9yKHJlYXNvbilcbiAgICogICAgIEVycm9yVHlwZXMtLT4+Q2FsbGVyOiBDb25mbGljdEVycm9yXG4gICAqICAgZWxzZSBjb2RlIGlzIDQyUDAxICh1bmRlZmluZWRfdGFibGUpXG4gICAqICAgICBwYXJzZUVycm9yLT4+RXJyb3JUeXBlczogbmV3IE5vdEZvdW5kRXJyb3IocmVhc29uKVxuICAgKiAgICAgRXJyb3JUeXBlcy0tPj5DYWxsZXI6IE5vdEZvdW5kRXJyb3JcbiAgICogICBlbHNlIGNvZGUgaXMgNDI3MDMgKHVuZGVmaW5lZF9jb2x1bW4pXG4gICAqICAgICBwYXJzZUVycm9yLT4+RXJyb3JUeXBlczogbmV3IE5vdEZvdW5kRXJyb3IocmVhc29uKVxuICAgKiAgICAgRXJyb3JUeXBlcy0tPj5DYWxsZXI6IE5vdEZvdW5kRXJyb3JcbiAgICogICBlbHNlIGNvZGUgaXMgNDJQMDcgKGR1cGxpY2F0ZV90YWJsZSlcbiAgICogICAgIHBhcnNlRXJyb3ItPj5FcnJvclR5cGVzOiBuZXcgQ29uZmxpY3RFcnJvcihyZWFzb24pXG4gICAqICAgICBFcnJvclR5cGVzLS0+PkNhbGxlcjogQ29uZmxpY3RFcnJvclxuICAgKiAgIGVsc2UgY29kZSBpcyA0MlAxNiAoaW52YWxpZF90YWJsZV9kZWZpbml0aW9uKVxuICAgKiAgICAgcGFyc2VFcnJvci0+PkVycm9yVHlwZXM6IG5ldyBJbmRleEVycm9yKGVycilcbiAgICogICAgIEVycm9yVHlwZXMtLT4+Q2FsbGVyOiBJbmRleEVycm9yXG4gICAqICAgZWxzZSBjb2RlIG1hdGNoZXMgXCJFQ09OTlJFRlVTRURcIlxuICAgKiAgICAgcGFyc2VFcnJvci0+PkVycm9yVHlwZXM6IG5ldyBDb25uZWN0aW9uRXJyb3IoZXJyKVxuICAgKiAgICAgRXJyb3JUeXBlcy0tPj5DYWxsZXI6IENvbm5lY3Rpb25FcnJvclxuICAgKiAgIGVsc2VcbiAgICogICAgIHBhcnNlRXJyb3ItPj5FcnJvclR5cGVzOiBuZXcgSW50ZXJuYWxFcnJvcihlcnIpXG4gICAqICAgICBFcnJvclR5cGVzLS0+PkNhbGxlcjogSW50ZXJuYWxFcnJvclxuICAgKiAgIGVuZFxuICAgKi9cbiAgcHJvdGVjdGVkIHN0YXRpYyBwYXJzZUVycm9yKGVycjogRXJyb3IgfCBzdHJpbmcsIHJlYXNvbj86IHN0cmluZyk6IEJhc2VFcnJvciB7XG4gICAgaWYgKGVyciBpbnN0YW5jZW9mIEJhc2VFcnJvcikgcmV0dXJuIGVyciBhcyBhbnk7XG4gICAgY29uc3QgY29kZTogc3RyaW5nID0gdHlwZW9mIGVyciA9PT0gXCJzdHJpbmdcIiA/IGVyciA6IGVyci5tZXNzYWdlO1xuXG4gICAgaWYgKGNvZGUubWF0Y2goL2R1cGxpY2F0ZSBrZXl8YWxyZWFkeSBleGlzdHMvZykpXG4gICAgICByZXR1cm4gbmV3IENvbmZsaWN0RXJyb3IoY29kZSk7XG4gICAgaWYgKGNvZGUubWF0Y2goL2RvZXMgbm90IGV4aXN0fG5vdCBmb3VuZC9nKSkgcmV0dXJuIG5ldyBOb3RGb3VuZEVycm9yKGNvZGUpO1xuXG4gICAgLy8gUG9zdGdyZVNRTCBlcnJvciBjb2RlczogaHR0cHM6Ly93d3cucG9zdGdyZXNxbC5vcmcvZG9jcy9jdXJyZW50L2VycmNvZGVzLWFwcGVuZGl4Lmh0bWxcbiAgICBzd2l0Y2ggKGNvZGUudG9TdHJpbmcoKSkge1xuICAgICAgLy8gSW50ZWdyaXR5IGNvbnN0cmFpbnQgdmlvbGF0aW9uc1xuICAgICAgY2FzZSBcIjIzNTA1XCI6IC8vIHVuaXF1ZV92aW9sYXRpb25cbiAgICAgIGNhc2UgXCIyMzUwM1wiOiAvLyBmb3JlaWduX2tleV92aW9sYXRpb25cbiAgICAgIGNhc2UgXCI0MlAwN1wiOiAvLyBkdXBsaWNhdGVfdGFibGVcbiAgICAgICAgcmV0dXJuIG5ldyBDb25mbGljdEVycm9yKHJlYXNvbiBhcyBzdHJpbmcpO1xuXG4gICAgICAvLyBPYmplY3Qgbm90IGZvdW5kIGVycm9yc1xuICAgICAgY2FzZSBcIjQyUDAxXCI6IC8vIHVuZGVmaW5lZF90YWJsZVxuICAgICAgY2FzZSBcIjQyNzAzXCI6IC8vIHVuZGVmaW5lZF9jb2x1bW5cbiAgICAgICAgcmV0dXJuIG5ldyBOb3RGb3VuZEVycm9yKHJlYXNvbiBhcyBzdHJpbmcpO1xuXG4gICAgICAvLyBJbnZhbGlkIG9iamVjdCBkZWZpbml0aW9uXG4gICAgICBjYXNlIFwiNDJQMTZcIjogLy8gaW52YWxpZF90YWJsZV9kZWZpbml0aW9uXG4gICAgICAgIHJldHVybiBuZXcgSW5kZXhFcnJvcihlcnIpO1xuXG4gICAgICAvLyBDb25uZWN0aW9uIGVycm9yc1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGNvZGUudG9TdHJpbmcoKS5tYXRjaCgvRUNPTk5SRUZVU0VEL2cpKVxuICAgICAgICAgIHJldHVybiBuZXcgQ29ubmVjdGlvbkVycm9yKGVycik7XG4gICAgICAgIHJldHVybiBuZXcgSW50ZXJuYWxFcnJvcihlcnIpO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBhc3luYyBjb25uZWN0KGNvbmZpZzogRGF0YVNvdXJjZU9wdGlvbnMpOiBQcm9taXNlPERhdGFTb3VyY2U+IHtcbiAgICBjb25zdCBjb24gPSBuZXcgRGF0YVNvdXJjZShjb25maWcpO1xuICAgIGlmICghY29uLmlzSW5pdGlhbGl6ZWQpIGF3YWl0IGNvbi5pbml0aWFsaXplKCk7XG4gICAgcmV0dXJuIGNvbjtcbiAgfVxuXG4gIHN0YXRpYyBhc3luYyBjcmVhdGVEYXRhYmFzZShcbiAgICBkYXRhU291cmNlOiBEYXRhU291cmNlLFxuICAgIGRiTmFtZTogc3RyaW5nXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGxvZyA9IExvZ2dpbmcuZm9yKHRoaXMuY3JlYXRlRGF0YWJhc2UpO1xuICAgIGxvZy52ZXJib3NlKGBDcmVhdGluZyBkYXRhYmFzZSAke2RiTmFtZX1gKTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgZGF0YVNvdXJjZS5xdWVyeShgQ1JFQVRFIERBVEFCQVNFICR7ZGJOYW1lfWApO1xuICAgICAgbG9nLmluZm8oYENyZWF0ZWQgZGF0YWJhc2UgJHtkYk5hbWV9YCk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUgYXMgRXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBhc3luYyBjcmVhdGVOb3RpZnlGdW5jdGlvbihcbiAgICBkYXRhU291cmNlOiBEYXRhU291cmNlLFxuICAgIHVzZXI6IHN0cmluZ1xuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBsb2cgPSBMb2dnaW5nLmZvcih0aGlzLmNyZWF0ZU5vdGlmeUZ1bmN0aW9uKTtcbiAgICBsb2cudmVyYm9zZShgQ3JlYXRpbmcgbm90aWZ5IGZ1bmN0aW9uYCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGRhdGFTb3VyY2UucXVlcnkoXG4gICAgICAgIGBDUkVBVEUgT1IgUkVQTEFDRSBGVU5DVElPTiBub3RpZnlfdGFibGVfY2hhbmdlcygpXG5SRVRVUk5TIHRyaWdnZXIgQVMgJCRcbkJFR0lOXG4gICAgUEVSRk9STSBwZ19ub3RpZnkoXG4gICAgICAgICd0YWJsZV9jaGFuZ2VzJyxcbiAgICAgICAganNvbl9idWlsZF9vYmplY3QoXG4gICAgICAgICAgICAndGFibGUnLCBUR19UQUJMRV9OQU1FLFxuICAgICAgICAgICAgJ2FjdGlvbicsIFRHX09QLFxuICAgICAgICAgICAgJ2RhdGEnLCByb3dfdG9fanNvbihORVcpLFxuICAgICAgICAgICAgJ29sZF9kYXRhJywgcm93X3RvX2pzb24oT0xEKVxuICAgICAgICApOjp0ZXh0XG4gICAgKTtcbiAgICBSRVRVUk4gTkVXO1xuRU5EO1xuJCQgTEFOR1VBR0UgcGxwZ3NxbCBTRUNVUklUWSBERUZJTkVSXG47YFxuICAgICAgKTtcbiAgICAgIGF3YWl0IGRhdGFTb3VyY2UucXVlcnkoXG4gICAgICAgIGBBTFRFUiBGVU5DVElPTiBub3RpZnlfdGFibGVfY2hhbmdlcygpIE9XTkVSIFRPICR7dXNlcn07YFxuICAgICAgKTtcbiAgICAgIGF3YWl0IGRhdGFTb3VyY2UucXVlcnkoYFxuICAgICAgICAgICAgR1JBTlQgRVhFQ1VURSBPTiBGVU5DVElPTiBub3RpZnlfdGFibGVfY2hhbmdlcygpIFRPIHB1YmxpYztcbiAgICAgICAgYCk7XG4gICAgICBsb2cuaW5mbyhgQ3JlYXRlZCBub3RpZnkgZnVuY3Rpb25gKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGFzeW5jIGRlbGV0ZURhdGFiYXNlKFxuICAgIGRhdGFTb3VyY2U6IERhdGFTb3VyY2UsXG4gICAgZGJOYW1lOiBzdHJpbmcsXG4gICAgdXNlcj86IHN0cmluZ1xuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgaWYgKHVzZXIpIGF3YWl0IGRhdGFTb3VyY2UucXVlcnkoYERST1AgT1dORUQgQlkgJHt1c2VyfSBDQVNDQURFO2ApO1xuICAgICAgYXdhaXQgZGF0YVNvdXJjZS5xdWVyeShgRFJPUCBEQVRBQkFTRSAke2RiTmFtZX1gKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGFzeW5jIGNyZWF0ZVVzZXIoXG4gICAgZGF0YVNvdXJjZTogRGF0YVNvdXJjZSxcbiAgICBkYk5hbWU6IHN0cmluZyxcbiAgICB1c2VyOiBzdHJpbmcsXG4gICAgcGFzc3dvcmQ6IHN0cmluZ1xuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgZGF0YVNvdXJjZS5xdWVyeShgQ1JFQVRFIFVTRVIgJHt1c2VyfSBXSVRIIFBBU1NXT1JEICcke3Bhc3N3b3JkfSdgKTtcbiAgICAgIGF3YWl0IGRhdGFTb3VyY2UucXVlcnkoYEdSQU5UIENPTk5FQ1QgT04gREFUQUJBU0UgJHtkYk5hbWV9IFRPICR7dXNlcn1gKTtcblxuICAgICAgYXdhaXQgZGF0YVNvdXJjZS5xdWVyeShgR1JBTlQgVVNBR0UgT04gU0NIRU1BIHB1YmxpYyBUTyAke3VzZXJ9YCk7XG4gICAgICBhd2FpdCBkYXRhU291cmNlLnF1ZXJ5KGBHUkFOVCBDUkVBVEUgT04gU0NIRU1BIHB1YmxpYyBUTyAke3VzZXJ9YCk7XG4gICAgICBhd2FpdCBkYXRhU291cmNlLnF1ZXJ5KFxuICAgICAgICBgR1JBTlQgQUxMIFBSSVZJTEVHRVMgT04gQUxMIFRBQkxFUyBJTiBTQ0hFTUEgcHVibGljIFRPICR7dXNlcn1gXG4gICAgICApO1xuICAgICAgYXdhaXQgZGF0YVNvdXJjZS5xdWVyeShcbiAgICAgICAgYEdSQU5UIEFMTCBQUklWSUxFR0VTIE9OIEFMTCBTRVFVRU5DRVMgSU4gU0NIRU1BIHB1YmxpYyBUTyAke3VzZXJ9YFxuICAgICAgKTtcbiAgICAgIGF3YWl0IGRhdGFTb3VyY2UucXVlcnkoXG4gICAgICAgIGBHUkFOVCBBTEwgUFJJVklMRUdFUyBPTiBBTEwgRlVOQ1RJT05TIElOIFNDSEVNQSBwdWJsaWMgVE8gJHt1c2VyfWBcbiAgICAgICk7XG4gICAgICBhd2FpdCBkYXRhU291cmNlLnF1ZXJ5KFxuICAgICAgICBgQUxURVIgREVGQVVMVCBQUklWSUxFR0VTIElOIFNDSEVNQSBwdWJsaWMgR1JBTlQgQUxMIFBSSVZJTEVHRVMgT04gVEFCTEVTIFRPICR7dXNlcn1gXG4gICAgICApO1xuICAgICAgYXdhaXQgZGF0YVNvdXJjZS5xdWVyeShcbiAgICAgICAgYEFMVEVSIERFRkFVTFQgUFJJVklMRUdFUyBJTiBTQ0hFTUEgcHVibGljIEdSQU5UIEFMTCBQUklWSUxFR0VTIE9OIFNFUVVFTkNFUyBUTyAke3VzZXJ9YFxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGFzeW5jIGRlbGV0ZVVzZXIoXG4gICAgY2xpZW50OiBEYXRhU291cmNlLFxuICAgIHVzZXI6IHN0cmluZyxcbiAgICBhZG1pbjogc3RyaW5nXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBjbGllbnQucXVlcnkoYFJFQVNTSUdOIE9XTkVEIEJZICR7dXNlcn0gVE8gJHthZG1pbn1gKTtcbiAgICAgIGF3YWl0IGNsaWVudC5xdWVyeShcbiAgICAgICAgYFJFVk9LRSBBTEwgT04gQUxMIFRBQkxFUyBJTiBTQ0hFTUEgcHVibGljIEZST00gJHt1c2VyfWBcbiAgICAgICk7XG4gICAgICBhd2FpdCBjbGllbnQucXVlcnkoYFJFVk9LRSBBTEwgT04gU0NIRU1BIHB1YmxpYyBGUk9NICR7dXNlcn1gKTtcbiAgICAgIGF3YWl0IGNsaWVudC5xdWVyeShcbiAgICAgICAgYFJFVk9LRSBBTEwgUFJJVklMRUdFUyBPTiBBTEwgU0VRVUVOQ0VTIElOIFNDSEVNQSBwdWJsaWMgRlJPTSAke3VzZXJ9YFxuICAgICAgKTtcbiAgICAgIGF3YWl0IGNsaWVudC5xdWVyeShcbiAgICAgICAgYFJFVk9LRSBBTEwgUFJJVklMRUdFUyBPTiBBTEwgRlVOQ1RJT05TIElOIFNDSEVNQSBwdWJsaWMgRlJPTSAke3VzZXJ9YFxuICAgICAgKTtcbiAgICAgIGF3YWl0IGNsaWVudC5xdWVyeShcbiAgICAgICAgYEFMVEVSIERFRkFVTFQgUFJJVklMRUdFUyBGT1IgUk9MRSAke2FkbWlufSBJTiBTQ0hFTUEgcHVibGljIFJFVk9LRSBBTEwgT04gVEFCTEVTIEZST00gJHt1c2VyfWBcbiAgICAgICk7XG4gICAgICBhd2FpdCBjbGllbnQucXVlcnkoXG4gICAgICAgIGBBTFRFUiBERUZBVUxUIFBSSVZJTEVHRVMgRk9SIFJPTEUgJHthZG1pbn0gSU4gU0NIRU1BIHB1YmxpYyBSRVZPS0UgQUxMIE9OIFNFUVVFTkNFUyBGUk9NICR7dXNlcn07YFxuICAgICAgKTtcbiAgICAgIGF3YWl0IGNsaWVudC5xdWVyeShcbiAgICAgICAgYEFMVEVSIERFRkFVTFQgUFJJVklMRUdFUyBGT1IgUk9MRSAke2FkbWlufSBJTiBTQ0hFTUEgcHVibGljIFJFVk9LRSBBTEwgT04gRlVOQ1RJT05TIEZST00gJHt1c2VyfWBcbiAgICAgICk7XG4gICAgICBhd2FpdCBjbGllbnQucXVlcnkoYERST1AgT1dORUQgQlkgJHt1c2VyfSBDQVNDQURFYCk7XG4gICAgICBhd2FpdCBjbGllbnQucXVlcnkoYERST1AgVVNFUiBJRiBFWElTVFMgXCIke3VzZXJ9XCJgKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgcGFyc2VUeXBlVG9Qb3N0Z3JlcyhcbiAgICB0eXBlOiBzdHJpbmcsXG4gICAgaXNQazogYm9vbGVhbixcbiAgICBpc0ZrID0gZmFsc2VcbiAgKSB7XG4gICAgc3dpdGNoICh0eXBlLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgIGNhc2UgXCJzdHJpbmdcIjpcbiAgICAgICAgcmV0dXJuIGlzUGsgPyBcIlRFWFQgUFJJTUFSWSBLRVlcIiA6IGlzRmsgPyBcIlRFWFRcIiA6IFwiVkFSQ0hBUlwiO1xuICAgICAgY2FzZSBcIm51bWJlclwiOlxuICAgICAgICByZXR1cm4gaXNQayA/IFwiU0VSSUFMIFBSSU1BUlkgS0VZXCIgOiBcIklOVEVHRVJcIjtcbiAgICAgIGNhc2UgXCJib29sZWFuXCI6XG4gICAgICAgIHJldHVybiBcIkJPT0xFQU5cIjtcbiAgICAgIGNhc2UgXCJkYXRlXCI6XG4gICAgICAgIHJldHVybiBcIlRJTUVTVEFNUFwiO1xuICAgICAgY2FzZSBcImJpZ2ludFwiOlxuICAgICAgICByZXR1cm4gaXNQayA/IFwiQklHSU5UIFBSSU1BUlkgS0VZXCIgOiBcIkJJR0lOVFwiO1xuICAgICAgZGVmYXVsdDoge1xuICAgICAgICBjb25zdCBtID0gTW9kZWwuZ2V0KHR5cGUpO1xuICAgICAgICBpZiAobSkge1xuICAgICAgICAgIGNvbnN0IG1tID0gbmV3IG0oKTtcbiAgICAgICAgICBjb25zdCB0eXBlID0gUmVmbGVjdGlvbi5nZXRUeXBlRnJvbURlY29yYXRvcihcbiAgICAgICAgICAgIG1tLFxuICAgICAgICAgICAgZmluZFByaW1hcnlLZXkobW0pLmlkXG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbW9kZWw6IG0sXG4gICAgICAgICAgICBwa1R5cGU6IHR5cGUsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgVW5zdXBwb3J0ZWQgdHlwZTogJHt0eXBlfWApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIHBhcnNlVmFsaWRhdGlvblRvUG9zdGdyZXMoXG4gICAgcHJvcDogc3RyaW5nLFxuICAgIHR5cGU6IHN0cmluZyxcbiAgICBpc1BrOiBib29sZWFuLFxuICAgIGtleTogc3RyaW5nLFxuICAgIG9wdGlvbnM6IFZhbGlkYXRvck9wdGlvbnNcbiAgKSB7XG4gICAgc3dpdGNoIChrZXkpIHtcbiAgICAgIGNhc2UgVmFsaWRhdGlvbktleXMuUkVRVUlSRUQ6XG4gICAgICAgIHJldHVybiBcIk5PVCBOVUxMXCI7XG4gICAgICBjYXNlIFZhbGlkYXRpb25LZXlzLk1BWF9MRU5HVEg6XG4gICAgICAgIGlmIChpc1BrIHx8ICFvcHRpb25zIHx8IHR5cGUudG9Mb3dlckNhc2UoKSAhPT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgIHJldHVybiBcIlwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBgKCR7KG9wdGlvbnMgYXMgTWF4TGVuZ3RoVmFsaWRhdG9yT3B0aW9ucylbVmFsaWRhdGlvbktleXMuTUFYX0xFTkdUSF19KWA7XG4gICAgICBjYXNlIFZhbGlkYXRpb25LZXlzLk1JTl9MRU5HVEg6XG4gICAgICAgIHJldHVybiBgQ09OU1RSQUlOVCAke3Byb3B9X21pbl9sZW5ndGhfY2hlY2sgQ0hFQ0sgKExFTkdUSCgke3Byb3B9KSA+PSAkeyhvcHRpb25zIGFzIE1pbkxlbmd0aFZhbGlkYXRvck9wdGlvbnMpW1ZhbGlkYXRpb25LZXlzLk1JTl9MRU5HVEhdfSlgO1xuICAgICAgY2FzZSBWYWxpZGF0aW9uS2V5cy5QQVRURVJOOlxuICAgICAgY2FzZSBWYWxpZGF0aW9uS2V5cy5VUkw6XG4gICAgICBjYXNlIFZhbGlkYXRpb25LZXlzLkVNQUlMOlxuICAgICAgICByZXR1cm4gYENPTlNUUkFJTlQgJHtwcm9wfV9wYXR0ZXJuX2NoZWNrIENIRUNLICgke3Byb3B9IH4gJyR7Y29udmVydEpzUmVnZXhUb1Bvc3RncmVzKChvcHRpb25zIGFzIFBhdHRlcm5WYWxpZGF0b3JPcHRpb25zKVtWYWxpZGF0aW9uS2V5cy5QQVRURVJOXSBhcyBzdHJpbmcpfScpYDtcbiAgICAgIGNhc2UgVmFsaWRhdGlvbktleXMuVFlQRTpcbiAgICAgIGNhc2UgVmFsaWRhdGlvbktleXMuREFURTpcbiAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICBjYXNlIFZhbGlkYXRpb25LZXlzLk1JTjpcbiAgICAgICAgcmV0dXJuIGBDT05TVFJBSU5UICR7cHJvcH1fJHtrZXl9X2NoZWNrIENIRUNLICgke3Byb3B9ID49ICR7KG9wdGlvbnMgYXMgTWluVmFsaWRhdG9yT3B0aW9ucylbVmFsaWRhdGlvbktleXMuTUlOXX0pYDtcbiAgICAgIGNhc2UgVmFsaWRhdGlvbktleXMuTUFYOlxuICAgICAgICByZXR1cm4gYENPTlNUUkFJTlQgJHtwcm9wfV8ke2tleX1fY2hlY2sgQ0hFQ0sgKCR7cHJvcH0gPD0gJHsob3B0aW9ucyBhcyBNYXhWYWxpZGF0b3JPcHRpb25zKVtWYWxpZGF0aW9uS2V5cy5NQVhdfSlgO1xuICAgICAgY2FzZSBWYWxpZGF0aW9uS2V5cy5QQVNTV09SRDpcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGBVbnN1cHBvcnRlZCB0eXBlOiAke2tleX1gKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBwYXJzZVJlbGF0aW9uc1RvUG9zdGdyZXMoXG4gICAgcHJvcDogc3RyaW5nLFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNb2RlbD4sXG4gICAgcGs6IHN0cmluZyxcbiAgICBrZXk6IFBlcnNpc3RlbmNlS2V5cyxcbiAgICBvcHRpb25zOiBSZWxhdGlvbnNNZXRhZGF0YVxuICApIHtcbiAgICBjb25zdCB0YWJsZU5hbWUgPSBSZXBvc2l0b3J5LnRhYmxlKGNsYXp6KTtcbiAgICBjb25zdCB7IGNhc2NhZGUgfSA9IG9wdGlvbnM7XG4gICAgY29uc3QgY2FzY2FkZVN0ciA9IGAke2Nhc2NhZGUudXBkYXRlID8gXCIgT04gVVBEQVRFIENBU0NBREVcIiA6IFwiXCJ9JHtjYXNjYWRlLmRlbGV0ZSA/IFwiIE9OIERFTEVURSBDQVNDQURFXCIgOiBcIlwifWA7XG4gICAgc3dpdGNoIChgcmVsYXRpb25zJHtrZXl9YCkge1xuICAgICAgY2FzZSBQZXJzaXN0ZW5jZUtleXMuT05FX1RPX09ORTpcbiAgICAgICAgcmV0dXJuIGBGT1JFSUdOIEtFWSAoJHtwcm9wfSkgUkVGRVJFTkNFUyAke3RhYmxlTmFtZX0oJHtwa30pJHtjYXNjYWRlU3RyfWA7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgVW5zdXBwb3J0ZWQgb3BlcmF0aW9uOiAke2tleX1gKTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgYXN5bmMgY3JlYXRlVGFibGU8TSBleHRlbmRzIE1vZGVsPihcbiAgICBjbGllbnQ6IERhdGFTb3VyY2UsXG4gICAgbW9kZWw6IENvbnN0cnVjdG9yPE0+XG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgVHlwZU9STVRhYmxlU3BlYz4+IHtcbiAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIFR5cGVPUk1UYWJsZVNwZWM+ID0ge307XG4gICAgY29uc3QgbSA9IG5ldyBtb2RlbCh7fSk7XG4gICAgY29uc3QgdGFibGVOYW1lID0gUmVwb3NpdG9yeS50YWJsZShtb2RlbCk7XG4gICAgY29uc3QgeyBpZCB9ID0gZmluZFByaW1hcnlLZXkobSk7XG5cbiAgICBsZXQgaXNQazogYm9vbGVhbiwgY29sdW1uOiBzdHJpbmc7XG4gICAgY29uc3QgcHJvcGVydGllcyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKG0pIGFzIChrZXlvZiBNKVtdO1xuICAgIGZvciAoY29uc3QgcHJvcCBvZiBwcm9wZXJ0aWVzKSB7XG4gICAgICBpZiAoXG4gICAgICAgIHR5cGVvZiAodGhpcyBhcyBhbnkpW3Byb3BdID09PSBcImZ1bmN0aW9uXCIgfHxcbiAgICAgICAgcHJvcC50b1N0cmluZygpLnN0YXJ0c1dpdGgoXCJfXCIpIHx8XG4gICAgICAgIHByb3AgPT09IFwiY29uc3RydWN0b3JcIlxuICAgICAgKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpc1BrID0gcHJvcCA9PT0gaWQ7XG4gICAgICBjb2x1bW4gPSBSZXBvc2l0b3J5LmNvbHVtbihtLCBwcm9wLnRvU3RyaW5nKCkpO1xuXG4gICAgICBjb25zdCBhbGxEZWNzID0gUmVmbGVjdGlvbi5nZXRQcm9wZXJ0eURlY29yYXRvcnMoXG4gICAgICAgIFZhbGlkYXRpb25LZXlzLlJFRkxFQ1QsXG4gICAgICAgIG0sXG4gICAgICAgIHByb3AudG9TdHJpbmcoKSxcbiAgICAgICAgZmFsc2UsXG4gICAgICAgIHRydWVcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IGRlY29yYXRvckRhdGEgPSBhbGxEZWNzLmRlY29yYXRvcnMucmVkdWNlKFxuICAgICAgICAoYWNjdW06IFJlY29yZDxzdHJpbmcsIGFueT4sIGVsKSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBrZXksIHByb3BzIH0gPSBlbDtcbiAgICAgICAgICBpZiAoa2V5ID09PSBNb2RlbEtleXMuVFlQRSAmJiAhYWNjdW1bVmFsaWRhdGlvbktleXMuVFlQRV0pIHtcbiAgICAgICAgICAgIGFjY3VtW1ZhbGlkYXRpb25LZXlzLlRZUEVdID0ge1xuICAgICAgICAgICAgICBjdXN0b21UeXBlczogW3Byb3BzLm5hbWUgYXMgc3RyaW5nXSxcbiAgICAgICAgICAgICAgbWVzc2FnZTogREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5UWVBFLFxuICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogXCJkZWZpbmVzIHRoZSBhY2NlcHRlZCB0eXBlcyBmb3IgdGhlIGF0dHJpYnV0ZVwiLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGtleSAhPT0gVmFsaWRhdGlvbktleXMuVFlQRSkge1xuICAgICAgICAgICAgLy8gZG8gbm90aGluZy4gd2UgY2FuIG9ubHkgc3VwcG9ydCBiYXNpcyBjdHlwZXMgYXQgdGhpcyB0aW1lXG4gICAgICAgICAgICBhY2N1bVtrZXldID0gcHJvcHM7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBhY2N1bTtcbiAgICAgICAgfSxcbiAgICAgICAge31cbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IGRiRGVjcyA9IFJlZmxlY3Rpb24uZ2V0UHJvcGVydHlEZWNvcmF0b3JzKFxuICAgICAgICBSZXBvc2l0b3J5LmtleShcInJlbGF0aW9uc1wiKSxcbiAgICAgICAgbSxcbiAgICAgICAgcHJvcC50b1N0cmluZygpLFxuICAgICAgICB0cnVlLFxuICAgICAgICB0cnVlXG4gICAgICApO1xuXG4gICAgICBjb25zdCBxdWVyeTogc3RyaW5nW10gPSBbXTtcbiAgICAgIGNvbnN0IGNvbnN0cmFpbnRzOiBzdHJpbmdbXSA9IFtdO1xuICAgICAgY29uc3QgZm9yZWlnbktleXM6IHN0cmluZ1tdID0gW107XG4gICAgICBsZXQgdHlwZURhdGE6IFR5cGVNZXRhZGF0YSB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgICAgIGxldCBjaGlsZENsYXNzOiBDb25zdHJ1Y3RvcjxNb2RlbD4gfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gICAgICBsZXQgY2hpbGRQazogYW55O1xuXG4gICAgICBpZiAoT2JqZWN0LmtleXMoZGVjb3JhdG9yRGF0YSkubGVuZ3RoKSB7XG4gICAgICAgIHR5cGVEYXRhID0gZGVjb3JhdG9yRGF0YVtWYWxpZGF0aW9uS2V5cy5UWVBFXSBhcyBUeXBlTWV0YWRhdGE7XG5cbiAgICAgICAgaWYgKCF0eXBlRGF0YSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgTWlzc2luZyB0eXBlIGluZm9ybWF0aW9uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcGFyc2VkVHlwZTpcbiAgICAgICAgICB8IHN0cmluZ1xuICAgICAgICAgIHwgeyBtb2RlbDogQ29uc3RydWN0b3I8TW9kZWw+IHwgc3RyaW5nOyBwa1R5cGU/OiBzdHJpbmcgfSA9XG4gICAgICAgICAgdGhpcy5wYXJzZVR5cGVUb1Bvc3RncmVzKFxuICAgICAgICAgICAgdHlwZW9mICh0eXBlRGF0YS5jdXN0b21UeXBlcyBhcyBhbnlbXSlbMF0gPT09IFwiZnVuY3Rpb25cIlxuICAgICAgICAgICAgICA/ICh0eXBlRGF0YS5jdXN0b21UeXBlcyBhcyBhbnkpWzBdKClcbiAgICAgICAgICAgICAgOiAodHlwZURhdGEuY3VzdG9tVHlwZXMgYXMgYW55KVswXSxcbiAgICAgICAgICAgIGlzUGtcbiAgICAgICAgICApO1xuICAgICAgICBpZiAodHlwZW9mIHBhcnNlZFR5cGUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICBwYXJzZWRUeXBlID0geyBtb2RlbDogcGFyc2VkVHlwZSB9O1xuICAgICAgICB9XG4gICAgICAgIGxldCB0eXBlU3RyOlxuICAgICAgICAgIHwgc3RyaW5nXG4gICAgICAgICAgfCB7IG1vZGVsOiBDb25zdHJ1Y3RvcjxNb2RlbD4gfCBzdHJpbmc7IHBrVHlwZT86IHN0cmluZyB9ID1cbiAgICAgICAgICBwYXJzZWRUeXBlLm1vZGVsIGFzXG4gICAgICAgICAgICB8IHN0cmluZ1xuICAgICAgICAgICAgfCB7IG1vZGVsOiBDb25zdHJ1Y3RvcjxNb2RlbD4gfCBzdHJpbmc7IHBrVHlwZT86IHN0cmluZyB9O1xuXG4gICAgICAgIGlmICh0eXBlb2YgdHlwZVN0ciAhPT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHR5cGVTdHIpKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyh0eXBlU3RyKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBjb250aW51ZTtcbiAgICAgICAgICAvLyBjb25zdCByZXM6IFJlY29yZDxzdHJpbmcsIFBvc3RncmVzVGFibGVTcGVjPiA9IGF3YWl0IHRoaXMuY3JlYXRlVGFibGUocG9vbCwgdHlwZVN0cik7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNoaWxkQ2xhc3MgPSBwYXJzZWRUeXBlLm1vZGVsIGFzIENvbnN0cnVjdG9yPE1vZGVsPjtcbiAgICAgICAgICAgIGNvbnN0IG0gPSBuZXcgY2hpbGRDbGFzcygpO1xuICAgICAgICAgICAgY2hpbGRQayA9IGZpbmRQcmltYXJ5S2V5KG0pO1xuICAgICAgICAgICAgdHlwZVN0ciA9IHRoaXMucGFyc2VUeXBlVG9Qb3N0Z3JlcyhcbiAgICAgICAgICAgICAgcGFyc2VkVHlwZS5wa1R5cGUgYXMgc3RyaW5nLFxuICAgICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgICAgdHJ1ZVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY3JlYXRlVGFibGUoY2xpZW50LCBjaGlsZENsYXNzKTtcbiAgICAgICAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgQ29uZmxpY3RFcnJvcikpIHRocm93IGU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHRwID0gQXJyYXkuaXNBcnJheSh0eXBlRGF0YS5jdXN0b21UeXBlcylcbiAgICAgICAgICA/IHR5cGVEYXRhLmN1c3RvbVR5cGVzWzBdXG4gICAgICAgICAgOiB0eXBlRGF0YS5jdXN0b21UeXBlcztcbiAgICAgICAgdHAgPSB0eXBlb2YgdHAgPT09IFwiZnVuY3Rpb25cIiAmJiAhdHAubmFtZSA/IHRwKCkgOiB0cDtcbiAgICAgICAgY29uc3QgdmFsaWRhdGlvblN0ciA9IHRoaXMucGFyc2VWYWxpZGF0aW9uVG9Qb3N0Z3JlcyhcbiAgICAgICAgICBjb2x1bW4sXG4gICAgICAgICAgdHAgYXMgYW55LFxuICAgICAgICAgIGlzUGssXG4gICAgICAgICAgVmFsaWRhdGlvbktleXMuTUFYX0xFTkdUSCxcbiAgICAgICAgICAoZGVjb3JhdG9yRGF0YVtcbiAgICAgICAgICAgIFZhbGlkYXRpb25LZXlzLk1BWF9MRU5HVEhcbiAgICAgICAgICBdIGFzIE1heExlbmd0aFZhbGlkYXRvck9wdGlvbnMpIHx8IHtcbiAgICAgICAgICAgIFtWYWxpZGF0aW9uS2V5cy5NQVhfTEVOR1RIXTogMjU1LFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBxID0gYCR7Y29sdW1ufSAke3R5cGVTdHJ9JHt2YWxpZGF0aW9uU3RyfWA7XG5cbiAgICAgICAgaWYgKGlzUGspIHtcbiAgICAgICAgICBxdWVyeS51bnNoaWZ0KHEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHF1ZXJ5LnB1c2gocSk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGNvbnN0IFtrZXksIHByb3BzXSBvZiBPYmplY3QuZW50cmllcyhkZWNvcmF0b3JEYXRhKS5maWx0ZXIoXG4gICAgICAgICAgKFtrXSkgPT5cbiAgICAgICAgICAgICFbVmFsaWRhdGlvbktleXMuVFlQRSwgVmFsaWRhdGlvbktleXMuTUFYX0xFTkdUSF0uaW5jbHVkZXMoayBhcyBhbnkpXG4gICAgICAgICkpIHtcbiAgICAgICAgICBjb25zdCB2YWxpZGF0aW9uID0gdGhpcy5wYXJzZVZhbGlkYXRpb25Ub1Bvc3RncmVzKFxuICAgICAgICAgICAgY29sdW1uLFxuICAgICAgICAgICAgdHAgYXMgYW55LFxuICAgICAgICAgICAgaXNQayxcbiAgICAgICAgICAgIGtleSxcbiAgICAgICAgICAgIHByb3BzXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAodmFsaWRhdGlvbi5zdGFydHNXaXRoKFwiQ09OU1RSQUlOVFwiKSkge1xuICAgICAgICAgICAgY29uc3RyYWludHMucHVzaCh2YWxpZGF0aW9uKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHZhbGlkYXRpb24pIHtcbiAgICAgICAgICAgICAgcXVlcnkucHVzaCh2YWxpZGF0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gVE9ETyBpZ25vcmUgZm9yIG5vdy4gdGhpcyBsZWF2ZXMgZm9yZWlnbiBrZXlzIG91dFxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnN0YW50LWJpbmFyeS1leHByZXNzaW9uXG4gICAgICBpZiAoZmFsc2UgfHwgKGRiRGVjcyAmJiBkYkRlY3MuZGVjb3JhdG9ycy5sZW5ndGgpKSB7XG4gICAgICAgIGlmICghdHlwZURhdGEpIHRocm93IG5ldyBFcnJvcihgTWlzc2luZyB0eXBlIGluZm9ybWF0aW9uYCk7XG4gICAgICAgIGZvciAoY29uc3QgZGVjb3JhdG9yIG9mIGRiRGVjcy5kZWNvcmF0b3JzKSB7XG4gICAgICAgICAgY29uc3QgeyBrZXksIHByb3BzIH0gPSBkZWNvcmF0b3I7XG4gICAgICAgICAgY29uc3QgdmFsaWRhdGlvbiA9IHRoaXMucGFyc2VSZWxhdGlvbnNUb1Bvc3RncmVzKFxuICAgICAgICAgICAgY29sdW1uLFxuICAgICAgICAgICAgY2hpbGRDbGFzcyBhcyBDb25zdHJ1Y3RvcjxNb2RlbD4sXG4gICAgICAgICAgICBjaGlsZFBrLmlkLFxuICAgICAgICAgICAga2V5IGFzIFBlcnNpc3RlbmNlS2V5cyxcbiAgICAgICAgICAgIHByb3BzIGFzIHVua25vd24gYXMgUmVsYXRpb25zTWV0YWRhdGFcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmICh2YWxpZGF0aW9uLnN0YXJ0c1dpdGgoXCJGT1JFSUdOXCIpKSB7XG4gICAgICAgICAgICBmb3JlaWduS2V5cy5wdXNoKHZhbGlkYXRpb24pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgVW5zdXBwb3J0ZWQgcmVsYXRpb246ICR7a2V5fWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXN1bHRbcHJvcC50b1N0cmluZygpXSA9IHtcbiAgICAgICAgcXVlcnk6IHF1ZXJ5LmpvaW4oXCIgXCIpLFxuICAgICAgICB2YWx1ZXM6IFtdLFxuICAgICAgICBwcmltYXJ5S2V5OiBpc1BrLFxuICAgICAgICBjb25zdHJhaW50czogY29uc3RyYWludHMsXG4gICAgICAgIGZvcmVpZ25LZXlzOiBmb3JlaWduS2V5cyxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgdmFsdWVzID0gT2JqZWN0LnZhbHVlcyhyZXN1bHQpO1xuICAgIGNvbnN0IHF1ZXJ5ID0gdmFsdWVzLm1hcCgocikgPT4gci5xdWVyeSkuam9pbihcIixcXG5cIik7XG4gICAgY29uc3QgY29uc3RyYWludHMgPSB2YWx1ZXNcbiAgICAgIC5maWx0ZXIoKGMpID0+ICEhYy5jb25zdHJhaW50cy5sZW5ndGgpXG4gICAgICAubWFwKChyKSA9PiByLmNvbnN0cmFpbnRzKVxuICAgICAgLmpvaW4oXCIsXFxuXCIpO1xuICAgIGNvbnN0IGZvcmVpZ25LZXlzID0gdmFsdWVzXG4gICAgICAuZmlsdGVyKChjKSA9PiAhIWMuZm9yZWlnbktleXMubGVuZ3RoKVxuICAgICAgLm1hcCgocikgPT4gci5mb3JlaWduS2V5cylcbiAgICAgIC5qb2luKFwiLFxcblwiKTtcbiAgICBjb25zdCB2YWxzID0gW3F1ZXJ5LCBjb25zdHJhaW50c107XG4gICAgaWYgKGZvcmVpZ25LZXlzKSB7XG4gICAgICB2YWxzLnB1c2goZm9yZWlnbktleXMpO1xuICAgIH1cbiAgICBjb25zdCBxdWVyeVN0cmluZyA9IGBDUkVBVEUgVEFCTEUgJHt0YWJsZU5hbWV9ICgke3ZhbHMuZmlsdGVyKCh2KSA9PiAhIXYpLmpvaW4oXCIsXFxuXCIpfSlgO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBjbGllbnQucXVlcnkocXVlcnlTdHJpbmcpO1xuICAgICAgYXdhaXQgY2xpZW50LnF1ZXJ5KFxuICAgICAgICBgQ1JFQVRFIFRSSUdHRVIgbm90aWZ5X2NoYW5nZXNfJHt0YWJsZU5hbWV9XG5BRlRFUiBJTlNFUlQgT1IgVVBEQVRFIE9SIERFTEVURSBPTiAke3RhYmxlTmFtZX1cbiAgICBGT1IgRUFDSCBST1dcbiAgICBFWEVDVVRFIEZVTkNUSU9OIG5vdGlmeV90YWJsZV9jaGFuZ2VzKCk7YFxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBzdGF0aWMgYXN5bmMgZ2V0Q3VycmVudFVzZXIoY2xpZW50OiBEYXRhU291cmNlKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBxdWVyeVN0cmluZyA9IGBTRUxFQ1QgQ1VSUkVOVF9VU0VSO2A7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNsaWVudC5xdWVyeShxdWVyeVN0cmluZyk7XG4gICAgICByZXR1cm4gcmVzdWx0WzBdLmN1cnJlbnRfdXNlcjtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGRlY29yYXRpb24oKSB7XG4gICAgLy8gQHRhYmxlKCkgPT4gQEVudGl0eSgpXG4gICAgY29uc3QgdGFibGVLZXkgPSBBZGFwdGVyLmtleShQZXJzaXN0ZW5jZUtleXMuVEFCTEUpO1xuICAgIERlY29yYXRpb24uZmxhdm91cmVkQXMoVHlwZU9STUZsYXZvdXIpXG4gICAgICAuZm9yKHRhYmxlS2V5KVxuICAgICAgLmV4dGVuZCgob3JpZ2luYWw6IGFueSkgPT5cbiAgICAgICAgRW50aXR5KCkob3JpZ2luYWxbTW9kZWxLZXlzLkFOQ0hPUl0gfHwgb3JpZ2luYWwpXG4gICAgICApXG4gICAgICAuYXBwbHkoKTtcblxuICAgIC8vIEBwaygpID0+IEBQcmltYXJ5R2VuZXJhdGVkQ29sdW1uKCkgfCBAUHJpbWFyeUNvbHVtbigpXG4gICAgY29uc3QgcGtLZXkgPSBSZXBvc2l0b3J5LmtleShEQktleXMuSUQpO1xuXG4gICAgZnVuY3Rpb24gcGtEZWMob3B0aW9uczogU2VxdWVuY2VPcHRpb25zKSB7XG4gICAgICBjb25zdCBkZWNvcmF0b3JzOiBhbnlbXSA9IFtcbiAgICAgICAgcmVxdWlyZWQoKSxcbiAgICAgICAgcmVhZG9ubHkoKSxcbiAgICAgICAgcHJvcE1ldGFkYXRhKHBrS2V5LCBvcHRpb25zKSxcbiAgICAgIF07XG4gICAgICBpZiAob3B0aW9ucy50eXBlKSBkZWNvcmF0b3JzLnB1c2goUHJpbWFyeUdlbmVyYXRlZENvbHVtbigpKTtcbiAgICAgIGVsc2UgZGVjb3JhdG9ycy5wdXNoKFByaW1hcnlDb2x1bW4oeyB1bmlxdWU6IHRydWUgfSkpO1xuICAgICAgcmV0dXJuIGFwcGx5KC4uLmRlY29yYXRvcnMpO1xuICAgIH1cblxuICAgIERlY29yYXRpb24uZmxhdm91cmVkQXMoVHlwZU9STUZsYXZvdXIpXG4gICAgICAuZm9yKHBrS2V5KVxuICAgICAgLmRlZmluZSh7XG4gICAgICAgIGRlY29yYXRvcjogcGtEZWMsXG4gICAgICB9KVxuICAgICAgLmFwcGx5KCk7XG5cbiAgICAvLyBAY29sdW1uKFwiY29sdW1uTmFtZVwiKSA9PiBAQ29sdW1uKHtuYW1lOiBcImNvbHVtbk5hbWVcIn0pXG4gICAgY29uc3QgY29sdW1uS2V5ID0gQWRhcHRlci5rZXkoUGVyc2lzdGVuY2VLZXlzLkNPTFVNTik7XG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyZWRBcyhUeXBlT1JNRmxhdm91cilcbiAgICAgIC5mb3IoY29sdW1uS2V5KVxuICAgICAgLmV4dGVuZCh7XG4gICAgICAgIGRlY29yYXRvcjogZnVuY3Rpb24gY29sdW1tKG5hbWU6IHN0cmluZykge1xuICAgICAgICAgIHJldHVybiBmdW5jdGlvbiBjb2x1bW4ob2JqOiBhbnksIHByb3A6IGFueSkge1xuICAgICAgICAgICAgcmV0dXJuIENvbHVtbih7XG4gICAgICAgICAgICAgIG5hbWU6IG5hbWUgfHwgcHJvcCxcbiAgICAgICAgICAgICAgbnVsbGFibGU6IHRydWUsXG4gICAgICAgICAgICB9KShvYmosIHByb3ApO1xuICAgICAgICAgIH07XG4gICAgICAgIH0sXG4gICAgICAgIHRyYW5zZm9ybTogKGFyZ3M6IGFueVtdKSA9PiB7XG4gICAgICAgICAgY29uc3QgY29sdW1uTmFtZSA9IGFyZ3NbMV07XG4gICAgICAgICAgcmV0dXJuIFtjb2x1bW5OYW1lXTtcbiAgICAgICAgfSxcbiAgICAgIH0pXG4gICAgICAuYXBwbHkoKTtcblxuICAgIC8vIEB1bmlxdWUgPT4gQENvbHVtbih7dW5pcXVlOiB0cnVlfSlcbiAgICBjb25zdCB1bmlxdWVLZXkgPSBBZGFwdGVyLmtleShQZXJzaXN0ZW5jZUtleXMuVU5JUVVFKTtcbiAgICBEZWNvcmF0aW9uLmZsYXZvdXJlZEFzKFR5cGVPUk1GbGF2b3VyKVxuICAgICAgLmZvcih1bmlxdWVLZXkpXG4gICAgICAuZGVmaW5lKHByb3BNZXRhZGF0YSh1bmlxdWVLZXksIHt9KSlcbiAgICAgIC5leHRlbmQoQ29sdW1uKHsgdW5pcXVlOiB0cnVlIH0pKVxuICAgICAgLmFwcGx5KCk7XG5cbiAgICAvLyBAcmVxdWlyZWQgPT4gQENvbHVtbih7IG51bGxhYmxlOiBmYWxzZSB9KVxuICAgIGNvbnN0IHJlcXVpcmVkS2V5ID0gVmFsaWRhdGlvbi5rZXkoVmFsaWRhdGlvbktleXMuUkVRVUlSRUQpO1xuICAgIERlY29yYXRpb24uZmxhdm91cmVkQXMoVHlwZU9STUZsYXZvdXIpXG4gICAgICAuZm9yKHJlcXVpcmVkS2V5KVxuICAgICAgLmV4dGVuZChDb2x1bW4oeyBudWxsYWJsZTogZmFsc2UgfSkpXG4gICAgICAuYXBwbHkoKTtcblxuICAgIC8vIEB2ZXJzaW9uID0+IEBWZXJzaW9uQ29sdW1uKClcbiAgICBjb25zdCB2ZXJzaW9uS2V5ID0gUmVwb3NpdG9yeS5rZXkoREJLZXlzLlZFUlNJT04pO1xuICAgIERlY29yYXRpb24uZmxhdm91cmVkQXMoVHlwZU9STUZsYXZvdXIpXG4gICAgICAuZm9yKHZlcnNpb25LZXkpXG4gICAgICAuZGVmaW5lKHR5cGUoTnVtYmVyLm5hbWUpLCBWZXJzaW9uQ29sdW1uKCkpXG4gICAgICAuYXBwbHkoKTtcblxuICAgIGZ1bmN0aW9uIFZhbGlkYXRpb25VcGRhdGVLZXkoa2V5OiBzdHJpbmcpIHtcbiAgICAgIHJldHVybiBVcGRhdGVWYWxpZGF0aW9uS2V5cy5SRUZMRUNUICsga2V5O1xuICAgIH1cblxuICAgIC8vIEB0aW1lc3RhbXAob3ApID0+IEBDcmVhdGVEYXRlQ29sdW1uKCkgfHwgQFVwZGF0ZURhdGVDb2x1bW4oKVxuICAgIGNvbnN0IHRpbWVzdGFtcEtleSA9IFZhbGlkYXRpb25VcGRhdGVLZXkoREJLZXlzLlRJTUVTVEFNUCk7XG5cbiAgICBmdW5jdGlvbiB0cyhvcGVyYXRpb246IE9wZXJhdGlvbktleXNbXSwgZm9ybWF0OiBzdHJpbmcpIHtcbiAgICAgIGNvbnN0IGRlY29yYXRvcnM6IGFueVtdID0gW1xuICAgICAgICBkYXRlKGZvcm1hdCwgREJfREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5USU1FU1RBTVAuREFURSksXG4gICAgICAgIHJlcXVpcmVkKERCX0RFRkFVTFRfRVJST1JfTUVTU0FHRVMuVElNRVNUQU1QLlJFUVVJUkVEKSxcbiAgICAgICAgcHJvcE1ldGFkYXRhKFZhbGlkYXRpb24ua2V5KERCS2V5cy5USU1FU1RBTVApLCB7XG4gICAgICAgICAgb3BlcmF0aW9uOiBvcGVyYXRpb24sXG4gICAgICAgICAgZm9ybWF0OiBmb3JtYXQsXG4gICAgICAgIH0pLFxuICAgICAgXTtcbiAgICAgIGlmIChvcGVyYXRpb24uaW5kZXhPZihPcGVyYXRpb25LZXlzLlVQREFURSkgIT09IC0xKVxuICAgICAgICBkZWNvcmF0b3JzLnB1c2goXG4gICAgICAgICAgcHJvcE1ldGFkYXRhKHRpbWVzdGFtcEtleSwge1xuICAgICAgICAgICAgbWVzc2FnZTogREJfREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5USU1FU1RBTVAuSU5WQUxJRCxcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgZWxzZSBkZWNvcmF0b3JzLnB1c2gocmVhZG9ubHkoKSk7XG4gICAgICByZXR1cm4gYXBwbHkoLi4uZGVjb3JhdG9ycyk7XG4gICAgfVxuXG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyZWRBcyhUeXBlT1JNRmxhdm91cilcbiAgICAgIC5mb3IodGltZXN0YW1wS2V5KVxuICAgICAgLmRlZmluZSh7XG4gICAgICAgIGRlY29yYXRvcjogdHMsXG4gICAgICB9KVxuICAgICAgLmV4dGVuZCh7XG4gICAgICAgIGRlY29yYXRvcjogZnVuY3Rpb24gdGltZXN0YW1wKC4uLm9wczogT3BlcmF0aW9uS2V5c1tdKSB7XG4gICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIHRpbWVzdGFtcChvYmo6IGFueSwgcHJvcDogYW55KSB7XG4gICAgICAgICAgICBpZiAob3BzLmluZGV4T2YoT3BlcmF0aW9uS2V5cy5VUERBVEUpICE9PSAtMSlcbiAgICAgICAgICAgICAgcmV0dXJuIFVwZGF0ZURhdGVDb2x1bW4oKShvYmosIHByb3ApO1xuICAgICAgICAgICAgcmV0dXJuIENyZWF0ZURhdGVDb2x1bW4oKShvYmosIHByb3ApO1xuICAgICAgICAgIH07XG4gICAgICAgIH0sXG4gICAgICAgIHRyYW5zZm9ybTogKGFyZ3M6IGFueVtdKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGFyZ3NbMF07XG4gICAgICAgIH0sXG4gICAgICB9KVxuICAgICAgLmFwcGx5KCk7XG5cbiAgICAvLyBAb25lVG9PbmUoY2xhenopID0+IEBPbmVUb09uZSgoKSA9PiBjbGF6eilcbiAgICBjb25zdCBvbmVUb09uZUtleSA9IFJlcG9zaXRvcnkua2V5KFBlcnNpc3RlbmNlS2V5cy5PTkVfVE9fT05FKTtcbiAgICBEZWNvcmF0aW9uLmZsYXZvdXJlZEFzKFR5cGVPUk1GbGF2b3VyKVxuICAgICAgLmZvcihvbmVUb09uZUtleSlcbiAgICAgIC5kZWZpbmUoe1xuICAgICAgICBkZWNvcmF0b3I6IGZ1bmN0aW9uIG9uZVRvT25lKFxuICAgICAgICAgIGNsYXp6OiBDb25zdHJ1Y3Rvcjxhbnk+IHwgKCgpID0+IENvbnN0cnVjdG9yPGFueT4pLFxuICAgICAgICAgIGNhc2NhZGU6IENhc2NhZGVNZXRhZGF0YSxcbiAgICAgICAgICBwb3B1bGF0ZTogYm9vbGVhblxuICAgICAgICApIHtcbiAgICAgICAgICBjb25zdCBtZXRhZGF0YTogUmVsYXRpb25zTWV0YWRhdGEgPSB7XG4gICAgICAgICAgICBjbGFzczogKGNsYXp6Lm5hbWUgPyBjbGF6ei5uYW1lIDogY2xhenopIGFzIHN0cmluZyxcbiAgICAgICAgICAgIGNhc2NhZGU6IGNhc2NhZGUsXG4gICAgICAgICAgICBwb3B1bGF0ZTogcG9wdWxhdGUsXG4gICAgICAgICAgfTtcbiAgICAgICAgICBjb25zdCBvcm1NZXRhOiBSZWxhdGlvbk9wdGlvbnMgPSB7XG4gICAgICAgICAgICBjYXNjYWRlOlxuICAgICAgICAgICAgICBjYXNjYWRlLnVwZGF0ZSA9PT0gQ2FzY2FkZS5DQVNDQURFIHx8XG4gICAgICAgICAgICAgIGNhc2NhZGUuZGVsZXRlID09PSBDYXNjYWRlLkNBU0NBREUsXG4gICAgICAgICAgICBvbkRlbGV0ZTogY2FzY2FkZS5kZWxldGUgPyBcIkNBU0NBREVcIiA6IFwiREVGQVVMVFwiLFxuICAgICAgICAgICAgb25VcGRhdGU6IGNhc2NhZGUudXBkYXRlID8gXCJDQVNDQURFXCIgOiBcIkRFRkFVTFRcIixcbiAgICAgICAgICAgIG51bGxhYmxlOiB0cnVlLFxuICAgICAgICAgICAgZWFnZXI6IHBvcHVsYXRlLFxuICAgICAgICAgIH07XG4gICAgICAgICAgcmV0dXJuIGFwcGx5KFxuICAgICAgICAgICAgcHJvcChQZXJzaXN0ZW5jZUtleXMuUkVMQVRJT05TKSxcbiAgICAgICAgICAgIHR5cGUoW1xuICAgICAgICAgICAgICAodHlwZW9mIGNsYXp6ID09PSBcImZ1bmN0aW9uXCIgJiYgIWNsYXp6Lm5hbWVcbiAgICAgICAgICAgICAgICA/IGNsYXp6XG4gICAgICAgICAgICAgICAgOiBjbGF6ei5uYW1lKSBhcyBhbnksXG4gICAgICAgICAgICAgIFN0cmluZy5uYW1lLFxuICAgICAgICAgICAgICBOdW1iZXIubmFtZSxcbiAgICAgICAgICAgICAgQmlnSW50Lm5hbWUsXG4gICAgICAgICAgICBdKSxcbiAgICAgICAgICAgIHByb3BNZXRhZGF0YShvbmVUb09uZUtleSwgbWV0YWRhdGEpLFxuICAgICAgICAgICAgT25lVG9PbmUoXG4gICAgICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoIWNsYXp6Lm5hbWUpIGNsYXp6ID0gKGNsYXp6IGFzIGFueSkoKTtcbiAgICAgICAgICAgICAgICBpZiAoIWNsYXp6W01vZGVsS2V5cy5BTkNIT1IgYXMga2V5b2YgdHlwZW9mIGNsYXp6XSlcbiAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICAgICAgICAgICAgICBcIk9yaWdpbmFsIE1vZGVsIG5vdCBmb3VuZCBpbiBjb25zdHJ1Y3RvclwiXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHJldHVybiBjbGF6eltNb2RlbEtleXMuQU5DSE9SIGFzIGtleW9mIHR5cGVvZiBjbGF6el07XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIChtb2RlbDogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGsgPSBmaW5kUHJpbWFyeUtleShuZXcgKGNsYXp6IGFzIENvbnN0cnVjdG9yPGFueT4pKCkpLmlkO1xuICAgICAgICAgICAgICAgIHJldHVybiBtb2RlbFtwa107XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIG9ybU1ldGFcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBKb2luQ29sdW1uKClcbiAgICAgICAgICApO1xuICAgICAgICB9LFxuICAgICAgfSlcbiAgICAgIC5hcHBseSgpO1xuXG4gICAgLy8gQG9uZVRvTWFueShjbGF6eikgPT4gQE9uZVRvTWFueSgoKSA9PiBjbGF6eilcbiAgICBjb25zdCBvbmVUb01hbnlLZXkgPSBSZXBvc2l0b3J5LmtleShQZXJzaXN0ZW5jZUtleXMuT05FX1RPX01BTlkpO1xuICAgIERlY29yYXRpb24uZmxhdm91cmVkQXMoVHlwZU9STUZsYXZvdXIpXG4gICAgICAuZm9yKG9uZVRvTWFueUtleSlcbiAgICAgIC5kZWZpbmUoe1xuICAgICAgICBkZWNvcmF0b3I6IGZ1bmN0aW9uIG9uZVRvTWFueShcbiAgICAgICAgICBjbGF6ejogQ29uc3RydWN0b3I8YW55PiB8ICgoKSA9PiBDb25zdHJ1Y3Rvcjxhbnk+KSxcbiAgICAgICAgICBjYXNjYWRlOiBDYXNjYWRlTWV0YWRhdGEsXG4gICAgICAgICAgcG9wdWxhdGU6IGJvb2xlYW5cbiAgICAgICAgKSB7XG4gICAgICAgICAgY29uc3QgbWV0YWRhdGE6IFJlbGF0aW9uc01ldGFkYXRhID0ge1xuICAgICAgICAgICAgY2xhc3M6IChjbGF6ei5uYW1lID8gY2xhenoubmFtZSA6IGNsYXp6KSBhcyBzdHJpbmcsXG4gICAgICAgICAgICBjYXNjYWRlOiBjYXNjYWRlLFxuICAgICAgICAgICAgcG9wdWxhdGU6IHBvcHVsYXRlLFxuICAgICAgICAgIH07XG4gICAgICAgICAgcmV0dXJuIGFwcGx5KFxuICAgICAgICAgICAgcHJvcChQZXJzaXN0ZW5jZUtleXMuUkVMQVRJT05TKSxcbiAgICAgICAgICAgIGxpc3QoY2xhenopLFxuICAgICAgICAgICAgcHJvcE1ldGFkYXRhKG9uZVRvTWFueUtleSwgbWV0YWRhdGEpLFxuICAgICAgICAgICAgZnVuY3Rpb24gT25lVG9NYW55V3JhcHBlcihvYmo6IGFueSwgcHJvcDogYW55KTogYW55IHtcbiAgICAgICAgICAgICAgY29uc3Qgb3JtTWV0YTogUmVsYXRpb25PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIGNhc2NhZGU6XG4gICAgICAgICAgICAgICAgICBjYXNjYWRlLnVwZGF0ZSA9PT0gQ2FzY2FkZS5DQVNDQURFIHx8XG4gICAgICAgICAgICAgICAgICBjYXNjYWRlLmRlbGV0ZSA9PT0gQ2FzY2FkZS5DQVNDQURFLFxuICAgICAgICAgICAgICAgIG9uRGVsZXRlOiBjYXNjYWRlLmRlbGV0ZSA/IFwiQ0FTQ0FERVwiIDogXCJERUZBVUxUXCIsXG4gICAgICAgICAgICAgICAgb25VcGRhdGU6IGNhc2NhZGUudXBkYXRlID8gXCJDQVNDQURFXCIgOiBcIkRFRkFVTFRcIixcbiAgICAgICAgICAgICAgICBudWxsYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBlYWdlcjogcG9wdWxhdGUsXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgIHJldHVybiBPbmVUb01hbnkoXG4gICAgICAgICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKCFjbGF6ei5uYW1lKSBjbGF6eiA9IChjbGF6eiBhcyBhbnkpKCk7XG4gICAgICAgICAgICAgICAgICBpZiAoIWNsYXp6W01vZGVsS2V5cy5BTkNIT1IgYXMga2V5b2YgdHlwZW9mIGNsYXp6XSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgXCJPcmlnaW5hbCBNb2RlbCBub3QgZm91bmQgaW4gY29uc3RydWN0b3JcIlxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIGNsYXp6W01vZGVsS2V5cy5BTkNIT1IgYXMga2V5b2YgdHlwZW9mIGNsYXp6XTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIChtb2RlbDogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoIWNsYXp6Lm5hbWUpIGNsYXp6ID0gKGNsYXp6IGFzIGFueSkoKTtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IG0gPSBuZXcgKGNsYXp6IGFzIENvbnN0cnVjdG9yPGFueT4pKCk7XG4gICAgICAgICAgICAgICAgICBjb25zdCBjcm9zc1JlbGF0aW9uS2V5ID0gT2JqZWN0LmtleXMobSkuZmluZCgoaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBkZWNzID0gUmVmbGVjdGlvbi5nZXRQcm9wZXJ0eURlY29yYXRvcnMoXG4gICAgICAgICAgICAgICAgICAgICAgUmVwb3NpdG9yeS5rZXkoUGVyc2lzdGVuY2VLZXlzLk1BTllfVE9fT05FKSxcbiAgICAgICAgICAgICAgICAgICAgICBtLFxuICAgICAgICAgICAgICAgICAgICAgIGssXG4gICAgICAgICAgICAgICAgICAgICAgdHJ1ZVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWRlY3MgfHwgIWRlY3MuZGVjb3JhdG9ycyB8fCAhZGVjcy5kZWNvcmF0b3JzLmxlbmd0aClcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlc2lnblR5cGUgPSBSZWZsZWN0LmdldE1ldGFkYXRhKFxuICAgICAgICAgICAgICAgICAgICAgIE1vZGVsS2V5cy5UWVBFLFxuICAgICAgICAgICAgICAgICAgICAgIG0sXG4gICAgICAgICAgICAgICAgICAgICAga1xuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2lnblR5cGUpXG4gICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICBgTm8gVHlwZSBEZWZpbml0aW9uIGZvdW5kIGZvciAke2t9IGluICR7bS5jb25zdHJ1Y3Rvci5uYW1lfWBcbiAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGVzaWduVHlwZS5uYW1lID09PSBvYmouY29uc3RydWN0b3IubmFtZTtcbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgaWYgKCFjcm9zc1JlbGF0aW9uS2V5KVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICBgQ3Jvc3MgcmVsYXRpb24gbm90IGZvdW5kLiBEaWQgeW91IHVzZSBAbWFueVRvT25lIG9uIHRoZSAke2NsYXp6Lm5hbWV9P2BcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBtb2RlbFtjcm9zc1JlbGF0aW9uS2V5XTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9ybU1ldGFcbiAgICAgICAgICAgICAgKShvYmosIHByb3ApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICk7XG4gICAgICAgIH0sXG4gICAgICB9KVxuICAgICAgLmFwcGx5KCk7XG5cbiAgICAvLyBAbWFueVRvT25lKGNsYXp6KSA9PiBATWFueVRvT25lKCgpID0+IGNsYXp6KVxuICAgIGNvbnN0IG1hbnlUb09uZUtleSA9IFJlcG9zaXRvcnkua2V5KFBlcnNpc3RlbmNlS2V5cy5NQU5ZX1RPX09ORSk7XG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyZWRBcyhUeXBlT1JNRmxhdm91cilcbiAgICAgIC5mb3IobWFueVRvT25lS2V5KVxuICAgICAgLmRlZmluZSh7XG4gICAgICAgIGRlY29yYXRvcjogZnVuY3Rpb24gbWFueVRvT25lKFxuICAgICAgICAgIGNsYXp6OiBDb25zdHJ1Y3Rvcjxhbnk+IHwgKCgpID0+IENvbnN0cnVjdG9yPGFueT4pLFxuICAgICAgICAgIGNhc2NhZGU6IENhc2NhZGVNZXRhZGF0YSxcbiAgICAgICAgICBwb3B1bGF0ZTogYm9vbGVhblxuICAgICAgICApIHtcbiAgICAgICAgICBjb25zdCBtZXRhZGF0YTogUmVsYXRpb25zTWV0YWRhdGEgPSB7XG4gICAgICAgICAgICBjbGFzczogKGNsYXp6Lm5hbWUgPyBjbGF6ei5uYW1lIDogY2xhenopIGFzIHN0cmluZyxcbiAgICAgICAgICAgIGNhc2NhZGU6IGNhc2NhZGUsXG4gICAgICAgICAgICBwb3B1bGF0ZTogcG9wdWxhdGUsXG4gICAgICAgICAgfTtcbiAgICAgICAgICBjb25zdCBvcm1NZXRhOiBSZWxhdGlvbk9wdGlvbnMgPSB7XG4gICAgICAgICAgICBjYXNjYWRlOlxuICAgICAgICAgICAgICBjYXNjYWRlLnVwZGF0ZSA9PT0gQ2FzY2FkZS5DQVNDQURFIHx8XG4gICAgICAgICAgICAgIGNhc2NhZGUuZGVsZXRlID09PSBDYXNjYWRlLkNBU0NBREUsXG4gICAgICAgICAgICBvbkRlbGV0ZTogY2FzY2FkZS5kZWxldGUgPyBcIkNBU0NBREVcIiA6IFwiREVGQVVMVFwiLFxuICAgICAgICAgICAgb25VcGRhdGU6IGNhc2NhZGUudXBkYXRlID8gXCJDQVNDQURFXCIgOiBcIkRFRkFVTFRcIixcbiAgICAgICAgICAgIG51bGxhYmxlOiB0cnVlLFxuICAgICAgICAgICAgZWFnZXI6IHBvcHVsYXRlLFxuICAgICAgICAgIH07XG4gICAgICAgICAgcmV0dXJuIGFwcGx5KFxuICAgICAgICAgICAgcHJvcChQZXJzaXN0ZW5jZUtleXMuUkVMQVRJT05TKSxcbiAgICAgICAgICAgIHR5cGUoW1xuICAgICAgICAgICAgICAodHlwZW9mIGNsYXp6ID09PSBcImZ1bmN0aW9uXCIgJiYgIWNsYXp6Lm5hbWVcbiAgICAgICAgICAgICAgICA/IGNsYXp6XG4gICAgICAgICAgICAgICAgOiBjbGF6ei5uYW1lKSBhcyBhbnksXG4gICAgICAgICAgICAgIFN0cmluZy5uYW1lLFxuICAgICAgICAgICAgICBOdW1iZXIubmFtZSxcbiAgICAgICAgICAgICAgQmlnSW50Lm5hbWUsXG4gICAgICAgICAgICBdKSxcbiAgICAgICAgICAgIHByb3BNZXRhZGF0YShtYW55VG9PbmVLZXksIG1ldGFkYXRhKSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIE1hbnlUb09uZVdyYXBwZXIob2JqOiBhbnksIHByb3A6IGFueSk6IGFueSB7XG4gICAgICAgICAgICAgIHJldHVybiBNYW55VG9PbmUoXG4gICAgICAgICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKCFjbGF6ei5uYW1lKSBjbGF6eiA9IChjbGF6eiBhcyBhbnkpKCk7XG4gICAgICAgICAgICAgICAgICBpZiAoIWNsYXp6W01vZGVsS2V5cy5BTkNIT1IgYXMga2V5b2YgdHlwZW9mIGNsYXp6XSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgXCJPcmlnaW5hbCBNb2RlbCBub3QgZm91bmQgaW4gY29uc3RydWN0b3JcIlxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIGNsYXp6W01vZGVsS2V5cy5BTkNIT1IgYXMga2V5b2YgdHlwZW9mIGNsYXp6XTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIChtb2RlbDogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoIWNsYXp6Lm5hbWUpIGNsYXp6ID0gKGNsYXp6IGFzIGFueSkoKTtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IG0gPSBuZXcgKGNsYXp6IGFzIENvbnN0cnVjdG9yPGFueT4pKCk7XG4gICAgICAgICAgICAgICAgICBjb25zdCBjcm9zc1JlbGF0aW9uS2V5ID0gT2JqZWN0LmtleXMobSkuZmluZCgoaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBkZWNzID0gUmVmbGVjdGlvbi5nZXRQcm9wZXJ0eURlY29yYXRvcnMoXG4gICAgICAgICAgICAgICAgICAgICAgUmVwb3NpdG9yeS5rZXkoUGVyc2lzdGVuY2VLZXlzLk9ORV9UT19NQU5ZKSxcbiAgICAgICAgICAgICAgICAgICAgICBtLFxuICAgICAgICAgICAgICAgICAgICAgIGssXG4gICAgICAgICAgICAgICAgICAgICAgdHJ1ZVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWRlY3MgfHwgIWRlY3MuZGVjb3JhdG9ycyB8fCAhZGVjcy5kZWNvcmF0b3JzLmxlbmd0aClcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGxpc3REZWMgPSBSZWZsZWN0LmdldE1ldGFkYXRhKFxuICAgICAgICAgICAgICAgICAgICAgIFZhbGlkYXRpb24ua2V5KFZhbGlkYXRpb25LZXlzLkxJU1QpLFxuICAgICAgICAgICAgICAgICAgICAgIG0sXG4gICAgICAgICAgICAgICAgICAgICAga1xuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWxpc3REZWMpXG4gICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICBgTm8gVHlwZSBEZWZpbml0aW9uIGZvdW5kIGZvciAke2t9IGluICR7bS5jb25zdHJ1Y3Rvci5uYW1lfWBcbiAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBuYW1lID0gbGlzdERlYy5jbGF6elswXSgpLm5hbWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuYW1lID09PSBvYmouY29uc3RydWN0b3IubmFtZTtcbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgaWYgKCFjcm9zc1JlbGF0aW9uS2V5KVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICBgQ3Jvc3MgcmVsYXRpb24gbm90IGZvdW5kLiBEaWQgeW91IHVzZSBAbWFueVRvT25lIG9uIHRoZSAke2NsYXp6Lm5hbWV9P2BcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBtb2RlbFtjcm9zc1JlbGF0aW9uS2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICkob2JqLCBwcm9wKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICB9LFxuICAgICAgfSlcbiAgICAgIC5hcHBseSgpO1xuXG4gICAgLy8gQG1hbnlUb01hbnkoY2xhenopID0+IEBNYW55VG9NYW55KCgpID0+IGNsYXp6KVxuICAgIGNvbnN0IG1hbnlUb01hbnlLZXkgPSBSZXBvc2l0b3J5LmtleShQZXJzaXN0ZW5jZUtleXMuTUFOWV9UT19NQU5ZKTtcbiAgICBEZWNvcmF0aW9uLmZsYXZvdXJlZEFzKFR5cGVPUk1GbGF2b3VyKVxuICAgICAgLmZvcihtYW55VG9NYW55S2V5KVxuICAgICAgLmRlZmluZSh7XG4gICAgICAgIGRlY29yYXRvcjogZnVuY3Rpb24gbWFueVRvTWFueShcbiAgICAgICAgICBjbGF6ejogQ29uc3RydWN0b3I8YW55PiB8ICgoKSA9PiBDb25zdHJ1Y3Rvcjxhbnk+KSxcbiAgICAgICAgICBjYXNjYWRlOiBDYXNjYWRlTWV0YWRhdGEsXG4gICAgICAgICAgcG9wdWxhdGU6IGJvb2xlYW5cbiAgICAgICAgKSB7XG4gICAgICAgICAgY29uc3QgbWV0YWRhdGE6IFJlbGF0aW9uc01ldGFkYXRhID0ge1xuICAgICAgICAgICAgY2xhc3M6IGNsYXp6Lm5hbWUsXG4gICAgICAgICAgICBjYXNjYWRlOiBjYXNjYWRlLFxuICAgICAgICAgICAgcG9wdWxhdGU6IHBvcHVsYXRlLFxuICAgICAgICAgIH07XG4gICAgICAgICAgY29uc3Qgb3JtTWV0YTogUmVsYXRpb25PcHRpb25zID0ge1xuICAgICAgICAgICAgY2FzY2FkZTpcbiAgICAgICAgICAgICAgY2FzY2FkZS51cGRhdGUgPT09IENhc2NhZGUuQ0FTQ0FERSB8fFxuICAgICAgICAgICAgICBjYXNjYWRlLmRlbGV0ZSA9PT0gQ2FzY2FkZS5DQVNDQURFLFxuICAgICAgICAgICAgb25EZWxldGU6IGNhc2NhZGUuZGVsZXRlID8gXCJDQVNDQURFXCIgOiBcIkRFRkFVTFRcIixcbiAgICAgICAgICAgIG9uVXBkYXRlOiBjYXNjYWRlLnVwZGF0ZSA/IFwiQ0FTQ0FERVwiIDogXCJERUZBVUxUXCIsXG4gICAgICAgICAgICBudWxsYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGVhZ2VyOiBwb3B1bGF0ZSxcbiAgICAgICAgICB9O1xuICAgICAgICAgIHJldHVybiBhcHBseShcbiAgICAgICAgICAgIHByb3AoUGVyc2lzdGVuY2VLZXlzLlJFTEFUSU9OUyksXG4gICAgICAgICAgICBsaXN0KGNsYXp6KSxcbiAgICAgICAgICAgIHByb3BNZXRhZGF0YShtYW55VG9NYW55S2V5LCBtZXRhZGF0YSksXG4gICAgICAgICAgICBNYW55VG9NYW55KFxuICAgICAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFjbGF6ei5uYW1lKSBjbGF6eiA9IChjbGF6eiBhcyBhbnkpKCk7XG4gICAgICAgICAgICAgICAgaWYgKCFjbGF6eltNb2RlbEtleXMuQU5DSE9SIGFzIGtleW9mIHR5cGVvZiBjbGF6el0pXG4gICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgXCJPcmlnaW5hbCBNb2RlbCBub3QgZm91bmQgaW4gY29uc3RydWN0b3JcIlxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2xhenpbTW9kZWxLZXlzLkFOQ0hPUiBhcyBrZXlvZiB0eXBlb2YgY2xhenpdO1xuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAobW9kZWw6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghY2xhenoubmFtZSkgY2xhenogPSAoY2xhenogYXMgYW55KSgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHBrID0gZmluZFByaW1hcnlLZXkobmV3IChjbGF6eiBhcyBDb25zdHJ1Y3Rvcjxhbnk+KSgpKS5pZDtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9kZWxbcGtdO1xuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBvcm1NZXRhXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgSm9pblRhYmxlKClcbiAgICAgICAgICApO1xuICAgICAgICB9LFxuICAgICAgfSlcbiAgICAgIC5hcHBseSgpO1xuICB9XG59XG4iXX0=
|