@decaf-ts/for-couchdb 0.3.14 → 0.3.15
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 +159 -16
- package/README.md +20 -2
- package/dist/for-couchdb.cjs +2 -1450
- package/dist/for-couchdb.cjs.map +1 -0
- package/dist/for-couchdb.js +2 -0
- package/dist/for-couchdb.js.map +1 -0
- package/lib/adapter.cjs +1 -1
- package/lib/adapter.js.map +1 -0
- package/lib/constants.cjs +1 -1
- package/lib/constants.js.map +1 -0
- package/lib/errors.cjs +1 -1
- package/lib/errors.js.map +1 -0
- package/lib/esm/adapter.js +1 -1
- package/lib/esm/adapter.js.map +1 -0
- package/lib/esm/constants.js +1 -1
- package/lib/esm/constants.js.map +1 -0
- package/lib/esm/errors.js +1 -1
- package/lib/esm/errors.js.map +1 -0
- package/lib/esm/index.d.ts +1 -1
- package/lib/esm/index.js +2 -2
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/indexes/generator.js +1 -1
- package/lib/esm/indexes/generator.js.map +1 -0
- package/lib/esm/indexes/index.js +1 -1
- package/lib/esm/indexes/index.js.map +1 -0
- package/lib/esm/interfaces/CouchDBRepository.js +1 -1
- package/lib/esm/interfaces/CouchDBRepository.js.map +1 -0
- package/lib/esm/interfaces/index.js +1 -1
- package/lib/esm/interfaces/index.js.map +1 -0
- package/lib/esm/model/CouchDBSequence.js +1 -1
- package/lib/esm/model/CouchDBSequence.js.map +1 -0
- package/lib/esm/model/index.js +1 -1
- package/lib/esm/model/index.js.map +1 -0
- package/lib/esm/query/Paginator.js +1 -1
- package/lib/esm/query/Paginator.js.map +1 -0
- package/lib/esm/query/Statement.js +1 -1
- package/lib/esm/query/Statement.js.map +1 -0
- package/lib/esm/query/constants.js +1 -1
- package/lib/esm/query/constants.js.map +1 -0
- package/lib/esm/query/index.js +1 -1
- package/lib/esm/query/index.js.map +1 -0
- package/lib/esm/query/translate.js +1 -1
- package/lib/esm/query/translate.js.map +1 -0
- package/lib/esm/sequences/Sequence.js +1 -1
- package/lib/esm/sequences/Sequence.js.map +1 -0
- package/lib/esm/sequences/index.js +1 -1
- package/lib/esm/sequences/index.js.map +1 -0
- package/lib/esm/types.js +1 -1
- package/lib/esm/types.js.map +1 -0
- package/lib/esm/utils.js +1 -1
- package/lib/esm/utils.js.map +1 -0
- package/lib/index.cjs +2 -2
- package/lib/index.d.ts +1 -1
- package/lib/index.js.map +1 -0
- package/lib/indexes/generator.cjs +1 -1
- package/lib/indexes/generator.js.map +1 -0
- package/lib/indexes/index.cjs +1 -1
- package/lib/indexes/index.js.map +1 -0
- package/lib/interfaces/CouchDBRepository.cjs +1 -1
- package/lib/interfaces/CouchDBRepository.js.map +1 -0
- package/lib/interfaces/index.cjs +1 -1
- package/lib/interfaces/index.js.map +1 -0
- package/lib/model/CouchDBSequence.cjs +1 -1
- package/lib/model/CouchDBSequence.js.map +1 -0
- package/lib/model/index.cjs +1 -1
- package/lib/model/index.js.map +1 -0
- package/lib/query/Paginator.cjs +1 -1
- package/lib/query/Paginator.js.map +1 -0
- package/lib/query/Statement.cjs +1 -1
- package/lib/query/Statement.js.map +1 -0
- package/lib/query/constants.cjs +1 -1
- package/lib/query/constants.js.map +1 -0
- package/lib/query/index.cjs +1 -1
- package/lib/query/index.js.map +1 -0
- package/lib/query/translate.cjs +1 -1
- package/lib/query/translate.js.map +1 -0
- package/lib/sequences/Sequence.cjs +1 -1
- package/lib/sequences/Sequence.js.map +1 -0
- package/lib/sequences/index.cjs +1 -1
- package/lib/sequences/index.js.map +1 -0
- package/lib/types.cjs +1 -1
- package/lib/types.js.map +1 -0
- package/lib/utils.cjs +1 -1
- package/lib/utils.js.map +1 -0
- package/package.json +11 -21
- package/dist/for-couchdb.esm.cjs +0 -1430
package/dist/for-couchdb.cjs
CHANGED
|
@@ -1,1450 +1,2 @@
|
|
|
1
|
-
(function (global, factory) {
|
|
2
|
-
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports', '@decaf-ts/decoration', '@decaf-ts/core', '@decaf-ts/db-decorators', 'tslib', '@decaf-ts/decorator-validation', 'reflect-metadata'], factory) :
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["for-couchdb"] = {}, global.decoration, global.core, global.dbDecorators, global.tslib, global.decoratorValidation));
|
|
5
|
-
})(this, (function (exports, decoration, core, dbDecorators, tslib, decoratorValidation) { 'use strict';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @description Regular expression to identify reserved attributes in CouchDB
|
|
9
|
-
* @summary Matches any attribute that starts with an underscore
|
|
10
|
-
* @const reservedAttributes
|
|
11
|
-
* @memberOf module:for-couchdb
|
|
12
|
-
*/
|
|
13
|
-
const reservedAttributes = /^_.*$/g;
|
|
14
|
-
/**
|
|
15
|
-
* @description Key constants used in CouchDB operations
|
|
16
|
-
* @summary Collection of string constants for CouchDB document properties and operations
|
|
17
|
-
* @typedef {Object} CouchDBKeysType
|
|
18
|
-
* @property {string} SEPARATOR - Separator used for combining table name and ID
|
|
19
|
-
* @property {string} ID - CouchDB document ID field
|
|
20
|
-
* @property {string} REV - CouchDB document revision field
|
|
21
|
-
* @property {string} DELETED - CouchDB deleted document marker
|
|
22
|
-
* @property {string} TABLE - Table name marker
|
|
23
|
-
* @property {string} SEQUENCE - Sequence marker
|
|
24
|
-
* @property {string} DDOC - Design document marker
|
|
25
|
-
* @property {string} NATIVE - Native marker
|
|
26
|
-
* @property {string} INDEX - Index marker
|
|
27
|
-
* @memberOf module:for-couchdb
|
|
28
|
-
*/
|
|
29
|
-
/**
|
|
30
|
-
* @description Key constants used in CouchDB operations
|
|
31
|
-
* @summary Collection of string constants for CouchDB document properties and operations
|
|
32
|
-
* @const CouchDBKeys
|
|
33
|
-
* @type {CouchDBKeysType}
|
|
34
|
-
* @memberOf module:for-couchdb
|
|
35
|
-
*/
|
|
36
|
-
const CouchDBKeys = {
|
|
37
|
-
SEPARATOR: "__",
|
|
38
|
-
ID: "_id",
|
|
39
|
-
REV: "_rev",
|
|
40
|
-
DELETED: "_deleted",
|
|
41
|
-
TABLE: "??table",
|
|
42
|
-
SEQUENCE: "??sequence",
|
|
43
|
-
DDOC: "ddoc",
|
|
44
|
-
NATIVE: "__native",
|
|
45
|
-
INDEX: "index",
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* @description Default query limit for CouchDB queries
|
|
50
|
-
* @summary Maximum number of documents to return in a single query
|
|
51
|
-
* @const CouchDBQueryLimit
|
|
52
|
-
* @memberOf module:for-couchdb
|
|
53
|
-
*/
|
|
54
|
-
const CouchDBQueryLimit = 250;
|
|
55
|
-
/**
|
|
56
|
-
* @description Mapping of operator names to CouchDB Mango query operators
|
|
57
|
-
* @summary Constants for CouchDB comparison operators used in Mango queries
|
|
58
|
-
* @typedef {Object} CouchDBOperatorType
|
|
59
|
-
* @property {string} EQUAL - Equality operator ($eq)
|
|
60
|
-
* @property {string} DIFFERENT - Inequality operator ($ne)
|
|
61
|
-
* @property {string} BIGGER - Greater than operator ($gt)
|
|
62
|
-
* @property {string} BIGGER_EQ - Greater than or equal operator ($gte)
|
|
63
|
-
* @property {string} SMALLER - Less than operator ($lt)
|
|
64
|
-
* @property {string} SMALLER_EQ - Less than or equal operator ($lte)
|
|
65
|
-
* @property {string} NOT - Negation operator ($not)
|
|
66
|
-
* @property {string} IN - In array operator ($in)
|
|
67
|
-
* @property {string} REGEXP - Regular expression operator ($regex)
|
|
68
|
-
* @const CouchDBOperator
|
|
69
|
-
* @type {CouchDBOperatorType}
|
|
70
|
-
* @memberOf module:for-couchdb
|
|
71
|
-
*/
|
|
72
|
-
const CouchDBOperator = {
|
|
73
|
-
EQUAL: "$eq",
|
|
74
|
-
DIFFERENT: "$ne",
|
|
75
|
-
BIGGER: "$gt",
|
|
76
|
-
BIGGER_EQ: "$gte",
|
|
77
|
-
SMALLER: "$lt",
|
|
78
|
-
SMALLER_EQ: "$lte",
|
|
79
|
-
// BETWEEN = "BETWEEN",
|
|
80
|
-
NOT: "$not",
|
|
81
|
-
IN: "$in",
|
|
82
|
-
// IS = "IS",
|
|
83
|
-
REGEXP: "$regex",
|
|
84
|
-
};
|
|
85
|
-
/**
|
|
86
|
-
* @description Mapping of logical operator names to CouchDB Mango query operators
|
|
87
|
-
* @summary Constants for CouchDB logical operators used in Mango queries
|
|
88
|
-
* @typedef {Object} CouchDBGroupOperatorType
|
|
89
|
-
* @property {string} AND - Logical AND operator ($and)
|
|
90
|
-
* @property {string} OR - Logical OR operator ($or)
|
|
91
|
-
* @const CouchDBGroupOperator
|
|
92
|
-
* @type {CouchDBGroupOperatorType}
|
|
93
|
-
* @memberOf module:for-couchdb
|
|
94
|
-
*/
|
|
95
|
-
const CouchDBGroupOperator = {
|
|
96
|
-
AND: "$and",
|
|
97
|
-
OR: "$or",
|
|
98
|
-
};
|
|
99
|
-
/**
|
|
100
|
-
* @description Special constant values used in CouchDB queries
|
|
101
|
-
* @summary String constants representing special values in CouchDB
|
|
102
|
-
* @typedef {Object} CouchDBConstType
|
|
103
|
-
* @property {string} NULL - String representation of null value
|
|
104
|
-
* @const CouchDBConst
|
|
105
|
-
* @type {CouchDBConstType}
|
|
106
|
-
* @memberOf module:for-couchdb
|
|
107
|
-
*/
|
|
108
|
-
const CouchDBConst = {
|
|
109
|
-
NULL: "null",
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* @description Generates a name for a CouchDB index
|
|
114
|
-
* @summary Creates a standardized name for a CouchDB index by combining name parts, compositions, and direction
|
|
115
|
-
* @param {string[]} name - Array of name parts for the index
|
|
116
|
-
* @param {OrderDirection} [direction] - Optional sort direction for the index
|
|
117
|
-
* @param {string[]} [compositions] - Optional additional attributes to include in the index name
|
|
118
|
-
* @param {string} [separator=DefaultSeparator] - The separator to use between parts of the index name
|
|
119
|
-
* @return {string} The generated index name
|
|
120
|
-
* @memberOf module:for-couchdb
|
|
121
|
-
*/
|
|
122
|
-
function generateIndexName$1(name, direction, compositions, separator = dbDecorators.DefaultSeparator) {
|
|
123
|
-
return [
|
|
124
|
-
...name.map((n) => (n === CouchDBKeys.TABLE ? "table" : n)),
|
|
125
|
-
...([]),
|
|
126
|
-
...([]),
|
|
127
|
-
CouchDBKeys.INDEX,
|
|
128
|
-
].join(separator);
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* @description Generates CouchDB index configurations for models
|
|
132
|
-
* @summary Creates a set of CouchDB index configurations based on the metadata of the provided models
|
|
133
|
-
* @template M - The model type that extends Model
|
|
134
|
-
* @param models - Array of model constructors to generate indexes for
|
|
135
|
-
* @return {CreateIndexRequest[]} Array of CouchDB index configurations
|
|
136
|
-
* @function generateIndexes
|
|
137
|
-
* @memberOf module:for-couchdb
|
|
138
|
-
* @mermaid
|
|
139
|
-
* sequenceDiagram
|
|
140
|
-
* participant Caller
|
|
141
|
-
* participant generateIndexes
|
|
142
|
-
* participant generateIndexName
|
|
143
|
-
* participant Repository
|
|
144
|
-
*
|
|
145
|
-
* Caller->>generateIndexes: models
|
|
146
|
-
*
|
|
147
|
-
* Note over generateIndexes: Create base table index
|
|
148
|
-
* generateIndexes->>generateIndexName: [CouchDBKeys.TABLE]
|
|
149
|
-
* generateIndexName-->>generateIndexes: tableName
|
|
150
|
-
* generateIndexes->>generateIndexes: Create table index config
|
|
151
|
-
*
|
|
152
|
-
* loop For each model
|
|
153
|
-
* generateIndexes->>Repository: Get indexes metadata
|
|
154
|
-
* Repository-->>generateIndexes: index metadata
|
|
155
|
-
*
|
|
156
|
-
* loop For each index in metadata
|
|
157
|
-
* Note over generateIndexes: Extract index properties
|
|
158
|
-
* generateIndexes->>Repository: Get table name
|
|
159
|
-
* Repository-->>generateIndexes: tableName
|
|
160
|
-
*
|
|
161
|
-
* Note over generateIndexes: Define nested generate function
|
|
162
|
-
*
|
|
163
|
-
* generateIndexes->>generateIndexes: Call generate() for default order
|
|
164
|
-
* Note over generateIndexes: Create index name and config
|
|
165
|
-
*
|
|
166
|
-
* alt Has directions
|
|
167
|
-
* loop For each direction
|
|
168
|
-
* generateIndexes->>generateIndexes: Call generate(direction)
|
|
169
|
-
* Note over generateIndexes: Create ordered index config
|
|
170
|
-
* end
|
|
171
|
-
* end
|
|
172
|
-
* end
|
|
173
|
-
* end
|
|
174
|
-
*
|
|
175
|
-
* generateIndexes-->>Caller: Array of index configurations
|
|
176
|
-
*/
|
|
177
|
-
function generateIndexes(models) {
|
|
178
|
-
const tableName = generateIndexName$1([CouchDBKeys.TABLE]);
|
|
179
|
-
const indexes = {};
|
|
180
|
-
indexes[tableName] = {
|
|
181
|
-
index: {
|
|
182
|
-
fields: [CouchDBKeys.TABLE],
|
|
183
|
-
},
|
|
184
|
-
name: tableName,
|
|
185
|
-
ddoc: tableName,
|
|
186
|
-
type: "json",
|
|
187
|
-
};
|
|
188
|
-
models.forEach((m) => {
|
|
189
|
-
const ind = core.Repository.indexes(m);
|
|
190
|
-
Object.entries(ind).forEach(([key, value]) => {
|
|
191
|
-
const k = Object.keys(value)[0];
|
|
192
|
-
// eslint-disable-next-line prefer-const
|
|
193
|
-
let { directions, compositions } = value[k];
|
|
194
|
-
const tableName = core.Repository.table(m);
|
|
195
|
-
compositions = compositions || [];
|
|
196
|
-
function generate(sort) {
|
|
197
|
-
const name = [
|
|
198
|
-
tableName,
|
|
199
|
-
key,
|
|
200
|
-
...compositions,
|
|
201
|
-
core.PersistenceKeys.INDEX,
|
|
202
|
-
].join(dbDecorators.DefaultSeparator);
|
|
203
|
-
indexes[name] = {
|
|
204
|
-
index: {
|
|
205
|
-
fields: [key, ...compositions, CouchDBKeys.TABLE].reduce((accum, el) => {
|
|
206
|
-
if (sort) {
|
|
207
|
-
const res = {};
|
|
208
|
-
res[el] = sort;
|
|
209
|
-
accum.push(res);
|
|
210
|
-
}
|
|
211
|
-
else {
|
|
212
|
-
accum.push(el);
|
|
213
|
-
}
|
|
214
|
-
return accum;
|
|
215
|
-
}, []),
|
|
216
|
-
},
|
|
217
|
-
name: name,
|
|
218
|
-
ddoc: name,
|
|
219
|
-
type: "json",
|
|
220
|
-
};
|
|
221
|
-
if (!sort) {
|
|
222
|
-
const tableFilter = {};
|
|
223
|
-
tableFilter[CouchDBKeys.TABLE] = {};
|
|
224
|
-
tableFilter[CouchDBKeys.TABLE][CouchDBOperator.EQUAL] = tableName;
|
|
225
|
-
indexes[name].index.partial_filter_selector = tableFilter;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
generate();
|
|
229
|
-
if (directions)
|
|
230
|
-
directions.forEach((d) => generate(d));
|
|
231
|
-
});
|
|
232
|
-
});
|
|
233
|
-
return Object.values(indexes);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* @description Model for CouchDB sequence records
|
|
238
|
-
* @summary Represents a sequence in CouchDB used for generating sequential IDs
|
|
239
|
-
* @param {ModelArg<Sequence>} [seq] - Optional initialization data for the sequence
|
|
240
|
-
* @class
|
|
241
|
-
* @example
|
|
242
|
-
* // Example of creating and using a Sequence
|
|
243
|
-
* const sequence = new Sequence({ id: 'user-seq', current: 1 });
|
|
244
|
-
* // Increment the sequence
|
|
245
|
-
* sequence.current = Number(sequence.current) + 1;
|
|
246
|
-
*/
|
|
247
|
-
exports.Sequence = class Sequence extends core.BaseModel {
|
|
248
|
-
constructor(seq) {
|
|
249
|
-
super(seq);
|
|
250
|
-
}
|
|
251
|
-
};
|
|
252
|
-
tslib.__decorate([
|
|
253
|
-
core.pk(),
|
|
254
|
-
tslib.__metadata("design:type", String)
|
|
255
|
-
], exports.Sequence.prototype, "id", void 0);
|
|
256
|
-
tslib.__decorate([
|
|
257
|
-
decoratorValidation.required(),
|
|
258
|
-
core.index(),
|
|
259
|
-
tslib.__metadata("design:type", Object)
|
|
260
|
-
], exports.Sequence.prototype, "current", void 0);
|
|
261
|
-
exports.Sequence = tslib.__decorate([
|
|
262
|
-
core.table(CouchDBKeys.SEQUENCE),
|
|
263
|
-
decoratorValidation.model(),
|
|
264
|
-
tslib.__metadata("design:paramtypes", [Object])
|
|
265
|
-
], exports.Sequence);
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* @summary Abstract implementation of a Sequence
|
|
269
|
-
* @description provides the basic functionality for {@link Sequence}s
|
|
270
|
-
*
|
|
271
|
-
* @param {SequenceOptions} options
|
|
272
|
-
*
|
|
273
|
-
* @class CouchDBSequence
|
|
274
|
-
* @implements Sequence
|
|
275
|
-
*/
|
|
276
|
-
class CouchDBSequence extends core.Sequence {
|
|
277
|
-
constructor(options, adapter) {
|
|
278
|
-
super(options);
|
|
279
|
-
this.repo = core.Repository.forModel(exports.Sequence, adapter.alias);
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* @summary Retrieves the current value for the sequence
|
|
283
|
-
* @protected
|
|
284
|
-
*/
|
|
285
|
-
async current() {
|
|
286
|
-
const { name, startWith } = this.options;
|
|
287
|
-
try {
|
|
288
|
-
const sequence = await this.repo.read(name);
|
|
289
|
-
return this.parse(sequence.current);
|
|
290
|
-
}
|
|
291
|
-
catch (e) {
|
|
292
|
-
if (e instanceof dbDecorators.NotFoundError) {
|
|
293
|
-
if (typeof startWith === "undefined")
|
|
294
|
-
throw new dbDecorators.InternalError("Starting value is not defined for a non existing sequence");
|
|
295
|
-
try {
|
|
296
|
-
return this.parse(startWith);
|
|
297
|
-
}
|
|
298
|
-
catch (e) {
|
|
299
|
-
throw new dbDecorators.InternalError(`Failed to parse initial value for sequence ${startWith}: ${e}`);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
throw new dbDecorators.InternalError(`Failed to retrieve current value for sequence ${name}: ${e}`);
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* @summary Parses the {@link Sequence} value
|
|
307
|
-
*
|
|
308
|
-
* @protected
|
|
309
|
-
* @param value
|
|
310
|
-
*/
|
|
311
|
-
parse(value) {
|
|
312
|
-
return core.Sequence.parseValue(this.options.type, value);
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* @summary increments the sequence
|
|
316
|
-
* @description Sequence specific implementation
|
|
317
|
-
*
|
|
318
|
-
* @param {string | number | bigint} current
|
|
319
|
-
* @param count
|
|
320
|
-
* @protected
|
|
321
|
-
*/
|
|
322
|
-
async increment(current, count) {
|
|
323
|
-
const { type, incrementBy, name } = this.options;
|
|
324
|
-
let next;
|
|
325
|
-
const toIncrementBy = count || incrementBy;
|
|
326
|
-
if (toIncrementBy % incrementBy !== 0)
|
|
327
|
-
throw new dbDecorators.InternalError(`Value to increment does not consider the incrementBy setting: ${incrementBy}`);
|
|
328
|
-
switch (type) {
|
|
329
|
-
case "Number":
|
|
330
|
-
next = this.parse(current) + toIncrementBy;
|
|
331
|
-
break;
|
|
332
|
-
case "BigInt":
|
|
333
|
-
next = this.parse(current) + BigInt(toIncrementBy);
|
|
334
|
-
break;
|
|
335
|
-
default:
|
|
336
|
-
throw new dbDecorators.InternalError("Should never happen");
|
|
337
|
-
}
|
|
338
|
-
let seq;
|
|
339
|
-
try {
|
|
340
|
-
seq = await this.repo.update(new exports.Sequence({ id: name, current: next }));
|
|
341
|
-
}
|
|
342
|
-
catch (e) {
|
|
343
|
-
if (!(e instanceof dbDecorators.NotFoundError))
|
|
344
|
-
throw e;
|
|
345
|
-
seq = await this.repo.create(new exports.Sequence({ id: name, current: next }));
|
|
346
|
-
}
|
|
347
|
-
return seq.current;
|
|
348
|
-
}
|
|
349
|
-
/**
|
|
350
|
-
* @summary Generates the next value in th sequence
|
|
351
|
-
* @description calls {@link Sequence#parse} on the current value
|
|
352
|
-
* followed by {@link Sequence#increment}
|
|
353
|
-
*
|
|
354
|
-
*/
|
|
355
|
-
async next() {
|
|
356
|
-
const current = await this.current();
|
|
357
|
-
return this.increment(current);
|
|
358
|
-
}
|
|
359
|
-
async range(count) {
|
|
360
|
-
const current = (await this.current());
|
|
361
|
-
const incrementBy = this.parse(this.options.incrementBy);
|
|
362
|
-
const next = await this.increment(current, this.parse(count) * incrementBy);
|
|
363
|
-
const range = [];
|
|
364
|
-
for (let i = 1; i <= count; i++) {
|
|
365
|
-
range.push(current + incrementBy * this.parse(i));
|
|
366
|
-
}
|
|
367
|
-
if (range[range.length - 1] !== next)
|
|
368
|
-
throw new dbDecorators.InternalError("Miscalculation of range");
|
|
369
|
-
return range;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
/**
|
|
374
|
-
* @description Error thrown when there is an issue with CouchDB indexes
|
|
375
|
-
* @summary Represents an error related to CouchDB index operations
|
|
376
|
-
* @param {string|Error} msg - The error message or Error object
|
|
377
|
-
* @class
|
|
378
|
-
* @category Errors
|
|
379
|
-
* @example
|
|
380
|
-
* // Example of using IndexError
|
|
381
|
-
* try {
|
|
382
|
-
* // Some code that might throw an index error
|
|
383
|
-
* throw new IndexError("Index not found");
|
|
384
|
-
* } catch (error) {
|
|
385
|
-
* if (error instanceof IndexError) {
|
|
386
|
-
* console.error("Index error occurred:", error.message);
|
|
387
|
-
* }
|
|
388
|
-
* }
|
|
389
|
-
*/
|
|
390
|
-
class IndexError extends dbDecorators.BaseError {
|
|
391
|
-
constructor(msg) {
|
|
392
|
-
super(IndexError.name, msg, 404);
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
/**
|
|
397
|
-
* @description Paginator for CouchDB query results
|
|
398
|
-
* @summary Implements pagination for CouchDB queries using bookmarks for efficient navigation through result sets
|
|
399
|
-
* @template M - The model type that extends Model
|
|
400
|
-
* @template R - The result type
|
|
401
|
-
* @param {CouchDBAdapter<any, any, any>} adapter - The CouchDB adapter
|
|
402
|
-
* @param {MangoQuery} query - The Mango query to paginate
|
|
403
|
-
* @param {number} size - The page size
|
|
404
|
-
* @param {Constructor<M>} clazz - The model constructor
|
|
405
|
-
* @class CouchDBPaginator
|
|
406
|
-
* @example
|
|
407
|
-
* // Example of using CouchDBPaginator
|
|
408
|
-
* const adapter = new MyCouchDBAdapter(scope);
|
|
409
|
-
* const query = { selector: { type: "user" } };
|
|
410
|
-
* const paginator = new CouchDBPaginator(adapter, query, 10, User);
|
|
411
|
-
*
|
|
412
|
-
* // Get the first page
|
|
413
|
-
* const page1 = await paginator.page(1);
|
|
414
|
-
*
|
|
415
|
-
* // Get the next page
|
|
416
|
-
* const page2 = await paginator.page(2);
|
|
417
|
-
*/
|
|
418
|
-
class CouchDBPaginator extends core.Paginator {
|
|
419
|
-
/**
|
|
420
|
-
* @description Gets the total number of pages
|
|
421
|
-
* @summary Not supported in CouchDB - throws an error when accessed
|
|
422
|
-
* @return {number} Never returns as it throws an error
|
|
423
|
-
* @throws {InternalError} Always throws as this functionality is not available in CouchDB
|
|
424
|
-
*/
|
|
425
|
-
get total() {
|
|
426
|
-
throw new dbDecorators.InternalError(`The total pages api is not available for couchdb`);
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* @description Gets the total record count
|
|
430
|
-
* @summary Not supported in CouchDB - throws an error when accessed
|
|
431
|
-
* @return {number} Never returns as it throws an error
|
|
432
|
-
* @throws {InternalError} Always throws as this functionality is not available in CouchDB
|
|
433
|
-
*/
|
|
434
|
-
get count() {
|
|
435
|
-
throw new dbDecorators.InternalError(`The record count api is not available for couchdb`);
|
|
436
|
-
}
|
|
437
|
-
/**
|
|
438
|
-
* @description Creates a new CouchDBPaginator instance
|
|
439
|
-
* @summary Initializes a paginator for CouchDB query results
|
|
440
|
-
* @param {CouchDBAdapter<any, any, any, any>} adapter - The CouchDB adapter
|
|
441
|
-
* @param {MangoQuery} query - The Mango query to paginate
|
|
442
|
-
* @param {number} size - The page size
|
|
443
|
-
* @param {Constructor<M>} clazz - The model constructor
|
|
444
|
-
*/
|
|
445
|
-
constructor(adapter, query, size, clazz) {
|
|
446
|
-
super(adapter, query, size, clazz);
|
|
447
|
-
}
|
|
448
|
-
/**
|
|
449
|
-
* @description Prepares a query for pagination
|
|
450
|
-
* @summary Modifies the raw query to include pagination parameters
|
|
451
|
-
* @param {MangoQuery} rawStatement - The original Mango query
|
|
452
|
-
* @return {MangoQuery} The prepared query with pagination parameters
|
|
453
|
-
*/
|
|
454
|
-
prepare(rawStatement) {
|
|
455
|
-
const query = Object.assign({}, rawStatement);
|
|
456
|
-
if (query.limit)
|
|
457
|
-
this.limit = query.limit;
|
|
458
|
-
query.limit = this.size;
|
|
459
|
-
return query;
|
|
460
|
-
}
|
|
461
|
-
/**
|
|
462
|
-
* @description Retrieves a specific page of results
|
|
463
|
-
* @summary Executes the query with pagination and processes the results
|
|
464
|
-
* @param {number} [page=1] - The page number to retrieve
|
|
465
|
-
* @return {Promise<R[]>} A promise that resolves to an array of results
|
|
466
|
-
* @throws {PagingError} If trying to access a page other than the first without a bookmark, or if no class is defined
|
|
467
|
-
* @mermaid
|
|
468
|
-
* sequenceDiagram
|
|
469
|
-
* participant Client
|
|
470
|
-
* participant CouchDBPaginator
|
|
471
|
-
* participant Adapter
|
|
472
|
-
* participant CouchDB
|
|
473
|
-
*
|
|
474
|
-
* Client->>CouchDBPaginator: page(pageNumber)
|
|
475
|
-
* Note over CouchDBPaginator: Clone statement
|
|
476
|
-
* CouchDBPaginator->>CouchDBPaginator: validatePage(page)
|
|
477
|
-
*
|
|
478
|
-
* alt page !== 1
|
|
479
|
-
* CouchDBPaginator->>CouchDBPaginator: Check bookmark
|
|
480
|
-
* alt No bookmark
|
|
481
|
-
* CouchDBPaginator-->>Client: Throw PagingError
|
|
482
|
-
* else Has bookmark
|
|
483
|
-
* CouchDBPaginator->>CouchDBPaginator: Add bookmark to statement
|
|
484
|
-
* end
|
|
485
|
-
* end
|
|
486
|
-
*
|
|
487
|
-
* CouchDBPaginator->>Adapter: raw(statement, false)
|
|
488
|
-
* Adapter->>CouchDB: Execute query
|
|
489
|
-
* CouchDB-->>Adapter: Return results
|
|
490
|
-
* Adapter-->>CouchDBPaginator: Return MangoResponse
|
|
491
|
-
*
|
|
492
|
-
* Note over CouchDBPaginator: Process results
|
|
493
|
-
*
|
|
494
|
-
* alt Has warning
|
|
495
|
-
* CouchDBPaginator->>CouchDBPaginator: Log warning
|
|
496
|
-
* end
|
|
497
|
-
*
|
|
498
|
-
* CouchDBPaginator->>CouchDBPaginator: Check for clazz
|
|
499
|
-
*
|
|
500
|
-
* alt No clazz
|
|
501
|
-
* CouchDBPaginator-->>Client: Throw PagingError
|
|
502
|
-
* else Has clazz
|
|
503
|
-
* CouchDBPaginator->>CouchDBPaginator: Find primary key
|
|
504
|
-
*
|
|
505
|
-
* alt Has fields in statement
|
|
506
|
-
* CouchDBPaginator->>CouchDBPaginator: Use docs directly
|
|
507
|
-
* else No fields
|
|
508
|
-
* CouchDBPaginator->>CouchDBPaginator: Process each document
|
|
509
|
-
* loop For each document
|
|
510
|
-
* CouchDBPaginator->>CouchDBPaginator: Extract original ID
|
|
511
|
-
* CouchDBPaginator->>Adapter: revert(doc, clazz, pkDef.id, parsedId)
|
|
512
|
-
* end
|
|
513
|
-
* end
|
|
514
|
-
*
|
|
515
|
-
* CouchDBPaginator->>CouchDBPaginator: Store bookmark
|
|
516
|
-
* CouchDBPaginator->>CouchDBPaginator: Update currentPage
|
|
517
|
-
* CouchDBPaginator-->>Client: Return results
|
|
518
|
-
* end
|
|
519
|
-
*/
|
|
520
|
-
async page(page = 1) {
|
|
521
|
-
const statement = Object.assign({}, this.statement);
|
|
522
|
-
if (!this._recordCount || !this._totalPages) {
|
|
523
|
-
this._totalPages = this._recordCount = 0;
|
|
524
|
-
const results = (await this.adapter.raw({ ...statement, limit: undefined })) || [];
|
|
525
|
-
this._recordCount = results.length;
|
|
526
|
-
if (this._recordCount > 0) {
|
|
527
|
-
const size = statement?.limit || this.size;
|
|
528
|
-
this._totalPages = Math.ceil(this._recordCount / size);
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
this.validatePage(page);
|
|
532
|
-
if (page !== 1) {
|
|
533
|
-
if (!this.bookMark)
|
|
534
|
-
throw new core.PagingError("No bookmark. Did you start in the first page?");
|
|
535
|
-
statement["bookmark"] = this.bookMark;
|
|
536
|
-
}
|
|
537
|
-
const rawResult = await this.adapter.raw(statement, false);
|
|
538
|
-
const { docs, bookmark, warning } = rawResult;
|
|
539
|
-
if (warning)
|
|
540
|
-
console.warn(warning);
|
|
541
|
-
if (!this.clazz)
|
|
542
|
-
throw new core.PagingError("No statement target defined");
|
|
543
|
-
const pkDef = dbDecorators.findPrimaryKey(new this.clazz());
|
|
544
|
-
const results = statement.fields && statement.fields.length
|
|
545
|
-
? docs // has fields means its not full model
|
|
546
|
-
: docs.map((d) => {
|
|
547
|
-
//no fields means we need to revert to saving process
|
|
548
|
-
const originalId = d._id.split(CouchDBKeys.SEPARATOR);
|
|
549
|
-
originalId.splice(0, 1); // remove the table name
|
|
550
|
-
return this.adapter.revert(d, this.clazz, pkDef.id, core.Sequence.parseValue(pkDef.props.type, originalId.join(CouchDBKeys.SEPARATOR)));
|
|
551
|
-
});
|
|
552
|
-
this.bookMark = bookmark;
|
|
553
|
-
this._currentPage = page;
|
|
554
|
-
return results;
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
/**
|
|
559
|
-
* @description Translates core operators to CouchDB Mango operators
|
|
560
|
-
* @summary Converts Decaf.ts core operators to their equivalent CouchDB Mango query operators
|
|
561
|
-
* @param {GroupOperator | Operator} operator - The core operator to translate
|
|
562
|
-
* @return {MangoOperator} The equivalent CouchDB Mango operator
|
|
563
|
-
* @throws {QueryError} If no translation exists for the given operator
|
|
564
|
-
* @function translateOperators
|
|
565
|
-
* @memberOf module:for-couchdb
|
|
566
|
-
* @mermaid
|
|
567
|
-
* sequenceDiagram
|
|
568
|
-
* participant Caller
|
|
569
|
-
* participant translateOperators
|
|
570
|
-
* participant CouchDBOperator
|
|
571
|
-
* participant CouchDBGroupOperator
|
|
572
|
-
*
|
|
573
|
-
* Caller->>translateOperators: operator
|
|
574
|
-
*
|
|
575
|
-
* translateOperators->>CouchDBOperator: Check for match
|
|
576
|
-
* alt Found in CouchDBOperator
|
|
577
|
-
* CouchDBOperator-->>translateOperators: Return matching operator
|
|
578
|
-
* translateOperators-->>Caller: Return MangoOperator
|
|
579
|
-
* else Not found
|
|
580
|
-
* translateOperators->>CouchDBGroupOperator: Check for match
|
|
581
|
-
* alt Found in CouchDBGroupOperator
|
|
582
|
-
* CouchDBGroupOperator-->>translateOperators: Return matching operator
|
|
583
|
-
* translateOperators-->>Caller: Return MangoOperator
|
|
584
|
-
* else Not found
|
|
585
|
-
* translateOperators-->>Caller: Throw QueryError
|
|
586
|
-
* end
|
|
587
|
-
* end
|
|
588
|
-
*/
|
|
589
|
-
function translateOperators(operator) {
|
|
590
|
-
for (const operators of [CouchDBOperator, CouchDBGroupOperator]) {
|
|
591
|
-
const el = Object.keys(operators).find((k) => k === operator);
|
|
592
|
-
if (el)
|
|
593
|
-
return operators[el];
|
|
594
|
-
}
|
|
595
|
-
throw new core.QueryError(`Could not find adapter translation for operator ${operator}`);
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
/**
|
|
599
|
-
* @description Statement builder for CouchDB Mango queries
|
|
600
|
-
* @summary Provides a fluent interface for building CouchDB Mango queries with type safety
|
|
601
|
-
* @template M - The model type that extends Model
|
|
602
|
-
* @template R - The result type
|
|
603
|
-
* @param adapter - The CouchDB adapter
|
|
604
|
-
* @class CouchDBStatement
|
|
605
|
-
* @example
|
|
606
|
-
* // Example of using CouchDBStatement
|
|
607
|
-
* const adapter = new MyCouchDBAdapter(scope);
|
|
608
|
-
* const statement = new CouchDBStatement<User, User[]>(adapter);
|
|
609
|
-
*
|
|
610
|
-
* // Build a query
|
|
611
|
-
* const users = await statement
|
|
612
|
-
* .from(User)
|
|
613
|
-
* .where(Condition.attribute<User>('age').gt(18))
|
|
614
|
-
* .orderBy('lastName', 'asc')
|
|
615
|
-
* .limit(10)
|
|
616
|
-
* .execute();
|
|
617
|
-
*/
|
|
618
|
-
class CouchDBStatement extends core.Statement {
|
|
619
|
-
constructor(adapter) {
|
|
620
|
-
super(adapter);
|
|
621
|
-
}
|
|
622
|
-
/**
|
|
623
|
-
* @description Builds a CouchDB Mango query from the statement
|
|
624
|
-
* @summary Converts the statement's conditions, selectors, and options into a CouchDB Mango query
|
|
625
|
-
* @return {MangoQuery} The built Mango query
|
|
626
|
-
* @throws {Error} If there are invalid query conditions
|
|
627
|
-
* @mermaid
|
|
628
|
-
* sequenceDiagram
|
|
629
|
-
* participant Statement
|
|
630
|
-
* participant Repository
|
|
631
|
-
* participant parseCondition
|
|
632
|
-
*
|
|
633
|
-
* Statement->>Statement: build()
|
|
634
|
-
* Note over Statement: Initialize selectors
|
|
635
|
-
* Statement->>Repository: Get table name
|
|
636
|
-
* Repository-->>Statement: Return table name
|
|
637
|
-
* Statement->>Statement: Create base query
|
|
638
|
-
*
|
|
639
|
-
* alt Has selectSelector
|
|
640
|
-
* Statement->>Statement: Add fields to query
|
|
641
|
-
* end
|
|
642
|
-
*
|
|
643
|
-
* alt Has whereCondition
|
|
644
|
-
* Statement->>Statement: Create combined condition with table
|
|
645
|
-
* Statement->>parseCondition: Parse condition
|
|
646
|
-
* parseCondition-->>Statement: Return parsed condition
|
|
647
|
-
*
|
|
648
|
-
* alt Is group operator
|
|
649
|
-
* alt Is AND operator
|
|
650
|
-
* Statement->>Statement: Flatten nested AND conditions
|
|
651
|
-
* else Is OR operator
|
|
652
|
-
* Statement->>Statement: Combine with table condition
|
|
653
|
-
* else
|
|
654
|
-
* Statement->>Statement: Throw error
|
|
655
|
-
* end
|
|
656
|
-
* else
|
|
657
|
-
* Statement->>Statement: Merge conditions with existing selector
|
|
658
|
-
* end
|
|
659
|
-
* end
|
|
660
|
-
*
|
|
661
|
-
* alt Has orderBySelector
|
|
662
|
-
* Statement->>Statement: Add sort to query
|
|
663
|
-
* Statement->>Statement: Ensure field exists in selector
|
|
664
|
-
* end
|
|
665
|
-
*
|
|
666
|
-
* alt Has limitSelector
|
|
667
|
-
* Statement->>Statement: Set limit
|
|
668
|
-
* else
|
|
669
|
-
* Statement->>Statement: Use default limit
|
|
670
|
-
* end
|
|
671
|
-
*
|
|
672
|
-
* alt Has offsetSelector
|
|
673
|
-
* Statement->>Statement: Set skip
|
|
674
|
-
* end
|
|
675
|
-
*
|
|
676
|
-
* Statement-->>Statement: Return query
|
|
677
|
-
*/
|
|
678
|
-
build() {
|
|
679
|
-
const selectors = {};
|
|
680
|
-
selectors[CouchDBKeys.TABLE] = {};
|
|
681
|
-
selectors[CouchDBKeys.TABLE] = core.Repository.table(this.fromSelector);
|
|
682
|
-
const query = { selector: selectors };
|
|
683
|
-
if (this.selectSelector)
|
|
684
|
-
query.fields = this.selectSelector;
|
|
685
|
-
if (this.whereCondition) {
|
|
686
|
-
const condition = this.parseCondition(core.Condition.and(this.whereCondition, core.Condition.attribute(CouchDBKeys.TABLE).eq(query.selector[CouchDBKeys.TABLE]))).selector;
|
|
687
|
-
const selectorKeys = Object.keys(condition);
|
|
688
|
-
if (selectorKeys.length === 1 &&
|
|
689
|
-
Object.values(CouchDBGroupOperator).indexOf(selectorKeys[0]) !== -1)
|
|
690
|
-
switch (selectorKeys[0]) {
|
|
691
|
-
case CouchDBGroupOperator.AND:
|
|
692
|
-
condition[CouchDBGroupOperator.AND] = [
|
|
693
|
-
...Object.values(condition[CouchDBGroupOperator.AND]).reduce((accum, val) => {
|
|
694
|
-
const keys = Object.keys(val);
|
|
695
|
-
if (keys.length !== 1)
|
|
696
|
-
throw new Error("Too many keys in query selector. should be one");
|
|
697
|
-
const k = keys[0];
|
|
698
|
-
if (k === CouchDBGroupOperator.AND)
|
|
699
|
-
accum.push(...val[k]);
|
|
700
|
-
else
|
|
701
|
-
accum.push(val);
|
|
702
|
-
return accum;
|
|
703
|
-
}, []),
|
|
704
|
-
];
|
|
705
|
-
query.selector = condition;
|
|
706
|
-
break;
|
|
707
|
-
case CouchDBGroupOperator.OR: {
|
|
708
|
-
const s = {};
|
|
709
|
-
s[CouchDBGroupOperator.AND] = [
|
|
710
|
-
condition,
|
|
711
|
-
...Object.entries(query.selector).map(([key, val]) => {
|
|
712
|
-
const result = {};
|
|
713
|
-
result[key] = val;
|
|
714
|
-
return result;
|
|
715
|
-
}),
|
|
716
|
-
];
|
|
717
|
-
query.selector = s;
|
|
718
|
-
break;
|
|
719
|
-
}
|
|
720
|
-
default:
|
|
721
|
-
throw new Error("This should be impossible");
|
|
722
|
-
}
|
|
723
|
-
else {
|
|
724
|
-
Object.entries(condition).forEach(([key, val]) => {
|
|
725
|
-
if (query.selector[key])
|
|
726
|
-
console.warn(`A ${key} query param is about to be overridden: ${query.selector[key]} by ${val}`);
|
|
727
|
-
query.selector[key] = val;
|
|
728
|
-
});
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
if (this.orderBySelector) {
|
|
732
|
-
query.sort = query.sort || [];
|
|
733
|
-
query.selector = query.selector || {};
|
|
734
|
-
const [selector, value] = this.orderBySelector;
|
|
735
|
-
const rec = {};
|
|
736
|
-
rec[selector] = value;
|
|
737
|
-
query.sort.push(rec);
|
|
738
|
-
if (!query.selector[selector]) {
|
|
739
|
-
query.selector[selector] = {};
|
|
740
|
-
query.selector[selector][CouchDBOperator.BIGGER] =
|
|
741
|
-
null;
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
if (this.limitSelector) {
|
|
745
|
-
query.limit = this.limitSelector;
|
|
746
|
-
}
|
|
747
|
-
else {
|
|
748
|
-
console.warn(`No limit selector defined. Using default couchdb limit of ${CouchDBQueryLimit}`);
|
|
749
|
-
query.limit = CouchDBQueryLimit;
|
|
750
|
-
}
|
|
751
|
-
if (this.offsetSelector)
|
|
752
|
-
query.skip = this.offsetSelector;
|
|
753
|
-
return query;
|
|
754
|
-
}
|
|
755
|
-
/**
|
|
756
|
-
* @description Creates a paginator for the statement
|
|
757
|
-
* @summary Builds the query and returns a CouchDBPaginator for paginated results
|
|
758
|
-
* @template R - The result type
|
|
759
|
-
* @param {number} size - The page size
|
|
760
|
-
* @return {Promise<Paginator<M, R, MangoQuery>>} A promise that resolves to a paginator
|
|
761
|
-
* @throws {InternalError} If there's an error building the query
|
|
762
|
-
*/
|
|
763
|
-
async paginate(size) {
|
|
764
|
-
try {
|
|
765
|
-
const query = this.build();
|
|
766
|
-
return new CouchDBPaginator(this.adapter, query, size, this.fromSelector);
|
|
767
|
-
}
|
|
768
|
-
catch (e) {
|
|
769
|
-
throw new dbDecorators.InternalError(e);
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
/**
|
|
773
|
-
* @description Processes a record from CouchDB
|
|
774
|
-
* @summary Extracts the ID from a CouchDB document and reverts it to a model instance
|
|
775
|
-
* @param {any} r - The raw record from CouchDB
|
|
776
|
-
* @param pkAttr - The primary key attribute of the model
|
|
777
|
-
* @param {"Number" | "BigInt" | undefined} sequenceType - The type of the sequence
|
|
778
|
-
* @return {any} The processed record
|
|
779
|
-
*/
|
|
780
|
-
processRecord(r, pkAttr, sequenceType) {
|
|
781
|
-
if (r[CouchDBKeys.ID]) {
|
|
782
|
-
const [, ...keyArgs] = r[CouchDBKeys.ID].split(CouchDBKeys.SEPARATOR);
|
|
783
|
-
const id = keyArgs.join("_");
|
|
784
|
-
return this.adapter.revert(r, this.fromSelector, pkAttr, core.Sequence.parseValue(sequenceType, id));
|
|
785
|
-
}
|
|
786
|
-
return r;
|
|
787
|
-
}
|
|
788
|
-
/**
|
|
789
|
-
* @description Executes a raw Mango query
|
|
790
|
-
* @summary Sends a raw Mango query to CouchDB and processes the results
|
|
791
|
-
* @template R - The result type
|
|
792
|
-
* @param {MangoQuery} rawInput - The raw Mango query to execute
|
|
793
|
-
* @return {Promise<R>} A promise that resolves to the query results
|
|
794
|
-
*/
|
|
795
|
-
async raw(rawInput) {
|
|
796
|
-
const results = await this.adapter.raw(rawInput, true);
|
|
797
|
-
const pkDef = dbDecorators.findPrimaryKey(new this.fromSelector());
|
|
798
|
-
const pkAttr = pkDef.id;
|
|
799
|
-
const type = pkDef.props.type;
|
|
800
|
-
if (!this.selectSelector)
|
|
801
|
-
return results.map((r) => this.processRecord(r, pkAttr, type));
|
|
802
|
-
return results;
|
|
803
|
-
}
|
|
804
|
-
/**
|
|
805
|
-
* @description Parses a condition into a CouchDB Mango query selector
|
|
806
|
-
* @summary Converts a Condition object into a CouchDB Mango query selector structure
|
|
807
|
-
* @param {Condition<M>} condition - The condition to parse
|
|
808
|
-
* @return {MangoQuery} The Mango query with the parsed condition as its selector
|
|
809
|
-
* @mermaid
|
|
810
|
-
* sequenceDiagram
|
|
811
|
-
* participant Statement
|
|
812
|
-
* participant translateOperators
|
|
813
|
-
* participant merge
|
|
814
|
-
*
|
|
815
|
-
* Statement->>Statement: parseCondition(condition)
|
|
816
|
-
*
|
|
817
|
-
* Note over Statement: Extract condition parts
|
|
818
|
-
*
|
|
819
|
-
* alt Simple comparison operator
|
|
820
|
-
* Statement->>translateOperators: translateOperators(operator)
|
|
821
|
-
* translateOperators-->>Statement: Return CouchDB operator
|
|
822
|
-
* Statement->>Statement: Create selector with attribute and operator
|
|
823
|
-
* else NOT operator
|
|
824
|
-
* Statement->>Statement: parseCondition(attr1)
|
|
825
|
-
* Statement->>translateOperators: translateOperators(Operator.NOT)
|
|
826
|
-
* translateOperators-->>Statement: Return CouchDB NOT operator
|
|
827
|
-
* Statement->>Statement: Create negated selector
|
|
828
|
-
* else AND/OR operator
|
|
829
|
-
* Statement->>Statement: parseCondition(attr1)
|
|
830
|
-
* Statement->>Statement: parseCondition(comparison)
|
|
831
|
-
* Statement->>translateOperators: translateOperators(operator)
|
|
832
|
-
* translateOperators-->>Statement: Return CouchDB group operator
|
|
833
|
-
* Statement->>merge: merge(operator, op1, op2)
|
|
834
|
-
* merge-->>Statement: Return merged selector
|
|
835
|
-
* end
|
|
836
|
-
*
|
|
837
|
-
* Statement-->>Statement: Return query with selector
|
|
838
|
-
*/
|
|
839
|
-
parseCondition(condition) {
|
|
840
|
-
/**
|
|
841
|
-
* @description Merges two selectors with a logical operator
|
|
842
|
-
* @summary Helper function to combine two selectors with a logical operator
|
|
843
|
-
* @param {MangoOperator} op - The operator to use for merging
|
|
844
|
-
* @param {MangoSelector} obj1 - The first selector
|
|
845
|
-
* @param {MangoSelector} obj2 - The second selector
|
|
846
|
-
* @return {MangoQuery} The merged query
|
|
847
|
-
*/
|
|
848
|
-
function merge(op, obj1, obj2) {
|
|
849
|
-
const result = { selector: {} };
|
|
850
|
-
result.selector[op] = [obj1, obj2];
|
|
851
|
-
return result;
|
|
852
|
-
}
|
|
853
|
-
const { attr1, operator, comparison } = condition;
|
|
854
|
-
let op = {};
|
|
855
|
-
if ([core.GroupOperator.AND, core.GroupOperator.OR, core.Operator.NOT].indexOf(operator) === -1) {
|
|
856
|
-
op[attr1] = {};
|
|
857
|
-
op[attr1][translateOperators(operator)] =
|
|
858
|
-
comparison;
|
|
859
|
-
}
|
|
860
|
-
else if (operator === core.Operator.NOT) {
|
|
861
|
-
op = this.parseCondition(attr1).selector;
|
|
862
|
-
op[translateOperators(core.Operator.NOT)] = {};
|
|
863
|
-
op[translateOperators(core.Operator.NOT)][attr1.attr1] = comparison;
|
|
864
|
-
}
|
|
865
|
-
else {
|
|
866
|
-
const op1 = this.parseCondition(attr1).selector;
|
|
867
|
-
const op2 = this.parseCondition(comparison).selector;
|
|
868
|
-
op = merge(translateOperators(operator), op1, op2).selector;
|
|
869
|
-
}
|
|
870
|
-
return { selector: op };
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
/**
|
|
875
|
-
* @description Abstract adapter for CouchDB database operations
|
|
876
|
-
* @summary Provides a base implementation for CouchDB database operations, including CRUD operations, sequence management, and error handling
|
|
877
|
-
* @template Y - The scope type
|
|
878
|
-
* @template F - The repository flags type
|
|
879
|
-
* @template C - The context type
|
|
880
|
-
* @param {Y} scope - The scope for the adapter
|
|
881
|
-
* @param {string} flavour - The flavour of the adapter
|
|
882
|
-
* @param {string} [alias] - Optional alias for the adapter
|
|
883
|
-
* @class
|
|
884
|
-
* @example
|
|
885
|
-
* // Example of extending CouchDBAdapter
|
|
886
|
-
* class MyCouchDBAdapter extends CouchDBAdapter<MyScope, MyFlags, MyContext> {
|
|
887
|
-
* constructor(scope: MyScope) {
|
|
888
|
-
* super(scope, 'my-couchdb', 'my-alias');
|
|
889
|
-
* }
|
|
890
|
-
*
|
|
891
|
-
* // Implement abstract methods
|
|
892
|
-
* async index<M extends Model>(...models: Constructor<M>[]): Promise<void> {
|
|
893
|
-
* // Implementation
|
|
894
|
-
* }
|
|
895
|
-
*
|
|
896
|
-
* async raw<R>(rawInput: MangoQuery, docsOnly: boolean): Promise<R> {
|
|
897
|
-
* // Implementation
|
|
898
|
-
* }
|
|
899
|
-
*
|
|
900
|
-
* async create(tableName: string, id: string | number, model: Record<string, any>, ...args: any[]): Promise<Record<string, any>> {
|
|
901
|
-
* // Implementation
|
|
902
|
-
* }
|
|
903
|
-
*
|
|
904
|
-
* async read(tableName: string, id: string | number, ...args: any[]): Promise<Record<string, any>> {
|
|
905
|
-
* // Implementation
|
|
906
|
-
* }
|
|
907
|
-
*
|
|
908
|
-
* async update(tableName: string, id: string | number, model: Record<string, any>, ...args: any[]): Promise<Record<string, any>> {
|
|
909
|
-
* // Implementation
|
|
910
|
-
* }
|
|
911
|
-
*
|
|
912
|
-
* async delete(tableName: string, id: string | number, ...args: any[]): Promise<Record<string, any>> {
|
|
913
|
-
* // Implementation
|
|
914
|
-
* }
|
|
915
|
-
* }
|
|
916
|
-
*/
|
|
917
|
-
class CouchDBAdapter extends core.Adapter {
|
|
918
|
-
constructor(scope, flavour, alias) {
|
|
919
|
-
super(scope, flavour, alias);
|
|
920
|
-
[this.create, this.createAll, this.update, this.updateAll].forEach((m) => {
|
|
921
|
-
const name = m.name;
|
|
922
|
-
dbDecorators.prefixMethod(this, m, this[name + "Prefix"]);
|
|
923
|
-
});
|
|
924
|
-
}
|
|
925
|
-
/**
|
|
926
|
-
* @description Creates a new CouchDB statement for querying
|
|
927
|
-
* @summary Factory method that creates a new CouchDBStatement instance for building queries
|
|
928
|
-
* @template M - The model type
|
|
929
|
-
* @return {CouchDBStatement<M, any>} A new CouchDBStatement instance
|
|
930
|
-
*/
|
|
931
|
-
Statement() {
|
|
932
|
-
return new CouchDBStatement(this);
|
|
933
|
-
}
|
|
934
|
-
/**
|
|
935
|
-
* @description Creates a new CouchDB sequence
|
|
936
|
-
* @summary Factory method that creates a new CouchDBSequence instance for managing sequences
|
|
937
|
-
* @param {SequenceOptions} options - The options for the sequence
|
|
938
|
-
* @return {Promise<Sequence>} A promise that resolves to a new Sequence instance
|
|
939
|
-
*/
|
|
940
|
-
async Sequence(options) {
|
|
941
|
-
return new CouchDBSequence(options, this);
|
|
942
|
-
}
|
|
943
|
-
/**
|
|
944
|
-
* @description Initializes the adapter by creating indexes for all managed models
|
|
945
|
-
* @summary Sets up the necessary database indexes for all models managed by this adapter
|
|
946
|
-
* @return {Promise<void>} A promise that resolves when initialization is complete
|
|
947
|
-
*/
|
|
948
|
-
async initialize() {
|
|
949
|
-
const managedModels = core.Adapter.models(this.flavour);
|
|
950
|
-
return this.index(...managedModels);
|
|
951
|
-
}
|
|
952
|
-
/**
|
|
953
|
-
* @description Assigns metadata to a model
|
|
954
|
-
* @summary Adds revision metadata to a model as a non-enumerable property
|
|
955
|
-
* @param {Record<string, any>} model - The model to assign metadata to
|
|
956
|
-
* @param {string} rev - The revision string to assign
|
|
957
|
-
* @return {Record<string, any>} The model with metadata assigned
|
|
958
|
-
*/
|
|
959
|
-
assignMetadata(model, rev) {
|
|
960
|
-
Object.defineProperty(model, core.PersistenceKeys.METADATA, {
|
|
961
|
-
enumerable: false,
|
|
962
|
-
configurable: false,
|
|
963
|
-
writable: false,
|
|
964
|
-
value: rev,
|
|
965
|
-
});
|
|
966
|
-
return model;
|
|
967
|
-
}
|
|
968
|
-
/**
|
|
969
|
-
* @description Assigns metadata to multiple models
|
|
970
|
-
* @summary Adds revision metadata to multiple models as non-enumerable properties
|
|
971
|
-
* @param models - The models to assign metadata to
|
|
972
|
-
* @param {string[]} revs - The revision strings to assign
|
|
973
|
-
* @return The models with metadata assigned
|
|
974
|
-
*/
|
|
975
|
-
assignMultipleMetadata(models, revs) {
|
|
976
|
-
models.forEach((m, i) => {
|
|
977
|
-
core.Repository.setMetadata(m, revs[i]);
|
|
978
|
-
return m;
|
|
979
|
-
});
|
|
980
|
-
return models;
|
|
981
|
-
}
|
|
982
|
-
/**
|
|
983
|
-
* @description Prepares a record for creation
|
|
984
|
-
* @summary Adds necessary CouchDB fields to a record before creation
|
|
985
|
-
* @param {string} tableName - The name of the table
|
|
986
|
-
* @param {string|number} id - The ID of the record
|
|
987
|
-
* @param {Record<string, any>} model - The model to prepare
|
|
988
|
-
* @return A tuple containing the tableName, id, and prepared record
|
|
989
|
-
*/
|
|
990
|
-
createPrefix(tableName, id, model) {
|
|
991
|
-
const record = {};
|
|
992
|
-
record[CouchDBKeys.TABLE] = tableName;
|
|
993
|
-
record[CouchDBKeys.ID] = this.generateId(tableName, id);
|
|
994
|
-
Object.assign(record, model);
|
|
995
|
-
return [tableName, id, record];
|
|
996
|
-
}
|
|
997
|
-
/**
|
|
998
|
-
* @description Prepares multiple records for creation
|
|
999
|
-
* @summary Adds necessary CouchDB fields to multiple records before creation
|
|
1000
|
-
* @param {string} tableName - The name of the table
|
|
1001
|
-
* @param {string[]|number[]} ids - The IDs of the records
|
|
1002
|
-
* @param models - The models to prepare
|
|
1003
|
-
* @return A tuple containing the tableName, ids, and prepared records
|
|
1004
|
-
* @throws {InternalError} If ids and models arrays have different lengths
|
|
1005
|
-
*/
|
|
1006
|
-
createAllPrefix(tableName, ids, models) {
|
|
1007
|
-
if (ids.length !== models.length)
|
|
1008
|
-
throw new dbDecorators.InternalError("Ids and models must have the same length");
|
|
1009
|
-
const records = ids.map((id, count) => {
|
|
1010
|
-
const record = {};
|
|
1011
|
-
record[CouchDBKeys.TABLE] = tableName;
|
|
1012
|
-
record[CouchDBKeys.ID] = this.generateId(tableName, id);
|
|
1013
|
-
Object.assign(record, models[count]);
|
|
1014
|
-
return record;
|
|
1015
|
-
});
|
|
1016
|
-
return [tableName, ids, records];
|
|
1017
|
-
}
|
|
1018
|
-
/**
|
|
1019
|
-
* @description Prepares a record for update
|
|
1020
|
-
* @summary Adds necessary CouchDB fields to a record before update
|
|
1021
|
-
* @param {string} tableName - The name of the table
|
|
1022
|
-
* @param {string|number} id - The ID of the record
|
|
1023
|
-
* @param model - The model to prepare
|
|
1024
|
-
* @return A tuple containing the tableName, id, and prepared record
|
|
1025
|
-
* @throws {InternalError} If no revision number is found in the model
|
|
1026
|
-
*/
|
|
1027
|
-
updatePrefix(tableName, id, model) {
|
|
1028
|
-
const record = {};
|
|
1029
|
-
record[CouchDBKeys.TABLE] = tableName;
|
|
1030
|
-
record[CouchDBKeys.ID] = this.generateId(tableName, id);
|
|
1031
|
-
const rev = model[core.PersistenceKeys.METADATA];
|
|
1032
|
-
if (!rev)
|
|
1033
|
-
throw new dbDecorators.InternalError(`No revision number found for record with id ${id}`);
|
|
1034
|
-
Object.assign(record, model);
|
|
1035
|
-
record[CouchDBKeys.REV] = rev;
|
|
1036
|
-
return [tableName, id, record];
|
|
1037
|
-
}
|
|
1038
|
-
/**
|
|
1039
|
-
* @description Prepares multiple records for update
|
|
1040
|
-
* @summary Adds necessary CouchDB fields to multiple records before update
|
|
1041
|
-
* @param {string} tableName - The name of the table
|
|
1042
|
-
* @param {string[]|number[]} ids - The IDs of the records
|
|
1043
|
-
* @param models - The models to prepare
|
|
1044
|
-
* @return A tuple containing the tableName, ids, and prepared records
|
|
1045
|
-
* @throws {InternalError} If ids and models arrays have different lengths or if no revision number is found in a model
|
|
1046
|
-
*/
|
|
1047
|
-
updateAllPrefix(tableName, ids, models) {
|
|
1048
|
-
if (ids.length !== models.length)
|
|
1049
|
-
throw new dbDecorators.InternalError("Ids and models must have the same length");
|
|
1050
|
-
const records = ids.map((id, count) => {
|
|
1051
|
-
const record = {};
|
|
1052
|
-
record[CouchDBKeys.TABLE] = tableName;
|
|
1053
|
-
record[CouchDBKeys.ID] = this.generateId(tableName, id);
|
|
1054
|
-
const rev = models[count][core.PersistenceKeys.METADATA];
|
|
1055
|
-
if (!rev)
|
|
1056
|
-
throw new dbDecorators.InternalError(`No revision number found for record with id ${id}`);
|
|
1057
|
-
Object.assign(record, models[count]);
|
|
1058
|
-
record[CouchDBKeys.REV] = rev;
|
|
1059
|
-
return record;
|
|
1060
|
-
});
|
|
1061
|
-
return [tableName, ids, records];
|
|
1062
|
-
}
|
|
1063
|
-
/**
|
|
1064
|
-
* @description Generates a CouchDB document ID
|
|
1065
|
-
* @summary Combines the table name and ID to create a CouchDB document ID
|
|
1066
|
-
* @param {string} tableName - The name of the table
|
|
1067
|
-
* @param {string|number} id - The ID of the record
|
|
1068
|
-
* @return {string} The generated CouchDB document ID
|
|
1069
|
-
*/
|
|
1070
|
-
generateId(tableName, id) {
|
|
1071
|
-
return [tableName, id].join(CouchDBKeys.SEPARATOR);
|
|
1072
|
-
}
|
|
1073
|
-
/**
|
|
1074
|
-
* @description Parses an error and converts it to a BaseError
|
|
1075
|
-
* @summary Converts various error types to appropriate BaseError subtypes
|
|
1076
|
-
* @param {Error|string} err - The error to parse
|
|
1077
|
-
* @param {string} [reason] - Optional reason for the error
|
|
1078
|
-
* @return {BaseError} The parsed error as a BaseError
|
|
1079
|
-
*/
|
|
1080
|
-
parseError(err, reason) {
|
|
1081
|
-
return CouchDBAdapter.parseError(err, reason);
|
|
1082
|
-
}
|
|
1083
|
-
/**
|
|
1084
|
-
* @description Checks if an attribute is reserved
|
|
1085
|
-
* @summary Determines if an attribute name is reserved in CouchDB
|
|
1086
|
-
* @param {string} attr - The attribute name to check
|
|
1087
|
-
* @return {boolean} True if the attribute is reserved, false otherwise
|
|
1088
|
-
*/
|
|
1089
|
-
isReserved(attr) {
|
|
1090
|
-
return !!attr.match(reservedAttributes);
|
|
1091
|
-
}
|
|
1092
|
-
/**
|
|
1093
|
-
* @description Static method to parse an error and convert it to a BaseError
|
|
1094
|
-
* @summary Converts various error types to appropriate BaseError subtypes based on error codes and messages
|
|
1095
|
-
* @param {Error|string} err - The error to parse
|
|
1096
|
-
* @param {string} [reason] - Optional reason for the error
|
|
1097
|
-
* @return {BaseError} The parsed error as a BaseError
|
|
1098
|
-
* @mermaid
|
|
1099
|
-
* sequenceDiagram
|
|
1100
|
-
* participant Caller
|
|
1101
|
-
* participant parseError
|
|
1102
|
-
* participant ErrorTypes
|
|
1103
|
-
*
|
|
1104
|
-
* Caller->>parseError: err, reason
|
|
1105
|
-
* Note over parseError: Check if err is already a BaseError
|
|
1106
|
-
* alt err is BaseError
|
|
1107
|
-
* parseError-->>Caller: return err
|
|
1108
|
-
* else err is string
|
|
1109
|
-
* Note over parseError: Extract code from string
|
|
1110
|
-
* alt code matches "already exist|update conflict"
|
|
1111
|
-
* parseError->>ErrorTypes: new ConflictError(code)
|
|
1112
|
-
* ErrorTypes-->>Caller: ConflictError
|
|
1113
|
-
* else code matches "missing|deleted"
|
|
1114
|
-
* parseError->>ErrorTypes: new NotFoundError(code)
|
|
1115
|
-
* ErrorTypes-->>Caller: NotFoundError
|
|
1116
|
-
* end
|
|
1117
|
-
* else err has code property
|
|
1118
|
-
* Note over parseError: Extract code and reason
|
|
1119
|
-
* else err has statusCode property
|
|
1120
|
-
* Note over parseError: Extract code and reason
|
|
1121
|
-
* else
|
|
1122
|
-
* Note over parseError: Use err.message as code
|
|
1123
|
-
* end
|
|
1124
|
-
*
|
|
1125
|
-
* Note over parseError: Switch on code
|
|
1126
|
-
* alt code is 401, 412, or 409
|
|
1127
|
-
* parseError->>ErrorTypes: new ConflictError(reason)
|
|
1128
|
-
* ErrorTypes-->>Caller: ConflictError
|
|
1129
|
-
* else code is 404
|
|
1130
|
-
* parseError->>ErrorTypes: new NotFoundError(reason)
|
|
1131
|
-
* ErrorTypes-->>Caller: NotFoundError
|
|
1132
|
-
* else code is 400
|
|
1133
|
-
* alt code matches "No index exists"
|
|
1134
|
-
* parseError->>ErrorTypes: new IndexError(err)
|
|
1135
|
-
* ErrorTypes-->>Caller: IndexError
|
|
1136
|
-
* else
|
|
1137
|
-
* parseError->>ErrorTypes: new InternalError(err)
|
|
1138
|
-
* ErrorTypes-->>Caller: InternalError
|
|
1139
|
-
* end
|
|
1140
|
-
* else code matches "ECONNREFUSED"
|
|
1141
|
-
* parseError->>ErrorTypes: new ConnectionError(err)
|
|
1142
|
-
* ErrorTypes-->>Caller: ConnectionError
|
|
1143
|
-
* else
|
|
1144
|
-
* parseError->>ErrorTypes: new InternalError(err)
|
|
1145
|
-
* ErrorTypes-->>Caller: InternalError
|
|
1146
|
-
* end
|
|
1147
|
-
*/
|
|
1148
|
-
static parseError(err, reason) {
|
|
1149
|
-
if (err instanceof dbDecorators.BaseError)
|
|
1150
|
-
return err;
|
|
1151
|
-
let code = "";
|
|
1152
|
-
if (typeof err === "string") {
|
|
1153
|
-
code = err;
|
|
1154
|
-
if (code.match(/already exist|update conflict/g))
|
|
1155
|
-
return new dbDecorators.ConflictError(code);
|
|
1156
|
-
if (code.match(/missing|deleted/g))
|
|
1157
|
-
return new dbDecorators.NotFoundError(code);
|
|
1158
|
-
}
|
|
1159
|
-
else if (err.code) {
|
|
1160
|
-
code = err.code;
|
|
1161
|
-
reason = reason || err.message;
|
|
1162
|
-
}
|
|
1163
|
-
else if (err.statusCode) {
|
|
1164
|
-
code = err.statusCode;
|
|
1165
|
-
reason = reason || err.message;
|
|
1166
|
-
}
|
|
1167
|
-
else {
|
|
1168
|
-
code = err.message;
|
|
1169
|
-
}
|
|
1170
|
-
switch (code.toString()) {
|
|
1171
|
-
case "401":
|
|
1172
|
-
case "412":
|
|
1173
|
-
case "409":
|
|
1174
|
-
return new dbDecorators.ConflictError(reason);
|
|
1175
|
-
case "404":
|
|
1176
|
-
return new dbDecorators.NotFoundError(reason);
|
|
1177
|
-
case "400":
|
|
1178
|
-
if (code.toString().match(/No\sindex\sexists/g))
|
|
1179
|
-
return new IndexError(err);
|
|
1180
|
-
return new dbDecorators.InternalError(err);
|
|
1181
|
-
default:
|
|
1182
|
-
if (code.toString().match(/ECONNREFUSED/g))
|
|
1183
|
-
return new core.ConnectionError(err);
|
|
1184
|
-
return new dbDecorators.InternalError(err);
|
|
1185
|
-
}
|
|
1186
|
-
}
|
|
1187
|
-
}
|
|
1188
|
-
tslib.__decorate([
|
|
1189
|
-
core.final(),
|
|
1190
|
-
tslib.__metadata("design:type", Function),
|
|
1191
|
-
tslib.__metadata("design:paramtypes", []),
|
|
1192
|
-
tslib.__metadata("design:returntype", CouchDBStatement)
|
|
1193
|
-
], CouchDBAdapter.prototype, "Statement", null);
|
|
1194
|
-
tslib.__decorate([
|
|
1195
|
-
core.final(),
|
|
1196
|
-
tslib.__metadata("design:type", Function),
|
|
1197
|
-
tslib.__metadata("design:paramtypes", [Object]),
|
|
1198
|
-
tslib.__metadata("design:returntype", Promise)
|
|
1199
|
-
], CouchDBAdapter.prototype, "Sequence", null);
|
|
1200
|
-
tslib.__decorate([
|
|
1201
|
-
core.final(),
|
|
1202
|
-
tslib.__metadata("design:type", Function),
|
|
1203
|
-
tslib.__metadata("design:paramtypes", [Object, String]),
|
|
1204
|
-
tslib.__metadata("design:returntype", Object)
|
|
1205
|
-
], CouchDBAdapter.prototype, "assignMetadata", null);
|
|
1206
|
-
tslib.__decorate([
|
|
1207
|
-
core.final(),
|
|
1208
|
-
tslib.__metadata("design:type", Function),
|
|
1209
|
-
tslib.__metadata("design:paramtypes", [Array, Array]),
|
|
1210
|
-
tslib.__metadata("design:returntype", Array)
|
|
1211
|
-
], CouchDBAdapter.prototype, "assignMultipleMetadata", null);
|
|
1212
|
-
tslib.__decorate([
|
|
1213
|
-
core.final(),
|
|
1214
|
-
tslib.__metadata("design:type", Function),
|
|
1215
|
-
tslib.__metadata("design:paramtypes", [String, Object, Object]),
|
|
1216
|
-
tslib.__metadata("design:returntype", void 0)
|
|
1217
|
-
], CouchDBAdapter.prototype, "createPrefix", null);
|
|
1218
|
-
tslib.__decorate([
|
|
1219
|
-
core.final(),
|
|
1220
|
-
tslib.__metadata("design:type", Function),
|
|
1221
|
-
tslib.__metadata("design:paramtypes", [String, Array, Array]),
|
|
1222
|
-
tslib.__metadata("design:returntype", void 0)
|
|
1223
|
-
], CouchDBAdapter.prototype, "createAllPrefix", null);
|
|
1224
|
-
tslib.__decorate([
|
|
1225
|
-
core.final(),
|
|
1226
|
-
tslib.__metadata("design:type", Function),
|
|
1227
|
-
tslib.__metadata("design:paramtypes", [String, Object, Object]),
|
|
1228
|
-
tslib.__metadata("design:returntype", void 0)
|
|
1229
|
-
], CouchDBAdapter.prototype, "updatePrefix", null);
|
|
1230
|
-
tslib.__decorate([
|
|
1231
|
-
core.final(),
|
|
1232
|
-
tslib.__metadata("design:type", Function),
|
|
1233
|
-
tslib.__metadata("design:paramtypes", [String, Array, Array]),
|
|
1234
|
-
tslib.__metadata("design:returntype", void 0)
|
|
1235
|
-
], CouchDBAdapter.prototype, "updateAllPrefix", null);
|
|
1236
|
-
|
|
1237
|
-
/**
|
|
1238
|
-
* @description Re-authenticates a connection to CouchDB
|
|
1239
|
-
* @summary Refreshes the authentication for a CouchDB connection using the provided credentials
|
|
1240
|
-
* @param {any} con - The CouchDB connection object
|
|
1241
|
-
* @param {string} user - The username for authentication
|
|
1242
|
-
* @param {string} pass - The password for authentication
|
|
1243
|
-
* @return {Promise<any>} A promise that resolves to the authentication result
|
|
1244
|
-
* @function reAuth
|
|
1245
|
-
* @memberOf module:for-couchdb
|
|
1246
|
-
*/
|
|
1247
|
-
async function reAuth(con, user, pass) {
|
|
1248
|
-
return con.auth(user, pass);
|
|
1249
|
-
}
|
|
1250
|
-
/**
|
|
1251
|
-
* @description Wraps a CouchDB database connection with automatic re-authentication
|
|
1252
|
-
* @summary Creates a proxy around a CouchDB database connection that automatically re-authenticates before each operation
|
|
1253
|
-
* @param {any} con - The CouchDB connection object
|
|
1254
|
-
* @param {string} dbName - The name of the database to use
|
|
1255
|
-
* @param {string} user - The username for authentication
|
|
1256
|
-
* @param {string} pass - The password for authentication
|
|
1257
|
-
* @return {any} The wrapped database connection object
|
|
1258
|
-
* @function wrapDocumentScope
|
|
1259
|
-
* @memberOf module:for-couchdb
|
|
1260
|
-
* @mermaid
|
|
1261
|
-
* sequenceDiagram
|
|
1262
|
-
* participant Client
|
|
1263
|
-
* participant wrapDocumentScope
|
|
1264
|
-
* participant DB
|
|
1265
|
-
* participant reAuth
|
|
1266
|
-
*
|
|
1267
|
-
* Client->>wrapDocumentScope: con, dbName, user, pass
|
|
1268
|
-
* wrapDocumentScope->>DB: con.use(dbName)
|
|
1269
|
-
* Note over wrapDocumentScope: Wrap DB methods with re-auth
|
|
1270
|
-
*
|
|
1271
|
-
* loop For each method (insert, get, put, destroy, find)
|
|
1272
|
-
* wrapDocumentScope->>wrapDocumentScope: Store original method
|
|
1273
|
-
* wrapDocumentScope->>wrapDocumentScope: Define new method with re-auth
|
|
1274
|
-
* end
|
|
1275
|
-
*
|
|
1276
|
-
* wrapDocumentScope->>wrapDocumentScope: Add NATIVE property with con value
|
|
1277
|
-
* wrapDocumentScope-->>Client: Return wrapped DB
|
|
1278
|
-
*
|
|
1279
|
-
* Note over Client: Later when client uses DB methods
|
|
1280
|
-
* Client->>DB: Any wrapped method call
|
|
1281
|
-
* DB->>reAuth: Authenticate before operation
|
|
1282
|
-
* reAuth-->>DB: Authentication complete
|
|
1283
|
-
* DB->>DB: Call original method
|
|
1284
|
-
* DB-->>Client: Return result
|
|
1285
|
-
*/
|
|
1286
|
-
function wrapDocumentScope(con, dbName, user, pass) {
|
|
1287
|
-
const db = con.use(dbName);
|
|
1288
|
-
["insert", "get", "put", "destroy", "find"].forEach((k) => {
|
|
1289
|
-
const original = db[k];
|
|
1290
|
-
Object.defineProperty(db, k, {
|
|
1291
|
-
enumerable: false,
|
|
1292
|
-
configurable: true,
|
|
1293
|
-
value: async (...args) => {
|
|
1294
|
-
await reAuth(con, user, pass);
|
|
1295
|
-
return original.call(db, ...args);
|
|
1296
|
-
},
|
|
1297
|
-
});
|
|
1298
|
-
});
|
|
1299
|
-
Object.defineProperty(db, CouchDBKeys.NATIVE, {
|
|
1300
|
-
enumerable: false,
|
|
1301
|
-
configurable: false,
|
|
1302
|
-
writable: false,
|
|
1303
|
-
value: con,
|
|
1304
|
-
});
|
|
1305
|
-
return db;
|
|
1306
|
-
}
|
|
1307
|
-
/**
|
|
1308
|
-
* @description Tests if an attribute name is reserved in CouchDB
|
|
1309
|
-
* @summary Checks if an attribute name starts with an underscore, which indicates it's a reserved attribute in CouchDB
|
|
1310
|
-
* @param {string} attr - The attribute name to test
|
|
1311
|
-
* @return {RegExpMatchArray|null} The match result or null if no match
|
|
1312
|
-
* @function testReservedAttributes
|
|
1313
|
-
* @memberOf module:for-couchdb
|
|
1314
|
-
*/
|
|
1315
|
-
function testReservedAttributes(attr) {
|
|
1316
|
-
const regexp = /^_.*$/g;
|
|
1317
|
-
return attr.match(regexp);
|
|
1318
|
-
}
|
|
1319
|
-
/**
|
|
1320
|
-
* @description Generates a name for a CouchDB index
|
|
1321
|
-
* @summary Creates a standardized name for a CouchDB index based on the table, attribute, compositions, and order
|
|
1322
|
-
* @param {string} attribute - The primary attribute for the index
|
|
1323
|
-
* @param {string} tableName - The name of the table
|
|
1324
|
-
* @param {string[]} [compositions] - Optional additional attributes to include in the index
|
|
1325
|
-
* @param {OrderDirection} [order] - Optional sort order for the index
|
|
1326
|
-
* @param {string} [separator=DefaultSeparator] - The separator to use between parts of the index name
|
|
1327
|
-
* @return {string} The generated index name
|
|
1328
|
-
* @function generateIndexName
|
|
1329
|
-
* @memberOf module:for-couchdb
|
|
1330
|
-
*/
|
|
1331
|
-
function generateIndexName(attribute, tableName, compositions, order, separator = dbDecorators.DefaultSeparator) {
|
|
1332
|
-
const attr = [core.PersistenceKeys.INDEX, tableName, attribute];
|
|
1333
|
-
if (compositions)
|
|
1334
|
-
attr.push(...compositions);
|
|
1335
|
-
if (order)
|
|
1336
|
-
attr.push(order);
|
|
1337
|
-
return attr.join(separator);
|
|
1338
|
-
}
|
|
1339
|
-
/**
|
|
1340
|
-
* @description Generates a CouchDB index configuration
|
|
1341
|
-
* @summary Creates a complete CreateIndexRequest object for defining a CouchDB index based on specified parameters
|
|
1342
|
-
* @param {string} attribute - The primary attribute for the index
|
|
1343
|
-
* @param {string} tableName - The name of the table
|
|
1344
|
-
* @param {string[]} [compositions] - Optional additional attributes to include in the index
|
|
1345
|
-
* @param {OrderDirection} [order] - Optional sort order for the index
|
|
1346
|
-
* @param {string} [separator=DefaultSeparator] - The separator to use between parts of the index name
|
|
1347
|
-
* @return {CreateIndexRequest} The complete index configuration object
|
|
1348
|
-
* @function generateIndexDoc
|
|
1349
|
-
* @memberOf module:for-couchdb
|
|
1350
|
-
* @mermaid
|
|
1351
|
-
* sequenceDiagram
|
|
1352
|
-
* participant Caller
|
|
1353
|
-
* participant generateIndexDoc
|
|
1354
|
-
* participant generateIndexName
|
|
1355
|
-
*
|
|
1356
|
-
* Caller->>generateIndexDoc: attribute, tableName, compositions, order, separator
|
|
1357
|
-
*
|
|
1358
|
-
* Note over generateIndexDoc: Create partial filter selector
|
|
1359
|
-
* generateIndexDoc->>generateIndexDoc: Set up filter for tableName
|
|
1360
|
-
*
|
|
1361
|
-
* alt order is specified
|
|
1362
|
-
* Note over generateIndexDoc: Create ordered fields array
|
|
1363
|
-
* generateIndexDoc->>generateIndexDoc: Create orderProp for attribute
|
|
1364
|
-
* generateIndexDoc->>generateIndexDoc: Map compositions to ordered props
|
|
1365
|
-
* generateIndexDoc->>generateIndexDoc: Create sortedTable for table field
|
|
1366
|
-
* generateIndexDoc->>generateIndexDoc: Combine all ordered fields
|
|
1367
|
-
* else
|
|
1368
|
-
* Note over generateIndexDoc: Create simple fields array
|
|
1369
|
-
* generateIndexDoc->>generateIndexDoc: Use attribute, compositions, and table as strings
|
|
1370
|
-
* end
|
|
1371
|
-
*
|
|
1372
|
-
* generateIndexDoc->>generateIndexName: Generate index name
|
|
1373
|
-
* generateIndexName-->>generateIndexDoc: Return name
|
|
1374
|
-
*
|
|
1375
|
-
* Note over generateIndexDoc: Create final index request
|
|
1376
|
-
* generateIndexDoc-->>Caller: Return CreateIndexRequest
|
|
1377
|
-
*/
|
|
1378
|
-
function generateIndexDoc(attribute, tableName, compositions, order, separator = dbDecorators.DefaultSeparator) {
|
|
1379
|
-
const partialFilterSelector = {};
|
|
1380
|
-
partialFilterSelector[CouchDBKeys.TABLE] = {};
|
|
1381
|
-
partialFilterSelector[CouchDBKeys.TABLE][CouchDBOperator.EQUAL] = tableName;
|
|
1382
|
-
let fields;
|
|
1383
|
-
if (order) {
|
|
1384
|
-
const orderProp = {};
|
|
1385
|
-
orderProp[attribute] = order;
|
|
1386
|
-
const sortedCompositions = (compositions || []).map((c) => {
|
|
1387
|
-
const r = {};
|
|
1388
|
-
r[c] = order;
|
|
1389
|
-
return r;
|
|
1390
|
-
});
|
|
1391
|
-
const sortedTable = {};
|
|
1392
|
-
sortedTable[CouchDBKeys.TABLE] = order;
|
|
1393
|
-
fields = [orderProp, ...sortedCompositions, sortedTable];
|
|
1394
|
-
}
|
|
1395
|
-
else {
|
|
1396
|
-
fields = [attribute, ...(compositions || []), CouchDBKeys.TABLE];
|
|
1397
|
-
}
|
|
1398
|
-
const name = generateIndexName(attribute, tableName, compositions, order, separator);
|
|
1399
|
-
return {
|
|
1400
|
-
index: {
|
|
1401
|
-
fields: fields,
|
|
1402
|
-
// partial_filter_selector: partialFilterSelector,
|
|
1403
|
-
},
|
|
1404
|
-
ddoc: [name, CouchDBKeys.DDOC].join(separator),
|
|
1405
|
-
name: name,
|
|
1406
|
-
};
|
|
1407
|
-
}
|
|
1408
|
-
|
|
1409
|
-
/**
|
|
1410
|
-
* @description CouchDB adapter for Decaf.ts
|
|
1411
|
-
* @summary A TypeScript adapter for CouchDB database operations, providing a seamless integration with the Decaf.ts framework. This module includes classes, interfaces, and utilities for working with CouchDB databases, including support for Mango queries, document operations, and sequence management.
|
|
1412
|
-
* @module for-couchdb
|
|
1413
|
-
*/
|
|
1414
|
-
/**
|
|
1415
|
-
* @description Stores the current package version
|
|
1416
|
-
* @summary The version string of the for-couchdb package
|
|
1417
|
-
* @const VERSION
|
|
1418
|
-
*/
|
|
1419
|
-
const VERSION = "0.3.13";
|
|
1420
|
-
/**
|
|
1421
|
-
* @description Stores the current package name
|
|
1422
|
-
* @summary The version string of the for-couchdb package
|
|
1423
|
-
* @const PACKAGE_NAME
|
|
1424
|
-
*/
|
|
1425
|
-
const PACKAGE_NAME = "@decaf-ts/for-couchdb";
|
|
1426
|
-
decoration.Metadata.registerLibrary(PACKAGE_NAME, VERSION);
|
|
1427
|
-
|
|
1428
|
-
exports.CouchDBAdapter = CouchDBAdapter;
|
|
1429
|
-
exports.CouchDBConst = CouchDBConst;
|
|
1430
|
-
exports.CouchDBGroupOperator = CouchDBGroupOperator;
|
|
1431
|
-
exports.CouchDBKeys = CouchDBKeys;
|
|
1432
|
-
exports.CouchDBOperator = CouchDBOperator;
|
|
1433
|
-
exports.CouchDBPaginator = CouchDBPaginator;
|
|
1434
|
-
exports.CouchDBQueryLimit = CouchDBQueryLimit;
|
|
1435
|
-
exports.CouchDBSequence = CouchDBSequence;
|
|
1436
|
-
exports.CouchDBStatement = CouchDBStatement;
|
|
1437
|
-
exports.IndexError = IndexError;
|
|
1438
|
-
exports.PACKAGE_NAME = PACKAGE_NAME;
|
|
1439
|
-
exports.VERSION = VERSION;
|
|
1440
|
-
exports.generateIndexDoc = generateIndexDoc;
|
|
1441
|
-
exports.generateIndexName = generateIndexName;
|
|
1442
|
-
exports.generateIndexes = generateIndexes;
|
|
1443
|
-
exports.reAuth = reAuth;
|
|
1444
|
-
exports.reservedAttributes = reservedAttributes;
|
|
1445
|
-
exports.testReservedAttributes = testReservedAttributes;
|
|
1446
|
-
exports.translateOperators = translateOperators;
|
|
1447
|
-
exports.wrapDocumentScope = wrapDocumentScope;
|
|
1448
|
-
|
|
1449
|
-
}));
|
|
1450
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yLWNvdWNoZGIuY2pzIiwic291cmNlcyI6WyIuLi9zcmMvY29uc3RhbnRzLnRzIiwiLi4vc3JjL3F1ZXJ5L2NvbnN0YW50cy50cyIsIi4uL3NyYy9pbmRleGVzL2dlbmVyYXRvci50cyIsIi4uL3NyYy9tb2RlbC9Db3VjaERCU2VxdWVuY2UudHMiLCIuLi9zcmMvc2VxdWVuY2VzL1NlcXVlbmNlLnRzIiwiLi4vc3JjL2Vycm9ycy50cyIsIi4uL3NyYy9xdWVyeS9QYWdpbmF0b3IudHMiLCIuLi9zcmMvcXVlcnkvdHJhbnNsYXRlLnRzIiwiLi4vc3JjL3F1ZXJ5L1N0YXRlbWVudC50cyIsIi4uL3NyYy9hZGFwdGVyLnRzIiwiLi4vc3JjL3V0aWxzLnRzIiwiLi4vc3JjL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGRlc2NyaXB0aW9uIFJlZ3VsYXIgZXhwcmVzc2lvbiB0byBpZGVudGlmeSByZXNlcnZlZCBhdHRyaWJ1dGVzIGluIENvdWNoREJcbiAqIEBzdW1tYXJ5IE1hdGNoZXMgYW55IGF0dHJpYnV0ZSB0aGF0IHN0YXJ0cyB3aXRoIGFuIHVuZGVyc2NvcmVcbiAqIEBjb25zdCByZXNlcnZlZEF0dHJpYnV0ZXNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWNvdWNoZGJcbiAqL1xuZXhwb3J0IGNvbnN0IHJlc2VydmVkQXR0cmlidXRlcyA9IC9eXy4qJC9nO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBLZXkgY29uc3RhbnRzIHVzZWQgaW4gQ291Y2hEQiBvcGVyYXRpb25zXG4gKiBAc3VtbWFyeSBDb2xsZWN0aW9uIG9mIHN0cmluZyBjb25zdGFudHMgZm9yIENvdWNoREIgZG9jdW1lbnQgcHJvcGVydGllcyBhbmQgb3BlcmF0aW9uc1xuICogQHR5cGVkZWYge09iamVjdH0gQ291Y2hEQktleXNUeXBlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gU0VQQVJBVE9SIC0gU2VwYXJhdG9yIHVzZWQgZm9yIGNvbWJpbmluZyB0YWJsZSBuYW1lIGFuZCBJRFxuICogQHByb3BlcnR5IHtzdHJpbmd9IElEIC0gQ291Y2hEQiBkb2N1bWVudCBJRCBmaWVsZFxuICogQHByb3BlcnR5IHtzdHJpbmd9IFJFViAtIENvdWNoREIgZG9jdW1lbnQgcmV2aXNpb24gZmllbGRcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBERUxFVEVEIC0gQ291Y2hEQiBkZWxldGVkIGRvY3VtZW50IG1hcmtlclxuICogQHByb3BlcnR5IHtzdHJpbmd9IFRBQkxFIC0gVGFibGUgbmFtZSBtYXJrZXJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBTRVFVRU5DRSAtIFNlcXVlbmNlIG1hcmtlclxuICogQHByb3BlcnR5IHtzdHJpbmd9IERET0MgLSBEZXNpZ24gZG9jdW1lbnQgbWFya2VyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gTkFUSVZFIC0gTmF0aXZlIG1hcmtlclxuICogQHByb3BlcnR5IHtzdHJpbmd9IElOREVYIC0gSW5kZXggbWFya2VyXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1jb3VjaGRiXG4gKi9cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gS2V5IGNvbnN0YW50cyB1c2VkIGluIENvdWNoREIgb3BlcmF0aW9uc1xuICogQHN1bW1hcnkgQ29sbGVjdGlvbiBvZiBzdHJpbmcgY29uc3RhbnRzIGZvciBDb3VjaERCIGRvY3VtZW50IHByb3BlcnRpZXMgYW5kIG9wZXJhdGlvbnNcbiAqIEBjb25zdCBDb3VjaERCS2V5c1xuICogQHR5cGUge0NvdWNoREJLZXlzVHlwZX1cbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWNvdWNoZGJcbiAqL1xuZXhwb3J0IGNvbnN0IENvdWNoREJLZXlzID0ge1xuICBTRVBBUkFUT1I6IFwiX19cIixcbiAgSUQ6IFwiX2lkXCIsXG4gIFJFVjogXCJfcmV2XCIsXG4gIERFTEVURUQ6IFwiX2RlbGV0ZWRcIixcbiAgVEFCTEU6IFwiPz90YWJsZVwiLFxuICBTRVFVRU5DRTogXCI/P3NlcXVlbmNlXCIsXG4gIERET0M6IFwiZGRvY1wiLFxuICBOQVRJVkU6IFwiX19uYXRpdmVcIixcbiAgSU5ERVg6IFwiaW5kZXhcIixcbn07XG4iLCJpbXBvcnQgeyBNYW5nb09wZXJhdG9yIH0gZnJvbSBcIi4uL3R5cGVzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlZmF1bHQgcXVlcnkgbGltaXQgZm9yIENvdWNoREIgcXVlcmllc1xuICogQHN1bW1hcnkgTWF4aW11bSBudW1iZXIgb2YgZG9jdW1lbnRzIHRvIHJldHVybiBpbiBhIHNpbmdsZSBxdWVyeVxuICogQGNvbnN0IENvdWNoREJRdWVyeUxpbWl0XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1jb3VjaGRiXG4gKi9cbmV4cG9ydCBjb25zdCBDb3VjaERCUXVlcnlMaW1pdCA9IDI1MDtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTWFwcGluZyBvZiBvcGVyYXRvciBuYW1lcyB0byBDb3VjaERCIE1hbmdvIHF1ZXJ5IG9wZXJhdG9yc1xuICogQHN1bW1hcnkgQ29uc3RhbnRzIGZvciBDb3VjaERCIGNvbXBhcmlzb24gb3BlcmF0b3JzIHVzZWQgaW4gTWFuZ28gcXVlcmllc1xuICogQHR5cGVkZWYge09iamVjdH0gQ291Y2hEQk9wZXJhdG9yVHlwZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IEVRVUFMIC0gRXF1YWxpdHkgb3BlcmF0b3IgKCRlcSlcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBESUZGRVJFTlQgLSBJbmVxdWFsaXR5IG9wZXJhdG9yICgkbmUpXG4gKiBAcHJvcGVydHkge3N0cmluZ30gQklHR0VSIC0gR3JlYXRlciB0aGFuIG9wZXJhdG9yICgkZ3QpXG4gKiBAcHJvcGVydHkge3N0cmluZ30gQklHR0VSX0VRIC0gR3JlYXRlciB0aGFuIG9yIGVxdWFsIG9wZXJhdG9yICgkZ3RlKVxuICogQHByb3BlcnR5IHtzdHJpbmd9IFNNQUxMRVIgLSBMZXNzIHRoYW4gb3BlcmF0b3IgKCRsdClcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBTTUFMTEVSX0VRIC0gTGVzcyB0aGFuIG9yIGVxdWFsIG9wZXJhdG9yICgkbHRlKVxuICogQHByb3BlcnR5IHtzdHJpbmd9IE5PVCAtIE5lZ2F0aW9uIG9wZXJhdG9yICgkbm90KVxuICogQHByb3BlcnR5IHtzdHJpbmd9IElOIC0gSW4gYXJyYXkgb3BlcmF0b3IgKCRpbilcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBSRUdFWFAgLSBSZWd1bGFyIGV4cHJlc3Npb24gb3BlcmF0b3IgKCRyZWdleClcbiAqIEBjb25zdCBDb3VjaERCT3BlcmF0b3JcbiAqIEB0eXBlIHtDb3VjaERCT3BlcmF0b3JUeXBlfVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItY291Y2hkYlxuICovXG5leHBvcnQgY29uc3QgQ291Y2hEQk9wZXJhdG9yOiBSZWNvcmQ8c3RyaW5nLCBNYW5nb09wZXJhdG9yPiA9IHtcbiAgRVFVQUw6IFwiJGVxXCIsXG4gIERJRkZFUkVOVDogXCIkbmVcIixcbiAgQklHR0VSOiBcIiRndFwiLFxuICBCSUdHRVJfRVE6IFwiJGd0ZVwiLFxuICBTTUFMTEVSOiBcIiRsdFwiLFxuICBTTUFMTEVSX0VROiBcIiRsdGVcIixcbiAgLy8gQkVUV0VFTiA9IFwiQkVUV0VFTlwiLFxuICBOT1Q6IFwiJG5vdFwiLFxuICBJTjogXCIkaW5cIixcbiAgLy8gSVMgPSBcIklTXCIsXG4gIFJFR0VYUDogXCIkcmVnZXhcIixcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIE1hcHBpbmcgb2YgbG9naWNhbCBvcGVyYXRvciBuYW1lcyB0byBDb3VjaERCIE1hbmdvIHF1ZXJ5IG9wZXJhdG9yc1xuICogQHN1bW1hcnkgQ29uc3RhbnRzIGZvciBDb3VjaERCIGxvZ2ljYWwgb3BlcmF0b3JzIHVzZWQgaW4gTWFuZ28gcXVlcmllc1xuICogQHR5cGVkZWYge09iamVjdH0gQ291Y2hEQkdyb3VwT3BlcmF0b3JUeXBlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gQU5EIC0gTG9naWNhbCBBTkQgb3BlcmF0b3IgKCRhbmQpXG4gKiBAcHJvcGVydHkge3N0cmluZ30gT1IgLSBMb2dpY2FsIE9SIG9wZXJhdG9yICgkb3IpXG4gKiBAY29uc3QgQ291Y2hEQkdyb3VwT3BlcmF0b3JcbiAqIEB0eXBlIHtDb3VjaERCR3JvdXBPcGVyYXRvclR5cGV9XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1jb3VjaGRiXG4gKi9cbmV4cG9ydCBjb25zdCBDb3VjaERCR3JvdXBPcGVyYXRvcjogUmVjb3JkPHN0cmluZywgTWFuZ29PcGVyYXRvcj4gPSB7XG4gIEFORDogXCIkYW5kXCIsXG4gIE9SOiBcIiRvclwiLFxufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU3BlY2lhbCBjb25zdGFudCB2YWx1ZXMgdXNlZCBpbiBDb3VjaERCIHF1ZXJpZXNcbiAqIEBzdW1tYXJ5IFN0cmluZyBjb25zdGFudHMgcmVwcmVzZW50aW5nIHNwZWNpYWwgdmFsdWVzIGluIENvdWNoREJcbiAqIEB0eXBlZGVmIHtPYmplY3R9IENvdWNoREJDb25zdFR5cGVcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBOVUxMIC0gU3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIG51bGwgdmFsdWVcbiAqIEBjb25zdCBDb3VjaERCQ29uc3RcbiAqIEB0eXBlIHtDb3VjaERCQ29uc3RUeXBlfVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItY291Y2hkYlxuICovXG5leHBvcnQgY29uc3QgQ291Y2hEQkNvbnN0OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICBOVUxMOiBcIm51bGxcIixcbn07XG4iLCJpbXBvcnQge1xuICBJbmRleE1ldGFkYXRhLFxuICBPcmRlckRpcmVjdGlvbixcbiAgUGVyc2lzdGVuY2VLZXlzLFxuICBSZXBvc2l0b3J5LFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IENvdWNoREJLZXlzIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgRGVmYXVsdFNlcGFyYXRvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgQ291Y2hEQk9wZXJhdG9yIH0gZnJvbSBcIi4uL3F1ZXJ5L2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgQ3JlYXRlSW5kZXhSZXF1ZXN0IH0gZnJvbSBcIi4uL3R5cGVzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEdlbmVyYXRlcyBhIG5hbWUgZm9yIGEgQ291Y2hEQiBpbmRleFxuICogQHN1bW1hcnkgQ3JlYXRlcyBhIHN0YW5kYXJkaXplZCBuYW1lIGZvciBhIENvdWNoREIgaW5kZXggYnkgY29tYmluaW5nIG5hbWUgcGFydHMsIGNvbXBvc2l0aW9ucywgYW5kIGRpcmVjdGlvblxuICogQHBhcmFtIHtzdHJpbmdbXX0gbmFtZSAtIEFycmF5IG9mIG5hbWUgcGFydHMgZm9yIHRoZSBpbmRleFxuICogQHBhcmFtIHtPcmRlckRpcmVjdGlvbn0gW2RpcmVjdGlvbl0gLSBPcHRpb25hbCBzb3J0IGRpcmVjdGlvbiBmb3IgdGhlIGluZGV4XG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBbY29tcG9zaXRpb25zXSAtIE9wdGlvbmFsIGFkZGl0aW9uYWwgYXR0cmlidXRlcyB0byBpbmNsdWRlIGluIHRoZSBpbmRleCBuYW1lXG4gKiBAcGFyYW0ge3N0cmluZ30gW3NlcGFyYXRvcj1EZWZhdWx0U2VwYXJhdG9yXSAtIFRoZSBzZXBhcmF0b3IgdG8gdXNlIGJldHdlZW4gcGFydHMgb2YgdGhlIGluZGV4IG5hbWVcbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGdlbmVyYXRlZCBpbmRleCBuYW1lXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1jb3VjaGRiXG4gKi9cbmZ1bmN0aW9uIGdlbmVyYXRlSW5kZXhOYW1lKFxuICBuYW1lOiBzdHJpbmdbXSxcbiAgZGlyZWN0aW9uPzogT3JkZXJEaXJlY3Rpb24sXG4gIGNvbXBvc2l0aW9ucz86IHN0cmluZ1tdLFxuICBzZXBhcmF0b3IgPSBEZWZhdWx0U2VwYXJhdG9yXG4pIHtcbiAgcmV0dXJuIFtcbiAgICAuLi5uYW1lLm1hcCgobikgPT4gKG4gPT09IENvdWNoREJLZXlzLlRBQkxFID8gXCJ0YWJsZVwiIDogbikpLFxuICAgIC4uLihjb21wb3NpdGlvbnMgfHwgW10pLFxuICAgIC4uLihkaXJlY3Rpb24gPyBbZGlyZWN0aW9uXSA6IFtdKSxcbiAgICBDb3VjaERCS2V5cy5JTkRFWCxcbiAgXS5qb2luKHNlcGFyYXRvcik7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEdlbmVyYXRlcyBDb3VjaERCIGluZGV4IGNvbmZpZ3VyYXRpb25zIGZvciBtb2RlbHNcbiAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBzZXQgb2YgQ291Y2hEQiBpbmRleCBjb25maWd1cmF0aW9ucyBiYXNlZCBvbiB0aGUgbWV0YWRhdGEgb2YgdGhlIHByb3ZpZGVkIG1vZGVsc1xuICogQHRlbXBsYXRlIE0gLSBUaGUgbW9kZWwgdHlwZSB0aGF0IGV4dGVuZHMgTW9kZWxcbiAqIEBwYXJhbSBtb2RlbHMgLSBBcnJheSBvZiBtb2RlbCBjb25zdHJ1Y3RvcnMgdG8gZ2VuZXJhdGUgaW5kZXhlcyBmb3JcbiAqIEByZXR1cm4ge0NyZWF0ZUluZGV4UmVxdWVzdFtdfSBBcnJheSBvZiBDb3VjaERCIGluZGV4IGNvbmZpZ3VyYXRpb25zXG4gKiBAZnVuY3Rpb24gZ2VuZXJhdGVJbmRleGVzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1jb3VjaGRiXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBnZW5lcmF0ZUluZGV4ZXNcbiAqICAgcGFydGljaXBhbnQgZ2VuZXJhdGVJbmRleE5hbWVcbiAqICAgcGFydGljaXBhbnQgUmVwb3NpdG9yeVxuICpcbiAqICAgQ2FsbGVyLT4+Z2VuZXJhdGVJbmRleGVzOiBtb2RlbHNcbiAqXG4gKiAgIE5vdGUgb3ZlciBnZW5lcmF0ZUluZGV4ZXM6IENyZWF0ZSBiYXNlIHRhYmxlIGluZGV4XG4gKiAgIGdlbmVyYXRlSW5kZXhlcy0+PmdlbmVyYXRlSW5kZXhOYW1lOiBbQ291Y2hEQktleXMuVEFCTEVdXG4gKiAgIGdlbmVyYXRlSW5kZXhOYW1lLS0+PmdlbmVyYXRlSW5kZXhlczogdGFibGVOYW1lXG4gKiAgIGdlbmVyYXRlSW5kZXhlcy0+PmdlbmVyYXRlSW5kZXhlczogQ3JlYXRlIHRhYmxlIGluZGV4IGNvbmZpZ1xuICpcbiAqICAgbG9vcCBGb3IgZWFjaCBtb2RlbFxuICogICAgIGdlbmVyYXRlSW5kZXhlcy0+PlJlcG9zaXRvcnk6IEdldCBpbmRleGVzIG1ldGFkYXRhXG4gKiAgICAgUmVwb3NpdG9yeS0tPj5nZW5lcmF0ZUluZGV4ZXM6IGluZGV4IG1ldGFkYXRhXG4gKlxuICogICAgIGxvb3AgRm9yIGVhY2ggaW5kZXggaW4gbWV0YWRhdGFcbiAqICAgICAgIE5vdGUgb3ZlciBnZW5lcmF0ZUluZGV4ZXM6IEV4dHJhY3QgaW5kZXggcHJvcGVydGllc1xuICogICAgICAgZ2VuZXJhdGVJbmRleGVzLT4+UmVwb3NpdG9yeTogR2V0IHRhYmxlIG5hbWVcbiAqICAgICAgIFJlcG9zaXRvcnktLT4+Z2VuZXJhdGVJbmRleGVzOiB0YWJsZU5hbWVcbiAqXG4gKiAgICAgICBOb3RlIG92ZXIgZ2VuZXJhdGVJbmRleGVzOiBEZWZpbmUgbmVzdGVkIGdlbmVyYXRlIGZ1bmN0aW9uXG4gKlxuICogICAgICAgZ2VuZXJhdGVJbmRleGVzLT4+Z2VuZXJhdGVJbmRleGVzOiBDYWxsIGdlbmVyYXRlKCkgZm9yIGRlZmF1bHQgb3JkZXJcbiAqICAgICAgIE5vdGUgb3ZlciBnZW5lcmF0ZUluZGV4ZXM6IENyZWF0ZSBpbmRleCBuYW1lIGFuZCBjb25maWdcbiAqXG4gKiAgICAgICBhbHQgSGFzIGRpcmVjdGlvbnNcbiAqICAgICAgICAgbG9vcCBGb3IgZWFjaCBkaXJlY3Rpb25cbiAqICAgICAgICAgICBnZW5lcmF0ZUluZGV4ZXMtPj5nZW5lcmF0ZUluZGV4ZXM6IENhbGwgZ2VuZXJhdGUoZGlyZWN0aW9uKVxuICogICAgICAgICAgIE5vdGUgb3ZlciBnZW5lcmF0ZUluZGV4ZXM6IENyZWF0ZSBvcmRlcmVkIGluZGV4IGNvbmZpZ1xuICogICAgICAgICBlbmRcbiAqICAgICAgIGVuZFxuICogICAgIGVuZFxuICogICBlbmRcbiAqXG4gKiAgIGdlbmVyYXRlSW5kZXhlcy0tPj5DYWxsZXI6IEFycmF5IG9mIGluZGV4IGNvbmZpZ3VyYXRpb25zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZUluZGV4ZXM8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWxzOiBDb25zdHJ1Y3RvcjxNPltdXG4pOiBDcmVhdGVJbmRleFJlcXVlc3RbXSB7XG4gIGNvbnN0IHRhYmxlTmFtZSA9IGdlbmVyYXRlSW5kZXhOYW1lKFtDb3VjaERCS2V5cy5UQUJMRV0pO1xuICBjb25zdCBpbmRleGVzOiBSZWNvcmQ8c3RyaW5nLCBDcmVhdGVJbmRleFJlcXVlc3Q+ID0ge307XG4gIGluZGV4ZXNbdGFibGVOYW1lXSA9IHtcbiAgICBpbmRleDoge1xuICAgICAgZmllbGRzOiBbQ291Y2hEQktleXMuVEFCTEVdLFxuICAgIH0sXG4gICAgbmFtZTogdGFibGVOYW1lLFxuICAgIGRkb2M6IHRhYmxlTmFtZSxcbiAgICB0eXBlOiBcImpzb25cIixcbiAgfTtcblxuICBtb2RlbHMuZm9yRWFjaCgobSkgPT4ge1xuICAgIGNvbnN0IGluZDogUmVjb3JkPHN0cmluZywgSW5kZXhNZXRhZGF0YT4gPSBSZXBvc2l0b3J5LmluZGV4ZXMobSk7XG4gICAgT2JqZWN0LmVudHJpZXMoaW5kKS5mb3JFYWNoKChba2V5LCB2YWx1ZV0pID0+IHtcbiAgICAgIGNvbnN0IGsgPSBPYmplY3Qua2V5cyh2YWx1ZSlbMF07XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcHJlZmVyLWNvbnN0XG4gICAgICBsZXQgeyBkaXJlY3Rpb25zLCBjb21wb3NpdGlvbnMgfSA9ICh2YWx1ZSBhcyBhbnkpW2tdO1xuICAgICAgY29uc3QgdGFibGVOYW1lID0gUmVwb3NpdG9yeS50YWJsZShtKTtcbiAgICAgIGNvbXBvc2l0aW9ucyA9IGNvbXBvc2l0aW9ucyB8fCBbXTtcblxuICAgICAgZnVuY3Rpb24gZ2VuZXJhdGUoc29ydD86IE9yZGVyRGlyZWN0aW9uKSB7XG4gICAgICAgIGNvbnN0IG5hbWUgPSBbXG4gICAgICAgICAgdGFibGVOYW1lLFxuICAgICAgICAgIGtleSxcbiAgICAgICAgICAuLi4oY29tcG9zaXRpb25zIGFzIFtdKSxcbiAgICAgICAgICBQZXJzaXN0ZW5jZUtleXMuSU5ERVgsXG4gICAgICAgIF0uam9pbihEZWZhdWx0U2VwYXJhdG9yKTtcblxuICAgICAgICBpbmRleGVzW25hbWVdID0ge1xuICAgICAgICAgIGluZGV4OiB7XG4gICAgICAgICAgICBmaWVsZHM6IFtrZXksIC4uLihjb21wb3NpdGlvbnMgYXMgW10pLCBDb3VjaERCS2V5cy5UQUJMRV0ucmVkdWNlKFxuICAgICAgICAgICAgICAoYWNjdW06IGFueVtdLCBlbCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChzb3J0KSB7XG4gICAgICAgICAgICAgICAgICBjb25zdCByZXM6IGFueSA9IHt9O1xuICAgICAgICAgICAgICAgICAgcmVzW2VsXSA9IHNvcnQ7XG4gICAgICAgICAgICAgICAgICBhY2N1bS5wdXNoKHJlcyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIGFjY3VtLnB1c2goZWwpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gYWNjdW07XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIFtdXG4gICAgICAgICAgICApLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgICBkZG9jOiBuYW1lLFxuICAgICAgICAgIHR5cGU6IFwianNvblwiLFxuICAgICAgICB9O1xuICAgICAgICBpZiAoIXNvcnQpIHtcbiAgICAgICAgICBjb25zdCB0YWJsZUZpbHRlcjogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgICAgICAgIHRhYmxlRmlsdGVyW0NvdWNoREJLZXlzLlRBQkxFXSA9IHt9O1xuICAgICAgICAgIHRhYmxlRmlsdGVyW0NvdWNoREJLZXlzLlRBQkxFXVtDb3VjaERCT3BlcmF0b3IuRVFVQUxdID0gdGFibGVOYW1lO1xuICAgICAgICAgIGluZGV4ZXNbbmFtZV0uaW5kZXgucGFydGlhbF9maWx0ZXJfc2VsZWN0b3IgPSB0YWJsZUZpbHRlcjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBnZW5lcmF0ZSgpO1xuICAgICAgaWYgKGRpcmVjdGlvbnMpXG4gICAgICAgIChkaXJlY3Rpb25zIGFzIHVua25vd24gYXMgT3JkZXJEaXJlY3Rpb25bXSkuZm9yRWFjaCgoZCkgPT4gZ2VuZXJhdGUoZCkpO1xuICAgIH0pO1xuICB9KTtcbiAgcmV0dXJuIE9iamVjdC52YWx1ZXMoaW5kZXhlcyk7XG59XG4iLCJpbXBvcnQgdHlwZSB7IE1vZGVsQXJnIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgbW9kZWwsIHJlcXVpcmVkIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgQmFzZU1vZGVsLCBwaywgaW5kZXgsIHRhYmxlIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBDb3VjaERCS2V5cyB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTW9kZWwgZm9yIENvdWNoREIgc2VxdWVuY2UgcmVjb3Jkc1xuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhIHNlcXVlbmNlIGluIENvdWNoREIgdXNlZCBmb3IgZ2VuZXJhdGluZyBzZXF1ZW50aWFsIElEc1xuICogQHBhcmFtIHtNb2RlbEFyZzxTZXF1ZW5jZT59IFtzZXFdIC0gT3B0aW9uYWwgaW5pdGlhbGl6YXRpb24gZGF0YSBmb3IgdGhlIHNlcXVlbmNlXG4gKiBAY2xhc3NcbiAqIEBleGFtcGxlXG4gKiAvLyBFeGFtcGxlIG9mIGNyZWF0aW5nIGFuZCB1c2luZyBhIFNlcXVlbmNlXG4gKiBjb25zdCBzZXF1ZW5jZSA9IG5ldyBTZXF1ZW5jZSh7IGlkOiAndXNlci1zZXEnLCBjdXJyZW50OiAxIH0pO1xuICogLy8gSW5jcmVtZW50IHRoZSBzZXF1ZW5jZVxuICogc2VxdWVuY2UuY3VycmVudCA9IE51bWJlcihzZXF1ZW5jZS5jdXJyZW50KSArIDE7XG4gKi9cbkB0YWJsZShDb3VjaERCS2V5cy5TRVFVRU5DRSlcbkBtb2RlbCgpXG5leHBvcnQgY2xhc3MgU2VxdWVuY2UgZXh0ZW5kcyBCYXNlTW9kZWwge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSB1bmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHNlcXVlbmNlXG4gICAqIEBzdW1tYXJ5IFByaW1hcnkga2V5IGZvciB0aGUgc2VxdWVuY2UgcmVjb3JkXG4gICAqL1xuICBAcGsoKVxuICBpZCE6IHN0cmluZztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBjdXJyZW50IHZhbHVlIG9mIHRoZSBzZXF1ZW5jZVxuICAgKiBAc3VtbWFyeSBDdXJyZW50IHNlcXVlbmNlIHZhbHVlIHRoYXQgY2FuIGJlIGluY3JlbWVudGVkXG4gICAqL1xuICBAcmVxdWlyZWQoKVxuICBAaW5kZXgoKVxuICBjdXJyZW50ITogc3RyaW5nIHwgbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKHNlcT86IE1vZGVsQXJnPFNlcXVlbmNlPikge1xuICAgIHN1cGVyKHNlcSk7XG4gIH1cbn1cbiIsImltcG9ydCB7IFNlcXVlbmNlIGFzIFNlcSB9IGZyb20gXCIuLi9tb2RlbC9Db3VjaERCU2VxdWVuY2VcIjtcbmltcG9ydCB7IEludGVybmFsRXJyb3IsIE5vdEZvdW5kRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IEFkYXB0ZXIsIFJlcG9zaXRvcnksIFNlcXVlbmNlT3B0aW9ucyB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgU2VxdWVuY2UgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IE1hbmdvUXVlcnkgfSBmcm9tIFwiLi4vdHlwZXNcIjtcbmltcG9ydCB7IENvdWNoREJSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL2ludGVyZmFjZXNcIjtcblxuLyoqXG4gKiBAc3VtbWFyeSBBYnN0cmFjdCBpbXBsZW1lbnRhdGlvbiBvZiBhIFNlcXVlbmNlXG4gKiBAZGVzY3JpcHRpb24gcHJvdmlkZXMgdGhlIGJhc2ljIGZ1bmN0aW9uYWxpdHkgZm9yIHtAbGluayBTZXF1ZW5jZX1zXG4gKlxuICogQHBhcmFtIHtTZXF1ZW5jZU9wdGlvbnN9IG9wdGlvbnNcbiAqXG4gKiBAY2xhc3MgQ291Y2hEQlNlcXVlbmNlXG4gKiBAaW1wbGVtZW50cyBTZXF1ZW5jZVxuICovXG5leHBvcnQgY2xhc3MgQ291Y2hEQlNlcXVlbmNlIGV4dGVuZHMgU2VxdWVuY2Uge1xuICBwcm90ZWN0ZWQgcmVwbzogQ291Y2hEQlJlcG9zaXRvcnk8U2VxLCBhbnksIGFueSwgYW55LCBhbnk+O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIG9wdGlvbnM6IFNlcXVlbmNlT3B0aW9ucyxcbiAgICBhZGFwdGVyOiBBZGFwdGVyPGFueSwgYW55LCBNYW5nb1F1ZXJ5LCBhbnksIGFueT5cbiAgKSB7XG4gICAgc3VwZXIob3B0aW9ucyk7XG4gICAgdGhpcy5yZXBvID0gUmVwb3NpdG9yeS5mb3JNb2RlbChTZXEsIGFkYXB0ZXIuYWxpYXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyB0aGUgY3VycmVudCB2YWx1ZSBmb3IgdGhlIHNlcXVlbmNlXG4gICAqIEBwcm90ZWN0ZWRcbiAgICovXG4gIGFzeW5jIGN1cnJlbnQoKTogUHJvbWlzZTxzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQ+IHtcbiAgICBjb25zdCB7IG5hbWUsIHN0YXJ0V2l0aCB9ID0gdGhpcy5vcHRpb25zO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBzZXF1ZW5jZTogU2VxID0gYXdhaXQgdGhpcy5yZXBvLnJlYWQobmFtZSBhcyBzdHJpbmcpO1xuICAgICAgcmV0dXJuIHRoaXMucGFyc2Uoc2VxdWVuY2UuY3VycmVudCBhcyBzdHJpbmcgfCBudW1iZXIpO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgaWYgKGUgaW5zdGFuY2VvZiBOb3RGb3VuZEVycm9yKSB7XG4gICAgICAgIGlmICh0eXBlb2Ygc3RhcnRXaXRoID09PSBcInVuZGVmaW5lZFwiKVxuICAgICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICAgICAgXCJTdGFydGluZyB2YWx1ZSBpcyBub3QgZGVmaW5lZCBmb3IgYSBub24gZXhpc3Rpbmcgc2VxdWVuY2VcIlxuICAgICAgICAgICk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMucGFyc2Uoc3RhcnRXaXRoKTtcbiAgICAgICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICAgICAgYEZhaWxlZCB0byBwYXJzZSBpbml0aWFsIHZhbHVlIGZvciBzZXF1ZW5jZSAke3N0YXJ0V2l0aH06ICR7ZX1gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBGYWlsZWQgdG8gcmV0cmlldmUgY3VycmVudCB2YWx1ZSBmb3Igc2VxdWVuY2UgJHtuYW1lfTogJHtlfWBcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IFBhcnNlcyB0aGUge0BsaW5rIFNlcXVlbmNlfSB2YWx1ZVxuICAgKlxuICAgKiBAcHJvdGVjdGVkXG4gICAqIEBwYXJhbSB2YWx1ZVxuICAgKi9cbiAgcHJpdmF0ZSBwYXJzZSh2YWx1ZTogc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50KTogc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50IHtcbiAgICByZXR1cm4gU2VxdWVuY2UucGFyc2VWYWx1ZSh0aGlzLm9wdGlvbnMudHlwZSwgdmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IGluY3JlbWVudHMgdGhlIHNlcXVlbmNlXG4gICAqIEBkZXNjcmlwdGlvbiBTZXF1ZW5jZSBzcGVjaWZpYyBpbXBsZW1lbnRhdGlvblxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlciB8IGJpZ2ludH0gY3VycmVudFxuICAgKiBAcGFyYW0gY291bnRcbiAgICogQHByb3RlY3RlZFxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBpbmNyZW1lbnQoXG4gICAgY3VycmVudDogc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50LFxuICAgIGNvdW50PzogbnVtYmVyXG4gICk6IFByb21pc2U8c3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50PiB7XG4gICAgY29uc3QgeyB0eXBlLCBpbmNyZW1lbnRCeSwgbmFtZSB9ID0gdGhpcy5vcHRpb25zO1xuICAgIGxldCBuZXh0OiBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQ7XG4gICAgY29uc3QgdG9JbmNyZW1lbnRCeSA9IGNvdW50IHx8IGluY3JlbWVudEJ5O1xuICAgIGlmICh0b0luY3JlbWVudEJ5ICUgaW5jcmVtZW50QnkgIT09IDApXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgYFZhbHVlIHRvIGluY3JlbWVudCBkb2VzIG5vdCBjb25zaWRlciB0aGUgaW5jcmVtZW50Qnkgc2V0dGluZzogJHtpbmNyZW1lbnRCeX1gXG4gICAgICApO1xuICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgY2FzZSBcIk51bWJlclwiOlxuICAgICAgICBuZXh0ID0gKHRoaXMucGFyc2UoY3VycmVudCkgYXMgbnVtYmVyKSArIHRvSW5jcmVtZW50Qnk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcIkJpZ0ludFwiOlxuICAgICAgICBuZXh0ID0gKHRoaXMucGFyc2UoY3VycmVudCkgYXMgYmlnaW50KSArIEJpZ0ludCh0b0luY3JlbWVudEJ5KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIlNob3VsZCBuZXZlciBoYXBwZW5cIik7XG4gICAgfVxuICAgIGxldCBzZXE6IFNlcTtcbiAgICB0cnkge1xuICAgICAgc2VxID0gYXdhaXQgdGhpcy5yZXBvLnVwZGF0ZShuZXcgU2VxKHsgaWQ6IG5hbWUsIGN1cnJlbnQ6IG5leHQgfSkpO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIE5vdEZvdW5kRXJyb3IpKSB0aHJvdyBlO1xuICAgICAgc2VxID0gYXdhaXQgdGhpcy5yZXBvLmNyZWF0ZShuZXcgU2VxKHsgaWQ6IG5hbWUsIGN1cnJlbnQ6IG5leHQgfSkpO1xuICAgIH1cblxuICAgIHJldHVybiBzZXEuY3VycmVudCBhcyBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQ7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgR2VuZXJhdGVzIHRoZSBuZXh0IHZhbHVlIGluIHRoIHNlcXVlbmNlXG4gICAqIEBkZXNjcmlwdGlvbiBjYWxscyB7QGxpbmsgU2VxdWVuY2UjcGFyc2V9IG9uIHRoZSBjdXJyZW50IHZhbHVlXG4gICAqIGZvbGxvd2VkIGJ5IHtAbGluayBTZXF1ZW5jZSNpbmNyZW1lbnR9XG4gICAqXG4gICAqL1xuICBhc3luYyBuZXh0KCk6IFByb21pc2U8bnVtYmVyIHwgc3RyaW5nIHwgYmlnaW50PiB7XG4gICAgY29uc3QgY3VycmVudCA9IGF3YWl0IHRoaXMuY3VycmVudCgpO1xuICAgIHJldHVybiB0aGlzLmluY3JlbWVudChjdXJyZW50KTtcbiAgfVxuXG4gIGFzeW5jIHJhbmdlKGNvdW50OiBudW1iZXIpOiBQcm9taXNlPChudW1iZXIgfCBzdHJpbmcgfCBiaWdpbnQpW10+IHtcbiAgICBjb25zdCBjdXJyZW50ID0gKGF3YWl0IHRoaXMuY3VycmVudCgpKSBhcyBudW1iZXI7XG4gICAgY29uc3QgaW5jcmVtZW50QnkgPSB0aGlzLnBhcnNlKHRoaXMub3B0aW9ucy5pbmNyZW1lbnRCeSkgYXMgbnVtYmVyO1xuICAgIGNvbnN0IG5leHQ6IHN0cmluZyB8IG51bWJlciB8IGJpZ2ludCA9IGF3YWl0IHRoaXMuaW5jcmVtZW50KFxuICAgICAgY3VycmVudCxcbiAgICAgICh0aGlzLnBhcnNlKGNvdW50KSBhcyBudW1iZXIpICogaW5jcmVtZW50QnlcbiAgICApO1xuICAgIGNvbnN0IHJhbmdlOiAobnVtYmVyIHwgc3RyaW5nIHwgYmlnaW50KVtdID0gW107XG4gICAgZm9yIChsZXQgaTogbnVtYmVyID0gMTsgaSA8PSBjb3VudDsgaSsrKSB7XG4gICAgICByYW5nZS5wdXNoKGN1cnJlbnQgKyBpbmNyZW1lbnRCeSAqICh0aGlzLnBhcnNlKGkpIGFzIG51bWJlcikpO1xuICAgIH1cbiAgICBpZiAocmFuZ2VbcmFuZ2UubGVuZ3RoIC0gMV0gIT09IG5leHQpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIk1pc2NhbGN1bGF0aW9uIG9mIHJhbmdlXCIpO1xuICAgIHJldHVybiByYW5nZTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgQmFzZUVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVycm9yIHRocm93biB3aGVuIHRoZXJlIGlzIGFuIGlzc3VlIHdpdGggQ291Y2hEQiBpbmRleGVzXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIGFuIGVycm9yIHJlbGF0ZWQgdG8gQ291Y2hEQiBpbmRleCBvcGVyYXRpb25zXG4gKiBAcGFyYW0ge3N0cmluZ3xFcnJvcn0gbXNnIC0gVGhlIGVycm9yIG1lc3NhZ2Ugb3IgRXJyb3Igb2JqZWN0XG4gKiBAY2xhc3NcbiAqIEBjYXRlZ29yeSBFcnJvcnNcbiAqIEBleGFtcGxlXG4gKiAvLyBFeGFtcGxlIG9mIHVzaW5nIEluZGV4RXJyb3JcbiAqIHRyeSB7XG4gKiAgIC8vIFNvbWUgY29kZSB0aGF0IG1pZ2h0IHRocm93IGFuIGluZGV4IGVycm9yXG4gKiAgIHRocm93IG5ldyBJbmRleEVycm9yKFwiSW5kZXggbm90IGZvdW5kXCIpO1xuICogfSBjYXRjaCAoZXJyb3IpIHtcbiAqICAgaWYgKGVycm9yIGluc3RhbmNlb2YgSW5kZXhFcnJvcikge1xuICogICAgIGNvbnNvbGUuZXJyb3IoXCJJbmRleCBlcnJvciBvY2N1cnJlZDpcIiwgZXJyb3IubWVzc2FnZSk7XG4gKiAgIH1cbiAqIH1cbiAqL1xuZXhwb3J0IGNsYXNzIEluZGV4RXJyb3IgZXh0ZW5kcyBCYXNlRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIoSW5kZXhFcnJvci5uYW1lLCBtc2csIDQwNCk7XG4gIH1cbn1cbiIsImltcG9ydCB7IFBhZ2luYXRvciwgUGFnaW5nRXJyb3IsIFNlcXVlbmNlIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBmaW5kUHJpbWFyeUtleSwgSW50ZXJuYWxFcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgTWFuZ29RdWVyeSwgTWFuZ29SZXNwb25zZSB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgQ291Y2hEQkFkYXB0ZXIgfSBmcm9tIFwiLi4vYWRhcHRlclwiO1xuaW1wb3J0IHsgQ291Y2hEQktleXMgfSBmcm9tIFwiLi4vY29uc3RhbnRzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFBhZ2luYXRvciBmb3IgQ291Y2hEQiBxdWVyeSByZXN1bHRzXG4gKiBAc3VtbWFyeSBJbXBsZW1lbnRzIHBhZ2luYXRpb24gZm9yIENvdWNoREIgcXVlcmllcyB1c2luZyBib29rbWFya3MgZm9yIGVmZmljaWVudCBuYXZpZ2F0aW9uIHRocm91Z2ggcmVzdWx0IHNldHNcbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUgdGhhdCBleHRlbmRzIE1vZGVsXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSByZXN1bHQgdHlwZVxuICogQHBhcmFtIHtDb3VjaERCQWRhcHRlcjxhbnksIGFueSwgYW55Pn0gYWRhcHRlciAtIFRoZSBDb3VjaERCIGFkYXB0ZXJcbiAqIEBwYXJhbSB7TWFuZ29RdWVyeX0gcXVlcnkgLSBUaGUgTWFuZ28gcXVlcnkgdG8gcGFnaW5hdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSBzaXplIC0gVGhlIHBhZ2Ugc2l6ZVxuICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gY2xhenogLSBUaGUgbW9kZWwgY29uc3RydWN0b3JcbiAqIEBjbGFzcyBDb3VjaERCUGFnaW5hdG9yXG4gKiBAZXhhbXBsZVxuICogLy8gRXhhbXBsZSBvZiB1c2luZyBDb3VjaERCUGFnaW5hdG9yXG4gKiBjb25zdCBhZGFwdGVyID0gbmV3IE15Q291Y2hEQkFkYXB0ZXIoc2NvcGUpO1xuICogY29uc3QgcXVlcnkgPSB7IHNlbGVjdG9yOiB7IHR5cGU6IFwidXNlclwiIH0gfTtcbiAqIGNvbnN0IHBhZ2luYXRvciA9IG5ldyBDb3VjaERCUGFnaW5hdG9yKGFkYXB0ZXIsIHF1ZXJ5LCAxMCwgVXNlcik7XG4gKlxuICogLy8gR2V0IHRoZSBmaXJzdCBwYWdlXG4gKiBjb25zdCBwYWdlMSA9IGF3YWl0IHBhZ2luYXRvci5wYWdlKDEpO1xuICpcbiAqIC8vIEdldCB0aGUgbmV4dCBwYWdlXG4gKiBjb25zdCBwYWdlMiA9IGF3YWl0IHBhZ2luYXRvci5wYWdlKDIpO1xuICovXG5leHBvcnQgY2xhc3MgQ291Y2hEQlBhZ2luYXRvcjxNIGV4dGVuZHMgTW9kZWwsIFI+IGV4dGVuZHMgUGFnaW5hdG9yPFxuICBNLFxuICBSLFxuICBNYW5nb1F1ZXJ5XG4+IHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBCb29rbWFyayBmb3IgQ291Y2hEQiBwYWdpbmF0aW9uXG4gICAqIEBzdW1tYXJ5IFN0b3JlcyB0aGUgYm9va21hcmsgcmV0dXJuZWQgYnkgQ291Y2hEQiBmb3IgY29udGludWluZyBwYWdpbmF0aW9uXG4gICAqL1xuICBwcml2YXRlIGJvb2tNYXJrPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgdG90YWwgbnVtYmVyIG9mIHBhZ2VzXG4gICAqIEBzdW1tYXJ5IE5vdCBzdXBwb3J0ZWQgaW4gQ291Y2hEQiAtIHRocm93cyBhbiBlcnJvciB3aGVuIGFjY2Vzc2VkXG4gICAqIEByZXR1cm4ge251bWJlcn0gTmV2ZXIgcmV0dXJucyBhcyBpdCB0aHJvd3MgYW4gZXJyb3JcbiAgICogQHRocm93cyB7SW50ZXJuYWxFcnJvcn0gQWx3YXlzIHRocm93cyBhcyB0aGlzIGZ1bmN0aW9uYWxpdHkgaXMgbm90IGF2YWlsYWJsZSBpbiBDb3VjaERCXG4gICAqL1xuICBvdmVycmlkZSBnZXQgdG90YWwoKTogbnVtYmVyIHtcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgVGhlIHRvdGFsIHBhZ2VzIGFwaSBpcyBub3QgYXZhaWxhYmxlIGZvciBjb3VjaGRiYCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIHRvdGFsIHJlY29yZCBjb3VudFxuICAgKiBAc3VtbWFyeSBOb3Qgc3VwcG9ydGVkIGluIENvdWNoREIgLSB0aHJvd3MgYW4gZXJyb3Igd2hlbiBhY2Nlc3NlZFxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IE5ldmVyIHJldHVybnMgYXMgaXQgdGhyb3dzIGFuIGVycm9yXG4gICAqIEB0aHJvd3Mge0ludGVybmFsRXJyb3J9IEFsd2F5cyB0aHJvd3MgYXMgdGhpcyBmdW5jdGlvbmFsaXR5IGlzIG5vdCBhdmFpbGFibGUgaW4gQ291Y2hEQlxuICAgKi9cbiAgb3ZlcnJpZGUgZ2V0IGNvdW50KCk6IG51bWJlciB7XG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgVGhlIHJlY29yZCBjb3VudCBhcGkgaXMgbm90IGF2YWlsYWJsZSBmb3IgY291Y2hkYmBcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbmV3IENvdWNoREJQYWdpbmF0b3IgaW5zdGFuY2VcbiAgICogQHN1bW1hcnkgSW5pdGlhbGl6ZXMgYSBwYWdpbmF0b3IgZm9yIENvdWNoREIgcXVlcnkgcmVzdWx0c1xuICAgKiBAcGFyYW0ge0NvdWNoREJBZGFwdGVyPGFueSwgYW55LCBhbnksIGFueT59IGFkYXB0ZXIgLSBUaGUgQ291Y2hEQiBhZGFwdGVyXG4gICAqIEBwYXJhbSB7TWFuZ29RdWVyeX0gcXVlcnkgLSBUaGUgTWFuZ28gcXVlcnkgdG8gcGFnaW5hdGVcbiAgICogQHBhcmFtIHtudW1iZXJ9IHNpemUgLSBUaGUgcGFnZSBzaXplXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IGNsYXp6IC0gVGhlIG1vZGVsIGNvbnN0cnVjdG9yXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICBhZGFwdGVyOiBDb3VjaERCQWRhcHRlcjxhbnksIGFueSwgYW55LCBhbnk+LFxuICAgIHF1ZXJ5OiBNYW5nb1F1ZXJ5LFxuICAgIHNpemU6IG51bWJlcixcbiAgICBjbGF6ejogQ29uc3RydWN0b3I8TT5cbiAgKSB7XG4gICAgc3VwZXIoYWRhcHRlciwgcXVlcnksIHNpemUsIGNsYXp6KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJlcGFyZXMgYSBxdWVyeSBmb3IgcGFnaW5hdGlvblxuICAgKiBAc3VtbWFyeSBNb2RpZmllcyB0aGUgcmF3IHF1ZXJ5IHRvIGluY2x1ZGUgcGFnaW5hdGlvbiBwYXJhbWV0ZXJzXG4gICAqIEBwYXJhbSB7TWFuZ29RdWVyeX0gcmF3U3RhdGVtZW50IC0gVGhlIG9yaWdpbmFsIE1hbmdvIHF1ZXJ5XG4gICAqIEByZXR1cm4ge01hbmdvUXVlcnl9IFRoZSBwcmVwYXJlZCBxdWVyeSB3aXRoIHBhZ2luYXRpb24gcGFyYW1ldGVyc1xuICAgKi9cbiAgcHJvdGVjdGVkIHByZXBhcmUocmF3U3RhdGVtZW50OiBNYW5nb1F1ZXJ5KTogTWFuZ29RdWVyeSB7XG4gICAgY29uc3QgcXVlcnk6IE1hbmdvUXVlcnkgPSBPYmplY3QuYXNzaWduKHt9LCByYXdTdGF0ZW1lbnQpO1xuICAgIGlmIChxdWVyeS5saW1pdCkgdGhpcy5saW1pdCA9IHF1ZXJ5LmxpbWl0O1xuXG4gICAgcXVlcnkubGltaXQgPSB0aGlzLnNpemU7XG5cbiAgICByZXR1cm4gcXVlcnk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhIHNwZWNpZmljIHBhZ2Ugb2YgcmVzdWx0c1xuICAgKiBAc3VtbWFyeSBFeGVjdXRlcyB0aGUgcXVlcnkgd2l0aCBwYWdpbmF0aW9uIGFuZCBwcm9jZXNzZXMgdGhlIHJlc3VsdHNcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtwYWdlPTFdIC0gVGhlIHBhZ2UgbnVtYmVyIHRvIHJldHJpZXZlXG4gICAqIEByZXR1cm4ge1Byb21pc2U8UltdPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gYXJyYXkgb2YgcmVzdWx0c1xuICAgKiBAdGhyb3dzIHtQYWdpbmdFcnJvcn0gSWYgdHJ5aW5nIHRvIGFjY2VzcyBhIHBhZ2Ugb3RoZXIgdGhhbiB0aGUgZmlyc3Qgd2l0aG91dCBhIGJvb2ttYXJrLCBvciBpZiBubyBjbGFzcyBpcyBkZWZpbmVkXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IENsaWVudFxuICAgKiAgIHBhcnRpY2lwYW50IENvdWNoREJQYWdpbmF0b3JcbiAgICogICBwYXJ0aWNpcGFudCBBZGFwdGVyXG4gICAqICAgcGFydGljaXBhbnQgQ291Y2hEQlxuICAgKlxuICAgKiAgIENsaWVudC0+PkNvdWNoREJQYWdpbmF0b3I6IHBhZ2UocGFnZU51bWJlcilcbiAgICogICBOb3RlIG92ZXIgQ291Y2hEQlBhZ2luYXRvcjogQ2xvbmUgc3RhdGVtZW50XG4gICAqICAgQ291Y2hEQlBhZ2luYXRvci0+PkNvdWNoREJQYWdpbmF0b3I6IHZhbGlkYXRlUGFnZShwYWdlKVxuICAgKlxuICAgKiAgIGFsdCBwYWdlICE9PSAxXG4gICAqICAgICBDb3VjaERCUGFnaW5hdG9yLT4+Q291Y2hEQlBhZ2luYXRvcjogQ2hlY2sgYm9va21hcmtcbiAgICogICAgIGFsdCBObyBib29rbWFya1xuICAgKiAgICAgICBDb3VjaERCUGFnaW5hdG9yLS0+PkNsaWVudDogVGhyb3cgUGFnaW5nRXJyb3JcbiAgICogICAgIGVsc2UgSGFzIGJvb2ttYXJrXG4gICAqICAgICAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiBBZGQgYm9va21hcmsgdG8gc3RhdGVtZW50XG4gICAqICAgICBlbmRcbiAgICogICBlbmRcbiAgICpcbiAgICogICBDb3VjaERCUGFnaW5hdG9yLT4+QWRhcHRlcjogcmF3KHN0YXRlbWVudCwgZmFsc2UpXG4gICAqICAgQWRhcHRlci0+PkNvdWNoREI6IEV4ZWN1dGUgcXVlcnlcbiAgICogICBDb3VjaERCLS0+PkFkYXB0ZXI6IFJldHVybiByZXN1bHRzXG4gICAqICAgQWRhcHRlci0tPj5Db3VjaERCUGFnaW5hdG9yOiBSZXR1cm4gTWFuZ29SZXNwb25zZVxuICAgKlxuICAgKiAgIE5vdGUgb3ZlciBDb3VjaERCUGFnaW5hdG9yOiBQcm9jZXNzIHJlc3VsdHNcbiAgICpcbiAgICogICBhbHQgSGFzIHdhcm5pbmdcbiAgICogICAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiBMb2cgd2FybmluZ1xuICAgKiAgIGVuZFxuICAgKlxuICAgKiAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiBDaGVjayBmb3IgY2xhenpcbiAgICpcbiAgICogICBhbHQgTm8gY2xhenpcbiAgICogICAgIENvdWNoREJQYWdpbmF0b3ItLT4+Q2xpZW50OiBUaHJvdyBQYWdpbmdFcnJvclxuICAgKiAgIGVsc2UgSGFzIGNsYXp6XG4gICAqICAgICBDb3VjaERCUGFnaW5hdG9yLT4+Q291Y2hEQlBhZ2luYXRvcjogRmluZCBwcmltYXJ5IGtleVxuICAgKlxuICAgKiAgICAgYWx0IEhhcyBmaWVsZHMgaW4gc3RhdGVtZW50XG4gICAqICAgICAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiBVc2UgZG9jcyBkaXJlY3RseVxuICAgKiAgICAgZWxzZSBObyBmaWVsZHNcbiAgICogICAgICAgQ291Y2hEQlBhZ2luYXRvci0+PkNvdWNoREJQYWdpbmF0b3I6IFByb2Nlc3MgZWFjaCBkb2N1bWVudFxuICAgKiAgICAgICBsb29wIEZvciBlYWNoIGRvY3VtZW50XG4gICAqICAgICAgICAgQ291Y2hEQlBhZ2luYXRvci0+PkNvdWNoREJQYWdpbmF0b3I6IEV4dHJhY3Qgb3JpZ2luYWwgSURcbiAgICogICAgICAgICBDb3VjaERCUGFnaW5hdG9yLT4+QWRhcHRlcjogcmV2ZXJ0KGRvYywgY2xhenosIHBrRGVmLmlkLCBwYXJzZWRJZClcbiAgICogICAgICAgZW5kXG4gICAqICAgICBlbmRcbiAgICpcbiAgICogICAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiBTdG9yZSBib29rbWFya1xuICAgKiAgICAgQ291Y2hEQlBhZ2luYXRvci0+PkNvdWNoREJQYWdpbmF0b3I6IFVwZGF0ZSBjdXJyZW50UGFnZVxuICAgKiAgICAgQ291Y2hEQlBhZ2luYXRvci0tPj5DbGllbnQ6IFJldHVybiByZXN1bHRzXG4gICAqICAgZW5kXG4gICAqL1xuICBhc3luYyBwYWdlKHBhZ2U6IG51bWJlciA9IDEpOiBQcm9taXNlPFJbXT4ge1xuICAgIGNvbnN0IHN0YXRlbWVudCA9IE9iamVjdC5hc3NpZ24oe30sIHRoaXMuc3RhdGVtZW50KTtcblxuICAgIGlmICghdGhpcy5fcmVjb3JkQ291bnQgfHwgIXRoaXMuX3RvdGFsUGFnZXMpIHtcbiAgICAgIHRoaXMuX3RvdGFsUGFnZXMgPSB0aGlzLl9yZWNvcmRDb3VudCA9IDA7XG4gICAgICBjb25zdCByZXN1bHRzOiBSW10gPVxuICAgICAgICAoYXdhaXQgdGhpcy5hZGFwdGVyLnJhdyh7IC4uLnN0YXRlbWVudCwgbGltaXQ6IHVuZGVmaW5lZCB9KSkgfHwgW107XG4gICAgICB0aGlzLl9yZWNvcmRDb3VudCA9IHJlc3VsdHMubGVuZ3RoO1xuICAgICAgaWYgKHRoaXMuX3JlY29yZENvdW50ID4gMCkge1xuICAgICAgICBjb25zdCBzaXplID0gc3RhdGVtZW50Py5saW1pdCB8fCB0aGlzLnNpemU7XG4gICAgICAgIHRoaXMuX3RvdGFsUGFnZXMgPSBNYXRoLmNlaWwodGhpcy5fcmVjb3JkQ291bnQgLyBzaXplKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnZhbGlkYXRlUGFnZShwYWdlKTtcblxuICAgIGlmIChwYWdlICE9PSAxKSB7XG4gICAgICBpZiAoIXRoaXMuYm9va01hcmspXG4gICAgICAgIHRocm93IG5ldyBQYWdpbmdFcnJvcihcIk5vIGJvb2ttYXJrLiBEaWQgeW91IHN0YXJ0IGluIHRoZSBmaXJzdCBwYWdlP1wiKTtcbiAgICAgIHN0YXRlbWVudFtcImJvb2ttYXJrXCJdID0gdGhpcy5ib29rTWFyaztcbiAgICB9XG4gICAgY29uc3QgcmF3UmVzdWx0OiBNYW5nb1Jlc3BvbnNlPGFueT4gPSBhd2FpdCB0aGlzLmFkYXB0ZXIucmF3KFxuICAgICAgc3RhdGVtZW50LFxuICAgICAgZmFsc2VcbiAgICApO1xuXG4gICAgY29uc3QgeyBkb2NzLCBib29rbWFyaywgd2FybmluZyB9ID0gcmF3UmVzdWx0O1xuICAgIGlmICh3YXJuaW5nKSBjb25zb2xlLndhcm4od2FybmluZyk7XG4gICAgaWYgKCF0aGlzLmNsYXp6KSB0aHJvdyBuZXcgUGFnaW5nRXJyb3IoXCJObyBzdGF0ZW1lbnQgdGFyZ2V0IGRlZmluZWRcIik7XG4gICAgY29uc3QgcGtEZWYgPSBmaW5kUHJpbWFyeUtleShuZXcgdGhpcy5jbGF6eigpKTtcbiAgICBjb25zdCByZXN1bHRzID1cbiAgICAgIHN0YXRlbWVudC5maWVsZHMgJiYgc3RhdGVtZW50LmZpZWxkcy5sZW5ndGhcbiAgICAgICAgPyBkb2NzIC8vIGhhcyBmaWVsZHMgbWVhbnMgaXRzIG5vdCBmdWxsIG1vZGVsXG4gICAgICAgIDogZG9jcy5tYXAoKGQ6IGFueSkgPT4ge1xuICAgICAgICAgICAgLy9ubyBmaWVsZHMgbWVhbnMgd2UgbmVlZCB0byByZXZlcnQgdG8gc2F2aW5nIHByb2Nlc3NcbiAgICAgICAgICAgIGNvbnN0IG9yaWdpbmFsSWQgPSBkLl9pZC5zcGxpdChDb3VjaERCS2V5cy5TRVBBUkFUT1IpO1xuICAgICAgICAgICAgb3JpZ2luYWxJZC5zcGxpY2UoMCwgMSk7IC8vIHJlbW92ZSB0aGUgdGFibGUgbmFtZVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWRhcHRlci5yZXZlcnQoXG4gICAgICAgICAgICAgIGQsXG4gICAgICAgICAgICAgIHRoaXMuY2xhenosXG4gICAgICAgICAgICAgIHBrRGVmLmlkLFxuICAgICAgICAgICAgICBTZXF1ZW5jZS5wYXJzZVZhbHVlKFxuICAgICAgICAgICAgICAgIHBrRGVmLnByb3BzLnR5cGUsXG4gICAgICAgICAgICAgICAgb3JpZ2luYWxJZC5qb2luKENvdWNoREJLZXlzLlNFUEFSQVRPUilcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KTtcbiAgICB0aGlzLmJvb2tNYXJrID0gYm9va21hcms7XG4gICAgdGhpcy5fY3VycmVudFBhZ2UgPSBwYWdlO1xuICAgIHJldHVybiByZXN1bHRzO1xuICB9XG59XG4iLCJpbXBvcnQgeyBHcm91cE9wZXJhdG9yLCBPcGVyYXRvciB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgQ291Y2hEQkdyb3VwT3BlcmF0b3IsIENvdWNoREJPcGVyYXRvciB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUXVlcnlFcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgTWFuZ29PcGVyYXRvciB9IGZyb20gXCIuLi90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBUcmFuc2xhdGVzIGNvcmUgb3BlcmF0b3JzIHRvIENvdWNoREIgTWFuZ28gb3BlcmF0b3JzXG4gKiBAc3VtbWFyeSBDb252ZXJ0cyBEZWNhZi50cyBjb3JlIG9wZXJhdG9ycyB0byB0aGVpciBlcXVpdmFsZW50IENvdWNoREIgTWFuZ28gcXVlcnkgb3BlcmF0b3JzXG4gKiBAcGFyYW0ge0dyb3VwT3BlcmF0b3IgfCBPcGVyYXRvcn0gb3BlcmF0b3IgLSBUaGUgY29yZSBvcGVyYXRvciB0byB0cmFuc2xhdGVcbiAqIEByZXR1cm4ge01hbmdvT3BlcmF0b3J9IFRoZSBlcXVpdmFsZW50IENvdWNoREIgTWFuZ28gb3BlcmF0b3JcbiAqIEB0aHJvd3Mge1F1ZXJ5RXJyb3J9IElmIG5vIHRyYW5zbGF0aW9uIGV4aXN0cyBmb3IgdGhlIGdpdmVuIG9wZXJhdG9yXG4gKiBAZnVuY3Rpb24gdHJhbnNsYXRlT3BlcmF0b3JzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1jb3VjaGRiXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCB0cmFuc2xhdGVPcGVyYXRvcnNcbiAqICAgcGFydGljaXBhbnQgQ291Y2hEQk9wZXJhdG9yXG4gKiAgIHBhcnRpY2lwYW50IENvdWNoREJHcm91cE9wZXJhdG9yXG4gKiAgIFxuICogICBDYWxsZXItPj50cmFuc2xhdGVPcGVyYXRvcnM6IG9wZXJhdG9yXG4gKiAgIFxuICogICB0cmFuc2xhdGVPcGVyYXRvcnMtPj5Db3VjaERCT3BlcmF0b3I6IENoZWNrIGZvciBtYXRjaFxuICogICBhbHQgRm91bmQgaW4gQ291Y2hEQk9wZXJhdG9yXG4gKiAgICAgQ291Y2hEQk9wZXJhdG9yLS0+PnRyYW5zbGF0ZU9wZXJhdG9yczogUmV0dXJuIG1hdGNoaW5nIG9wZXJhdG9yXG4gKiAgICAgdHJhbnNsYXRlT3BlcmF0b3JzLS0+PkNhbGxlcjogUmV0dXJuIE1hbmdvT3BlcmF0b3JcbiAqICAgZWxzZSBOb3QgZm91bmRcbiAqICAgICB0cmFuc2xhdGVPcGVyYXRvcnMtPj5Db3VjaERCR3JvdXBPcGVyYXRvcjogQ2hlY2sgZm9yIG1hdGNoXG4gKiAgICAgYWx0IEZvdW5kIGluIENvdWNoREJHcm91cE9wZXJhdG9yXG4gKiAgICAgICBDb3VjaERCR3JvdXBPcGVyYXRvci0tPj50cmFuc2xhdGVPcGVyYXRvcnM6IFJldHVybiBtYXRjaGluZyBvcGVyYXRvclxuICogICAgICAgdHJhbnNsYXRlT3BlcmF0b3JzLS0+PkNhbGxlcjogUmV0dXJuIE1hbmdvT3BlcmF0b3JcbiAqICAgICBlbHNlIE5vdCBmb3VuZFxuICogICAgICAgdHJhbnNsYXRlT3BlcmF0b3JzLS0+PkNhbGxlcjogVGhyb3cgUXVlcnlFcnJvclxuICogICAgIGVuZFxuICogICBlbmRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zbGF0ZU9wZXJhdG9ycyhcbiAgb3BlcmF0b3I6IEdyb3VwT3BlcmF0b3IgfCBPcGVyYXRvclxuKTogTWFuZ29PcGVyYXRvciB7XG4gIGZvciAoY29uc3Qgb3BlcmF0b3JzIG9mIFtDb3VjaERCT3BlcmF0b3IsIENvdWNoREJHcm91cE9wZXJhdG9yXSkge1xuICAgIGNvbnN0IGVsID0gT2JqZWN0LmtleXMob3BlcmF0b3JzKS5maW5kKChrKSA9PiBrID09PSBvcGVyYXRvcik7XG4gICAgaWYgKGVsKSByZXR1cm4gb3BlcmF0b3JzW2VsXTtcbiAgfVxuICB0aHJvdyBuZXcgUXVlcnlFcnJvcihcbiAgICBgQ291bGQgbm90IGZpbmQgYWRhcHRlciB0cmFuc2xhdGlvbiBmb3Igb3BlcmF0b3IgJHtvcGVyYXRvcn1gXG4gICk7XG59XG4iLCJpbXBvcnQge1xuICBDb25kaXRpb24sXG4gIEdyb3VwT3BlcmF0b3IsXG4gIE9wZXJhdG9yLFxuICBPcmRlckRpcmVjdGlvbixcbiAgUGFnaW5hdG9yLFxuICBSZXBvc2l0b3J5LFxuICBTZXF1ZW5jZSxcbiAgU3RhdGVtZW50LFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IE1hbmdvT3BlcmF0b3IsIE1hbmdvUXVlcnksIE1hbmdvU2VsZWN0b3IgfSBmcm9tIFwiLi4vdHlwZXNcIjtcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgQ291Y2hEQkFkYXB0ZXIgfSBmcm9tIFwiLi4vYWRhcHRlclwiO1xuaW1wb3J0IHsgdHJhbnNsYXRlT3BlcmF0b3JzIH0gZnJvbSBcIi4vdHJhbnNsYXRlXCI7XG5pbXBvcnQgeyBDb3VjaERCS2V5cyB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcbmltcG9ydCB7XG4gIENvdWNoREJHcm91cE9wZXJhdG9yLFxuICBDb3VjaERCT3BlcmF0b3IsXG4gIENvdWNoREJRdWVyeUxpbWl0LFxufSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IENvdWNoREJQYWdpbmF0b3IgfSBmcm9tIFwiLi9QYWdpbmF0b3JcIjtcbmltcG9ydCB7IGZpbmRQcmltYXJ5S2V5LCBJbnRlcm5hbEVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFN0YXRlbWVudCBidWlsZGVyIGZvciBDb3VjaERCIE1hbmdvIHF1ZXJpZXNcbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIGEgZmx1ZW50IGludGVyZmFjZSBmb3IgYnVpbGRpbmcgQ291Y2hEQiBNYW5nbyBxdWVyaWVzIHdpdGggdHlwZSBzYWZldHlcbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUgdGhhdCBleHRlbmRzIE1vZGVsXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSByZXN1bHQgdHlwZVxuICogQHBhcmFtIGFkYXB0ZXIgLSBUaGUgQ291Y2hEQiBhZGFwdGVyXG4gKiBAY2xhc3MgQ291Y2hEQlN0YXRlbWVudFxuICogQGV4YW1wbGVcbiAqIC8vIEV4YW1wbGUgb2YgdXNpbmcgQ291Y2hEQlN0YXRlbWVudFxuICogY29uc3QgYWRhcHRlciA9IG5ldyBNeUNvdWNoREJBZGFwdGVyKHNjb3BlKTtcbiAqIGNvbnN0IHN0YXRlbWVudCA9IG5ldyBDb3VjaERCU3RhdGVtZW50PFVzZXIsIFVzZXJbXT4oYWRhcHRlcik7XG4gKlxuICogLy8gQnVpbGQgYSBxdWVyeVxuICogY29uc3QgdXNlcnMgPSBhd2FpdCBzdGF0ZW1lbnRcbiAqICAgLmZyb20oVXNlcilcbiAqICAgLndoZXJlKENvbmRpdGlvbi5hdHRyaWJ1dGU8VXNlcj4oJ2FnZScpLmd0KDE4KSlcbiAqICAgLm9yZGVyQnkoJ2xhc3ROYW1lJywgJ2FzYycpXG4gKiAgIC5saW1pdCgxMClcbiAqICAgLmV4ZWN1dGUoKTtcbiAqL1xuZXhwb3J0IGNsYXNzIENvdWNoREJTdGF0ZW1lbnQ8TSBleHRlbmRzIE1vZGVsLCBSPiBleHRlbmRzIFN0YXRlbWVudDxcbiAgTWFuZ29RdWVyeSxcbiAgTSxcbiAgUlxuPiB7XG4gIGNvbnN0cnVjdG9yKGFkYXB0ZXI6IENvdWNoREJBZGFwdGVyPGFueSwgYW55LCBhbnksIGFueT4pIHtcbiAgICBzdXBlcihhZGFwdGVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQnVpbGRzIGEgQ291Y2hEQiBNYW5nbyBxdWVyeSBmcm9tIHRoZSBzdGF0ZW1lbnRcbiAgICogQHN1bW1hcnkgQ29udmVydHMgdGhlIHN0YXRlbWVudCdzIGNvbmRpdGlvbnMsIHNlbGVjdG9ycywgYW5kIG9wdGlvbnMgaW50byBhIENvdWNoREIgTWFuZ28gcXVlcnlcbiAgICogQHJldHVybiB7TWFuZ29RdWVyeX0gVGhlIGJ1aWx0IE1hbmdvIHF1ZXJ5XG4gICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGVyZSBhcmUgaW52YWxpZCBxdWVyeSBjb25kaXRpb25zXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IFN0YXRlbWVudFxuICAgKiAgIHBhcnRpY2lwYW50IFJlcG9zaXRvcnlcbiAgICogICBwYXJ0aWNpcGFudCBwYXJzZUNvbmRpdGlvblxuICAgKlxuICAgKiAgIFN0YXRlbWVudC0+PlN0YXRlbWVudDogYnVpbGQoKVxuICAgKiAgIE5vdGUgb3ZlciBTdGF0ZW1lbnQ6IEluaXRpYWxpemUgc2VsZWN0b3JzXG4gICAqICAgU3RhdGVtZW50LT4+UmVwb3NpdG9yeTogR2V0IHRhYmxlIG5hbWVcbiAgICogICBSZXBvc2l0b3J5LS0+PlN0YXRlbWVudDogUmV0dXJuIHRhYmxlIG5hbWVcbiAgICogICBTdGF0ZW1lbnQtPj5TdGF0ZW1lbnQ6IENyZWF0ZSBiYXNlIHF1ZXJ5XG4gICAqXG4gICAqICAgYWx0IEhhcyBzZWxlY3RTZWxlY3RvclxuICAgKiAgICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBBZGQgZmllbGRzIHRvIHF1ZXJ5XG4gICAqICAgZW5kXG4gICAqXG4gICAqICAgYWx0IEhhcyB3aGVyZUNvbmRpdGlvblxuICAgKiAgICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBDcmVhdGUgY29tYmluZWQgY29uZGl0aW9uIHdpdGggdGFibGVcbiAgICogICAgIFN0YXRlbWVudC0+PnBhcnNlQ29uZGl0aW9uOiBQYXJzZSBjb25kaXRpb25cbiAgICogICAgIHBhcnNlQ29uZGl0aW9uLS0+PlN0YXRlbWVudDogUmV0dXJuIHBhcnNlZCBjb25kaXRpb25cbiAgICpcbiAgICogICAgIGFsdCBJcyBncm91cCBvcGVyYXRvclxuICAgKiAgICAgICBhbHQgSXMgQU5EIG9wZXJhdG9yXG4gICAqICAgICAgICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBGbGF0dGVuIG5lc3RlZCBBTkQgY29uZGl0aW9uc1xuICAgKiAgICAgICBlbHNlIElzIE9SIG9wZXJhdG9yXG4gICAqICAgICAgICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBDb21iaW5lIHdpdGggdGFibGUgY29uZGl0aW9uXG4gICAqICAgICAgIGVsc2VcbiAgICogICAgICAgICBTdGF0ZW1lbnQtPj5TdGF0ZW1lbnQ6IFRocm93IGVycm9yXG4gICAqICAgICAgIGVuZFxuICAgKiAgICAgZWxzZVxuICAgKiAgICAgICBTdGF0ZW1lbnQtPj5TdGF0ZW1lbnQ6IE1lcmdlIGNvbmRpdGlvbnMgd2l0aCBleGlzdGluZyBzZWxlY3RvclxuICAgKiAgICAgZW5kXG4gICAqICAgZW5kXG4gICAqXG4gICAqICAgYWx0IEhhcyBvcmRlckJ5U2VsZWN0b3JcbiAgICogICAgIFN0YXRlbWVudC0+PlN0YXRlbWVudDogQWRkIHNvcnQgdG8gcXVlcnlcbiAgICogICAgIFN0YXRlbWVudC0+PlN0YXRlbWVudDogRW5zdXJlIGZpZWxkIGV4aXN0cyBpbiBzZWxlY3RvclxuICAgKiAgIGVuZFxuICAgKlxuICAgKiAgIGFsdCBIYXMgbGltaXRTZWxlY3RvclxuICAgKiAgICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBTZXQgbGltaXRcbiAgICogICBlbHNlXG4gICAqICAgICBTdGF0ZW1lbnQtPj5TdGF0ZW1lbnQ6IFVzZSBkZWZhdWx0IGxpbWl0XG4gICAqICAgZW5kXG4gICAqXG4gICAqICAgYWx0IEhhcyBvZmZzZXRTZWxlY3RvclxuICAgKiAgICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBTZXQgc2tpcFxuICAgKiAgIGVuZFxuICAgKlxuICAgKiAgIFN0YXRlbWVudC0tPj5TdGF0ZW1lbnQ6IFJldHVybiBxdWVyeVxuICAgKi9cbiAgcHJvdGVjdGVkIGJ1aWxkKCk6IE1hbmdvUXVlcnkge1xuICAgIGNvbnN0IHNlbGVjdG9yczogTWFuZ29TZWxlY3RvciA9IHt9O1xuICAgIHNlbGVjdG9yc1tDb3VjaERCS2V5cy5UQUJMRV0gPSB7fTtcbiAgICBzZWxlY3RvcnNbQ291Y2hEQktleXMuVEFCTEVdID0gUmVwb3NpdG9yeS50YWJsZSh0aGlzLmZyb21TZWxlY3Rvcik7XG4gICAgY29uc3QgcXVlcnk6IE1hbmdvUXVlcnkgPSB7IHNlbGVjdG9yOiBzZWxlY3RvcnMgfTtcbiAgICBpZiAodGhpcy5zZWxlY3RTZWxlY3RvcikgcXVlcnkuZmllbGRzID0gdGhpcy5zZWxlY3RTZWxlY3RvciBhcyBzdHJpbmdbXTtcblxuICAgIGlmICh0aGlzLndoZXJlQ29uZGl0aW9uKSB7XG4gICAgICBjb25zdCBjb25kaXRpb246IE1hbmdvU2VsZWN0b3IgPSB0aGlzLnBhcnNlQ29uZGl0aW9uKFxuICAgICAgICBDb25kaXRpb24uYW5kKFxuICAgICAgICAgIHRoaXMud2hlcmVDb25kaXRpb24sXG4gICAgICAgICAgQ29uZGl0aW9uLmF0dHJpYnV0ZTxNPihDb3VjaERCS2V5cy5UQUJMRSBhcyBrZXlvZiBNKS5lcShcbiAgICAgICAgICAgIHF1ZXJ5LnNlbGVjdG9yW0NvdWNoREJLZXlzLlRBQkxFXVxuICAgICAgICAgIClcbiAgICAgICAgKVxuICAgICAgKS5zZWxlY3RvcjtcbiAgICAgIGNvbnN0IHNlbGVjdG9yS2V5cyA9IE9iamVjdC5rZXlzKGNvbmRpdGlvbikgYXMgTWFuZ29PcGVyYXRvcltdO1xuICAgICAgaWYgKFxuICAgICAgICBzZWxlY3RvcktleXMubGVuZ3RoID09PSAxICYmXG4gICAgICAgIE9iamVjdC52YWx1ZXMoQ291Y2hEQkdyb3VwT3BlcmF0b3IpLmluZGV4T2Yoc2VsZWN0b3JLZXlzWzBdKSAhPT0gLTFcbiAgICAgIClcbiAgICAgICAgc3dpdGNoIChzZWxlY3RvcktleXNbMF0pIHtcbiAgICAgICAgICBjYXNlIENvdWNoREJHcm91cE9wZXJhdG9yLkFORDpcbiAgICAgICAgICAgIGNvbmRpdGlvbltDb3VjaERCR3JvdXBPcGVyYXRvci5BTkRdID0gW1xuICAgICAgICAgICAgICAuLi5PYmplY3QudmFsdWVzKFxuICAgICAgICAgICAgICAgIGNvbmRpdGlvbltDb3VjaERCR3JvdXBPcGVyYXRvci5BTkRdIGFzIE1hbmdvU2VsZWN0b3JcbiAgICAgICAgICAgICAgKS5yZWR1Y2UoKGFjY3VtOiBNYW5nb1NlbGVjdG9yW10sIHZhbDogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKHZhbCk7XG4gICAgICAgICAgICAgICAgaWYgKGtleXMubGVuZ3RoICE9PSAxKVxuICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICAgICBcIlRvbyBtYW55IGtleXMgaW4gcXVlcnkgc2VsZWN0b3IuIHNob3VsZCBiZSBvbmVcIlxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBjb25zdCBrID0ga2V5c1swXTtcbiAgICAgICAgICAgICAgICBpZiAoayA9PT0gQ291Y2hEQkdyb3VwT3BlcmF0b3IuQU5EKVxuICAgICAgICAgICAgICAgICAgYWNjdW0ucHVzaCguLi4odmFsW2tdIGFzIGFueVtdKSk7XG4gICAgICAgICAgICAgICAgZWxzZSBhY2N1bS5wdXNoKHZhbCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFjY3VtO1xuICAgICAgICAgICAgICB9LCBbXSksXG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgcXVlcnkuc2VsZWN0b3IgPSBjb25kaXRpb247XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlIENvdWNoREJHcm91cE9wZXJhdG9yLk9SOiB7XG4gICAgICAgICAgICBjb25zdCBzOiBSZWNvcmQ8YW55LCBhbnk+ID0ge307XG4gICAgICAgICAgICBzW0NvdWNoREJHcm91cE9wZXJhdG9yLkFORF0gPSBbXG4gICAgICAgICAgICAgIGNvbmRpdGlvbixcbiAgICAgICAgICAgICAgLi4uT2JqZWN0LmVudHJpZXMocXVlcnkuc2VsZWN0b3IpLm1hcCgoW2tleSwgdmFsXSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPGFueSwgYW55PiA9IHt9O1xuICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdmFsO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIHF1ZXJ5LnNlbGVjdG9yID0gcztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhpcyBzaG91bGQgYmUgaW1wb3NzaWJsZVwiKTtcbiAgICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIE9iamVjdC5lbnRyaWVzKGNvbmRpdGlvbikuZm9yRWFjaCgoW2tleSwgdmFsXSkgPT4ge1xuICAgICAgICAgIGlmIChxdWVyeS5zZWxlY3RvcltrZXldKVxuICAgICAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgICBgQSAke2tleX0gcXVlcnkgcGFyYW0gaXMgYWJvdXQgdG8gYmUgb3ZlcnJpZGRlbjogJHtxdWVyeS5zZWxlY3RvcltrZXldfSBieSAke3ZhbH1gXG4gICAgICAgICAgICApO1xuICAgICAgICAgIHF1ZXJ5LnNlbGVjdG9yW2tleV0gPSB2YWw7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLm9yZGVyQnlTZWxlY3Rvcikge1xuICAgICAgcXVlcnkuc29ydCA9IHF1ZXJ5LnNvcnQgfHwgW107XG4gICAgICBxdWVyeS5zZWxlY3RvciA9IHF1ZXJ5LnNlbGVjdG9yIHx8ICh7fSBhcyBNYW5nb1NlbGVjdG9yKTtcbiAgICAgIGNvbnN0IFtzZWxlY3RvciwgdmFsdWVdID0gdGhpcy5vcmRlckJ5U2VsZWN0b3IgYXMgW1xuICAgICAgICBzdHJpbmcsXG4gICAgICAgIE9yZGVyRGlyZWN0aW9uLFxuICAgICAgXTtcbiAgICAgIGNvbnN0IHJlYzogYW55ID0ge307XG4gICAgICByZWNbc2VsZWN0b3JdID0gdmFsdWU7XG4gICAgICAocXVlcnkuc29ydCBhcyBhbnlbXSkucHVzaChyZWMgYXMgYW55KTtcbiAgICAgIGlmICghcXVlcnkuc2VsZWN0b3Jbc2VsZWN0b3JdKSB7XG4gICAgICAgIHF1ZXJ5LnNlbGVjdG9yW3NlbGVjdG9yXSA9IHt9IGFzIE1hbmdvU2VsZWN0b3I7XG4gICAgICAgIChxdWVyeS5zZWxlY3RvcltzZWxlY3Rvcl0gYXMgTWFuZ29TZWxlY3RvcilbQ291Y2hEQk9wZXJhdG9yLkJJR0dFUl0gPVxuICAgICAgICAgIG51bGw7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMubGltaXRTZWxlY3Rvcikge1xuICAgICAgcXVlcnkubGltaXQgPSB0aGlzLmxpbWl0U2VsZWN0b3I7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYE5vIGxpbWl0IHNlbGVjdG9yIGRlZmluZWQuIFVzaW5nIGRlZmF1bHQgY291Y2hkYiBsaW1pdCBvZiAke0NvdWNoREJRdWVyeUxpbWl0fWBcbiAgICAgICk7XG4gICAgICBxdWVyeS5saW1pdCA9IENvdWNoREJRdWVyeUxpbWl0O1xuICAgIH1cblxuICAgIGlmICh0aGlzLm9mZnNldFNlbGVjdG9yKSBxdWVyeS5za2lwID0gdGhpcy5vZmZzZXRTZWxlY3RvcjtcblxuICAgIHJldHVybiBxdWVyeTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIHBhZ2luYXRvciBmb3IgdGhlIHN0YXRlbWVudFxuICAgKiBAc3VtbWFyeSBCdWlsZHMgdGhlIHF1ZXJ5IGFuZCByZXR1cm5zIGEgQ291Y2hEQlBhZ2luYXRvciBmb3IgcGFnaW5hdGVkIHJlc3VsdHNcbiAgICogQHRlbXBsYXRlIFIgLSBUaGUgcmVzdWx0IHR5cGVcbiAgICogQHBhcmFtIHtudW1iZXJ9IHNpemUgLSBUaGUgcGFnZSBzaXplXG4gICAqIEByZXR1cm4ge1Byb21pc2U8UGFnaW5hdG9yPE0sIFIsIE1hbmdvUXVlcnk+Pn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBwYWdpbmF0b3JcbiAgICogQHRocm93cyB7SW50ZXJuYWxFcnJvcn0gSWYgdGhlcmUncyBhbiBlcnJvciBidWlsZGluZyB0aGUgcXVlcnlcbiAgICovXG4gIGFzeW5jIHBhZ2luYXRlPFI+KHNpemU6IG51bWJlcik6IFByb21pc2U8UGFnaW5hdG9yPE0sIFIsIE1hbmdvUXVlcnk+PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHF1ZXJ5OiBNYW5nb1F1ZXJ5ID0gdGhpcy5idWlsZCgpO1xuICAgICAgcmV0dXJuIG5ldyBDb3VjaERCUGFnaW5hdG9yKFxuICAgICAgICB0aGlzLmFkYXB0ZXIgYXMgYW55LFxuICAgICAgICBxdWVyeSxcbiAgICAgICAgc2l6ZSxcbiAgICAgICAgdGhpcy5mcm9tU2VsZWN0b3JcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByb2Nlc3NlcyBhIHJlY29yZCBmcm9tIENvdWNoREJcbiAgICogQHN1bW1hcnkgRXh0cmFjdHMgdGhlIElEIGZyb20gYSBDb3VjaERCIGRvY3VtZW50IGFuZCByZXZlcnRzIGl0IHRvIGEgbW9kZWwgaW5zdGFuY2VcbiAgICogQHBhcmFtIHthbnl9IHIgLSBUaGUgcmF3IHJlY29yZCBmcm9tIENvdWNoREJcbiAgICogQHBhcmFtIHBrQXR0ciAtIFRoZSBwcmltYXJ5IGtleSBhdHRyaWJ1dGUgb2YgdGhlIG1vZGVsXG4gICAqIEBwYXJhbSB7XCJOdW1iZXJcIiB8IFwiQmlnSW50XCIgfCB1bmRlZmluZWR9IHNlcXVlbmNlVHlwZSAtIFRoZSB0eXBlIG9mIHRoZSBzZXF1ZW5jZVxuICAgKiBAcmV0dXJuIHthbnl9IFRoZSBwcm9jZXNzZWQgcmVjb3JkXG4gICAqL1xuICBwcm90ZWN0ZWQgcHJvY2Vzc1JlY29yZChcbiAgICByOiBhbnksXG4gICAgcGtBdHRyOiBrZXlvZiBNLFxuICAgIHNlcXVlbmNlVHlwZTogXCJOdW1iZXJcIiB8IFwiQmlnSW50XCIgfCB1bmRlZmluZWRcbiAgKSB7XG4gICAgaWYgKHJbQ291Y2hEQktleXMuSURdKSB7XG4gICAgICBjb25zdCBbLCAuLi5rZXlBcmdzXSA9IHJbQ291Y2hEQktleXMuSURdLnNwbGl0KENvdWNoREJLZXlzLlNFUEFSQVRPUik7XG5cbiAgICAgIGNvbnN0IGlkID0ga2V5QXJncy5qb2luKFwiX1wiKTtcbiAgICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmV2ZXJ0KFxuICAgICAgICByLFxuICAgICAgICB0aGlzLmZyb21TZWxlY3RvcixcbiAgICAgICAgcGtBdHRyLFxuICAgICAgICBTZXF1ZW5jZS5wYXJzZVZhbHVlKHNlcXVlbmNlVHlwZSwgaWQpXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXhlY3V0ZXMgYSByYXcgTWFuZ28gcXVlcnlcbiAgICogQHN1bW1hcnkgU2VuZHMgYSByYXcgTWFuZ28gcXVlcnkgdG8gQ291Y2hEQiBhbmQgcHJvY2Vzc2VzIHRoZSByZXN1bHRzXG4gICAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHJlc3VsdCB0eXBlXG4gICAqIEBwYXJhbSB7TWFuZ29RdWVyeX0gcmF3SW5wdXQgLSBUaGUgcmF3IE1hbmdvIHF1ZXJ5IHRvIGV4ZWN1dGVcbiAgICogQHJldHVybiB7UHJvbWlzZTxSPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHF1ZXJ5IHJlc3VsdHNcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIHJhdzxSPihyYXdJbnB1dDogTWFuZ29RdWVyeSk6IFByb21pc2U8Uj4ge1xuICAgIGNvbnN0IHJlc3VsdHM6IGFueVtdID0gYXdhaXQgdGhpcy5hZGFwdGVyLnJhdyhyYXdJbnB1dCwgdHJ1ZSk7XG5cbiAgICBjb25zdCBwa0RlZiA9IGZpbmRQcmltYXJ5S2V5KG5ldyB0aGlzLmZyb21TZWxlY3RvcigpKTtcbiAgICBjb25zdCBwa0F0dHIgPSBwa0RlZi5pZDtcbiAgICBjb25zdCB0eXBlID0gcGtEZWYucHJvcHMudHlwZTtcblxuICAgIGlmICghdGhpcy5zZWxlY3RTZWxlY3RvcilcbiAgICAgIHJldHVybiByZXN1bHRzLm1hcCgocikgPT4gdGhpcy5wcm9jZXNzUmVjb3JkKHIsIHBrQXR0ciwgdHlwZSkpIGFzIFI7XG4gICAgcmV0dXJuIHJlc3VsdHMgYXMgUjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUGFyc2VzIGEgY29uZGl0aW9uIGludG8gYSBDb3VjaERCIE1hbmdvIHF1ZXJ5IHNlbGVjdG9yXG4gICAqIEBzdW1tYXJ5IENvbnZlcnRzIGEgQ29uZGl0aW9uIG9iamVjdCBpbnRvIGEgQ291Y2hEQiBNYW5nbyBxdWVyeSBzZWxlY3RvciBzdHJ1Y3R1cmVcbiAgICogQHBhcmFtIHtDb25kaXRpb248TT59IGNvbmRpdGlvbiAtIFRoZSBjb25kaXRpb24gdG8gcGFyc2VcbiAgICogQHJldHVybiB7TWFuZ29RdWVyeX0gVGhlIE1hbmdvIHF1ZXJ5IHdpdGggdGhlIHBhcnNlZCBjb25kaXRpb24gYXMgaXRzIHNlbGVjdG9yXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IFN0YXRlbWVudFxuICAgKiAgIHBhcnRpY2lwYW50IHRyYW5zbGF0ZU9wZXJhdG9yc1xuICAgKiAgIHBhcnRpY2lwYW50IG1lcmdlXG4gICAqXG4gICAqICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBwYXJzZUNvbmRpdGlvbihjb25kaXRpb24pXG4gICAqXG4gICAqICAgTm90ZSBvdmVyIFN0YXRlbWVudDogRXh0cmFjdCBjb25kaXRpb24gcGFydHNcbiAgICpcbiAgICogICBhbHQgU2ltcGxlIGNvbXBhcmlzb24gb3BlcmF0b3JcbiAgICogICAgIFN0YXRlbWVudC0+PnRyYW5zbGF0ZU9wZXJhdG9yczogdHJhbnNsYXRlT3BlcmF0b3JzKG9wZXJhdG9yKVxuICAgKiAgICAgdHJhbnNsYXRlT3BlcmF0b3JzLS0+PlN0YXRlbWVudDogUmV0dXJuIENvdWNoREIgb3BlcmF0b3JcbiAgICogICAgIFN0YXRlbWVudC0+PlN0YXRlbWVudDogQ3JlYXRlIHNlbGVjdG9yIHdpdGggYXR0cmlidXRlIGFuZCBvcGVyYXRvclxuICAgKiAgIGVsc2UgTk9UIG9wZXJhdG9yXG4gICAqICAgICBTdGF0ZW1lbnQtPj5TdGF0ZW1lbnQ6IHBhcnNlQ29uZGl0aW9uKGF0dHIxKVxuICAgKiAgICAgU3RhdGVtZW50LT4+dHJhbnNsYXRlT3BlcmF0b3JzOiB0cmFuc2xhdGVPcGVyYXRvcnMoT3BlcmF0b3IuTk9UKVxuICAgKiAgICAgdHJhbnNsYXRlT3BlcmF0b3JzLS0+PlN0YXRlbWVudDogUmV0dXJuIENvdWNoREIgTk9UIG9wZXJhdG9yXG4gICAqICAgICBTdGF0ZW1lbnQtPj5TdGF0ZW1lbnQ6IENyZWF0ZSBuZWdhdGVkIHNlbGVjdG9yXG4gICAqICAgZWxzZSBBTkQvT1Igb3BlcmF0b3JcbiAgICogICAgIFN0YXRlbWVudC0+PlN0YXRlbWVudDogcGFyc2VDb25kaXRpb24oYXR0cjEpXG4gICAqICAgICBTdGF0ZW1lbnQtPj5TdGF0ZW1lbnQ6IHBhcnNlQ29uZGl0aW9uKGNvbXBhcmlzb24pXG4gICAqICAgICBTdGF0ZW1lbnQtPj50cmFuc2xhdGVPcGVyYXRvcnM6IHRyYW5zbGF0ZU9wZXJhdG9ycyhvcGVyYXRvcilcbiAgICogICAgIHRyYW5zbGF0ZU9wZXJhdG9ycy0tPj5TdGF0ZW1lbnQ6IFJldHVybiBDb3VjaERCIGdyb3VwIG9wZXJhdG9yXG4gICAqICAgICBTdGF0ZW1lbnQtPj5tZXJnZTogbWVyZ2Uob3BlcmF0b3IsIG9wMSwgb3AyKVxuICAgKiAgICAgbWVyZ2UtLT4+U3RhdGVtZW50OiBSZXR1cm4gbWVyZ2VkIHNlbGVjdG9yXG4gICAqICAgZW5kXG4gICAqXG4gICAqICAgU3RhdGVtZW50LS0+PlN0YXRlbWVudDogUmV0dXJuIHF1ZXJ5IHdpdGggc2VsZWN0b3JcbiAgICovXG4gIHByb3RlY3RlZCBwYXJzZUNvbmRpdGlvbihjb25kaXRpb246IENvbmRpdGlvbjxNPik6IE1hbmdvUXVlcnkge1xuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBNZXJnZXMgdHdvIHNlbGVjdG9ycyB3aXRoIGEgbG9naWNhbCBvcGVyYXRvclxuICAgICAqIEBzdW1tYXJ5IEhlbHBlciBmdW5jdGlvbiB0byBjb21iaW5lIHR3byBzZWxlY3RvcnMgd2l0aCBhIGxvZ2ljYWwgb3BlcmF0b3JcbiAgICAgKiBAcGFyYW0ge01hbmdvT3BlcmF0b3J9IG9wIC0gVGhlIG9wZXJhdG9yIHRvIHVzZSBmb3IgbWVyZ2luZ1xuICAgICAqIEBwYXJhbSB7TWFuZ29TZWxlY3Rvcn0gb2JqMSAtIFRoZSBmaXJzdCBzZWxlY3RvclxuICAgICAqIEBwYXJhbSB7TWFuZ29TZWxlY3Rvcn0gb2JqMiAtIFRoZSBzZWNvbmQgc2VsZWN0b3JcbiAgICAgKiBAcmV0dXJuIHtNYW5nb1F1ZXJ5fSBUaGUgbWVyZ2VkIHF1ZXJ5XG4gICAgICovXG4gICAgZnVuY3Rpb24gbWVyZ2UoXG4gICAgICBvcDogTWFuZ29PcGVyYXRvcixcbiAgICAgIG9iajE6IE1hbmdvU2VsZWN0b3IsXG4gICAgICBvYmoyOiBNYW5nb1NlbGVjdG9yXG4gICAgKTogTWFuZ29RdWVyeSB7XG4gICAgICBjb25zdCByZXN1bHQ6IE1hbmdvUXVlcnkgPSB7IHNlbGVjdG9yOiB7fSBhcyBNYW5nb1NlbGVjdG9yIH07XG4gICAgICByZXN1bHQuc2VsZWN0b3Jbb3BdID0gW29iajEsIG9iajJdO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICBjb25zdCB7IGF0dHIxLCBvcGVyYXRvciwgY29tcGFyaXNvbiB9ID0gY29uZGl0aW9uIGFzIHVua25vd24gYXMge1xuICAgICAgYXR0cjE6IHN0cmluZyB8IENvbmRpdGlvbjxNPjtcbiAgICAgIG9wZXJhdG9yOiBPcGVyYXRvciB8IEdyb3VwT3BlcmF0b3I7XG4gICAgICBjb21wYXJpc29uOiBhbnk7XG4gICAgfTtcblxuICAgIGxldCBvcDogTWFuZ29TZWxlY3RvciA9IHt9IGFzIE1hbmdvU2VsZWN0b3I7XG4gICAgaWYgKFxuICAgICAgW0dyb3VwT3BlcmF0b3IuQU5ELCBHcm91cE9wZXJhdG9yLk9SLCBPcGVyYXRvci5OT1RdLmluZGV4T2YoXG4gICAgICAgIG9wZXJhdG9yIGFzIEdyb3VwT3BlcmF0b3JcbiAgICAgICkgPT09IC0xXG4gICAgKSB7XG4gICAgICBvcFthdHRyMSBhcyBzdHJpbmddID0ge30gYXMgTWFuZ29TZWxlY3RvcjtcbiAgICAgIChvcFthdHRyMSBhcyBzdHJpbmddIGFzIE1hbmdvU2VsZWN0b3IpW3RyYW5zbGF0ZU9wZXJhdG9ycyhvcGVyYXRvcildID1cbiAgICAgICAgY29tcGFyaXNvbjtcbiAgICB9IGVsc2UgaWYgKG9wZXJhdG9yID09PSBPcGVyYXRvci5OT1QpIHtcbiAgICAgIG9wID0gdGhpcy5wYXJzZUNvbmRpdGlvbihhdHRyMSBhcyBDb25kaXRpb248TT4pLnNlbGVjdG9yIGFzIE1hbmdvU2VsZWN0b3I7XG4gICAgICBvcFt0cmFuc2xhdGVPcGVyYXRvcnMoT3BlcmF0b3IuTk9UKV0gPSB7fSBhcyBNYW5nb1NlbGVjdG9yO1xuICAgICAgKG9wW3RyYW5zbGF0ZU9wZXJhdG9ycyhPcGVyYXRvci5OT1QpXSBhcyBNYW5nb1NlbGVjdG9yKVtcbiAgICAgICAgKGF0dHIxIGFzIHVua25vd24gYXMgeyBhdHRyMTogc3RyaW5nIH0pLmF0dHIxXG4gICAgICBdID0gY29tcGFyaXNvbjtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3Qgb3AxOiBhbnkgPSB0aGlzLnBhcnNlQ29uZGl0aW9uKGF0dHIxIGFzIENvbmRpdGlvbjxNPikuc2VsZWN0b3I7XG4gICAgICBjb25zdCBvcDI6IGFueSA9IHRoaXMucGFyc2VDb25kaXRpb24oY29tcGFyaXNvbiBhcyBDb25kaXRpb248TT4pLnNlbGVjdG9yO1xuICAgICAgb3AgPSBtZXJnZSh0cmFuc2xhdGVPcGVyYXRvcnMob3BlcmF0b3IpLCBvcDEsIG9wMikuc2VsZWN0b3I7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgc2VsZWN0b3I6IG9wIH07XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIEFkYXB0ZXIsXG4gIFNlcXVlbmNlLFxuICB0eXBlIFNlcXVlbmNlT3B0aW9ucyxcbiAgUGVyc2lzdGVuY2VLZXlzLFxuICBDb25uZWN0aW9uRXJyb3IsXG4gIFJlcG9zaXRvcnksXG59IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgQ291Y2hEQktleXMsIHJlc2VydmVkQXR0cmlidXRlcyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHtcbiAgQmFzZUVycm9yLFxuICBDb25mbGljdEVycm9yLFxuICBDb250ZXh0LFxuICBJbnRlcm5hbEVycm9yLFxuICBOb3RGb3VuZEVycm9yLFxuICBwcmVmaXhNZXRob2QsXG4gIFJlcG9zaXRvcnlGbGFncyxcbn0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgXCJyZWZsZWN0LW1ldGFkYXRhXCI7XG5cbmltcG9ydCB7IENvdWNoREJTZXF1ZW5jZSB9IGZyb20gXCIuL3NlcXVlbmNlcy9TZXF1ZW5jZVwiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgSW5kZXhFcnJvciB9IGZyb20gXCIuL2Vycm9yc1wiO1xuaW1wb3J0IHsgTWFuZ29RdWVyeSB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBDb3VjaERCU3RhdGVtZW50IH0gZnJvbSBcIi4vcXVlcnlcIjtcbmltcG9ydCB7IGZpbmFsIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEFic3RyYWN0IGFkYXB0ZXIgZm9yIENvdWNoREIgZGF0YWJhc2Ugb3BlcmF0aW9uc1xuICogQHN1bW1hcnkgUHJvdmlkZXMgYSBiYXNlIGltcGxlbWVudGF0aW9uIGZvciBDb3VjaERCIGRhdGFiYXNlIG9wZXJhdGlvbnMsIGluY2x1ZGluZyBDUlVEIG9wZXJhdGlvbnMsIHNlcXVlbmNlIG1hbmFnZW1lbnQsIGFuZCBlcnJvciBoYW5kbGluZ1xuICogQHRlbXBsYXRlIFkgLSBUaGUgc2NvcGUgdHlwZVxuICogQHRlbXBsYXRlIEYgLSBUaGUgcmVwb3NpdG9yeSBmbGFncyB0eXBlXG4gKiBAdGVtcGxhdGUgQyAtIFRoZSBjb250ZXh0IHR5cGVcbiAqIEBwYXJhbSB7WX0gc2NvcGUgLSBUaGUgc2NvcGUgZm9yIHRoZSBhZGFwdGVyXG4gKiBAcGFyYW0ge3N0cmluZ30gZmxhdm91ciAtIFRoZSBmbGF2b3VyIG9mIHRoZSBhZGFwdGVyXG4gKiBAcGFyYW0ge3N0cmluZ30gW2FsaWFzXSAtIE9wdGlvbmFsIGFsaWFzIGZvciB0aGUgYWRhcHRlclxuICogQGNsYXNzXG4gKiBAZXhhbXBsZVxuICogLy8gRXhhbXBsZSBvZiBleHRlbmRpbmcgQ291Y2hEQkFkYXB0ZXJcbiAqIGNsYXNzIE15Q291Y2hEQkFkYXB0ZXIgZXh0ZW5kcyBDb3VjaERCQWRhcHRlcjxNeVNjb3BlLCBNeUZsYWdzLCBNeUNvbnRleHQ+IHtcbiAqICAgY29uc3RydWN0b3Ioc2NvcGU6IE15U2NvcGUpIHtcbiAqICAgICBzdXBlcihzY29wZSwgJ215LWNvdWNoZGInLCAnbXktYWxpYXMnKTtcbiAqICAgfVxuICpcbiAqICAgLy8gSW1wbGVtZW50IGFic3RyYWN0IG1ldGhvZHNcbiAqICAgYXN5bmMgaW5kZXg8TSBleHRlbmRzIE1vZGVsPiguLi5tb2RlbHM6IENvbnN0cnVjdG9yPE0+W10pOiBQcm9taXNlPHZvaWQ+IHtcbiAqICAgICAvLyBJbXBsZW1lbnRhdGlvblxuICogICB9XG4gKlxuICogICBhc3luYyByYXc8Uj4ocmF3SW5wdXQ6IE1hbmdvUXVlcnksIGRvY3NPbmx5OiBib29sZWFuKTogUHJvbWlzZTxSPiB7XG4gKiAgICAgLy8gSW1wbGVtZW50YXRpb25cbiAqICAgfVxuICpcbiAqICAgYXN5bmMgY3JlYXRlKHRhYmxlTmFtZTogc3RyaW5nLCBpZDogc3RyaW5nIHwgbnVtYmVyLCBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PiwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+IHtcbiAqICAgICAvLyBJbXBsZW1lbnRhdGlvblxuICogICB9XG4gKlxuICogICBhc3luYyByZWFkKHRhYmxlTmFtZTogc3RyaW5nLCBpZDogc3RyaW5nIHwgbnVtYmVyLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj4ge1xuICogICAgIC8vIEltcGxlbWVudGF0aW9uXG4gKiAgIH1cbiAqXG4gKiAgIGFzeW5jIHVwZGF0ZSh0YWJsZU5hbWU6IHN0cmluZywgaWQ6IHN0cmluZyB8IG51bWJlciwgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT4sIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gKiAgICAgLy8gSW1wbGVtZW50YXRpb25cbiAqICAgfVxuICpcbiAqICAgYXN5bmMgZGVsZXRlKHRhYmxlTmFtZTogc3RyaW5nLCBpZDogc3RyaW5nIHwgbnVtYmVyLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj4ge1xuICogICAgIC8vIEltcGxlbWVudGF0aW9uXG4gKiAgIH1cbiAqIH1cbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIENvdWNoREJBZGFwdGVyPFxuICBZLFxuICBDT05OLFxuICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPixcbj4gZXh0ZW5kcyBBZGFwdGVyPFksIENPTk4sIE1hbmdvUXVlcnksIEYsIEM+IHtcbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKHNjb3BlOiBZLCBmbGF2b3VyOiBzdHJpbmcsIGFsaWFzPzogc3RyaW5nKSB7XG4gICAgc3VwZXIoc2NvcGUsIGZsYXZvdXIsIGFsaWFzKTtcbiAgICBbdGhpcy5jcmVhdGUsIHRoaXMuY3JlYXRlQWxsLCB0aGlzLnVwZGF0ZSwgdGhpcy51cGRhdGVBbGxdLmZvckVhY2goKG0pID0+IHtcbiAgICAgIGNvbnN0IG5hbWUgPSBtLm5hbWU7XG4gICAgICBwcmVmaXhNZXRob2QodGhpcywgbSwgKHRoaXMgYXMgYW55KVtuYW1lICsgXCJQcmVmaXhcIl0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbmV3IENvdWNoREIgc3RhdGVtZW50IGZvciBxdWVyeWluZ1xuICAgKiBAc3VtbWFyeSBGYWN0b3J5IG1ldGhvZCB0aGF0IGNyZWF0ZXMgYSBuZXcgQ291Y2hEQlN0YXRlbWVudCBpbnN0YW5jZSBmb3IgYnVpbGRpbmcgcXVlcmllc1xuICAgKiBAdGVtcGxhdGUgTSAtIFRoZSBtb2RlbCB0eXBlXG4gICAqIEByZXR1cm4ge0NvdWNoREJTdGF0ZW1lbnQ8TSwgYW55Pn0gQSBuZXcgQ291Y2hEQlN0YXRlbWVudCBpbnN0YW5jZVxuICAgKi9cbiAgQGZpbmFsKClcbiAgU3RhdGVtZW50PE0gZXh0ZW5kcyBNb2RlbD4oKTogQ291Y2hEQlN0YXRlbWVudDxNLCBhbnk+IHtcbiAgICByZXR1cm4gbmV3IENvdWNoREJTdGF0ZW1lbnQodGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgQ291Y2hEQiBzZXF1ZW5jZVxuICAgKiBAc3VtbWFyeSBGYWN0b3J5IG1ldGhvZCB0aGF0IGNyZWF0ZXMgYSBuZXcgQ291Y2hEQlNlcXVlbmNlIGluc3RhbmNlIGZvciBtYW5hZ2luZyBzZXF1ZW5jZXNcbiAgICogQHBhcmFtIHtTZXF1ZW5jZU9wdGlvbnN9IG9wdGlvbnMgLSBUaGUgb3B0aW9ucyBmb3IgdGhlIHNlcXVlbmNlXG4gICAqIEByZXR1cm4ge1Byb21pc2U8U2VxdWVuY2U+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIG5ldyBTZXF1ZW5jZSBpbnN0YW5jZVxuICAgKi9cbiAgQGZpbmFsKClcbiAgYXN5bmMgU2VxdWVuY2Uob3B0aW9uczogU2VxdWVuY2VPcHRpb25zKTogUHJvbWlzZTxTZXF1ZW5jZT4ge1xuICAgIHJldHVybiBuZXcgQ291Y2hEQlNlcXVlbmNlKG9wdGlvbnMsIHRoaXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplcyB0aGUgYWRhcHRlciBieSBjcmVhdGluZyBpbmRleGVzIGZvciBhbGwgbWFuYWdlZCBtb2RlbHNcbiAgICogQHN1bW1hcnkgU2V0cyB1cCB0aGUgbmVjZXNzYXJ5IGRhdGFiYXNlIGluZGV4ZXMgZm9yIGFsbCBtb2RlbHMgbWFuYWdlZCBieSB0aGlzIGFkYXB0ZXJcbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBpbml0aWFsaXphdGlvbiBpcyBjb21wbGV0ZVxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgaW5pdGlhbGl6ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBtYW5hZ2VkTW9kZWxzID0gQWRhcHRlci5tb2RlbHModGhpcy5mbGF2b3VyKTtcbiAgICByZXR1cm4gdGhpcy5pbmRleCguLi5tYW5hZ2VkTW9kZWxzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBpbmRleGVzIGZvciB0aGUgZ2l2ZW4gbW9kZWxzXG4gICAqIEBzdW1tYXJ5IEFic3RyYWN0IG1ldGhvZCB0aGF0IG11c3QgYmUgaW1wbGVtZW50ZWQgdG8gY3JlYXRlIGRhdGFiYXNlIGluZGV4ZXMgZm9yIHRoZSBzcGVjaWZpZWQgbW9kZWxzXG4gICAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGVcbiAgICogQHBhcmFtIHsuLi5Db25zdHJ1Y3RvcjxNPn0gbW9kZWxzIC0gVGhlIG1vZGVsIGNvbnN0cnVjdG9ycyB0byBjcmVhdGUgaW5kZXhlcyBmb3JcbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBhbGwgaW5kZXhlcyBhcmUgY3JlYXRlZFxuICAgKi9cbiAgcHJvdGVjdGVkIGFic3RyYWN0IGluZGV4PE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgLi4ubW9kZWxzOiBDb25zdHJ1Y3RvcjxNPltdXG4gICk6IFByb21pc2U8dm9pZD47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBFeGVjdXRlcyBhIHJhdyBNYW5nbyBxdWVyeSBhZ2FpbnN0IHRoZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBBYnN0cmFjdCBtZXRob2QgdGhhdCBtdXN0IGJlIGltcGxlbWVudGVkIHRvIGV4ZWN1dGUgcmF3IE1hbmdvIHF1ZXJpZXNcbiAgICogQHRlbXBsYXRlIFIgLSBUaGUgcmVzdWx0IHR5cGVcbiAgICogQHBhcmFtIHtNYW5nb1F1ZXJ5fSByYXdJbnB1dCAtIFRoZSByYXcgTWFuZ28gcXVlcnkgdG8gZXhlY3V0ZVxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGRvY3NPbmx5IC0gV2hldGhlciB0byByZXR1cm4gb25seSB0aGUgZG9jdW1lbnRzIG9yIHRoZSBmdWxsIHJlc3BvbnNlXG4gICAqIEByZXR1cm4ge1Byb21pc2U8Uj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBxdWVyeSByZXN1bHRcbiAgICovXG4gIGFic3RyYWN0IG92ZXJyaWRlIHJhdzxSPihyYXdJbnB1dDogTWFuZ29RdWVyeSwgZG9jc09ubHk6IGJvb2xlYW4pOiBQcm9taXNlPFI+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXNzaWducyBtZXRhZGF0YSB0byBhIG1vZGVsXG4gICAqIEBzdW1tYXJ5IEFkZHMgcmV2aXNpb24gbWV0YWRhdGEgdG8gYSBtb2RlbCBhcyBhIG5vbi1lbnVtZXJhYmxlIHByb3BlcnR5XG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gbW9kZWwgLSBUaGUgbW9kZWwgdG8gYXNzaWduIG1ldGFkYXRhIHRvXG4gICAqIEBwYXJhbSB7c3RyaW5nfSByZXYgLSBUaGUgcmV2aXNpb24gc3RyaW5nIHRvIGFzc2lnblxuICAgKiBAcmV0dXJuIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBUaGUgbW9kZWwgd2l0aCBtZXRhZGF0YSBhc3NpZ25lZFxuICAgKi9cbiAgQGZpbmFsKClcbiAgcHJvdGVjdGVkIGFzc2lnbk1ldGFkYXRhKFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIHJldjogc3RyaW5nXG4gICk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShtb2RlbCwgUGVyc2lzdGVuY2VLZXlzLk1FVEFEQVRBLCB7XG4gICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICB2YWx1ZTogcmV2LFxuICAgIH0pO1xuICAgIHJldHVybiBtb2RlbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXNzaWducyBtZXRhZGF0YSB0byBtdWx0aXBsZSBtb2RlbHNcbiAgICogQHN1bW1hcnkgQWRkcyByZXZpc2lvbiBtZXRhZGF0YSB0byBtdWx0aXBsZSBtb2RlbHMgYXMgbm9uLWVudW1lcmFibGUgcHJvcGVydGllc1xuICAgKiBAcGFyYW0gbW9kZWxzIC0gVGhlIG1vZGVscyB0byBhc3NpZ24gbWV0YWRhdGEgdG9cbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gcmV2cyAtIFRoZSByZXZpc2lvbiBzdHJpbmdzIHRvIGFzc2lnblxuICAgKiBAcmV0dXJuIFRoZSBtb2RlbHMgd2l0aCBtZXRhZGF0YSBhc3NpZ25lZFxuICAgKi9cbiAgQGZpbmFsKClcbiAgcHJvdGVjdGVkIGFzc2lnbk11bHRpcGxlTWV0YWRhdGEoXG4gICAgbW9kZWxzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+W10sXG4gICAgcmV2czogc3RyaW5nW11cbiAgKTogUmVjb3JkPHN0cmluZywgYW55PltdIHtcbiAgICBtb2RlbHMuZm9yRWFjaCgobSwgaSkgPT4ge1xuICAgICAgUmVwb3NpdG9yeS5zZXRNZXRhZGF0YShtIGFzIGFueSwgcmV2c1tpXSk7XG4gICAgICByZXR1cm4gbTtcbiAgICB9KTtcbiAgICByZXR1cm4gbW9kZWxzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyBhIHJlY29yZCBmb3IgY3JlYXRpb25cbiAgICogQHN1bW1hcnkgQWRkcyBuZWNlc3NhcnkgQ291Y2hEQiBmaWVsZHMgdG8gYSByZWNvcmQgYmVmb3JlIGNyZWF0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGVcbiAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBpZCAtIFRoZSBJRCBvZiB0aGUgcmVjb3JkXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gbW9kZWwgLSBUaGUgbW9kZWwgdG8gcHJlcGFyZVxuICAgKiBAcmV0dXJuIEEgdHVwbGUgY29udGFpbmluZyB0aGUgdGFibGVOYW1lLCBpZCwgYW5kIHByZXBhcmVkIHJlY29yZFxuICAgKi9cbiAgQGZpbmFsKClcbiAgcHJvdGVjdGVkIGNyZWF0ZVByZWZpeChcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZDogc3RyaW5nIHwgbnVtYmVyLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+XG4gICkge1xuICAgIGNvbnN0IHJlY29yZDogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgIHJlY29yZFtDb3VjaERCS2V5cy5UQUJMRV0gPSB0YWJsZU5hbWU7XG4gICAgcmVjb3JkW0NvdWNoREJLZXlzLklEXSA9IHRoaXMuZ2VuZXJhdGVJZCh0YWJsZU5hbWUsIGlkKTtcbiAgICBPYmplY3QuYXNzaWduKHJlY29yZCwgbW9kZWwpO1xuICAgIHJldHVybiBbdGFibGVOYW1lLCBpZCwgcmVjb3JkXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIG5ldyByZWNvcmQgaW4gdGhlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IEFic3RyYWN0IG1ldGhvZCB0aGF0IG11c3QgYmUgaW1wbGVtZW50ZWQgdG8gY3JlYXRlIGEgbmV3IHJlY29yZFxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlXG4gICAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gaWQgLSBUaGUgSUQgb2YgdGhlIHJlY29yZFxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IG1vZGVsIC0gVGhlIG1vZGVsIHRvIGNyZWF0ZVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIGNyZWF0ZWQgcmVjb3JkXG4gICAqL1xuICBhYnN0cmFjdCBvdmVycmlkZSBjcmVhdGUoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IHN0cmluZyB8IG51bWJlcixcbiAgICBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJlcGFyZXMgbXVsdGlwbGUgcmVjb3JkcyBmb3IgY3JlYXRpb25cbiAgICogQHN1bW1hcnkgQWRkcyBuZWNlc3NhcnkgQ291Y2hEQiBmaWVsZHMgdG8gbXVsdGlwbGUgcmVjb3JkcyBiZWZvcmUgY3JlYXRpb25cbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZVxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfG51bWJlcltdfSBpZHMgLSBUaGUgSURzIG9mIHRoZSByZWNvcmRzXG4gICAqIEBwYXJhbSBtb2RlbHMgLSBUaGUgbW9kZWxzIHRvIHByZXBhcmVcbiAgICogQHJldHVybiBBIHR1cGxlIGNvbnRhaW5pbmcgdGhlIHRhYmxlTmFtZSwgaWRzLCBhbmQgcHJlcGFyZWQgcmVjb3Jkc1xuICAgKiBAdGhyb3dzIHtJbnRlcm5hbEVycm9yfSBJZiBpZHMgYW5kIG1vZGVscyBhcnJheXMgaGF2ZSBkaWZmZXJlbnQgbGVuZ3Roc1xuICAgKi9cbiAgQGZpbmFsKClcbiAgcHJvdGVjdGVkIGNyZWF0ZUFsbFByZWZpeChcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZHM6IHN0cmluZ1tdIHwgbnVtYmVyW10sXG4gICAgbW9kZWxzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+W11cbiAgKSB7XG4gICAgaWYgKGlkcy5sZW5ndGggIT09IG1vZGVscy5sZW5ndGgpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIklkcyBhbmQgbW9kZWxzIG11c3QgaGF2ZSB0aGUgc2FtZSBsZW5ndGhcIik7XG5cbiAgICBjb25zdCByZWNvcmRzID0gaWRzLm1hcCgoaWQsIGNvdW50KSA9PiB7XG4gICAgICBjb25zdCByZWNvcmQ6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcbiAgICAgIHJlY29yZFtDb3VjaERCS2V5cy5UQUJMRV0gPSB0YWJsZU5hbWU7XG4gICAgICByZWNvcmRbQ291Y2hEQktleXMuSURdID0gdGhpcy5nZW5lcmF0ZUlkKHRhYmxlTmFtZSwgaWQpO1xuICAgICAgT2JqZWN0LmFzc2lnbihyZWNvcmQsIG1vZGVsc1tjb3VudF0pO1xuICAgICAgcmV0dXJuIHJlY29yZDtcbiAgICB9KTtcbiAgICByZXR1cm4gW3RhYmxlTmFtZSwgaWRzLCByZWNvcmRzXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVhZHMgYSByZWNvcmQgZnJvbSB0aGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgQWJzdHJhY3QgbWV0aG9kIHRoYXQgbXVzdCBiZSBpbXBsZW1lbnRlZCB0byByZWFkIGEgcmVjb3JkXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGVcbiAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBpZCAtIFRoZSBJRCBvZiB0aGUgcmVjb3JkXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgcmVhZCByZWNvcmRcbiAgICovXG4gIGFic3RyYWN0IG92ZXJyaWRlIHJlYWQoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IHN0cmluZyB8IG51bWJlcixcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJlcGFyZXMgYSByZWNvcmQgZm9yIHVwZGF0ZVxuICAgKiBAc3VtbWFyeSBBZGRzIG5lY2Vzc2FyeSBDb3VjaERCIGZpZWxkcyB0byBhIHJlY29yZCBiZWZvcmUgdXBkYXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGVcbiAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBpZCAtIFRoZSBJRCBvZiB0aGUgcmVjb3JkXG4gICAqIEBwYXJhbSBtb2RlbCAtIFRoZSBtb2RlbCB0byBwcmVwYXJlXG4gICAqIEByZXR1cm4gQSB0dXBsZSBjb250YWluaW5nIHRoZSB0YWJsZU5hbWUsIGlkLCBhbmQgcHJlcGFyZWQgcmVjb3JkXG4gICAqIEB0aHJvd3Mge0ludGVybmFsRXJyb3J9IElmIG5vIHJldmlzaW9uIG51bWJlciBpcyBmb3VuZCBpbiB0aGUgbW9kZWxcbiAgICovXG4gIEBmaW5hbCgpXG4gIHVwZGF0ZVByZWZpeChcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZDogc3RyaW5nIHwgbnVtYmVyLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+XG4gICkge1xuICAgIGNvbnN0IHJlY29yZDogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgIHJlY29yZFtDb3VjaERCS2V5cy5UQUJMRV0gPSB0YWJsZU5hbWU7XG4gICAgcmVjb3JkW0NvdWNoREJLZXlzLklEXSA9IHRoaXMuZ2VuZXJhdGVJZCh0YWJsZU5hbWUsIGlkKTtcbiAgICBjb25zdCByZXYgPSBtb2RlbFtQZXJzaXN0ZW5jZUtleXMuTUVUQURBVEFdO1xuICAgIGlmICghcmV2KVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBObyByZXZpc2lvbiBudW1iZXIgZm91bmQgZm9yIHJlY29yZCB3aXRoIGlkICR7aWR9YFxuICAgICAgKTtcbiAgICBPYmplY3QuYXNzaWduKHJlY29yZCwgbW9kZWwpO1xuICAgIHJlY29yZFtDb3VjaERCS2V5cy5SRVZdID0gcmV2O1xuICAgIHJldHVybiBbdGFibGVOYW1lLCBpZCwgcmVjb3JkXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVXBkYXRlcyBhIHJlY29yZCBpbiB0aGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgQWJzdHJhY3QgbWV0aG9kIHRoYXQgbXVzdCBiZSBpbXBsZW1lbnRlZCB0byB1cGRhdGUgYSByZWNvcmRcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZVxuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIC0gVGhlIElEIG9mIHRoZSByZWNvcmRcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBtb2RlbCAtIFRoZSBtb2RlbCB0byB1cGRhdGVcbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHVwZGF0ZWQgcmVjb3JkXG4gICAqL1xuICBhYnN0cmFjdCBvdmVycmlkZSB1cGRhdGUoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IHN0cmluZyB8IG51bWJlcixcbiAgICBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJlcGFyZXMgbXVsdGlwbGUgcmVjb3JkcyBmb3IgdXBkYXRlXG4gICAqIEBzdW1tYXJ5IEFkZHMgbmVjZXNzYXJ5IENvdWNoREIgZmllbGRzIHRvIG11bHRpcGxlIHJlY29yZHMgYmVmb3JlIHVwZGF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlXG4gICAqIEBwYXJhbSB7c3RyaW5nW118bnVtYmVyW119IGlkcyAtIFRoZSBJRHMgb2YgdGhlIHJlY29yZHNcbiAgICogQHBhcmFtIG1vZGVscyAtIFRoZSBtb2RlbHMgdG8gcHJlcGFyZVxuICAgKiBAcmV0dXJuIEEgdHVwbGUgY29udGFpbmluZyB0aGUgdGFibGVOYW1lLCBpZHMsIGFuZCBwcmVwYXJlZCByZWNvcmRzXG4gICAqIEB0aHJvd3Mge0ludGVybmFsRXJyb3J9IElmIGlkcyBhbmQgbW9kZWxzIGFycmF5cyBoYXZlIGRpZmZlcmVudCBsZW5ndGhzIG9yIGlmIG5vIHJldmlzaW9uIG51bWJlciBpcyBmb3VuZCBpbiBhIG1vZGVsXG4gICAqL1xuICBAZmluYWwoKVxuICBwcm90ZWN0ZWQgdXBkYXRlQWxsUHJlZml4KFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIGlkczogc3RyaW5nW10gfCBudW1iZXJbXSxcbiAgICBtb2RlbHM6IFJlY29yZDxzdHJpbmcsIGFueT5bXVxuICApIHtcbiAgICBpZiAoaWRzLmxlbmd0aCAhPT0gbW9kZWxzLmxlbmd0aClcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiSWRzIGFuZCBtb2RlbHMgbXVzdCBoYXZlIHRoZSBzYW1lIGxlbmd0aFwiKTtcblxuICAgIGNvbnN0IHJlY29yZHMgPSBpZHMubWFwKChpZCwgY291bnQpID0+IHtcbiAgICAgIGNvbnN0IHJlY29yZDogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgICAgcmVjb3JkW0NvdWNoREJLZXlzLlRBQkxFXSA9IHRhYmxlTmFtZTtcbiAgICAgIHJlY29yZFtDb3VjaERCS2V5cy5JRF0gPSB0aGlzLmdlbmVyYXRlSWQodGFibGVOYW1lLCBpZCk7XG4gICAgICBjb25zdCByZXYgPSBtb2RlbHNbY291bnRdW1BlcnNpc3RlbmNlS2V5cy5NRVRBREFUQV07XG4gICAgICBpZiAoIXJldilcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgYE5vIHJldmlzaW9uIG51bWJlciBmb3VuZCBmb3IgcmVjb3JkIHdpdGggaWQgJHtpZH1gXG4gICAgICAgICk7XG4gICAgICBPYmplY3QuYXNzaWduKHJlY29yZCwgbW9kZWxzW2NvdW50XSk7XG4gICAgICByZWNvcmRbQ291Y2hEQktleXMuUkVWXSA9IHJldjtcbiAgICAgIHJldHVybiByZWNvcmQ7XG4gICAgfSk7XG4gICAgcmV0dXJuIFt0YWJsZU5hbWUsIGlkcywgcmVjb3Jkc107XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERlbGV0ZXMgYSByZWNvcmQgZnJvbSB0aGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgQWJzdHJhY3QgbWV0aG9kIHRoYXQgbXVzdCBiZSBpbXBsZW1lbnRlZCB0byBkZWxldGUgYSByZWNvcmRcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZVxuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIC0gVGhlIElEIG9mIHRoZSByZWNvcmRcbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIGRlbGV0ZWQgcmVjb3JkXG4gICAqL1xuICBhYnN0cmFjdCBvdmVycmlkZSBkZWxldGUoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IHN0cmluZyB8IG51bWJlcixcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2VuZXJhdGVzIGEgQ291Y2hEQiBkb2N1bWVudCBJRFxuICAgKiBAc3VtbWFyeSBDb21iaW5lcyB0aGUgdGFibGUgbmFtZSBhbmQgSUQgdG8gY3JlYXRlIGEgQ291Y2hEQiBkb2N1bWVudCBJRFxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlXG4gICAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gaWQgLSBUaGUgSUQgb2YgdGhlIHJlY29yZFxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBnZW5lcmF0ZWQgQ291Y2hEQiBkb2N1bWVudCBJRFxuICAgKi9cbiAgcHJvdGVjdGVkIGdlbmVyYXRlSWQodGFibGVOYW1lOiBzdHJpbmcsIGlkOiBzdHJpbmcgfCBudW1iZXIpIHtcbiAgICByZXR1cm4gW3RhYmxlTmFtZSwgaWRdLmpvaW4oQ291Y2hEQktleXMuU0VQQVJBVE9SKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUGFyc2VzIGFuIGVycm9yIGFuZCBjb252ZXJ0cyBpdCB0byBhIEJhc2VFcnJvclxuICAgKiBAc3VtbWFyeSBDb252ZXJ0cyB2YXJpb3VzIGVycm9yIHR5cGVzIHRvIGFwcHJvcHJpYXRlIEJhc2VFcnJvciBzdWJ0eXBlc1xuICAgKiBAcGFyYW0ge0Vycm9yfHN0cmluZ30gZXJyIC0gVGhlIGVycm9yIHRvIHBhcnNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIE9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGVycm9yXG4gICAqIEByZXR1cm4ge0Jhc2VFcnJvcn0gVGhlIHBhcnNlZCBlcnJvciBhcyBhIEJhc2VFcnJvclxuICAgKi9cbiAgcGFyc2VFcnJvcihlcnI6IEVycm9yIHwgc3RyaW5nLCByZWFzb24/OiBzdHJpbmcpOiBCYXNlRXJyb3Ige1xuICAgIHJldHVybiBDb3VjaERCQWRhcHRlci5wYXJzZUVycm9yKGVyciwgcmVhc29uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ2hlY2tzIGlmIGFuIGF0dHJpYnV0ZSBpcyByZXNlcnZlZFxuICAgKiBAc3VtbWFyeSBEZXRlcm1pbmVzIGlmIGFuIGF0dHJpYnV0ZSBuYW1lIGlzIHJlc2VydmVkIGluIENvdWNoREJcbiAgICogQHBhcmFtIHtzdHJpbmd9IGF0dHIgLSBUaGUgYXR0cmlidXRlIG5hbWUgdG8gY2hlY2tcbiAgICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgYXR0cmlidXRlIGlzIHJlc2VydmVkLCBmYWxzZSBvdGhlcndpc2VcbiAgICovXG4gIHByb3RlY3RlZCBvdmVycmlkZSBpc1Jlc2VydmVkKGF0dHI6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhIWF0dHIubWF0Y2gocmVzZXJ2ZWRBdHRyaWJ1dGVzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3RhdGljIG1ldGhvZCB0byBwYXJzZSBhbiBlcnJvciBhbmQgY29udmVydCBpdCB0byBhIEJhc2VFcnJvclxuICAgKiBAc3VtbWFyeSBDb252ZXJ0cyB2YXJpb3VzIGVycm9yIHR5cGVzIHRvIGFwcHJvcHJpYXRlIEJhc2VFcnJvciBzdWJ0eXBlcyBiYXNlZCBvbiBlcnJvciBjb2RlcyBhbmQgbWVzc2FnZXNcbiAgICogQHBhcmFtIHtFcnJvcnxzdHJpbmd9IGVyciAtIFRoZSBlcnJvciB0byBwYXJzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3JlYXNvbl0gLSBPcHRpb25hbCByZWFzb24gZm9yIHRoZSBlcnJvclxuICAgKiBAcmV0dXJuIHtCYXNlRXJyb3J9IFRoZSBwYXJzZWQgZXJyb3IgYXMgYSBCYXNlRXJyb3JcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gICAqICAgcGFydGljaXBhbnQgcGFyc2VFcnJvclxuICAgKiAgIHBhcnRpY2lwYW50IEVycm9yVHlwZXNcbiAgICpcbiAgICogICBDYWxsZXItPj5wYXJzZUVycm9yOiBlcnIsIHJlYXNvblxuICAgKiAgIE5vdGUgb3ZlciBwYXJzZUVycm9yOiBDaGVjayBpZiBlcnIgaXMgYWxyZWFkeSBhIEJhc2VFcnJvclxuICAgKiAgIGFsdCBlcnIgaXMgQmFzZUVycm9yXG4gICAqICAgICBwYXJzZUVycm9yLS0+PkNhbGxlcjogcmV0dXJuIGVyclxuICAgKiAgIGVsc2UgZXJyIGlzIHN0cmluZ1xuICAgKiAgICAgTm90ZSBvdmVyIHBhcnNlRXJyb3I6IEV4dHJhY3QgY29kZSBmcm9tIHN0cmluZ1xuICAgKiAgICAgYWx0IGNvZGUgbWF0Y2hlcyBcImFscmVhZHkgZXhpc3R8dXBkYXRlIGNvbmZsaWN0XCJcbiAgICogICAgICAgcGFyc2VFcnJvci0+PkVycm9yVHlwZXM6IG5ldyBDb25mbGljdEVycm9yKGNvZGUpXG4gICAqICAgICAgIEVycm9yVHlwZXMtLT4+Q2FsbGVyOiBDb25mbGljdEVycm9yXG4gICAqICAgICBlbHNlIGNvZGUgbWF0Y2hlcyBcIm1pc3Npbmd8ZGVsZXRlZFwiXG4gICAqICAgICAgIHBhcnNlRXJyb3ItPj5FcnJvclR5cGVzOiBuZXcgTm90Rm91bmRFcnJvcihjb2RlKVxuICAgKiAgICAgICBFcnJvclR5cGVzLS0+PkNhbGxlcjogTm90Rm91bmRFcnJvclxuICAgKiAgICAgZW5kXG4gICAqICAgZWxzZSBlcnIgaGFzIGNvZGUgcHJvcGVydHlcbiAgICogICAgIE5vdGUgb3ZlciBwYXJzZUVycm9yOiBFeHRyYWN0IGNvZGUgYW5kIHJlYXNvblxuICAgKiAgIGVsc2UgZXJyIGhhcyBzdGF0dXNDb2RlIHByb3BlcnR5XG4gICAqICAgICBOb3RlIG92ZXIgcGFyc2VFcnJvcjogRXh0cmFjdCBjb2RlIGFuZCByZWFzb25cbiAgICogICBlbHNlXG4gICAqICAgICBOb3RlIG92ZXIgcGFyc2VFcnJvcjogVXNlIGVyci5tZXNzYWdlIGFzIGNvZGVcbiAgICogICBlbmRcbiAgICpcbiAgICogICBOb3RlIG92ZXIgcGFyc2VFcnJvcjogU3dpdGNoIG9uIGNvZGVcbiAgICogICBhbHQgY29kZSBpcyA0MDEsIDQxMiwgb3IgNDA5XG4gICAqICAgICBwYXJzZUVycm9yLT4+RXJyb3JUeXBlczogbmV3IENvbmZsaWN0RXJyb3IocmVhc29uKVxuICAgKiAgICAgRXJyb3JUeXBlcy0tPj5DYWxsZXI6IENvbmZsaWN0RXJyb3JcbiAgICogICBlbHNlIGNvZGUgaXMgNDA0XG4gICAqICAgICBwYXJzZUVycm9yLT4+RXJyb3JUeXBlczogbmV3IE5vdEZvdW5kRXJyb3IocmVhc29uKVxuICAgKiAgICAgRXJyb3JUeXBlcy0tPj5DYWxsZXI6IE5vdEZvdW5kRXJyb3JcbiAgICogICBlbHNlIGNvZGUgaXMgNDAwXG4gICAqICAgICBhbHQgY29kZSBtYXRjaGVzIFwiTm8gaW5kZXggZXhpc3RzXCJcbiAgICogICAgICAgcGFyc2VFcnJvci0+PkVycm9yVHlwZXM6IG5ldyBJbmRleEVycm9yKGVycilcbiAgICogICAgICAgRXJyb3JUeXBlcy0tPj5DYWxsZXI6IEluZGV4RXJyb3JcbiAgICogICAgIGVsc2VcbiAgICogICAgICAgcGFyc2VFcnJvci0+PkVycm9yVHlwZXM6IG5ldyBJbnRlcm5hbEVycm9yKGVycilcbiAgICogICAgICAgRXJyb3JUeXBlcy0tPj5DYWxsZXI6IEludGVybmFsRXJyb3JcbiAgICogICAgIGVuZFxuICAgKiAgIGVsc2UgY29kZSBtYXRjaGVzIFwiRUNPTk5SRUZVU0VEXCJcbiAgICogICAgIHBhcnNlRXJyb3ItPj5FcnJvclR5cGVzOiBuZXcgQ29ubmVjdGlvbkVycm9yKGVycilcbiAgICogICAgIEVycm9yVHlwZXMtLT4+Q2FsbGVyOiBDb25uZWN0aW9uRXJyb3JcbiAgICogICBlbHNlXG4gICAqICAgICBwYXJzZUVycm9yLT4+RXJyb3JUeXBlczogbmV3IEludGVybmFsRXJyb3IoZXJyKVxuICAgKiAgICAgRXJyb3JUeXBlcy0tPj5DYWxsZXI6IEludGVybmFsRXJyb3JcbiAgICogICBlbmRcbiAgICovXG4gIHByb3RlY3RlZCBzdGF0aWMgcGFyc2VFcnJvcihlcnI6IEVycm9yIHwgc3RyaW5nLCByZWFzb24/OiBzdHJpbmcpOiBCYXNlRXJyb3Ige1xuICAgIGlmIChlcnIgaW5zdGFuY2VvZiBCYXNlRXJyb3IpIHJldHVybiBlcnIgYXMgYW55O1xuICAgIGxldCBjb2RlOiBzdHJpbmcgPSBcIlwiO1xuICAgIGlmICh0eXBlb2YgZXJyID09PSBcInN0cmluZ1wiKSB7XG4gICAgICBjb2RlID0gZXJyO1xuICAgICAgaWYgKGNvZGUubWF0Y2goL2FscmVhZHkgZXhpc3R8dXBkYXRlIGNvbmZsaWN0L2cpKVxuICAgICAgICByZXR1cm4gbmV3IENvbmZsaWN0RXJyb3IoY29kZSk7XG4gICAgICBpZiAoY29kZS5tYXRjaCgvbWlzc2luZ3xkZWxldGVkL2cpKSByZXR1cm4gbmV3IE5vdEZvdW5kRXJyb3IoY29kZSk7XG4gICAgfSBlbHNlIGlmICgoZXJyIGFzIGFueSkuY29kZSkge1xuICAgICAgY29kZSA9IChlcnIgYXMgYW55KS5jb2RlO1xuICAgICAgcmVhc29uID0gcmVhc29uIHx8IGVyci5tZXNzYWdlO1xuICAgIH0gZWxzZSBpZiAoKGVyciBhcyBhbnkpLnN0YXR1c0NvZGUpIHtcbiAgICAgIGNvZGUgPSAoZXJyIGFzIGFueSkuc3RhdHVzQ29kZTtcbiAgICAgIHJlYXNvbiA9IHJlYXNvbiB8fCBlcnIubWVzc2FnZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29kZSA9IGVyci5tZXNzYWdlO1xuICAgIH1cblxuICAgIHN3aXRjaCAoY29kZS50b1N0cmluZygpKSB7XG4gICAgICBjYXNlIFwiNDAxXCI6XG4gICAgICBjYXNlIFwiNDEyXCI6XG4gICAgICBjYXNlIFwiNDA5XCI6XG4gICAgICAgIHJldHVybiBuZXcgQ29uZmxpY3RFcnJvcihyZWFzb24gYXMgc3RyaW5nKTtcbiAgICAgIGNhc2UgXCI0MDRcIjpcbiAgICAgICAgcmV0dXJuIG5ldyBOb3RGb3VuZEVycm9yKHJlYXNvbiBhcyBzdHJpbmcpO1xuICAgICAgY2FzZSBcIjQwMFwiOlxuICAgICAgICBpZiAoY29kZS50b1N0cmluZygpLm1hdGNoKC9Ob1xcc2luZGV4XFxzZXhpc3RzL2cpKVxuICAgICAgICAgIHJldHVybiBuZXcgSW5kZXhFcnJvcihlcnIpO1xuICAgICAgICByZXR1cm4gbmV3IEludGVybmFsRXJyb3IoZXJyKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChjb2RlLnRvU3RyaW5nKCkubWF0Y2goL0VDT05OUkVGVVNFRC9nKSlcbiAgICAgICAgICByZXR1cm4gbmV3IENvbm5lY3Rpb25FcnJvcihlcnIpO1xuICAgICAgICByZXR1cm4gbmV3IEludGVybmFsRXJyb3IoZXJyKTtcbiAgICB9XG4gIH1cbn1cbiIsImltcG9ydCB7IE9yZGVyRGlyZWN0aW9uLCBQZXJzaXN0ZW5jZUtleXMgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IENvdWNoREJLZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBEZWZhdWx0U2VwYXJhdG9yIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBDb3VjaERCT3BlcmF0b3IgfSBmcm9tIFwiLi9xdWVyeS9jb25zdGFudHNcIjtcbmltcG9ydCB7IENyZWF0ZUluZGV4UmVxdWVzdCwgTWFuZ29TZWxlY3RvciwgU29ydE9yZGVyIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmUtYXV0aGVudGljYXRlcyBhIGNvbm5lY3Rpb24gdG8gQ291Y2hEQlxuICogQHN1bW1hcnkgUmVmcmVzaGVzIHRoZSBhdXRoZW50aWNhdGlvbiBmb3IgYSBDb3VjaERCIGNvbm5lY3Rpb24gdXNpbmcgdGhlIHByb3ZpZGVkIGNyZWRlbnRpYWxzXG4gKiBAcGFyYW0ge2FueX0gY29uIC0gVGhlIENvdWNoREIgY29ubmVjdGlvbiBvYmplY3RcbiAqIEBwYXJhbSB7c3RyaW5nfSB1c2VyIC0gVGhlIHVzZXJuYW1lIGZvciBhdXRoZW50aWNhdGlvblxuICogQHBhcmFtIHtzdHJpbmd9IHBhc3MgLSBUaGUgcGFzc3dvcmQgZm9yIGF1dGhlbnRpY2F0aW9uXG4gKiBAcmV0dXJuIHtQcm9taXNlPGFueT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBhdXRoZW50aWNhdGlvbiByZXN1bHRcbiAqIEBmdW5jdGlvbiByZUF1dGhcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWNvdWNoZGJcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlQXV0aChjb246IGFueSwgdXNlcjogc3RyaW5nLCBwYXNzOiBzdHJpbmcpIHtcbiAgcmV0dXJuIGNvbi5hdXRoKHVzZXIsIHBhc3MpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBXcmFwcyBhIENvdWNoREIgZGF0YWJhc2UgY29ubmVjdGlvbiB3aXRoIGF1dG9tYXRpYyByZS1hdXRoZW50aWNhdGlvblxuICogQHN1bW1hcnkgQ3JlYXRlcyBhIHByb3h5IGFyb3VuZCBhIENvdWNoREIgZGF0YWJhc2UgY29ubmVjdGlvbiB0aGF0IGF1dG9tYXRpY2FsbHkgcmUtYXV0aGVudGljYXRlcyBiZWZvcmUgZWFjaCBvcGVyYXRpb25cbiAqIEBwYXJhbSB7YW55fSBjb24gLSBUaGUgQ291Y2hEQiBjb25uZWN0aW9uIG9iamVjdFxuICogQHBhcmFtIHtzdHJpbmd9IGRiTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBkYXRhYmFzZSB0byB1c2VcbiAqIEBwYXJhbSB7c3RyaW5nfSB1c2VyIC0gVGhlIHVzZXJuYW1lIGZvciBhdXRoZW50aWNhdGlvblxuICogQHBhcmFtIHtzdHJpbmd9IHBhc3MgLSBUaGUgcGFzc3dvcmQgZm9yIGF1dGhlbnRpY2F0aW9uXG4gKiBAcmV0dXJuIHthbnl9IFRoZSB3cmFwcGVkIGRhdGFiYXNlIGNvbm5lY3Rpb24gb2JqZWN0XG4gKiBAZnVuY3Rpb24gd3JhcERvY3VtZW50U2NvcGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWNvdWNoZGJcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2xpZW50XG4gKiAgIHBhcnRpY2lwYW50IHdyYXBEb2N1bWVudFNjb3BlXG4gKiAgIHBhcnRpY2lwYW50IERCXG4gKiAgIHBhcnRpY2lwYW50IHJlQXV0aFxuICogICBcbiAqICAgQ2xpZW50LT4+d3JhcERvY3VtZW50U2NvcGU6IGNvbiwgZGJOYW1lLCB1c2VyLCBwYXNzXG4gKiAgIHdyYXBEb2N1bWVudFNjb3BlLT4+REI6IGNvbi51c2UoZGJOYW1lKVxuICogICBOb3RlIG92ZXIgd3JhcERvY3VtZW50U2NvcGU6IFdyYXAgREIgbWV0aG9kcyB3aXRoIHJlLWF1dGhcbiAqICAgXG4gKiAgIGxvb3AgRm9yIGVhY2ggbWV0aG9kIChpbnNlcnQsIGdldCwgcHV0LCBkZXN0cm95LCBmaW5kKVxuICogICAgIHdyYXBEb2N1bWVudFNjb3BlLT4+d3JhcERvY3VtZW50U2NvcGU6IFN0b3JlIG9yaWdpbmFsIG1ldGhvZFxuICogICAgIHdyYXBEb2N1bWVudFNjb3BlLT4+d3JhcERvY3VtZW50U2NvcGU6IERlZmluZSBuZXcgbWV0aG9kIHdpdGggcmUtYXV0aFxuICogICBlbmRcbiAqICAgXG4gKiAgIHdyYXBEb2N1bWVudFNjb3BlLT4+d3JhcERvY3VtZW50U2NvcGU6IEFkZCBOQVRJVkUgcHJvcGVydHkgd2l0aCBjb24gdmFsdWVcbiAqICAgd3JhcERvY3VtZW50U2NvcGUtLT4+Q2xpZW50OiBSZXR1cm4gd3JhcHBlZCBEQlxuICogICBcbiAqICAgTm90ZSBvdmVyIENsaWVudDogTGF0ZXIgd2hlbiBjbGllbnQgdXNlcyBEQiBtZXRob2RzXG4gKiAgIENsaWVudC0+PkRCOiBBbnkgd3JhcHBlZCBtZXRob2QgY2FsbFxuICogICBEQi0+PnJlQXV0aDogQXV0aGVudGljYXRlIGJlZm9yZSBvcGVyYXRpb25cbiAqICAgcmVBdXRoLS0+PkRCOiBBdXRoZW50aWNhdGlvbiBjb21wbGV0ZVxuICogICBEQi0+PkRCOiBDYWxsIG9yaWdpbmFsIG1ldGhvZFxuICogICBEQi0tPj5DbGllbnQ6IFJldHVybiByZXN1bHRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdyYXBEb2N1bWVudFNjb3BlKFxuICBjb246IGFueSxcbiAgZGJOYW1lOiBzdHJpbmcsXG4gIHVzZXI6IHN0cmluZyxcbiAgcGFzczogc3RyaW5nXG4pOiBhbnkge1xuICBjb25zdCBkYiA9IGNvbi51c2UoZGJOYW1lKTtcbiAgW1wiaW5zZXJ0XCIsIFwiZ2V0XCIsIFwicHV0XCIsIFwiZGVzdHJveVwiLCBcImZpbmRcIl0uZm9yRWFjaCgoaykgPT4ge1xuICAgIGNvbnN0IG9yaWdpbmFsID0gKGRiIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW2tdO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShkYiwgaywge1xuICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICB2YWx1ZTogYXN5bmMgKC4uLmFyZ3M6IGFueVtdKSA9PiB7XG4gICAgICAgIGF3YWl0IHJlQXV0aChjb24sIHVzZXIsIHBhc3MpO1xuICAgICAgICByZXR1cm4gb3JpZ2luYWwuY2FsbChkYiwgLi4uYXJncyk7XG4gICAgICB9LFxuICAgIH0pO1xuICB9KTtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGRiLCBDb3VjaERCS2V5cy5OQVRJVkUsIHtcbiAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICBjb25maWd1cmFibGU6IGZhbHNlLFxuICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICB2YWx1ZTogY29uLFxuICB9KTtcbiAgcmV0dXJuIGRiO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBUZXN0cyBpZiBhbiBhdHRyaWJ1dGUgbmFtZSBpcyByZXNlcnZlZCBpbiBDb3VjaERCXG4gKiBAc3VtbWFyeSBDaGVja3MgaWYgYW4gYXR0cmlidXRlIG5hbWUgc3RhcnRzIHdpdGggYW4gdW5kZXJzY29yZSwgd2hpY2ggaW5kaWNhdGVzIGl0J3MgYSByZXNlcnZlZCBhdHRyaWJ1dGUgaW4gQ291Y2hEQlxuICogQHBhcmFtIHtzdHJpbmd9IGF0dHIgLSBUaGUgYXR0cmlidXRlIG5hbWUgdG8gdGVzdFxuICogQHJldHVybiB7UmVnRXhwTWF0Y2hBcnJheXxudWxsfSBUaGUgbWF0Y2ggcmVzdWx0IG9yIG51bGwgaWYgbm8gbWF0Y2hcbiAqIEBmdW5jdGlvbiB0ZXN0UmVzZXJ2ZWRBdHRyaWJ1dGVzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1jb3VjaGRiXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0ZXN0UmVzZXJ2ZWRBdHRyaWJ1dGVzKGF0dHI6IHN0cmluZykge1xuICBjb25zdCByZWdleHAgPSAvXl8uKiQvZztcbiAgcmV0dXJuIGF0dHIubWF0Y2gocmVnZXhwKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gR2VuZXJhdGVzIGEgbmFtZSBmb3IgYSBDb3VjaERCIGluZGV4XG4gKiBAc3VtbWFyeSBDcmVhdGVzIGEgc3RhbmRhcmRpemVkIG5hbWUgZm9yIGEgQ291Y2hEQiBpbmRleCBiYXNlZCBvbiB0aGUgdGFibGUsIGF0dHJpYnV0ZSwgY29tcG9zaXRpb25zLCBhbmQgb3JkZXJcbiAqIEBwYXJhbSB7c3RyaW5nfSBhdHRyaWJ1dGUgLSBUaGUgcHJpbWFyeSBhdHRyaWJ1dGUgZm9yIHRoZSBpbmRleFxuICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZVxuICogQHBhcmFtIHtzdHJpbmdbXX0gW2NvbXBvc2l0aW9uc10gLSBPcHRpb25hbCBhZGRpdGlvbmFsIGF0dHJpYnV0ZXMgdG8gaW5jbHVkZSBpbiB0aGUgaW5kZXhcbiAqIEBwYXJhbSB7T3JkZXJEaXJlY3Rpb259IFtvcmRlcl0gLSBPcHRpb25hbCBzb3J0IG9yZGVyIGZvciB0aGUgaW5kZXhcbiAqIEBwYXJhbSB7c3RyaW5nfSBbc2VwYXJhdG9yPURlZmF1bHRTZXBhcmF0b3JdIC0gVGhlIHNlcGFyYXRvciB0byB1c2UgYmV0d2VlbiBwYXJ0cyBvZiB0aGUgaW5kZXggbmFtZVxuICogQHJldHVybiB7c3RyaW5nfSBUaGUgZ2VuZXJhdGVkIGluZGV4IG5hbWVcbiAqIEBmdW5jdGlvbiBnZW5lcmF0ZUluZGV4TmFtZVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItY291Y2hkYlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVJbmRleE5hbWUoXG4gIGF0dHJpYnV0ZTogc3RyaW5nLFxuICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgY29tcG9zaXRpb25zPzogc3RyaW5nW10sXG4gIG9yZGVyPzogT3JkZXJEaXJlY3Rpb24sXG4gIHNlcGFyYXRvciA9IERlZmF1bHRTZXBhcmF0b3Jcbik6IHN0cmluZyB7XG4gIGNvbnN0IGF0dHIgPSBbUGVyc2lzdGVuY2VLZXlzLklOREVYLCB0YWJsZU5hbWUsIGF0dHJpYnV0ZV07XG4gIGlmIChjb21wb3NpdGlvbnMpIGF0dHIucHVzaCguLi5jb21wb3NpdGlvbnMpO1xuICBpZiAob3JkZXIpIGF0dHIucHVzaChvcmRlcik7XG4gIHJldHVybiBhdHRyLmpvaW4oc2VwYXJhdG9yKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gR2VuZXJhdGVzIGEgQ291Y2hEQiBpbmRleCBjb25maWd1cmF0aW9uXG4gKiBAc3VtbWFyeSBDcmVhdGVzIGEgY29tcGxldGUgQ3JlYXRlSW5kZXhSZXF1ZXN0IG9iamVjdCBmb3IgZGVmaW5pbmcgYSBDb3VjaERCIGluZGV4IGJhc2VkIG9uIHNwZWNpZmllZCBwYXJhbWV0ZXJzXG4gKiBAcGFyYW0ge3N0cmluZ30gYXR0cmlidXRlIC0gVGhlIHByaW1hcnkgYXR0cmlidXRlIGZvciB0aGUgaW5kZXhcbiAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGVcbiAqIEBwYXJhbSB7c3RyaW5nW119IFtjb21wb3NpdGlvbnNdIC0gT3B0aW9uYWwgYWRkaXRpb25hbCBhdHRyaWJ1dGVzIHRvIGluY2x1ZGUgaW4gdGhlIGluZGV4XG4gKiBAcGFyYW0ge09yZGVyRGlyZWN0aW9ufSBbb3JkZXJdIC0gT3B0aW9uYWwgc29ydCBvcmRlciBmb3IgdGhlIGluZGV4XG4gKiBAcGFyYW0ge3N0cmluZ30gW3NlcGFyYXRvcj1EZWZhdWx0U2VwYXJhdG9yXSAtIFRoZSBzZXBhcmF0b3IgdG8gdXNlIGJldHdlZW4gcGFydHMgb2YgdGhlIGluZGV4IG5hbWVcbiAqIEByZXR1cm4ge0NyZWF0ZUluZGV4UmVxdWVzdH0gVGhlIGNvbXBsZXRlIGluZGV4IGNvbmZpZ3VyYXRpb24gb2JqZWN0XG4gKiBAZnVuY3Rpb24gZ2VuZXJhdGVJbmRleERvY1xuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItY291Y2hkYlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgZ2VuZXJhdGVJbmRleERvY1xuICogICBwYXJ0aWNpcGFudCBnZW5lcmF0ZUluZGV4TmFtZVxuICogICBcbiAqICAgQ2FsbGVyLT4+Z2VuZXJhdGVJbmRleERvYzogYXR0cmlidXRlLCB0YWJsZU5hbWUsIGNvbXBvc2l0aW9ucywgb3JkZXIsIHNlcGFyYXRvclxuICogICBcbiAqICAgTm90ZSBvdmVyIGdlbmVyYXRlSW5kZXhEb2M6IENyZWF0ZSBwYXJ0aWFsIGZpbHRlciBzZWxlY3RvclxuICogICBnZW5lcmF0ZUluZGV4RG9jLT4+Z2VuZXJhdGVJbmRleERvYzogU2V0IHVwIGZpbHRlciBmb3IgdGFibGVOYW1lXG4gKiAgIFxuICogICBhbHQgb3JkZXIgaXMgc3BlY2lmaWVkXG4gKiAgICAgTm90ZSBvdmVyIGdlbmVyYXRlSW5kZXhEb2M6IENyZWF0ZSBvcmRlcmVkIGZpZWxkcyBhcnJheVxuICogICAgIGdlbmVyYXRlSW5kZXhEb2MtPj5nZW5lcmF0ZUluZGV4RG9jOiBDcmVhdGUgb3JkZXJQcm9wIGZvciBhdHRyaWJ1dGVcbiAqICAgICBnZW5lcmF0ZUluZGV4RG9jLT4+Z2VuZXJhdGVJbmRleERvYzogTWFwIGNvbXBvc2l0aW9ucyB0byBvcmRlcmVkIHByb3BzXG4gKiAgICAgZ2VuZXJhdGVJbmRleERvYy0+PmdlbmVyYXRlSW5kZXhEb2M6IENyZWF0ZSBzb3J0ZWRUYWJsZSBmb3IgdGFibGUgZmllbGRcbiAqICAgICBnZW5lcmF0ZUluZGV4RG9jLT4+Z2VuZXJhdGVJbmRleERvYzogQ29tYmluZSBhbGwgb3JkZXJlZCBmaWVsZHNcbiAqICAgZWxzZVxuICogICAgIE5vdGUgb3ZlciBnZW5lcmF0ZUluZGV4RG9jOiBDcmVhdGUgc2ltcGxlIGZpZWxkcyBhcnJheVxuICogICAgIGdlbmVyYXRlSW5kZXhEb2MtPj5nZW5lcmF0ZUluZGV4RG9jOiBVc2UgYXR0cmlidXRlLCBjb21wb3NpdGlvbnMsIGFuZCB0YWJsZSBhcyBzdHJpbmdzXG4gKiAgIGVuZFxuICogICBcbiAqICAgZ2VuZXJhdGVJbmRleERvYy0+PmdlbmVyYXRlSW5kZXhOYW1lOiBHZW5lcmF0ZSBpbmRleCBuYW1lXG4gKiAgIGdlbmVyYXRlSW5kZXhOYW1lLS0+PmdlbmVyYXRlSW5kZXhEb2M6IFJldHVybiBuYW1lXG4gKiAgIFxuICogICBOb3RlIG92ZXIgZ2VuZXJhdGVJbmRleERvYzogQ3JlYXRlIGZpbmFsIGluZGV4IHJlcXVlc3RcbiAqICAgZ2VuZXJhdGVJbmRleERvYy0tPj5DYWxsZXI6IFJldHVybiBDcmVhdGVJbmRleFJlcXVlc3RcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlSW5kZXhEb2MoXG4gIGF0dHJpYnV0ZTogc3RyaW5nLFxuICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgY29tcG9zaXRpb25zPzogc3RyaW5nW10sXG4gIG9yZGVyPzogT3JkZXJEaXJlY3Rpb24sXG4gIHNlcGFyYXRvciA9IERlZmF1bHRTZXBhcmF0b3Jcbik6IENyZWF0ZUluZGV4UmVxdWVzdCB7XG4gIGNvbnN0IHBhcnRpYWxGaWx0ZXJTZWxlY3RvcjogTWFuZ29TZWxlY3RvciA9IHt9O1xuICBwYXJ0aWFsRmlsdGVyU2VsZWN0b3JbQ291Y2hEQktleXMuVEFCTEVdID0ge30gYXMgTWFuZ29TZWxlY3RvcjtcbiAgKHBhcnRpYWxGaWx0ZXJTZWxlY3RvcltDb3VjaERCS2V5cy5UQUJMRV0gYXMgTWFuZ29TZWxlY3RvcilbXG4gICAgQ291Y2hEQk9wZXJhdG9yLkVRVUFMXG4gIF0gPSB0YWJsZU5hbWU7XG4gIGxldCBmaWVsZHM6IFNvcnRPcmRlcltdO1xuICBpZiAob3JkZXIpIHtcbiAgICBjb25zdCBvcmRlclByb3A6IFNvcnRPcmRlciA9IHt9O1xuICAgIG9yZGVyUHJvcFthdHRyaWJ1dGVdID0gb3JkZXIgYXMgXCJhc2NcIiB8IFwiZGVzY1wiO1xuICAgIGNvbnN0IHNvcnRlZENvbXBvc2l0aW9uczogU29ydE9yZGVyW10gPSAoY29tcG9zaXRpb25zIHx8IFtdKS5tYXAoKGMpID0+IHtcbiAgICAgIGNvbnN0IHI6IFNvcnRPcmRlciA9IHt9O1xuICAgICAgcltjXSA9IG9yZGVyIGFzIFwiYXNjXCIgfCBcImRlc2NcIjtcbiAgICAgIHJldHVybiByO1xuICAgIH0pO1xuICAgIGNvbnN0IHNvcnRlZFRhYmxlOiBTb3J0T3JkZXIgPSB7fTtcbiAgICBzb3J0ZWRUYWJsZVtDb3VjaERCS2V5cy5UQUJMRV0gPSBvcmRlciBhcyBcImFzY1wiIHwgXCJkZXNjXCI7XG4gICAgZmllbGRzID0gW29yZGVyUHJvcCwgLi4uc29ydGVkQ29tcG9zaXRpb25zLCBzb3J0ZWRUYWJsZV07XG4gIH0gZWxzZSB7XG4gICAgZmllbGRzID0gW2F0dHJpYnV0ZSwgLi4uKGNvbXBvc2l0aW9ucyB8fCBbXSksIENvdWNoREJLZXlzLlRBQkxFXTtcbiAgfVxuICBjb25zdCBuYW1lID0gZ2VuZXJhdGVJbmRleE5hbWUoXG4gICAgYXR0cmlidXRlLFxuICAgIHRhYmxlTmFtZSxcbiAgICBjb21wb3NpdGlvbnMsXG4gICAgb3JkZXIsXG4gICAgc2VwYXJhdG9yXG4gICk7XG4gIHJldHVybiB7XG4gICAgaW5kZXg6IHtcbiAgICAgIGZpZWxkczogZmllbGRzLFxuICAgICAgLy8gcGFydGlhbF9maWx0ZXJfc2VsZWN0b3I6IHBhcnRpYWxGaWx0ZXJTZWxlY3RvcixcbiAgICB9LFxuICAgIGRkb2M6IFtuYW1lLCBDb3VjaERCS2V5cy5ERE9DXS5qb2luKHNlcGFyYXRvciksXG4gICAgbmFtZTogbmFtZSxcbiAgfTtcbn1cbiIsImltcG9ydCB7IE1ldGFkYXRhIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCI7XG5cbmV4cG9ydCAqIGZyb20gXCIuL2luZGV4ZXNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2ludGVyZmFjZXNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL21vZGVsXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9zZXF1ZW5jZXNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2FkYXB0ZXJcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vZXJyb3JzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi90eXBlc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vdXRpbHNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3F1ZXJ5XCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvdWNoREIgYWRhcHRlciBmb3IgRGVjYWYudHNcbiAqIEBzdW1tYXJ5IEEgVHlwZVNjcmlwdCBhZGFwdGVyIGZvciBDb3VjaERCIGRhdGFiYXNlIG9wZXJhdGlvbnMsIHByb3ZpZGluZyBhIHNlYW1sZXNzIGludGVncmF0aW9uIHdpdGggdGhlIERlY2FmLnRzIGZyYW1ld29yay4gVGhpcyBtb2R1bGUgaW5jbHVkZXMgY2xhc3NlcywgaW50ZXJmYWNlcywgYW5kIHV0aWxpdGllcyBmb3Igd29ya2luZyB3aXRoIENvdWNoREIgZGF0YWJhc2VzLCBpbmNsdWRpbmcgc3VwcG9ydCBmb3IgTWFuZ28gcXVlcmllcywgZG9jdW1lbnQgb3BlcmF0aW9ucywgYW5kIHNlcXVlbmNlIG1hbmFnZW1lbnQuXG4gKiBAbW9kdWxlIGZvci1jb3VjaGRiXG4gKi9cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU3RvcmVzIHRoZSBjdXJyZW50IHBhY2thZ2UgdmVyc2lvblxuICogQHN1bW1hcnkgVGhlIHZlcnNpb24gc3RyaW5nIG9mIHRoZSBmb3ItY291Y2hkYiBwYWNrYWdlXG4gKiBAY29uc3QgVkVSU0lPTlxuICovXG5leHBvcnQgY29uc3QgVkVSU0lPTiA9IFwiIyNWRVJTSU9OIyNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU3RvcmVzIHRoZSBjdXJyZW50IHBhY2thZ2UgbmFtZVxuICogQHN1bW1hcnkgVGhlIHZlcnNpb24gc3RyaW5nIG9mIHRoZSBmb3ItY291Y2hkYiBwYWNrYWdlXG4gKiBAY29uc3QgUEFDS0FHRV9OQU1FXG4gKi9cbmV4cG9ydCBjb25zdCBQQUNLQUdFX05BTUUgPSBcIiMjUEFDS0FHRSMjXCI7XG5cbk1ldGFkYXRhLnJlZ2lzdGVyTGlicmFyeShQQUNLQUdFX05BTUUsIFZFUlNJT04pO1xuIl0sIm5hbWVzIjpbImdlbmVyYXRlSW5kZXhOYW1lIiwiRGVmYXVsdFNlcGFyYXRvciIsIlJlcG9zaXRvcnkiLCJQZXJzaXN0ZW5jZUtleXMiLCJTZXF1ZW5jZSIsIkJhc2VNb2RlbCIsIl9fZGVjb3JhdGUiLCJwayIsInJlcXVpcmVkIiwiaW5kZXgiLCJ0YWJsZSIsIm1vZGVsIiwiU2VxIiwiTm90Rm91bmRFcnJvciIsIkludGVybmFsRXJyb3IiLCJCYXNlRXJyb3IiLCJQYWdpbmF0b3IiLCJQYWdpbmdFcnJvciIsImZpbmRQcmltYXJ5S2V5IiwiUXVlcnlFcnJvciIsIlN0YXRlbWVudCIsIkNvbmRpdGlvbiIsIkdyb3VwT3BlcmF0b3IiLCJPcGVyYXRvciIsIkFkYXB0ZXIiLCJwcmVmaXhNZXRob2QiLCJDb25mbGljdEVycm9yIiwiQ29ubmVjdGlvbkVycm9yIiwiZmluYWwiLCJNZXRhZGF0YSJdLCJtYXBwaW5ncyI6Ijs7Ozs7O0lBQUE7Ozs7O0lBS0c7QUFDSSxVQUFNLGtCQUFrQixHQUFHO0lBRWxDOzs7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
|
|
1
|
+
var e,t;e=this,t=function(e,t,r,n,a,o){"use strict";const s=/^_.*$/g,i={SEPARATOR:"__",ID:"_id",REV:"_rev",DELETED:"_deleted",TABLE:"??table",SEQUENCE:"??sequence",DDOC:"ddoc",NATIVE:"__native",INDEX:"index"},c={EQUAL:"$eq",DIFFERENT:"$ne",BIGGER:"$gt",BIGGER_EQ:"$gte",SMALLER:"$lt",SMALLER_EQ:"$lte",NOT:"$not",IN:"$in",REGEXP:"$regex"},d={AND:"$and",OR:"$or"};e.Sequence=class extends r.BaseModel{constructor(e){super(e)}},a.__decorate([r.pk(),a.__metadata("design:type",String)],e.Sequence.prototype,"id",void 0),a.__decorate([o.required(),r.index(),a.__metadata("design:type",Object)],e.Sequence.prototype,"current",void 0),e.Sequence=a.__decorate([r.table(i.SEQUENCE),o.model(),a.__metadata("design:paramtypes",[Object])],e.Sequence);class l extends r.Sequence{constructor(t,n){super(t),this.repo=r.Repository.forModel(e.Sequence,n.alias)}async current(){const{name:e,startWith:t}=this.options;try{const t=await this.repo.read(e);return this.parse(t.current)}catch(r){if(r instanceof n.NotFoundError){if(void 0===t)throw new n.InternalError("Starting value is not defined for a non existing sequence");try{return this.parse(t)}catch(e){throw new n.InternalError(`Failed to parse initial value for sequence ${t}: ${e}`)}}throw new n.InternalError(`Failed to retrieve current value for sequence ${e}: ${r}`)}}parse(e){return r.Sequence.parseValue(this.options.type,e)}async increment(t,r){const{type:a,incrementBy:o,name:s}=this.options;let i;const c=r||o;if(c%o!==0)throw new n.InternalError("Value to increment does not consider the incrementBy setting: "+o);switch(a){case"Number":i=this.parse(t)+c;break;case"BigInt":i=this.parse(t)+BigInt(c);break;default:throw new n.InternalError("Should never happen")}let d;try{d=await this.repo.update(new e.Sequence({id:s,current:i}))}catch(t){if(!(t instanceof n.NotFoundError))throw t;d=await this.repo.create(new e.Sequence({id:s,current:i}))}return d.current}async next(){const e=await this.current();return this.increment(e)}async range(e){const t=await this.current(),r=this.parse(this.options.incrementBy),a=await this.increment(t,this.parse(e)*r),o=[];for(let n=1;e>=n;n++)o.push(t+r*this.parse(n));if(o[o.length-1]!==a)throw new n.InternalError("Miscalculation of range");return o}}class u extends n.BaseError{constructor(e){super(u.name,e,404)}}class p extends r.Paginator{get total(){throw new n.InternalError("The total pages api is not available for couchdb")}get count(){throw new n.InternalError("The record count api is not available for couchdb")}constructor(e,t,r,n){super(e,t,r,n)}prepare(e){const t=Object.assign({},e);return t.limit&&(this.limit=t.limit),t.limit=this.size,t}async page(e=1){const t=Object.assign({},this.statement);if(!this._recordCount||!this._totalPages){this._totalPages=this._recordCount=0;const e=await this.adapter.raw({...t,limit:void 0})||[];if(this._recordCount=e.length,this._recordCount>0){const e=t?.limit||this.size;this._totalPages=Math.ceil(this._recordCount/e)}}if(this.validatePage(e),1!==e){if(!this.bookMark)throw new r.PagingError("No bookmark. Did you start in the first page?");t.bookmark=this.bookMark}const a=await this.adapter.raw(t,!1),{docs:o,bookmark:s,warning:c}=a;if(!this.clazz)throw new r.PagingError("No statement target defined");const d=n.findPrimaryKey(new this.clazz),l=t.fields&&t.fields.length?o:o.map(e=>{const t=e._id.split(i.SEPARATOR);return t.splice(0,1),this.adapter.revert(e,this.clazz,d.id,r.Sequence.parseValue(d.props.type,t.join(i.SEPARATOR)))});return this.bookMark=s,this._currentPage=e,l}}function h(e){for(const t of[c,d]){const r=Object.keys(t).find(t=>t===e);if(r)return t[r]}throw new r.QueryError("Could not find adapter translation for operator "+e)}class f extends r.Statement{constructor(e){super(e)}build(){const e={};e[i.TABLE]={},e[i.TABLE]=r.Repository.table(this.fromSelector);const t={selector:e};if(this.selectSelector&&(t.fields=this.selectSelector),this.whereCondition){const e=this.parseCondition(r.Condition.and(this.whereCondition,r.Condition.attribute(i.TABLE).eq(t.selector[i.TABLE]))).selector,n=Object.keys(e);if(1===n.length&&-1!==Object.values(d).indexOf(n[0]))switch(n[0]){case d.AND:e[d.AND]=[...Object.values(e[d.AND]).reduce((e,t)=>{const r=Object.keys(t);if(1!==r.length)throw Error("Too many keys in query selector. should be one");const n=r[0];return n===d.AND?e.push(...t[n]):e.push(t),e},[])],t.selector=e;break;case d.OR:{const r={};r[d.AND]=[e,...Object.entries(t.selector).map(([e,t])=>{const r={};return r[e]=t,r})],t.selector=r;break}default:throw Error("This should be impossible")}else Object.entries(e).forEach(([e,r])=>{t.selector[e],t.selector[e]=r})}if(this.orderBySelector){t.sort=t.sort||[],t.selector=t.selector||{};const[e,r]=this.orderBySelector,n={};n[e]=r,t.sort.push(n),t.selector[e]||(t.selector[e]={},t.selector[e][c.BIGGER]=null)}return this.limitSelector?t.limit=this.limitSelector:t.limit=250,this.offsetSelector&&(t.skip=this.offsetSelector),t}async paginate(e){try{const t=this.build();return new p(this.adapter,t,e,this.fromSelector)}catch(e){throw new n.InternalError(e)}}processRecord(e,t,n){if(e[i.ID]){const[,...a]=e[i.ID].split(i.SEPARATOR),o=a.join("_");return this.adapter.revert(e,this.fromSelector,t,r.Sequence.parseValue(n,o))}return e}async raw(e){const t=await this.adapter.raw(e,!0),r=n.findPrimaryKey(new this.fromSelector),a=r.id,o=r.props.type;return this.selectSelector?t:t.map(e=>this.processRecord(e,a,o))}parseCondition(e){const{attr1:t,operator:n,comparison:a}=e;let o={};if(-1===[r.GroupOperator.AND,r.GroupOperator.OR,r.Operator.NOT].indexOf(n))o[t]={},o[t][h(n)]=a;else if(n===r.Operator.NOT)o=this.parseCondition(t).selector,o[h(r.Operator.NOT)]={},o[h(r.Operator.NOT)][t.attr1]=a;else{const e=this.parseCondition(t).selector,r=this.parseCondition(a).selector;o=((e,t,r)=>{const n={selector:{}};return n.selector[e]=[t,r],n})(h(n),e,r).selector}return{selector:o}}}class m extends r.Adapter{constructor(e,t,r){super(e,t,r),[this.create,this.createAll,this.update,this.updateAll].forEach(e=>{const t=e.name;n.prefixMethod(this,e,this[t+"Prefix"])})}Statement(){return new f(this)}async Sequence(e){return new l(e,this)}async initialize(){const e=r.Adapter.models(this.flavour);return this.index(...e)}assignMetadata(e,t){return Object.defineProperty(e,r.PersistenceKeys.METADATA,{enumerable:!1,configurable:!1,writable:!1,value:t}),e}assignMultipleMetadata(e,t){return e.forEach((e,n)=>(r.Repository.setMetadata(e,t[n]),e)),e}createPrefix(e,t,r){const n={};return n[i.TABLE]=e,n[i.ID]=this.generateId(e,t),Object.assign(n,r),[e,t,n]}createAllPrefix(e,t,r){if(t.length!==r.length)throw new n.InternalError("Ids and models must have the same length");const a=t.map((t,n)=>{const a={};return a[i.TABLE]=e,a[i.ID]=this.generateId(e,t),Object.assign(a,r[n]),a});return[e,t,a]}updatePrefix(e,t,a){const o={};o[i.TABLE]=e,o[i.ID]=this.generateId(e,t);const s=a[r.PersistenceKeys.METADATA];if(!s)throw new n.InternalError("No revision number found for record with id "+t);return Object.assign(o,a),o[i.REV]=s,[e,t,o]}updateAllPrefix(e,t,a){if(t.length!==a.length)throw new n.InternalError("Ids and models must have the same length");const o=t.map((t,o)=>{const s={};s[i.TABLE]=e,s[i.ID]=this.generateId(e,t);const c=a[o][r.PersistenceKeys.METADATA];if(!c)throw new n.InternalError("No revision number found for record with id "+t);return Object.assign(s,a[o]),s[i.REV]=c,s});return[e,t,o]}generateId(e,t){return[e,t].join(i.SEPARATOR)}parseError(e,t){return m.parseError(e,t)}isReserved(e){return!!e.match(s)}static parseError(e,t){if(e instanceof n.BaseError)return e;let a="";if("string"==typeof e){if(a=e,a.match(/already exist|update conflict/g))return new n.ConflictError(a);if(a.match(/missing|deleted/g))return new n.NotFoundError(a)}else e.code?(a=e.code,t=t||e.message):e.statusCode?(a=e.statusCode,t=t||e.message):a=e.message;switch(a.toString()){case"401":case"412":case"409":return new n.ConflictError(t);case"404":return new n.NotFoundError(t);case"400":return a.toString().match(/No\sindex\sexists/g)?new u(e):new n.InternalError(e);default:return a.toString().match(/ECONNREFUSED/g)?new r.ConnectionError(e):new n.InternalError(e)}}}async function g(e,t,r){return e.auth(t,r)}function E(e,t,a,o,s=n.DefaultSeparator){const i=[r.PersistenceKeys.INDEX,t,e];return a&&i.push(...a),o&&i.push(o),i.join(s)}a.__decorate([r.final(),a.__metadata("design:type",Function),a.__metadata("design:paramtypes",[]),a.__metadata("design:returntype",f)],m.prototype,"Statement",null),a.__decorate([r.final(),a.__metadata("design:type",Function),a.__metadata("design:paramtypes",[Object]),a.__metadata("design:returntype",Promise)],m.prototype,"Sequence",null),a.__decorate([r.final(),a.__metadata("design:type",Function),a.__metadata("design:paramtypes",[Object,String]),a.__metadata("design:returntype",Object)],m.prototype,"assignMetadata",null),a.__decorate([r.final(),a.__metadata("design:type",Function),a.__metadata("design:paramtypes",[Array,Array]),a.__metadata("design:returntype",Array)],m.prototype,"assignMultipleMetadata",null),a.__decorate([r.final(),a.__metadata("design:type",Function),a.__metadata("design:paramtypes",[String,Object,Object]),a.__metadata("design:returntype",void 0)],m.prototype,"createPrefix",null),a.__decorate([r.final(),a.__metadata("design:type",Function),a.__metadata("design:paramtypes",[String,Array,Array]),a.__metadata("design:returntype",void 0)],m.prototype,"createAllPrefix",null),a.__decorate([r.final(),a.__metadata("design:type",Function),a.__metadata("design:paramtypes",[String,Object,Object]),a.__metadata("design:returntype",void 0)],m.prototype,"updatePrefix",null),a.__decorate([r.final(),a.__metadata("design:type",Function),a.__metadata("design:paramtypes",[String,Array,Array]),a.__metadata("design:returntype",void 0)],m.prototype,"updateAllPrefix",null);const y="##VERSION##",_="##PACKAGE##";t.Metadata.registerLibrary(_,y),e.CouchDBAdapter=m,e.CouchDBConst={NULL:"null"},e.CouchDBGroupOperator=d,e.CouchDBKeys=i,e.CouchDBOperator=c,e.CouchDBPaginator=p,e.CouchDBQueryLimit=250,e.CouchDBSequence=l,e.CouchDBStatement=f,e.IndexError=u,e.PACKAGE_NAME=_,e.VERSION=y,e.generateIndexDoc=(e,t,r,a,o=n.DefaultSeparator)=>{const s={};let d;if(s[i.TABLE]={},s[i.TABLE][c.EQUAL]=t,a){const t={};t[e]=a;const n=(r||[]).map(e=>{const t={};return t[e]=a,t}),o={};o[i.TABLE]=a,d=[t,...n,o]}else d=[e,...r||[],i.TABLE];const l=E(e,t,r,a,o);return{index:{fields:d},ddoc:[l,i.DDOC].join(o),name:l}},e.generateIndexName=E,e.generateIndexes=e=>{const t=((e,t,r,a=n.DefaultSeparator)=>[...e.map(e=>e===i.TABLE?"table":e),...r||[],...t?[t]:[],i.INDEX].join(a))([i.TABLE]),a={};return a[t]={index:{fields:[i.TABLE]},name:t,ddoc:t,type:"json"},e.forEach(e=>{const t=r.Repository.indexes(e);Object.entries(t).forEach(([t,o])=>{const s=Object.keys(o)[0];let{directions:d,compositions:l}=o[s];const u=r.Repository.table(e);function p(e){const o=[u,t,...l,r.PersistenceKeys.INDEX].join(n.DefaultSeparator);if(a[o]={index:{fields:[t,...l,i.TABLE].reduce((t,r)=>{if(e){const n={};n[r]=e,t.push(n)}else t.push(r);return t},[])},name:o,ddoc:o,type:"json"},!e){const e={};e[i.TABLE]={},e[i.TABLE][c.EQUAL]=u,a[o].index.partial_filter_selector=e}}l=l||[],p(),d&&d.forEach(e=>p(e))})}),Object.values(a)},e.reAuth=g,e.reservedAttributes=s,e.testReservedAttributes=e=>e.match(/^_.*$/g),e.translateOperators=h,e.wrapDocumentScope=(e,t,r,n)=>{const a=e.use(t);return["insert","get","put","destroy","find"].forEach(t=>{const o=a[t];Object.defineProperty(a,t,{enumerable:!1,configurable:!0,value:async(...t)=>(await g(e,r,n),o.call(a,...t))})}),Object.defineProperty(a,i.NATIVE,{enumerable:!1,configurable:!1,writable:!1,value:e}),a}},"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@decaf-ts/decoration"),require("@decaf-ts/core"),require("@decaf-ts/db-decorators"),require("tslib"),require("@decaf-ts/decorator-validation"),require("reflect-metadata")):"function"==typeof define&&define.amd?define(["exports","@decaf-ts/decoration","@decaf-ts/core","@decaf-ts/db-decorators","tslib","@decaf-ts/decorator-validation","reflect-metadata"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self)["for-couchdb"]={},e.decafTsDecoration,e.decafTsCore,e.decafTsDbDecorators,e.tslib,e.decafTsDecoratorValidation);
|
|
2
|
+
//# sourceMappingURL=for-couchdb.cjs.map
|