@decaf-ts/decoration 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +385 -0
- package/dist/decoration.cjs +649 -0
- package/dist/decoration.esm.cjs +633 -0
- package/lib/constants.cjs +64 -0
- package/lib/constants.d.ts +58 -0
- package/lib/decoration/Decoration.cjs +270 -0
- package/lib/decoration/Decoration.d.ts +196 -0
- package/lib/decoration/index.cjs +19 -0
- package/lib/decoration/index.d.ts +2 -0
- package/lib/decoration/types.cjs +3 -0
- package/lib/decoration/types.d.ts +95 -0
- package/lib/decorators.cjs +97 -0
- package/lib/decorators.d.ts +57 -0
- package/lib/esm/constants.d.ts +58 -0
- package/lib/esm/constants.js +61 -0
- package/lib/esm/decoration/Decoration.d.ts +196 -0
- package/lib/esm/decoration/Decoration.js +266 -0
- package/lib/esm/decoration/index.d.ts +2 -0
- package/lib/esm/decoration/index.js +3 -0
- package/lib/esm/decoration/types.d.ts +95 -0
- package/lib/esm/decoration/types.js +2 -0
- package/lib/esm/decorators.d.ts +57 -0
- package/lib/esm/decorators.js +90 -0
- package/lib/esm/index.d.ts +21 -0
- package/lib/esm/index.js +22 -0
- package/lib/esm/metadata/Metadata.d.ts +99 -0
- package/lib/esm/metadata/Metadata.js +199 -0
- package/lib/esm/metadata/index.d.ts +2 -0
- package/lib/esm/metadata/index.js +3 -0
- package/lib/esm/metadata/types.d.ts +16 -0
- package/lib/esm/metadata/types.js +2 -0
- package/lib/index.cjs +39 -0
- package/lib/index.d.ts +21 -0
- package/lib/metadata/Metadata.cjs +203 -0
- package/lib/metadata/Metadata.d.ts +99 -0
- package/lib/metadata/index.cjs +19 -0
- package/lib/metadata/index.d.ts +2 -0
- package/lib/metadata/types.cjs +4 -0
- package/lib/metadata/types.d.ts +16 -0
- package/package.json +114 -0
|
@@ -0,0 +1,649 @@
|
|
|
1
|
+
(function (global, factory) {
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('reflect-metadata')) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports', 'reflect-metadata'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.decoration = {}));
|
|
5
|
+
})(this, (function (exports) { 'use strict';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @description Default flavour identifier for the decorator system
|
|
9
|
+
* @summary Defines the default flavour used by the Decoration class when no specific flavour is provided.
|
|
10
|
+
* This constant is used throughout the library as the fallback flavour for decorators.
|
|
11
|
+
* @const DefaultFlavour
|
|
12
|
+
* @memberOf module:decoration
|
|
13
|
+
*/
|
|
14
|
+
const DefaultFlavour = "decaf";
|
|
15
|
+
/**
|
|
16
|
+
* @description Character used to split nested metadata keys
|
|
17
|
+
* @summary The delimiter used by the metadata store to traverse nested object paths when reading/writing values.
|
|
18
|
+
* @const ObjectKeySplitter
|
|
19
|
+
* @memberOf module:decoration
|
|
20
|
+
*/
|
|
21
|
+
const ObjectKeySplitter = ".";
|
|
22
|
+
/**
|
|
23
|
+
* @description Enum containing metadata keys used for reflection in the model system
|
|
24
|
+
* @summary Defines the various Model keys used for reflection and metadata storage.
|
|
25
|
+
* These keys are used throughout the library to store and retrieve metadata about models,
|
|
26
|
+
* their properties, and their behavior.
|
|
27
|
+
* @readonly
|
|
28
|
+
* @enum {string}
|
|
29
|
+
* @readonly
|
|
30
|
+
* @memberOf module:decoration
|
|
31
|
+
*/
|
|
32
|
+
exports.DecorationKeys = void 0;
|
|
33
|
+
(function (DecorationKeys) {
|
|
34
|
+
/** Storage key used on the constructor to mirror runtime metadata */
|
|
35
|
+
DecorationKeys["REFLECT"] = "__decaf";
|
|
36
|
+
/** Map of model property keys to their reflected design types */
|
|
37
|
+
DecorationKeys["PROPERTIES"] = "properties";
|
|
38
|
+
/** Key under which the model's constructor is stored */
|
|
39
|
+
DecorationKeys["CLASS"] = "class";
|
|
40
|
+
/** Container of human-friendly descriptions per class and property */
|
|
41
|
+
DecorationKeys["DESCRIPTION"] = "description";
|
|
42
|
+
/** Reflect metadata key for design time type of a property */
|
|
43
|
+
DecorationKeys["DESIGN_TYPE"] = "design:type";
|
|
44
|
+
/** Reflect metadata key for constructor parameter types */
|
|
45
|
+
DecorationKeys["DESIGN_PARAMS"] = "design:paramtypes";
|
|
46
|
+
/** Reflect metadata key for method return type */
|
|
47
|
+
DecorationKeys["DESIGN_RETURN"] = "design:returntype";
|
|
48
|
+
})(exports.DecorationKeys || (exports.DecorationKeys = {}));
|
|
49
|
+
/**
|
|
50
|
+
* @description Typedef for the default metadata object shape
|
|
51
|
+
* @summary Describes the minimal structure persisted for a model before any metadata is recorded.
|
|
52
|
+
* @template M
|
|
53
|
+
* @typedef {object} DefaultMetadataType<M>
|
|
54
|
+
* @property {Record<string, Constructor | undefined>} properties - Mapping of property names to their design types
|
|
55
|
+
* @memberOf module:decoration
|
|
56
|
+
*/
|
|
57
|
+
/**
|
|
58
|
+
* @description Default metadata instance
|
|
59
|
+
* @summary Concrete default metadata object used when initializing metadata for a model
|
|
60
|
+
* @type {DefaultMetadataType<any>}
|
|
61
|
+
* @const DefaultMetadata
|
|
62
|
+
* @memberOf module:decoration
|
|
63
|
+
*/
|
|
64
|
+
const DefaultMetadata = {
|
|
65
|
+
[exports.DecorationKeys.PROPERTIES]: [],
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @description Default resolver that returns the current default flavour
|
|
70
|
+
* @summary Resolves the flavour for a given target by always returning the library's DefaultFlavour value.
|
|
71
|
+
* @param {object} target The target object being decorated
|
|
72
|
+
* @return {string} The resolved flavour identifier
|
|
73
|
+
* @function defaultFlavourResolver
|
|
74
|
+
* @memberOf module:decoration
|
|
75
|
+
*/
|
|
76
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
77
|
+
function defaultFlavourResolver(target) {
|
|
78
|
+
return DefaultFlavour;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* @description A decorator management class that handles flavoured decorators
|
|
82
|
+
* @summary The Decoration class provides a builder pattern for creating and managing decorators with different flavours.
|
|
83
|
+
* It supports registering, extending, and applying decorators with context-aware flavour resolution.
|
|
84
|
+
* The class implements a fluent interface for defining, extending, and applying decorators with different flavours,
|
|
85
|
+
* allowing for framework-specific decorator implementations while maintaining a consistent API.
|
|
86
|
+
* @template T Type of the decorator (ClassDecorator | PropertyDecorator | MethodDecorator)
|
|
87
|
+
* @param {string} [flavour] Optional flavour parameter for the decorator context
|
|
88
|
+
* @class
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* // Create a new decoration for 'component' with default flavour
|
|
92
|
+
* const componentDecorator = new Decoration()
|
|
93
|
+
* .for('component')
|
|
94
|
+
* .define(customComponentDecorator);
|
|
95
|
+
*
|
|
96
|
+
* // Create a flavoured decoration
|
|
97
|
+
* const vueComponent = new Decoration('vue')
|
|
98
|
+
* .for('component')
|
|
99
|
+
* .define(vueComponentDecorator);
|
|
100
|
+
*
|
|
101
|
+
* // Apply the decoration
|
|
102
|
+
* @componentDecorator
|
|
103
|
+
* class MyComponent {}
|
|
104
|
+
* ```
|
|
105
|
+
* @mermaid
|
|
106
|
+
* sequenceDiagram
|
|
107
|
+
* participant C as Client
|
|
108
|
+
* participant D as Decoration
|
|
109
|
+
* participant R as FlavourResolver
|
|
110
|
+
* participant F as DecoratorFactory
|
|
111
|
+
*
|
|
112
|
+
* C->>D: new Decoration(flavour)
|
|
113
|
+
* C->>D: for(key)
|
|
114
|
+
* C->>D: define(decorators)
|
|
115
|
+
* D->>D: register(key, flavour, decorators)
|
|
116
|
+
* D->>F: decoratorFactory(key, flavour)
|
|
117
|
+
* F->>R: resolve(target)
|
|
118
|
+
* R-->>F: resolved flavour
|
|
119
|
+
* F->>F: apply decorators
|
|
120
|
+
* F-->>C: decorated target
|
|
121
|
+
*/
|
|
122
|
+
class Decoration {
|
|
123
|
+
/**
|
|
124
|
+
* @description Static map of registered decorators
|
|
125
|
+
* @summary Stores all registered decorators organized by key and flavour
|
|
126
|
+
*/
|
|
127
|
+
static { this.decorators = {}; }
|
|
128
|
+
/**
|
|
129
|
+
* @description Function to resolve flavour from a target
|
|
130
|
+
* @summary Resolver function that determines the appropriate flavour for a given target
|
|
131
|
+
*/
|
|
132
|
+
static { this.flavourResolver = defaultFlavourResolver; }
|
|
133
|
+
constructor(flavour = DefaultFlavour) {
|
|
134
|
+
this.flavour = flavour;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* @description Sets the key for the decoration builder
|
|
138
|
+
* @summary Initializes a new decoration chain with the specified key
|
|
139
|
+
* @param {string} key The identifier for the decorator
|
|
140
|
+
* @return {DecorationBuilderMid} Builder instance for method chaining
|
|
141
|
+
*/
|
|
142
|
+
for(key) {
|
|
143
|
+
this.key = key;
|
|
144
|
+
return this;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* @description Adds decorators to the current context
|
|
148
|
+
* @summary Internal method to add decorators with addon support
|
|
149
|
+
* @param {boolean} [addon=false] Whether the decorators are addons
|
|
150
|
+
* @param decorators Array of decorators
|
|
151
|
+
* @return {this} Current instance for chaining
|
|
152
|
+
*/
|
|
153
|
+
decorate(addon = false, ...decorators) {
|
|
154
|
+
if (!this.key)
|
|
155
|
+
throw new Error("key must be provided before decorators can be added");
|
|
156
|
+
if ((!decorators || !decorators.length) &&
|
|
157
|
+
!addon &&
|
|
158
|
+
this.flavour !== DefaultFlavour)
|
|
159
|
+
throw new Error("Must provide overrides or addons to override or extend decaf's decorators");
|
|
160
|
+
if (this.flavour === DefaultFlavour && addon)
|
|
161
|
+
throw new Error("Default flavour cannot be extended");
|
|
162
|
+
this[addon ? "extras" : "decorators"] = new Set([
|
|
163
|
+
...(this[addon ? "extras" : "decorators"] || new Set()).values(),
|
|
164
|
+
...decorators,
|
|
165
|
+
]);
|
|
166
|
+
return this;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* @description Defines the base decorators
|
|
170
|
+
* @summary Sets the primary decorators for the current context
|
|
171
|
+
* @param decorators Decorators to define
|
|
172
|
+
* @return Builder instance for finishing the chain
|
|
173
|
+
*/
|
|
174
|
+
define(...decorators) {
|
|
175
|
+
return this.decorate(false, ...decorators);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* @description Extends existing decorators
|
|
179
|
+
* @summary Adds additional decorators to the current context
|
|
180
|
+
* @param decorators Additional decorators
|
|
181
|
+
* @return {DecorationBuilderBuild} Builder instance for building the decorator
|
|
182
|
+
*/
|
|
183
|
+
extend(...decorators) {
|
|
184
|
+
return this.decorate(true, ...decorators);
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* @description Factory that creates a context-aware decorator for a key/flavour
|
|
188
|
+
* @summary Produces a decorator function bound to the provided key and flavour. The resulting decorator resolves the actual
|
|
189
|
+
* decorators to apply at invocation time based on the target's resolved flavour and the registered base and extra decorators.
|
|
190
|
+
* @param {string} key The decoration key used to look up registered decorators
|
|
191
|
+
* @param {string} [f=DefaultFlavour] Optional explicit flavour to bind the factory to
|
|
192
|
+
* @return {function(object, any, TypedPropertyDescriptor<any>): any} A decorator function that applies the resolved decorators
|
|
193
|
+
* @mermaid
|
|
194
|
+
* sequenceDiagram
|
|
195
|
+
* participant U as User Code
|
|
196
|
+
* participant B as Decoration (builder)
|
|
197
|
+
* participant F as decoratorFactory(key, f)
|
|
198
|
+
* participant R as flavourResolver
|
|
199
|
+
* participant A as Applied Decorators
|
|
200
|
+
* U->>B: define()/extend() and apply()
|
|
201
|
+
* B->>F: create context decorator
|
|
202
|
+
* F->>R: resolve(target)
|
|
203
|
+
* R-->>F: flavour
|
|
204
|
+
* F->>A: collect base + extras
|
|
205
|
+
* loop each decorator
|
|
206
|
+
* A->>U: invoke decorator(target, key?, desc?)
|
|
207
|
+
* end
|
|
208
|
+
*/
|
|
209
|
+
decoratorFactory(key, f = DefaultFlavour) {
|
|
210
|
+
function contextDecorator(target, propertyKey, descriptor) {
|
|
211
|
+
const flavour = Decoration.flavourResolver(target);
|
|
212
|
+
const cache = Decoration.decorators[key];
|
|
213
|
+
let decorators;
|
|
214
|
+
const extras = cache[flavour]
|
|
215
|
+
? cache[flavour].extras
|
|
216
|
+
: cache[DefaultFlavour].extras;
|
|
217
|
+
const extraArgs = [
|
|
218
|
+
...(cache[DefaultFlavour].extras
|
|
219
|
+
? cache[DefaultFlavour].extras.values()
|
|
220
|
+
: []),
|
|
221
|
+
].reduce((accum, e, i) => {
|
|
222
|
+
if (e.args)
|
|
223
|
+
accum[i] = e.args;
|
|
224
|
+
return accum;
|
|
225
|
+
}, {});
|
|
226
|
+
if (cache &&
|
|
227
|
+
cache[flavour] &&
|
|
228
|
+
cache[flavour].decorators &&
|
|
229
|
+
cache[flavour].decorators.size) {
|
|
230
|
+
decorators = cache[flavour].decorators;
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
decorators = cache[DefaultFlavour].decorators;
|
|
234
|
+
}
|
|
235
|
+
const decoratorArgs = [
|
|
236
|
+
...cache[DefaultFlavour].decorators.values(),
|
|
237
|
+
].reduce((accum, e, i) => {
|
|
238
|
+
if (e.args)
|
|
239
|
+
accum[i] = e.args;
|
|
240
|
+
return accum;
|
|
241
|
+
}, {});
|
|
242
|
+
const toApply = [
|
|
243
|
+
...(decorators ? decorators.values() : []),
|
|
244
|
+
...(extras ? extras.values() : []),
|
|
245
|
+
];
|
|
246
|
+
return toApply.reduce((_, d, i) => {
|
|
247
|
+
switch (typeof d) {
|
|
248
|
+
case "object": {
|
|
249
|
+
const { decorator, args } = d;
|
|
250
|
+
const argz = args || i < (decorators ? decorators.size : 0)
|
|
251
|
+
? decoratorArgs[i]
|
|
252
|
+
: extraArgs[i - (decorators ? decorators.size : 0)] ||
|
|
253
|
+
(decorators ? decoratorArgs[i - decorators.size] : []);
|
|
254
|
+
return decorator(...(argz || []))(target, propertyKey, descriptor);
|
|
255
|
+
}
|
|
256
|
+
case "function":
|
|
257
|
+
return d(target, propertyKey, descriptor);
|
|
258
|
+
default:
|
|
259
|
+
throw new Error(`Unexpected decorator type: ${typeof d}`);
|
|
260
|
+
}
|
|
261
|
+
}, { target, propertyKey, descriptor });
|
|
262
|
+
}
|
|
263
|
+
Object.defineProperty(contextDecorator, "name", {
|
|
264
|
+
value: [f, key].join("_decorator_for_"),
|
|
265
|
+
writable: false,
|
|
266
|
+
});
|
|
267
|
+
return contextDecorator;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* @description Creates the final decorator function
|
|
271
|
+
* @summary Builds and returns the decorator factory function
|
|
272
|
+
* @return {function(any, any?, TypedPropertyDescriptor?): any} The generated decorator function
|
|
273
|
+
*/
|
|
274
|
+
apply() {
|
|
275
|
+
if (!this.key)
|
|
276
|
+
throw new Error("No key provided for the decoration builder");
|
|
277
|
+
Decoration.register(this.key, this.flavour, this.decorators || new Set(), this.extras);
|
|
278
|
+
return this.decoratorFactory(this.key, this.flavour);
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* @description Registers decorators for a specific key and flavour
|
|
282
|
+
* @summary Internal method to store decorators in the static registry
|
|
283
|
+
* @param {string} key Decorator key
|
|
284
|
+
* @param {string} flavour Decorator flavour
|
|
285
|
+
* @param [decorators] Primary decorators
|
|
286
|
+
* @param [extras] Additional decorators
|
|
287
|
+
*/
|
|
288
|
+
static register(key, flavour, decorators, extras) {
|
|
289
|
+
if (!key) {
|
|
290
|
+
throw new Error("No key provided for the decoration builder");
|
|
291
|
+
}
|
|
292
|
+
if (!decorators)
|
|
293
|
+
throw new Error("No decorators provided for the decoration builder");
|
|
294
|
+
if (!flavour)
|
|
295
|
+
throw new Error("No flavour provided for the decoration builder");
|
|
296
|
+
if (!Decoration.decorators[key])
|
|
297
|
+
Decoration.decorators[key] = {};
|
|
298
|
+
if (!Decoration.decorators[key][flavour])
|
|
299
|
+
Decoration.decorators[key][flavour] = {};
|
|
300
|
+
if (decorators)
|
|
301
|
+
Decoration.decorators[key][flavour].decorators = decorators;
|
|
302
|
+
if (extras)
|
|
303
|
+
Decoration.decorators[key][flavour].extras = extras;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* @description Sets the global flavour resolver
|
|
307
|
+
* @summary Configures the function used to determine decorator flavours
|
|
308
|
+
* @param {FlavourResolver} resolver Function to resolve flavours
|
|
309
|
+
*/
|
|
310
|
+
static setFlavourResolver(resolver) {
|
|
311
|
+
Decoration.flavourResolver = resolver;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* @description Convenience static entry to start a decoration builder
|
|
315
|
+
* @summary Creates a new Decoration instance and initiates the builder chain with the provided key.
|
|
316
|
+
* @param {string} key The decoration key to configure
|
|
317
|
+
* @return {DecorationBuilderMid} A builder instance for chaining definitions
|
|
318
|
+
*/
|
|
319
|
+
static for(key) {
|
|
320
|
+
return new Decoration().for(key);
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* @description Starts a builder for a specific flavour
|
|
324
|
+
* @summary Convenience method to begin a Decoration builder chain bound to the given flavour identifier, allowing registration of flavour-specific decorators.
|
|
325
|
+
* @param {string} flavour The flavour name to bind to the builder
|
|
326
|
+
* @return {DecorationBuilderStart} A builder start interface to continue configuration
|
|
327
|
+
*/
|
|
328
|
+
static flavouredAs(flavour) {
|
|
329
|
+
return new Decoration(flavour);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* @description Retrieves a nested value from an object given a path
|
|
335
|
+
* @summary Walks an object structure using a splitter-delimited path and returns the value at that location or undefined if any key is missing.
|
|
336
|
+
* @param {Record<string, any>} obj The object to traverse
|
|
337
|
+
* @param {string} path The path to the desired value (e.g., "a.b.c")
|
|
338
|
+
* @param {string} [splitter=ObjectKeySplitter] The delimiter used to split the path
|
|
339
|
+
* @return {*} The resolved value at the given path or undefined if not found
|
|
340
|
+
* @function getValueBySplitter
|
|
341
|
+
* @mermaid
|
|
342
|
+
* sequenceDiagram
|
|
343
|
+
* participant C as Caller
|
|
344
|
+
* participant F as getValueBySplitter
|
|
345
|
+
* participant O as Object
|
|
346
|
+
* C->>F: (obj, path, splitter)
|
|
347
|
+
* F->>F: split path into keys
|
|
348
|
+
* loop for each key
|
|
349
|
+
* F->>O: access current[key]
|
|
350
|
+
* alt missing or nullish
|
|
351
|
+
* F-->>C: return undefined
|
|
352
|
+
* end
|
|
353
|
+
* end
|
|
354
|
+
* F-->>C: return final value
|
|
355
|
+
* @memberOf module:decoration
|
|
356
|
+
*/
|
|
357
|
+
function getValueBySplitter(obj, path, splitter = ObjectKeySplitter) {
|
|
358
|
+
const keys = path.split(splitter);
|
|
359
|
+
let current = obj;
|
|
360
|
+
for (const key of keys) {
|
|
361
|
+
if (current === null ||
|
|
362
|
+
current === undefined ||
|
|
363
|
+
!Object.prototype.hasOwnProperty.call(current, key))
|
|
364
|
+
return undefined;
|
|
365
|
+
current = current[key];
|
|
366
|
+
}
|
|
367
|
+
return current;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* @description Sets a nested value on an object given a path
|
|
371
|
+
* @summary Traverses or creates intermediate objects following a splitter-delimited path and assigns the provided value at the destination key.
|
|
372
|
+
* @param {Record<string, any>} obj The object to mutate
|
|
373
|
+
* @param {string} path The destination path (e.g., "a.b.c")
|
|
374
|
+
* @param {*} value The value to set at the destination
|
|
375
|
+
* @param {string} [splitter=ObjectKeySplitter] The delimiter used to split the path
|
|
376
|
+
* @return {void}
|
|
377
|
+
* @function setValueBySplitter
|
|
378
|
+
* @mermaid
|
|
379
|
+
* sequenceDiagram
|
|
380
|
+
* participant C as Caller
|
|
381
|
+
* participant F as setValueBySplitter
|
|
382
|
+
* participant O as Object
|
|
383
|
+
* C->>F: (obj, path, value, splitter)
|
|
384
|
+
* F->>F: split path into keys
|
|
385
|
+
* loop for each key
|
|
386
|
+
* alt key missing
|
|
387
|
+
* F->>O: create intermediate object
|
|
388
|
+
* else key exists
|
|
389
|
+
* F->>O: descend into existing object
|
|
390
|
+
* end
|
|
391
|
+
* end
|
|
392
|
+
* F-->>C: void
|
|
393
|
+
* @memberOf module:decoration
|
|
394
|
+
*/
|
|
395
|
+
function setValueBySplitter(obj, path, value, splitter = ObjectKeySplitter) {
|
|
396
|
+
const keys = path.split(splitter).filter((k) => k.length > 0);
|
|
397
|
+
if (keys.length === 0)
|
|
398
|
+
return;
|
|
399
|
+
let current = obj;
|
|
400
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
401
|
+
const key = keys[i];
|
|
402
|
+
if (current[key] === undefined ||
|
|
403
|
+
current[key] === null ||
|
|
404
|
+
typeof current[key] !== "object") {
|
|
405
|
+
current[key] = {};
|
|
406
|
+
}
|
|
407
|
+
current = current[key];
|
|
408
|
+
}
|
|
409
|
+
const lastKey = keys[keys.length - 1];
|
|
410
|
+
current[lastKey] = value;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* @description Centralized runtime metadata store bound to constructors
|
|
414
|
+
* @summary Provides utilities to read and write structured metadata for classes and their members, with optional mirroring onto the constructor via a well-known symbol key. Supports nested key paths using a configurable splitter and offers both instance and static APIs.
|
|
415
|
+
* @template M The model type the metadata belongs to
|
|
416
|
+
* @template META Extends BasicMetadata<M> representing the metadata structure
|
|
417
|
+
* @class
|
|
418
|
+
* @example
|
|
419
|
+
* // Define and read metadata for a class
|
|
420
|
+
* class User { name!: string }
|
|
421
|
+
* Metadata.set(User, "description.class", "A user model");
|
|
422
|
+
* Metadata.set(User, "properties.name", String);
|
|
423
|
+
* const desc = Metadata.get(User, "description.class"); // "A user model"
|
|
424
|
+
* const type = Metadata.type(User, "name"); // String
|
|
425
|
+
* @mermaid
|
|
426
|
+
* sequenceDiagram
|
|
427
|
+
* participant C as Constructor
|
|
428
|
+
* participant S as Metadata (static)
|
|
429
|
+
* C->>S: set(User, "properties.name", String)
|
|
430
|
+
* C->>S: get(User, "properties.name")
|
|
431
|
+
* S-->>C: String
|
|
432
|
+
*/
|
|
433
|
+
class Metadata {
|
|
434
|
+
/**
|
|
435
|
+
* @description In-memory storage of metadata by constructor symbol
|
|
436
|
+
* @summary Maps a Symbol derived from the constructor to its metadata object, enabling efficient lookup.
|
|
437
|
+
*/
|
|
438
|
+
static { this._metadata = {}; }
|
|
439
|
+
/**
|
|
440
|
+
* @description Path delimiter for nested metadata keys
|
|
441
|
+
* @summary Used by get/set operations to navigate nested structures, defaults to ObjectKeySplitter.
|
|
442
|
+
*/
|
|
443
|
+
static { this.splitter = ObjectKeySplitter; }
|
|
444
|
+
/**
|
|
445
|
+
* @description Symbol key used to mirror metadata on the constructor
|
|
446
|
+
* @summary When mirroring is enabled, the metadata object is defined on the constructor under this non-enumerable key.
|
|
447
|
+
*/
|
|
448
|
+
static { this.baseKey = exports.DecorationKeys.REFLECT; }
|
|
449
|
+
/**
|
|
450
|
+
* @description Controls whether metadata is mirrored onto the constructor
|
|
451
|
+
* @summary When true, the metadata object is defined on the constructor under the non-enumerable baseKey.
|
|
452
|
+
*/
|
|
453
|
+
static { this.mirror = true; }
|
|
454
|
+
constructor() { }
|
|
455
|
+
/**
|
|
456
|
+
* @description Lists known property keys for a model
|
|
457
|
+
* @summary Reads the metadata entry and returns the names of properties that have recorded type information.
|
|
458
|
+
* @param {Constructor} model The target constructor
|
|
459
|
+
* @return {string[]|undefined} Array of property names or undefined if no metadata exists
|
|
460
|
+
*/
|
|
461
|
+
static properties(model) {
|
|
462
|
+
const meta = this.get(model);
|
|
463
|
+
if (!meta)
|
|
464
|
+
return undefined;
|
|
465
|
+
return Object.keys(meta.properties);
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* @description Retrieves a human-readable description for a class or a property
|
|
469
|
+
* @summary Looks up the description stored under the metadata "description" map. If a property key is provided, returns the property's description; otherwise returns the class description.
|
|
470
|
+
* @template M
|
|
471
|
+
* @param {Constructor<M>} model The target constructor whose description is being retrieved
|
|
472
|
+
* @param {string} [prop] Optional property key for which to fetch the description
|
|
473
|
+
* @return {string|undefined} The description text if present, otherwise undefined
|
|
474
|
+
*/
|
|
475
|
+
static description(model, prop) {
|
|
476
|
+
return this.get(model, [exports.DecorationKeys.DESCRIPTION, prop ? prop : exports.DecorationKeys.CLASS].join(ObjectKeySplitter));
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* @description Retrieves the recorded design type for a property
|
|
480
|
+
* @summary Reads the metadata entry under "properties.<prop>" to return the constructor recorded for the given property name.
|
|
481
|
+
* @param {Constructor} model The target constructor
|
|
482
|
+
* @param {string} prop The property name whose type should be returned
|
|
483
|
+
* @return {Constructor|undefined} The constructor reference of the property type or undefined if not available
|
|
484
|
+
*/
|
|
485
|
+
static type(model, prop) {
|
|
486
|
+
return this.get(model, `${exports.DecorationKeys.PROPERTIES}.${prop}`);
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* @description Retrieves metadata for a model or a specific key within it
|
|
490
|
+
* @summary When called with a constructor only, returns the entire metadata object associated with the model. When a key path is provided, returns the value stored at that nested key.
|
|
491
|
+
* @template M
|
|
492
|
+
* @template META
|
|
493
|
+
* @param {Constructor<M>} model The target constructor used to locate the metadata record
|
|
494
|
+
* @param {string} [key] Optional nested key path to fetch a specific value
|
|
495
|
+
* @return {META|*|undefined} The metadata object, the value at the key path, or undefined if nothing exists
|
|
496
|
+
*/
|
|
497
|
+
static get(model, key) {
|
|
498
|
+
const symbol = Symbol.for(model.toString());
|
|
499
|
+
if (!this._metadata[symbol])
|
|
500
|
+
return undefined;
|
|
501
|
+
if (!key)
|
|
502
|
+
return this._metadata[symbol];
|
|
503
|
+
return getValueBySplitter(this._metadata[symbol], key, this.splitter);
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* @description Writes a metadata value at a given nested key path
|
|
507
|
+
* @summary Ensures the metadata record exists for the constructor, mirrors it on the constructor when enabled, and sets the provided value on the nested key path using the configured splitter.
|
|
508
|
+
* @param {Constructor} model The target constructor to which the metadata belongs
|
|
509
|
+
* @param {string} key The nested key path at which to store the value
|
|
510
|
+
* @param {*} value The value to store in the metadata
|
|
511
|
+
* @return {void}
|
|
512
|
+
*/
|
|
513
|
+
static set(model, key, value) {
|
|
514
|
+
const symbol = Symbol.for(model.toString());
|
|
515
|
+
if (!this._metadata[symbol])
|
|
516
|
+
this._metadata[symbol] = {};
|
|
517
|
+
if (Metadata.mirror &&
|
|
518
|
+
!Object.prototype.hasOwnProperty.call(model, this.baseKey)) {
|
|
519
|
+
Object.defineProperty(model, this.baseKey, {
|
|
520
|
+
enumerable: false,
|
|
521
|
+
configurable: false,
|
|
522
|
+
writable: false,
|
|
523
|
+
value: this._metadata[symbol],
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
setValueBySplitter(this._metadata[symbol], key, value, this.splitter);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* @description Assigns arbitrary metadata to a target using a string key
|
|
532
|
+
* @summary Decorator factory that stores a key/value pair in the central Metadata store for the provided class or member.
|
|
533
|
+
* @param {string} key The metadata key to associate with the target
|
|
534
|
+
* @param {*} value The metadata value to store under the given key
|
|
535
|
+
* @return A decorator that writes the metadata when applied
|
|
536
|
+
* @function metadata
|
|
537
|
+
* @category Decorators
|
|
538
|
+
*/
|
|
539
|
+
function metadata(key, value) {
|
|
540
|
+
return function metadata(model, prop,
|
|
541
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
542
|
+
descriptor) {
|
|
543
|
+
Metadata.set(prop ? model.constructor : model, key, value);
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* @description Captures and stores a property's design type
|
|
548
|
+
* @summary Decorator factory that reads the reflected design:type for a property and registers it in the Metadata store under the properties map.
|
|
549
|
+
* @return A decorator that records the property's type metadata when applied
|
|
550
|
+
* @function prop
|
|
551
|
+
* @category Property Decorators
|
|
552
|
+
*/
|
|
553
|
+
function prop() {
|
|
554
|
+
return function prop(model, prop) {
|
|
555
|
+
const designType = Reflect.getOwnMetadata(exports.DecorationKeys.DESIGN_TYPE, model, prop);
|
|
556
|
+
return metadata(`${exports.DecorationKeys.PROPERTIES}.${prop}`, designType)(model, prop);
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* @description Decorator factory that applies multiple decorators to a single target
|
|
561
|
+
* @summary Creates a composite decorator that applies multiple decorators in sequence, correctly handling class, method, and property decorators.
|
|
562
|
+
* @param {Array<ClassDecorator | MethodDecorator | PropertyDecorator>} decorators - Array of decorators to apply
|
|
563
|
+
* @return {Function} A decorator function that applies all provided decorators to the target
|
|
564
|
+
* @function apply
|
|
565
|
+
* @mermaid
|
|
566
|
+
* sequenceDiagram
|
|
567
|
+
* participant U as User Code
|
|
568
|
+
* participant A as apply(...decorators)
|
|
569
|
+
* participant D as Decorator
|
|
570
|
+
* U->>A: get decorator(...decorators)
|
|
571
|
+
* A->>U: returns (target, key?, desc?) => void
|
|
572
|
+
* U->>A: invoke on target
|
|
573
|
+
* loop for each decorator
|
|
574
|
+
* A->>D: invoke appropriate decorator type
|
|
575
|
+
* end
|
|
576
|
+
* @category Decorators
|
|
577
|
+
*/
|
|
578
|
+
function apply(...decorators) {
|
|
579
|
+
return (target, propertyKey, descriptor) => {
|
|
580
|
+
for (const decorator of decorators) {
|
|
581
|
+
if (target instanceof Function && !descriptor) {
|
|
582
|
+
decorator(target);
|
|
583
|
+
continue;
|
|
584
|
+
}
|
|
585
|
+
decorator(target, propertyKey, descriptor);
|
|
586
|
+
}
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* @description Creates a property metadata decorator
|
|
591
|
+
* @summary Convenience factory that combines metadata(key, value) and prop() to both set an arbitrary metadata key and record the property's design type.
|
|
592
|
+
* @param {string} key The metadata key to set for the property
|
|
593
|
+
* @param {*} value The metadata value to associate with the key
|
|
594
|
+
* @return A decorator that sets the metadata and captures the property's type
|
|
595
|
+
* @function propMetadata
|
|
596
|
+
* @category Property Decorators
|
|
597
|
+
*/
|
|
598
|
+
function propMetadata(key, value) {
|
|
599
|
+
return apply(metadata(key, value), prop());
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* @description Attaches a human-readable description to a class or member
|
|
603
|
+
* @summary Decorator factory that stores a textual description in the Metadata store under the appropriate description key for a class or its property.
|
|
604
|
+
* @param {string} desc The descriptive text to associate with the class or property
|
|
605
|
+
* @return A decorator that records the description when applied
|
|
606
|
+
* @function description
|
|
607
|
+
* @category Decorators
|
|
608
|
+
*/
|
|
609
|
+
function description(desc) {
|
|
610
|
+
return function description(original, prop, descriptor) {
|
|
611
|
+
return metadata([
|
|
612
|
+
exports.DecorationKeys.DESCRIPTION,
|
|
613
|
+
prop ? prop.toString() : exports.DecorationKeys.CLASS,
|
|
614
|
+
].join(ObjectKeySplitter), desc)(original, prop, descriptor);
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* @description Root entry point for the decoration module
|
|
620
|
+
* @summary Aggregates and re-exports the public API of the decoration library, including core classes like {@link Decoration}, utility decorators, metadata helpers, and constants. This module is the primary import surface for consumers and exposes:
|
|
621
|
+
* - Core builder: {@link Decoration}
|
|
622
|
+
* - Decorator utilities: {@link module:decoration | decorators in ./decorators}
|
|
623
|
+
* - Metadata utilities: {@link Metadata}
|
|
624
|
+
* - Constants and enums: {@link DecorationKeys}, {@link DefaultFlavour}
|
|
625
|
+
*
|
|
626
|
+
* @module decoration
|
|
627
|
+
*/
|
|
628
|
+
/**
|
|
629
|
+
* @description Current version of the reflection package
|
|
630
|
+
* @summary Stores the semantic version number of the package
|
|
631
|
+
* @const VERSION
|
|
632
|
+
* @memberOf module:decoration
|
|
633
|
+
*/
|
|
634
|
+
const VERSION = "0.0.2";
|
|
635
|
+
|
|
636
|
+
exports.Decoration = Decoration;
|
|
637
|
+
exports.DefaultFlavour = DefaultFlavour;
|
|
638
|
+
exports.DefaultMetadata = DefaultMetadata;
|
|
639
|
+
exports.Metadata = Metadata;
|
|
640
|
+
exports.ObjectKeySplitter = ObjectKeySplitter;
|
|
641
|
+
exports.VERSION = VERSION;
|
|
642
|
+
exports.apply = apply;
|
|
643
|
+
exports.description = description;
|
|
644
|
+
exports.metadata = metadata;
|
|
645
|
+
exports.prop = prop;
|
|
646
|
+
exports.propMetadata = propMetadata;
|
|
647
|
+
|
|
648
|
+
}));
|
|
649
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVjb3JhdGlvbi5janMiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb25zdGFudHMudHMiLCIuLi9zcmMvZGVjb3JhdGlvbi9EZWNvcmF0aW9uLnRzIiwiLi4vc3JjL21ldGFkYXRhL01ldGFkYXRhLnRzIiwiLi4vc3JjL2RlY29yYXRvcnMudHMiLCIuLi9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQmFzaWNNZXRhZGF0YSB9IGZyb20gXCIuL21ldGFkYXRhL3R5cGVzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlZmF1bHQgZmxhdm91ciBpZGVudGlmaWVyIGZvciB0aGUgZGVjb3JhdG9yIHN5c3RlbVxuICogQHN1bW1hcnkgRGVmaW5lcyB0aGUgZGVmYXVsdCBmbGF2b3VyIHVzZWQgYnkgdGhlIERlY29yYXRpb24gY2xhc3Mgd2hlbiBubyBzcGVjaWZpYyBmbGF2b3VyIGlzIHByb3ZpZGVkLlxuICogVGhpcyBjb25zdGFudCBpcyB1c2VkIHRocm91Z2hvdXQgdGhlIGxpYnJhcnkgYXMgdGhlIGZhbGxiYWNrIGZsYXZvdXIgZm9yIGRlY29yYXRvcnMuXG4gKiBAY29uc3QgRGVmYXVsdEZsYXZvdXJcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdGlvblxuICovXG5leHBvcnQgY29uc3QgRGVmYXVsdEZsYXZvdXIgPSBcImRlY2FmXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENoYXJhY3RlciB1c2VkIHRvIHNwbGl0IG5lc3RlZCBtZXRhZGF0YSBrZXlzXG4gKiBAc3VtbWFyeSBUaGUgZGVsaW1pdGVyIHVzZWQgYnkgdGhlIG1ldGFkYXRhIHN0b3JlIHRvIHRyYXZlcnNlIG5lc3RlZCBvYmplY3QgcGF0aHMgd2hlbiByZWFkaW5nL3dyaXRpbmcgdmFsdWVzLlxuICogQGNvbnN0IE9iamVjdEtleVNwbGl0dGVyXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRpb25cbiAqL1xuZXhwb3J0IGNvbnN0IE9iamVjdEtleVNwbGl0dGVyID0gXCIuXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVudW0gY29udGFpbmluZyBtZXRhZGF0YSBrZXlzIHVzZWQgZm9yIHJlZmxlY3Rpb24gaW4gdGhlIG1vZGVsIHN5c3RlbVxuICogQHN1bW1hcnkgRGVmaW5lcyB0aGUgdmFyaW91cyBNb2RlbCBrZXlzIHVzZWQgZm9yIHJlZmxlY3Rpb24gYW5kIG1ldGFkYXRhIHN0b3JhZ2UuXG4gKiBUaGVzZSBrZXlzIGFyZSB1c2VkIHRocm91Z2hvdXQgdGhlIGxpYnJhcnkgdG8gc3RvcmUgYW5kIHJldHJpZXZlIG1ldGFkYXRhIGFib3V0IG1vZGVscyxcbiAqIHRoZWlyIHByb3BlcnRpZXMsIGFuZCB0aGVpciBiZWhhdmlvci5cbiAqIEByZWFkb25seVxuICogQGVudW0ge3N0cmluZ31cbiAqIEByZWFkb25seVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCBlbnVtIERlY29yYXRpb25LZXlzIHtcbiAgLyoqIFN0b3JhZ2Uga2V5IHVzZWQgb24gdGhlIGNvbnN0cnVjdG9yIHRvIG1pcnJvciBydW50aW1lIG1ldGFkYXRhICovXG4gIFJFRkxFQ1QgPSBgX18ke0RlZmF1bHRGbGF2b3VyfWAsXG4gIC8qKiBNYXAgb2YgbW9kZWwgcHJvcGVydHkga2V5cyB0byB0aGVpciByZWZsZWN0ZWQgZGVzaWduIHR5cGVzICovXG4gIFBST1BFUlRJRVMgPSBcInByb3BlcnRpZXNcIixcbiAgLyoqIEtleSB1bmRlciB3aGljaCB0aGUgbW9kZWwncyBjb25zdHJ1Y3RvciBpcyBzdG9yZWQgKi9cbiAgQ0xBU1MgPSBcImNsYXNzXCIsXG4gIC8qKiBDb250YWluZXIgb2YgaHVtYW4tZnJpZW5kbHkgZGVzY3JpcHRpb25zIHBlciBjbGFzcyBhbmQgcHJvcGVydHkgKi9cbiAgREVTQ1JJUFRJT04gPSBcImRlc2NyaXB0aW9uXCIsXG4gIC8qKiBSZWZsZWN0IG1ldGFkYXRhIGtleSBmb3IgZGVzaWduIHRpbWUgdHlwZSBvZiBhIHByb3BlcnR5ICovXG4gIERFU0lHTl9UWVBFID0gXCJkZXNpZ246dHlwZVwiLFxuICAvKiogUmVmbGVjdCBtZXRhZGF0YSBrZXkgZm9yIGNvbnN0cnVjdG9yIHBhcmFtZXRlciB0eXBlcyAqL1xuICBERVNJR05fUEFSQU1TID0gXCJkZXNpZ246cGFyYW10eXBlc1wiLFxuICAvKiogUmVmbGVjdCBtZXRhZGF0YSBrZXkgZm9yIG1ldGhvZCByZXR1cm4gdHlwZSAqL1xuICBERVNJR05fUkVUVVJOID0gXCJkZXNpZ246cmV0dXJudHlwZVwiLFxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBUeXBlZGVmIGZvciB0aGUgZGVmYXVsdCBtZXRhZGF0YSBvYmplY3Qgc2hhcGVcbiAqIEBzdW1tYXJ5IERlc2NyaWJlcyB0aGUgbWluaW1hbCBzdHJ1Y3R1cmUgcGVyc2lzdGVkIGZvciBhIG1vZGVsIGJlZm9yZSBhbnkgbWV0YWRhdGEgaXMgcmVjb3JkZWQuXG4gKiBAdGVtcGxhdGUgTVxuICogQHR5cGVkZWYge29iamVjdH0gRGVmYXVsdE1ldGFkYXRhVHlwZTxNPlxuICogQHByb3BlcnR5IHtSZWNvcmQ8c3RyaW5nLCBDb25zdHJ1Y3RvciB8IHVuZGVmaW5lZD59IHByb3BlcnRpZXMgLSBNYXBwaW5nIG9mIHByb3BlcnR5IG5hbWVzIHRvIHRoZWlyIGRlc2lnbiB0eXBlc1xuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVmYXVsdCBtZXRhZGF0YSBpbnN0YW5jZVxuICogQHN1bW1hcnkgQ29uY3JldGUgZGVmYXVsdCBtZXRhZGF0YSBvYmplY3QgdXNlZCB3aGVuIGluaXRpYWxpemluZyBtZXRhZGF0YSBmb3IgYSBtb2RlbFxuICogQHR5cGUge0RlZmF1bHRNZXRhZGF0YVR5cGU8YW55Pn1cbiAqIEBjb25zdCBEZWZhdWx0TWV0YWRhdGFcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdGlvblxuICovXG5leHBvcnQgY29uc3QgRGVmYXVsdE1ldGFkYXRhOiBCYXNpY01ldGFkYXRhPGFueT4gPSB7XG4gIFtEZWNvcmF0aW9uS2V5cy5QUk9QRVJUSUVTXTogW10sXG59IGFzIHVua25vd24gYXMgQmFzaWNNZXRhZGF0YTxhbnk+O1xuIiwiaW1wb3J0IHtcbiAgRGVjb3JhdGlvbkJ1aWxkZXJCdWlsZCxcbiAgRGVjb3JhdGlvbkJ1aWxkZXJFbmQsXG4gIERlY29yYXRpb25CdWlsZGVyTWlkLFxuICBEZWNvcmF0aW9uQnVpbGRlclN0YXJ0LFxuICBGbGF2b3VyUmVzb2x2ZXIsXG4gIElEZWNvcmF0aW9uQnVpbGRlcixcbn0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IERlZmF1bHRGbGF2b3VyIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWZhdWx0IHJlc29sdmVyIHRoYXQgcmV0dXJucyB0aGUgY3VycmVudCBkZWZhdWx0IGZsYXZvdXJcbiAqIEBzdW1tYXJ5IFJlc29sdmVzIHRoZSBmbGF2b3VyIGZvciBhIGdpdmVuIHRhcmdldCBieSBhbHdheXMgcmV0dXJuaW5nIHRoZSBsaWJyYXJ5J3MgRGVmYXVsdEZsYXZvdXIgdmFsdWUuXG4gKiBAcGFyYW0ge29iamVjdH0gdGFyZ2V0IFRoZSB0YXJnZXQgb2JqZWN0IGJlaW5nIGRlY29yYXRlZFxuICogQHJldHVybiB7c3RyaW5nfSBUaGUgcmVzb2x2ZWQgZmxhdm91ciBpZGVudGlmaWVyXG4gKiBAZnVuY3Rpb24gZGVmYXVsdEZsYXZvdXJSZXNvbHZlclxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbmZ1bmN0aW9uIGRlZmF1bHRGbGF2b3VyUmVzb2x2ZXIodGFyZ2V0OiBvYmplY3QpIHtcbiAgcmV0dXJuIERlZmF1bHRGbGF2b3VyO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBVbmlvbiB0eXBlIGNvdmVyaW5nIHN1cHBvcnRlZCBkZWNvcmF0b3Iga2luZHNcbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYW55IG9mIHRoZSBzdGFuZGFyZCBUeXBlU2NyaXB0IGRlY29yYXRvciBzaWduYXR1cmVzIChjbGFzcywgcHJvcGVydHksIG9yIG1ldGhvZCksIGVuYWJsaW5nIGZsZXhpYmxlIHJlZ2lzdHJhdGlvbiBhbmQgYXBwbGljYXRpb24gd2l0aGluIHRoZSBEZWNvcmF0aW9uIHN5c3RlbS5cbiAqIEB0ZW1wbGF0ZSBUXG4gKiBAdHlwZURlZiBEZWNvcmF0b3JUeXBlc1xuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCB0eXBlIERlY29yYXRvclR5cGVzID1cbiAgfCBDbGFzc0RlY29yYXRvclxuICB8IFByb3BlcnR5RGVjb3JhdG9yXG4gIHwgTWV0aG9kRGVjb3JhdG9yO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBUeXBlIGRlZmluaXRpb24gZm9yIGEgZGVjb3JhdG9yIGZhY3RvcnkgZnVuY3Rpb25cbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYSBmdW5jdGlvbiB0aGF0IGFjY2VwdHMgYXJiaXRyYXJ5IGFyZ3VtZW50cyBhbmQgcmV0dXJucyBhIGNvbmNyZXRlIGRlY29yYXRvciBmdW5jdGlvbiB0byBiZSBhcHBsaWVkIHRvIGEgdGFyZ2V0LlxuICogQHRlbXBsYXRlIEFcbiAqIEB0eXBlRGVmIERlY29yYXRvckZhY3RvcnlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdGlvblxuICovXG5leHBvcnQgdHlwZSBEZWNvcmF0b3JGYWN0b3J5ID0gKC4uLmFyZ3M6IGFueVtdKSA9PiBEZWNvcmF0b3JUeXBlcztcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQXJndW1lbnQgYnVuZGxlIGZvciBhIGRlY29yYXRvciBmYWN0b3J5XG4gKiBAc3VtbWFyeSBPYmplY3QgZm9ybSB1c2VkIHRvIGRlZmVyIGRlY29yYXRvciBjcmVhdGlvbiwgY2FycnlpbmcgYm90aCB0aGUgZmFjdG9yeSBmdW5jdGlvbiBhbmQgaXRzIGFyZ3VtZW50IGxpc3QgdG8gYmUgaW52b2tlZCBsYXRlciBkdXJpbmcgYXBwbGljYXRpb24uXG4gKiBAdHlwZURlZiBEZWNvcmF0b3JGYWN0b3J5QXJnc1xuICogQHByb3BlcnR5IHtEZWNvcmF0b3JGYWN0b3J5fSBkZWNvcmF0b3IgVGhlIGZhY3RvcnkgZnVuY3Rpb24gdGhhdCBwcm9kdWNlcyBhIGRlY29yYXRvciB3aGVuIGludm9rZWRcbiAqIEBwcm9wZXJ0eSB7YW55W119IFthcmdzXSBPcHRpb25hbCBsaXN0IG9mIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBkZWNvcmF0b3IgZmFjdG9yeVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCB0eXBlIERlY29yYXRvckZhY3RvcnlBcmdzID0ge1xuICBkZWNvcmF0b3I6IERlY29yYXRvckZhY3Rvcnk7XG4gIGFyZ3M/OiBhbnlbXTtcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFVuaW9uIHRoYXQgcmVwcmVzZW50cyBlaXRoZXIgYSByZWFkeS10by1hcHBseSBkZWNvcmF0b3Igb3IgYSBmYWN0b3J5IHdpdGggYXJndW1lbnRzXG4gKiBAc3VtbWFyeSBBbGxvd3MgcmVnaXN0ZXJpbmcgZGVjb3JhdG9ycyBpbiB0d28gZm9ybXM6IGFzIGRpcmVjdCBkZWNvcmF0b3IgZnVuY3Rpb25zIG9yIGFzIGRlZmVycmVkIGZhY3RvcmllcyBwYWlyZWQgd2l0aCB0aGVpciBhcmd1bWVudCBsaXN0cyBmb3IgbGF0ZXIgaW5zdGFudGlhdGlvbi5cbiAqIEB0eXBlRGVmIERlY29yYXRvckRhdGFcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdGlvblxuICovXG5leHBvcnQgdHlwZSBEZWNvcmF0b3JEYXRhID0gRGVjb3JhdG9yVHlwZXMgfCBEZWNvcmF0b3JGYWN0b3J5QXJncztcbi8qKlxuICogQGRlc2NyaXB0aW9uIEEgZGVjb3JhdG9yIG1hbmFnZW1lbnQgY2xhc3MgdGhhdCBoYW5kbGVzIGZsYXZvdXJlZCBkZWNvcmF0b3JzXG4gKiBAc3VtbWFyeSBUaGUgRGVjb3JhdGlvbiBjbGFzcyBwcm92aWRlcyBhIGJ1aWxkZXIgcGF0dGVybiBmb3IgY3JlYXRpbmcgYW5kIG1hbmFnaW5nIGRlY29yYXRvcnMgd2l0aCBkaWZmZXJlbnQgZmxhdm91cnMuXG4gKiBJdCBzdXBwb3J0cyByZWdpc3RlcmluZywgZXh0ZW5kaW5nLCBhbmQgYXBwbHlpbmcgZGVjb3JhdG9ycyB3aXRoIGNvbnRleHQtYXdhcmUgZmxhdm91ciByZXNvbHV0aW9uLlxuICogVGhlIGNsYXNzIGltcGxlbWVudHMgYSBmbHVlbnQgaW50ZXJmYWNlIGZvciBkZWZpbmluZywgZXh0ZW5kaW5nLCBhbmQgYXBwbHlpbmcgZGVjb3JhdG9ycyB3aXRoIGRpZmZlcmVudCBmbGF2b3VycyxcbiAqIGFsbG93aW5nIGZvciBmcmFtZXdvcmstc3BlY2lmaWMgZGVjb3JhdG9yIGltcGxlbWVudGF0aW9ucyB3aGlsZSBtYWludGFpbmluZyBhIGNvbnNpc3RlbnQgQVBJLlxuICogQHRlbXBsYXRlIFQgVHlwZSBvZiB0aGUgZGVjb3JhdG9yIChDbGFzc0RlY29yYXRvciB8IFByb3BlcnR5RGVjb3JhdG9yIHwgTWV0aG9kRGVjb3JhdG9yKVxuICogQHBhcmFtIHtzdHJpbmd9IFtmbGF2b3VyXSBPcHRpb25hbCBmbGF2b3VyIHBhcmFtZXRlciBmb3IgdGhlIGRlY29yYXRvciBjb250ZXh0XG4gKiBAY2xhc3NcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBDcmVhdGUgYSBuZXcgZGVjb3JhdGlvbiBmb3IgJ2NvbXBvbmVudCcgd2l0aCBkZWZhdWx0IGZsYXZvdXJcbiAqIGNvbnN0IGNvbXBvbmVudERlY29yYXRvciA9IG5ldyBEZWNvcmF0aW9uKClcbiAqICAgLmZvcignY29tcG9uZW50JylcbiAqICAgLmRlZmluZShjdXN0b21Db21wb25lbnREZWNvcmF0b3IpO1xuICpcbiAqIC8vIENyZWF0ZSBhIGZsYXZvdXJlZCBkZWNvcmF0aW9uXG4gKiBjb25zdCB2dWVDb21wb25lbnQgPSBuZXcgRGVjb3JhdGlvbigndnVlJylcbiAqICAgLmZvcignY29tcG9uZW50JylcbiAqICAgLmRlZmluZSh2dWVDb21wb25lbnREZWNvcmF0b3IpO1xuICpcbiAqIC8vIEFwcGx5IHRoZSBkZWNvcmF0aW9uXG4gKiBAY29tcG9uZW50RGVjb3JhdG9yXG4gKiBjbGFzcyBNeUNvbXBvbmVudCB7fVxuICogYGBgXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEMgYXMgQ2xpZW50XG4gKiAgIHBhcnRpY2lwYW50IEQgYXMgRGVjb3JhdGlvblxuICogICBwYXJ0aWNpcGFudCBSIGFzIEZsYXZvdXJSZXNvbHZlclxuICogICBwYXJ0aWNpcGFudCBGIGFzIERlY29yYXRvckZhY3RvcnlcbiAqXG4gKiAgIEMtPj5EOiBuZXcgRGVjb3JhdGlvbihmbGF2b3VyKVxuICogICBDLT4+RDogZm9yKGtleSlcbiAqICAgQy0+PkQ6IGRlZmluZShkZWNvcmF0b3JzKVxuICogICBELT4+RDogcmVnaXN0ZXIoa2V5LCBmbGF2b3VyLCBkZWNvcmF0b3JzKVxuICogICBELT4+RjogZGVjb3JhdG9yRmFjdG9yeShrZXksIGZsYXZvdXIpXG4gKiAgIEYtPj5SOiByZXNvbHZlKHRhcmdldClcbiAqICAgUi0tPj5GOiByZXNvbHZlZCBmbGF2b3VyXG4gKiAgIEYtPj5GOiBhcHBseSBkZWNvcmF0b3JzXG4gKiAgIEYtLT4+QzogZGVjb3JhdGVkIHRhcmdldFxuICovXG5leHBvcnQgY2xhc3MgRGVjb3JhdGlvbiBpbXBsZW1lbnRzIElEZWNvcmF0aW9uQnVpbGRlciB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3RhdGljIG1hcCBvZiByZWdpc3RlcmVkIGRlY29yYXRvcnNcbiAgICogQHN1bW1hcnkgU3RvcmVzIGFsbCByZWdpc3RlcmVkIGRlY29yYXRvcnMgb3JnYW5pemVkIGJ5IGtleSBhbmQgZmxhdm91clxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZGVjb3JhdG9yczogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBSZWNvcmQ8XG4gICAgICBzdHJpbmcsXG4gICAgICB7XG4gICAgICAgIGRlY29yYXRvcnM/OiBTZXQ8RGVjb3JhdG9yRGF0YT47XG4gICAgICAgIGV4dHJhcz86IFNldDxEZWNvcmF0b3JEYXRhPjtcbiAgICAgIH1cbiAgICA+XG4gID4gPSB7fTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEZ1bmN0aW9uIHRvIHJlc29sdmUgZmxhdm91ciBmcm9tIGEgdGFyZ2V0XG4gICAqIEBzdW1tYXJ5IFJlc29sdmVyIGZ1bmN0aW9uIHRoYXQgZGV0ZXJtaW5lcyB0aGUgYXBwcm9wcmlhdGUgZmxhdm91ciBmb3IgYSBnaXZlbiB0YXJnZXRcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGZsYXZvdXJSZXNvbHZlcjogRmxhdm91clJlc29sdmVyID0gZGVmYXVsdEZsYXZvdXJSZXNvbHZlcjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldCBvZiBkZWNvcmF0b3JzIGZvciB0aGUgY3VycmVudCBjb250ZXh0XG4gICAqL1xuICBwcml2YXRlIGRlY29yYXRvcnM/OiBTZXQ8RGVjb3JhdG9yRGF0YT47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXQgb2YgYWRkaXRpb25hbCBkZWNvcmF0b3JzXG4gICAqL1xuICBwcml2YXRlIGV4dHJhcz86IFNldDxEZWNvcmF0b3JEYXRhPjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEN1cnJlbnQgZGVjb3JhdG9yIGtleVxuICAgKi9cbiAgcHJpdmF0ZSBrZXk/OiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBmbGF2b3VyOiBzdHJpbmcgPSBEZWZhdWx0Rmxhdm91cikge31cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIGtleSBmb3IgdGhlIGRlY29yYXRpb24gYnVpbGRlclxuICAgKiBAc3VtbWFyeSBJbml0aWFsaXplcyBhIG5ldyBkZWNvcmF0aW9uIGNoYWluIHdpdGggdGhlIHNwZWNpZmllZCBrZXlcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUgaWRlbnRpZmllciBmb3IgdGhlIGRlY29yYXRvclxuICAgKiBAcmV0dXJuIHtEZWNvcmF0aW9uQnVpbGRlck1pZH0gQnVpbGRlciBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nXG4gICAqL1xuICBmb3Ioa2V5OiBzdHJpbmcpOiBEZWNvcmF0aW9uQnVpbGRlck1pZCB7XG4gICAgdGhpcy5rZXkgPSBrZXk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFkZHMgZGVjb3JhdG9ycyB0byB0aGUgY3VycmVudCBjb250ZXh0XG4gICAqIEBzdW1tYXJ5IEludGVybmFsIG1ldGhvZCB0byBhZGQgZGVjb3JhdG9ycyB3aXRoIGFkZG9uIHN1cHBvcnRcbiAgICogQHBhcmFtIHtib29sZWFufSBbYWRkb249ZmFsc2VdIFdoZXRoZXIgdGhlIGRlY29yYXRvcnMgYXJlIGFkZG9uc1xuICAgKiBAcGFyYW0gZGVjb3JhdG9ycyBBcnJheSBvZiBkZWNvcmF0b3JzXG4gICAqIEByZXR1cm4ge3RoaXN9IEN1cnJlbnQgaW5zdGFuY2UgZm9yIGNoYWluaW5nXG4gICAqL1xuICBwcml2YXRlIGRlY29yYXRlKFxuICAgIGFkZG9uOiBib29sZWFuID0gZmFsc2UsXG4gICAgLi4uZGVjb3JhdG9yczogRGVjb3JhdG9yRGF0YVtdXG4gICk6IHRoaXMge1xuICAgIGlmICghdGhpcy5rZXkpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJrZXkgbXVzdCBiZSBwcm92aWRlZCBiZWZvcmUgZGVjb3JhdG9ycyBjYW4gYmUgYWRkZWRcIik7XG4gICAgaWYgKFxuICAgICAgKCFkZWNvcmF0b3JzIHx8ICFkZWNvcmF0b3JzLmxlbmd0aCkgJiZcbiAgICAgICFhZGRvbiAmJlxuICAgICAgdGhpcy5mbGF2b3VyICE9PSBEZWZhdWx0Rmxhdm91clxuICAgIClcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJNdXN0IHByb3ZpZGUgb3ZlcnJpZGVzIG9yIGFkZG9ucyB0byBvdmVycmlkZSBvciBleHRlbmQgZGVjYWYncyBkZWNvcmF0b3JzXCJcbiAgICAgICk7XG4gICAgaWYgKHRoaXMuZmxhdm91ciA9PT0gRGVmYXVsdEZsYXZvdXIgJiYgYWRkb24pXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJEZWZhdWx0IGZsYXZvdXIgY2Fubm90IGJlIGV4dGVuZGVkXCIpO1xuXG4gICAgdGhpc1thZGRvbiA/IFwiZXh0cmFzXCIgOiBcImRlY29yYXRvcnNcIl0gPSBuZXcgU2V0KFtcbiAgICAgIC4uLih0aGlzW2FkZG9uID8gXCJleHRyYXNcIiA6IFwiZGVjb3JhdG9yc1wiXSB8fCBuZXcgU2V0KCkpLnZhbHVlcygpLFxuICAgICAgLi4uZGVjb3JhdG9ycyxcbiAgICBdKTtcblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWZpbmVzIHRoZSBiYXNlIGRlY29yYXRvcnNcbiAgICogQHN1bW1hcnkgU2V0cyB0aGUgcHJpbWFyeSBkZWNvcmF0b3JzIGZvciB0aGUgY3VycmVudCBjb250ZXh0XG4gICAqIEBwYXJhbSBkZWNvcmF0b3JzIERlY29yYXRvcnMgdG8gZGVmaW5lXG4gICAqIEByZXR1cm4gQnVpbGRlciBpbnN0YW5jZSBmb3IgZmluaXNoaW5nIHRoZSBjaGFpblxuICAgKi9cbiAgZGVmaW5lKFxuICAgIC4uLmRlY29yYXRvcnM6IERlY29yYXRvckRhdGFbXVxuICApOiBEZWNvcmF0aW9uQnVpbGRlckVuZCAmIERlY29yYXRpb25CdWlsZGVyQnVpbGQge1xuICAgIHJldHVybiB0aGlzLmRlY29yYXRlKGZhbHNlLCAuLi5kZWNvcmF0b3JzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXh0ZW5kcyBleGlzdGluZyBkZWNvcmF0b3JzXG4gICAqIEBzdW1tYXJ5IEFkZHMgYWRkaXRpb25hbCBkZWNvcmF0b3JzIHRvIHRoZSBjdXJyZW50IGNvbnRleHRcbiAgICogQHBhcmFtIGRlY29yYXRvcnMgQWRkaXRpb25hbCBkZWNvcmF0b3JzXG4gICAqIEByZXR1cm4ge0RlY29yYXRpb25CdWlsZGVyQnVpbGR9IEJ1aWxkZXIgaW5zdGFuY2UgZm9yIGJ1aWxkaW5nIHRoZSBkZWNvcmF0b3JcbiAgICovXG4gIGV4dGVuZCguLi5kZWNvcmF0b3JzOiBEZWNvcmF0b3JEYXRhW10pOiBEZWNvcmF0aW9uQnVpbGRlckJ1aWxkIHtcbiAgICByZXR1cm4gdGhpcy5kZWNvcmF0ZSh0cnVlLCAuLi5kZWNvcmF0b3JzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRmFjdG9yeSB0aGF0IGNyZWF0ZXMgYSBjb250ZXh0LWF3YXJlIGRlY29yYXRvciBmb3IgYSBrZXkvZmxhdm91clxuICAgKiBAc3VtbWFyeSBQcm9kdWNlcyBhIGRlY29yYXRvciBmdW5jdGlvbiBib3VuZCB0byB0aGUgcHJvdmlkZWQga2V5IGFuZCBmbGF2b3VyLiBUaGUgcmVzdWx0aW5nIGRlY29yYXRvciByZXNvbHZlcyB0aGUgYWN0dWFsXG4gICAqIGRlY29yYXRvcnMgdG8gYXBwbHkgYXQgaW52b2NhdGlvbiB0aW1lIGJhc2VkIG9uIHRoZSB0YXJnZXQncyByZXNvbHZlZCBmbGF2b3VyIGFuZCB0aGUgcmVnaXN0ZXJlZCBiYXNlIGFuZCBleHRyYSBkZWNvcmF0b3JzLlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBkZWNvcmF0aW9uIGtleSB1c2VkIHRvIGxvb2sgdXAgcmVnaXN0ZXJlZCBkZWNvcmF0b3JzXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbZj1EZWZhdWx0Rmxhdm91cl0gT3B0aW9uYWwgZXhwbGljaXQgZmxhdm91ciB0byBiaW5kIHRoZSBmYWN0b3J5IHRvXG4gICAqIEByZXR1cm4ge2Z1bmN0aW9uKG9iamVjdCwgYW55LCBUeXBlZFByb3BlcnR5RGVzY3JpcHRvcjxhbnk+KTogYW55fSBBIGRlY29yYXRvciBmdW5jdGlvbiB0aGF0IGFwcGxpZXMgdGhlIHJlc29sdmVkIGRlY29yYXRvcnNcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgVSBhcyBVc2VyIENvZGVcbiAgICogICBwYXJ0aWNpcGFudCBCIGFzIERlY29yYXRpb24gKGJ1aWxkZXIpXG4gICAqICAgcGFydGljaXBhbnQgRiBhcyBkZWNvcmF0b3JGYWN0b3J5KGtleSwgZilcbiAgICogICBwYXJ0aWNpcGFudCBSIGFzIGZsYXZvdXJSZXNvbHZlclxuICAgKiAgIHBhcnRpY2lwYW50IEEgYXMgQXBwbGllZCBEZWNvcmF0b3JzXG4gICAqICAgVS0+PkI6IGRlZmluZSgpL2V4dGVuZCgpIGFuZCBhcHBseSgpXG4gICAqICAgQi0+PkY6IGNyZWF0ZSBjb250ZXh0IGRlY29yYXRvclxuICAgKiAgIEYtPj5SOiByZXNvbHZlKHRhcmdldClcbiAgICogICBSLS0+PkY6IGZsYXZvdXJcbiAgICogICBGLT4+QTogY29sbGVjdCBiYXNlICsgZXh0cmFzXG4gICAqICAgbG9vcCBlYWNoIGRlY29yYXRvclxuICAgKiAgICAgQS0+PlU6IGludm9rZSBkZWNvcmF0b3IodGFyZ2V0LCBrZXk/LCBkZXNjPylcbiAgICogICBlbmRcbiAgICovXG4gIHByb3RlY3RlZCBkZWNvcmF0b3JGYWN0b3J5KGtleTogc3RyaW5nLCBmOiBzdHJpbmcgPSBEZWZhdWx0Rmxhdm91cikge1xuICAgIGZ1bmN0aW9uIGNvbnRleHREZWNvcmF0b3IoXG4gICAgICB0YXJnZXQ6IG9iamVjdCxcbiAgICAgIHByb3BlcnR5S2V5PzogYW55LFxuICAgICAgZGVzY3JpcHRvcj86IFR5cGVkUHJvcGVydHlEZXNjcmlwdG9yPGFueT5cbiAgICApIHtcbiAgICAgIGNvbnN0IGZsYXZvdXIgPSBEZWNvcmF0aW9uLmZsYXZvdXJSZXNvbHZlcih0YXJnZXQpO1xuICAgICAgY29uc3QgY2FjaGUgPSBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XTtcbiAgICAgIGxldCBkZWNvcmF0b3JzO1xuICAgICAgY29uc3QgZXh0cmFzID0gY2FjaGVbZmxhdm91cl1cbiAgICAgICAgPyBjYWNoZVtmbGF2b3VyXS5leHRyYXNcbiAgICAgICAgOiBjYWNoZVtEZWZhdWx0Rmxhdm91cl0uZXh0cmFzO1xuICAgICAgY29uc3QgZXh0cmFBcmdzID0gW1xuICAgICAgICAuLi4oKGNhY2hlW0RlZmF1bHRGbGF2b3VyXSBhcyBhbnkpLmV4dHJhc1xuICAgICAgICAgID8gKGNhY2hlW0RlZmF1bHRGbGF2b3VyXSBhcyBhbnkpLmV4dHJhcy52YWx1ZXMoKVxuICAgICAgICAgIDogW10pLFxuICAgICAgXS5yZWR1Y2UoKGFjY3VtOiBSZWNvcmQ8bnVtYmVyLCBhbnk+LCBlLCBpKSA9PiB7XG4gICAgICAgIGlmIChlLmFyZ3MpIGFjY3VtW2ldID0gZS5hcmdzO1xuICAgICAgICByZXR1cm4gYWNjdW07XG4gICAgICB9LCB7fSk7XG5cbiAgICAgIGlmIChcbiAgICAgICAgY2FjaGUgJiZcbiAgICAgICAgY2FjaGVbZmxhdm91cl0gJiZcbiAgICAgICAgY2FjaGVbZmxhdm91cl0uZGVjb3JhdG9ycyAmJlxuICAgICAgICBjYWNoZVtmbGF2b3VyXS5kZWNvcmF0b3JzLnNpemVcbiAgICAgICkge1xuICAgICAgICBkZWNvcmF0b3JzID0gY2FjaGVbZmxhdm91cl0uZGVjb3JhdG9ycztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlY29yYXRvcnMgPSBjYWNoZVtEZWZhdWx0Rmxhdm91cl0uZGVjb3JhdG9ycztcbiAgICAgIH1cblxuICAgICAgY29uc3QgZGVjb3JhdG9yQXJncyA9IFtcbiAgICAgICAgLi4uKGNhY2hlW0RlZmF1bHRGbGF2b3VyXSBhcyBhbnkpLmRlY29yYXRvcnMudmFsdWVzKCksXG4gICAgICBdLnJlZHVjZSgoYWNjdW06IFJlY29yZDxudW1iZXIsIGFueT4sIGUsIGkpID0+IHtcbiAgICAgICAgaWYgKGUuYXJncykgYWNjdW1baV0gPSBlLmFyZ3M7XG4gICAgICAgIHJldHVybiBhY2N1bTtcbiAgICAgIH0sIHt9KTtcblxuICAgICAgY29uc3QgdG9BcHBseSA9IFtcbiAgICAgICAgLi4uKGRlY29yYXRvcnMgPyBkZWNvcmF0b3JzLnZhbHVlcygpIDogW10pLFxuICAgICAgICAuLi4oZXh0cmFzID8gZXh0cmFzLnZhbHVlcygpIDogW10pLFxuICAgICAgXTtcblxuICAgICAgcmV0dXJuIHRvQXBwbHkucmVkdWNlKFxuICAgICAgICAoXywgZCwgaSkgPT4ge1xuICAgICAgICAgIHN3aXRjaCAodHlwZW9mIGQpIHtcbiAgICAgICAgICAgIGNhc2UgXCJvYmplY3RcIjoge1xuICAgICAgICAgICAgICBjb25zdCB7IGRlY29yYXRvciwgYXJncyB9ID0gZCBhcyBEZWNvcmF0b3JGYWN0b3J5QXJncztcbiAgICAgICAgICAgICAgY29uc3QgYXJneiA9XG4gICAgICAgICAgICAgICAgYXJncyB8fCBpIDwgKGRlY29yYXRvcnMgPyBkZWNvcmF0b3JzLnNpemUgOiAwKVxuICAgICAgICAgICAgICAgICAgPyBkZWNvcmF0b3JBcmdzW2ldXG4gICAgICAgICAgICAgICAgICA6IGV4dHJhQXJnc1tpIC0gKGRlY29yYXRvcnMgPyBkZWNvcmF0b3JzLnNpemUgOiAwKV0gfHxcbiAgICAgICAgICAgICAgICAgICAgKGRlY29yYXRvcnMgPyBkZWNvcmF0b3JBcmdzW2kgLSBkZWNvcmF0b3JzLnNpemVdIDogW10pO1xuXG4gICAgICAgICAgICAgIHJldHVybiAoZGVjb3JhdG9yKC4uLihhcmd6IHx8IFtdKSkgYXMgYW55KShcbiAgICAgICAgICAgICAgICB0YXJnZXQsXG4gICAgICAgICAgICAgICAgcHJvcGVydHlLZXksXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRvclxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FzZSBcImZ1bmN0aW9uXCI6XG4gICAgICAgICAgICAgIHJldHVybiAoZCBhcyBhbnkpKHRhcmdldCwgcHJvcGVydHlLZXksIGRlc2NyaXB0b3IpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmV4cGVjdGVkIGRlY29yYXRvciB0eXBlOiAke3R5cGVvZiBkfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgeyB0YXJnZXQsIHByb3BlcnR5S2V5LCBkZXNjcmlwdG9yIH1cbiAgICAgICk7XG4gICAgfVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjb250ZXh0RGVjb3JhdG9yLCBcIm5hbWVcIiwge1xuICAgICAgdmFsdWU6IFtmLCBrZXldLmpvaW4oXCJfZGVjb3JhdG9yX2Zvcl9cIiksXG4gICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgfSk7XG4gICAgcmV0dXJuIGNvbnRleHREZWNvcmF0b3I7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgdGhlIGZpbmFsIGRlY29yYXRvciBmdW5jdGlvblxuICAgKiBAc3VtbWFyeSBCdWlsZHMgYW5kIHJldHVybnMgdGhlIGRlY29yYXRvciBmYWN0b3J5IGZ1bmN0aW9uXG4gICAqIEByZXR1cm4ge2Z1bmN0aW9uKGFueSwgYW55PywgVHlwZWRQcm9wZXJ0eURlc2NyaXB0b3I/KTogYW55fSBUaGUgZ2VuZXJhdGVkIGRlY29yYXRvciBmdW5jdGlvblxuICAgKi9cbiAgYXBwbHkoKTogKFxuICAgIHRhcmdldDogYW55LFxuICAgIHByb3BlcnR5S2V5PzogYW55LFxuICAgIGRlc2NyaXB0b3I/OiBUeXBlZFByb3BlcnR5RGVzY3JpcHRvcjxhbnk+XG4gICkgPT4gYW55IHtcbiAgICBpZiAoIXRoaXMua2V5KVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8ga2V5IHByb3ZpZGVkIGZvciB0aGUgZGVjb3JhdGlvbiBidWlsZGVyXCIpO1xuICAgIERlY29yYXRpb24ucmVnaXN0ZXIoXG4gICAgICB0aGlzLmtleSxcbiAgICAgIHRoaXMuZmxhdm91cixcbiAgICAgIHRoaXMuZGVjb3JhdG9ycyB8fCBuZXcgU2V0KCksXG4gICAgICB0aGlzLmV4dHJhc1xuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuZGVjb3JhdG9yRmFjdG9yeSh0aGlzLmtleSwgdGhpcy5mbGF2b3VyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVnaXN0ZXJzIGRlY29yYXRvcnMgZm9yIGEgc3BlY2lmaWMga2V5IGFuZCBmbGF2b3VyXG4gICAqIEBzdW1tYXJ5IEludGVybmFsIG1ldGhvZCB0byBzdG9yZSBkZWNvcmF0b3JzIGluIHRoZSBzdGF0aWMgcmVnaXN0cnlcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBEZWNvcmF0b3Iga2V5XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmbGF2b3VyIERlY29yYXRvciBmbGF2b3VyXG4gICAqIEBwYXJhbSBbZGVjb3JhdG9yc10gUHJpbWFyeSBkZWNvcmF0b3JzXG4gICAqIEBwYXJhbSBbZXh0cmFzXSBBZGRpdGlvbmFsIGRlY29yYXRvcnNcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHJlZ2lzdGVyKFxuICAgIGtleTogc3RyaW5nLFxuICAgIGZsYXZvdXI6IHN0cmluZyxcbiAgICBkZWNvcmF0b3JzPzogU2V0PERlY29yYXRvckRhdGE+LFxuICAgIGV4dHJhcz86IFNldDxEZWNvcmF0b3JEYXRhPlxuICApIHtcbiAgICBpZiAoIWtleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8ga2V5IHByb3ZpZGVkIGZvciB0aGUgZGVjb3JhdGlvbiBidWlsZGVyXCIpO1xuICAgIH1cbiAgICBpZiAoIWRlY29yYXRvcnMpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBkZWNvcmF0b3JzIHByb3ZpZGVkIGZvciB0aGUgZGVjb3JhdGlvbiBidWlsZGVyXCIpO1xuICAgIGlmICghZmxhdm91cilcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGZsYXZvdXIgcHJvdmlkZWQgZm9yIHRoZSBkZWNvcmF0aW9uIGJ1aWxkZXJcIik7XG5cbiAgICBpZiAoIURlY29yYXRpb24uZGVjb3JhdG9yc1trZXldKSBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XSA9IHt9O1xuICAgIGlmICghRGVjb3JhdGlvbi5kZWNvcmF0b3JzW2tleV1bZmxhdm91cl0pXG4gICAgICBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXSA9IHt9O1xuICAgIGlmIChkZWNvcmF0b3JzKSBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXS5kZWNvcmF0b3JzID0gZGVjb3JhdG9ycztcbiAgICBpZiAoZXh0cmFzKSBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXS5leHRyYXMgPSBleHRyYXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIGdsb2JhbCBmbGF2b3VyIHJlc29sdmVyXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIGZ1bmN0aW9uIHVzZWQgdG8gZGV0ZXJtaW5lIGRlY29yYXRvciBmbGF2b3Vyc1xuICAgKiBAcGFyYW0ge0ZsYXZvdXJSZXNvbHZlcn0gcmVzb2x2ZXIgRnVuY3Rpb24gdG8gcmVzb2x2ZSBmbGF2b3Vyc1xuICAgKi9cbiAgc3RhdGljIHNldEZsYXZvdXJSZXNvbHZlcihyZXNvbHZlcjogRmxhdm91clJlc29sdmVyKSB7XG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyUmVzb2x2ZXIgPSByZXNvbHZlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ29udmVuaWVuY2Ugc3RhdGljIGVudHJ5IHRvIHN0YXJ0IGEgZGVjb3JhdGlvbiBidWlsZGVyXG4gICAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBuZXcgRGVjb3JhdGlvbiBpbnN0YW5jZSBhbmQgaW5pdGlhdGVzIHRoZSBidWlsZGVyIGNoYWluIHdpdGggdGhlIHByb3ZpZGVkIGtleS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUgZGVjb3JhdGlvbiBrZXkgdG8gY29uZmlndXJlXG4gICAqIEByZXR1cm4ge0RlY29yYXRpb25CdWlsZGVyTWlkfSBBIGJ1aWxkZXIgaW5zdGFuY2UgZm9yIGNoYWluaW5nIGRlZmluaXRpb25zXG4gICAqL1xuICBzdGF0aWMgZm9yKGtleTogc3RyaW5nKTogRGVjb3JhdGlvbkJ1aWxkZXJNaWQge1xuICAgIHJldHVybiBuZXcgRGVjb3JhdGlvbigpLmZvcihrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTdGFydHMgYSBidWlsZGVyIGZvciBhIHNwZWNpZmljIGZsYXZvdXJcbiAgICogQHN1bW1hcnkgQ29udmVuaWVuY2UgbWV0aG9kIHRvIGJlZ2luIGEgRGVjb3JhdGlvbiBidWlsZGVyIGNoYWluIGJvdW5kIHRvIHRoZSBnaXZlbiBmbGF2b3VyIGlkZW50aWZpZXIsIGFsbG93aW5nIHJlZ2lzdHJhdGlvbiBvZiBmbGF2b3VyLXNwZWNpZmljIGRlY29yYXRvcnMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmbGF2b3VyIFRoZSBmbGF2b3VyIG5hbWUgdG8gYmluZCB0byB0aGUgYnVpbGRlclxuICAgKiBAcmV0dXJuIHtEZWNvcmF0aW9uQnVpbGRlclN0YXJ0fSBBIGJ1aWxkZXIgc3RhcnQgaW50ZXJmYWNlIHRvIGNvbnRpbnVlIGNvbmZpZ3VyYXRpb25cbiAgICovXG4gIHN0YXRpYyBmbGF2b3VyZWRBcyhmbGF2b3VyOiBzdHJpbmcpOiBEZWNvcmF0aW9uQnVpbGRlclN0YXJ0IHtcbiAgICByZXR1cm4gbmV3IERlY29yYXRpb24oZmxhdm91cik7XG4gIH1cbn1cbiIsImltcG9ydCB7IEJhc2ljTWV0YWRhdGEsIENvbnN0cnVjdG9yIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IERlY29yYXRpb25LZXlzLCBPYmplY3RLZXlTcGxpdHRlciB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcbmltcG9ydCBcInJlZmxlY3QtbWV0YWRhdGFcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGEgbmVzdGVkIHZhbHVlIGZyb20gYW4gb2JqZWN0IGdpdmVuIGEgcGF0aFxuICogQHN1bW1hcnkgV2Fsa3MgYW4gb2JqZWN0IHN0cnVjdHVyZSB1c2luZyBhIHNwbGl0dGVyLWRlbGltaXRlZCBwYXRoIGFuZCByZXR1cm5zIHRoZSB2YWx1ZSBhdCB0aGF0IGxvY2F0aW9uIG9yIHVuZGVmaW5lZCBpZiBhbnkga2V5IGlzIG1pc3NpbmcuXG4gKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IG9iaiBUaGUgb2JqZWN0IHRvIHRyYXZlcnNlXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCBUaGUgcGF0aCB0byB0aGUgZGVzaXJlZCB2YWx1ZSAoZS5nLiwgXCJhLmIuY1wiKVxuICogQHBhcmFtIHtzdHJpbmd9IFtzcGxpdHRlcj1PYmplY3RLZXlTcGxpdHRlcl0gVGhlIGRlbGltaXRlciB1c2VkIHRvIHNwbGl0IHRoZSBwYXRoXG4gKiBAcmV0dXJuIHsqfSBUaGUgcmVzb2x2ZWQgdmFsdWUgYXQgdGhlIGdpdmVuIHBhdGggb3IgdW5kZWZpbmVkIGlmIG5vdCBmb3VuZFxuICogQGZ1bmN0aW9uIGdldFZhbHVlQnlTcGxpdHRlclxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDIGFzIENhbGxlclxuICogICBwYXJ0aWNpcGFudCBGIGFzIGdldFZhbHVlQnlTcGxpdHRlclxuICogICBwYXJ0aWNpcGFudCBPIGFzIE9iamVjdFxuICogICBDLT4+RjogKG9iaiwgcGF0aCwgc3BsaXR0ZXIpXG4gKiAgIEYtPj5GOiBzcGxpdCBwYXRoIGludG8ga2V5c1xuICogICBsb29wIGZvciBlYWNoIGtleVxuICogICAgIEYtPj5POiBhY2Nlc3MgY3VycmVudFtrZXldXG4gKiAgICAgYWx0IG1pc3Npbmcgb3IgbnVsbGlzaFxuICogICAgICAgRi0tPj5DOiByZXR1cm4gdW5kZWZpbmVkXG4gKiAgICAgZW5kXG4gKiAgIGVuZFxuICogICBGLS0+PkM6IHJldHVybiBmaW5hbCB2YWx1ZVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmZ1bmN0aW9uIGdldFZhbHVlQnlTcGxpdHRlcihcbiAgb2JqOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICBwYXRoOiBzdHJpbmcsXG4gIHNwbGl0dGVyOiBzdHJpbmcgPSBPYmplY3RLZXlTcGxpdHRlclxuKTogYW55IHtcbiAgY29uc3Qga2V5cyA9IHBhdGguc3BsaXQoc3BsaXR0ZXIpO1xuICBsZXQgY3VycmVudCA9IG9iajtcblxuICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7XG4gICAgaWYgKFxuICAgICAgY3VycmVudCA9PT0gbnVsbCB8fFxuICAgICAgY3VycmVudCA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGN1cnJlbnQsIGtleSlcbiAgICApXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGN1cnJlbnQgPSBjdXJyZW50W2tleV07XG4gIH1cblxuICByZXR1cm4gY3VycmVudDtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU2V0cyBhIG5lc3RlZCB2YWx1ZSBvbiBhbiBvYmplY3QgZ2l2ZW4gYSBwYXRoXG4gKiBAc3VtbWFyeSBUcmF2ZXJzZXMgb3IgY3JlYXRlcyBpbnRlcm1lZGlhdGUgb2JqZWN0cyBmb2xsb3dpbmcgYSBzcGxpdHRlci1kZWxpbWl0ZWQgcGF0aCBhbmQgYXNzaWducyB0aGUgcHJvdmlkZWQgdmFsdWUgYXQgdGhlIGRlc3RpbmF0aW9uIGtleS5cbiAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gb2JqIFRoZSBvYmplY3QgdG8gbXV0YXRlXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCBUaGUgZGVzdGluYXRpb24gcGF0aCAoZS5nLiwgXCJhLmIuY1wiKVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0IGF0IHRoZSBkZXN0aW5hdGlvblxuICogQHBhcmFtIHtzdHJpbmd9IFtzcGxpdHRlcj1PYmplY3RLZXlTcGxpdHRlcl0gVGhlIGRlbGltaXRlciB1c2VkIHRvIHNwbGl0IHRoZSBwYXRoXG4gKiBAcmV0dXJuIHt2b2lkfVxuICogQGZ1bmN0aW9uIHNldFZhbHVlQnlTcGxpdHRlclxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDIGFzIENhbGxlclxuICogICBwYXJ0aWNpcGFudCBGIGFzIHNldFZhbHVlQnlTcGxpdHRlclxuICogICBwYXJ0aWNpcGFudCBPIGFzIE9iamVjdFxuICogICBDLT4+RjogKG9iaiwgcGF0aCwgdmFsdWUsIHNwbGl0dGVyKVxuICogICBGLT4+Rjogc3BsaXQgcGF0aCBpbnRvIGtleXNcbiAqICAgbG9vcCBmb3IgZWFjaCBrZXlcbiAqICAgICBhbHQga2V5IG1pc3NpbmdcbiAqICAgICAgIEYtPj5POiBjcmVhdGUgaW50ZXJtZWRpYXRlIG9iamVjdFxuICogICAgIGVsc2Uga2V5IGV4aXN0c1xuICogICAgICAgRi0+Pk86IGRlc2NlbmQgaW50byBleGlzdGluZyBvYmplY3RcbiAqICAgICBlbmRcbiAqICAgZW5kXG4gKiAgIEYtLT4+Qzogdm9pZFxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmZ1bmN0aW9uIHNldFZhbHVlQnlTcGxpdHRlcihcbiAgb2JqOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICBwYXRoOiBzdHJpbmcsXG4gIHZhbHVlOiBhbnksXG4gIHNwbGl0dGVyID0gT2JqZWN0S2V5U3BsaXR0ZXJcbik6IHZvaWQge1xuICBjb25zdCBrZXlzID0gcGF0aC5zcGxpdChzcGxpdHRlcikuZmlsdGVyKChrKSA9PiBrLmxlbmd0aCA+IDApO1xuICBpZiAoa2V5cy5sZW5ndGggPT09IDApIHJldHVybjtcblxuICBsZXQgY3VycmVudDogUmVjb3JkPGFueSwgYW55PiA9IG9iajtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGtleXMubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgY29uc3Qga2V5ID0ga2V5c1tpXTtcbiAgICBpZiAoXG4gICAgICBjdXJyZW50W2tleV0gPT09IHVuZGVmaW5lZCB8fFxuICAgICAgY3VycmVudFtrZXldID09PSBudWxsIHx8XG4gICAgICB0eXBlb2YgY3VycmVudFtrZXldICE9PSBcIm9iamVjdFwiXG4gICAgKSB7XG4gICAgICBjdXJyZW50W2tleV0gPSB7fTtcbiAgICB9XG4gICAgY3VycmVudCA9IGN1cnJlbnRba2V5XTtcbiAgfVxuXG4gIGNvbnN0IGxhc3RLZXkgPSBrZXlzW2tleXMubGVuZ3RoIC0gMV07XG4gIGN1cnJlbnRbbGFzdEtleV0gPSB2YWx1ZTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ2VudHJhbGl6ZWQgcnVudGltZSBtZXRhZGF0YSBzdG9yZSBib3VuZCB0byBjb25zdHJ1Y3RvcnNcbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIHV0aWxpdGllcyB0byByZWFkIGFuZCB3cml0ZSBzdHJ1Y3R1cmVkIG1ldGFkYXRhIGZvciBjbGFzc2VzIGFuZCB0aGVpciBtZW1iZXJzLCB3aXRoIG9wdGlvbmFsIG1pcnJvcmluZyBvbnRvIHRoZSBjb25zdHJ1Y3RvciB2aWEgYSB3ZWxsLWtub3duIHN5bWJvbCBrZXkuIFN1cHBvcnRzIG5lc3RlZCBrZXkgcGF0aHMgdXNpbmcgYSBjb25maWd1cmFibGUgc3BsaXR0ZXIgYW5kIG9mZmVycyBib3RoIGluc3RhbmNlIGFuZCBzdGF0aWMgQVBJcy5cbiAqIEB0ZW1wbGF0ZSBNIFRoZSBtb2RlbCB0eXBlIHRoZSBtZXRhZGF0YSBiZWxvbmdzIHRvXG4gKiBAdGVtcGxhdGUgTUVUQSBFeHRlbmRzIEJhc2ljTWV0YWRhdGE8TT4gcmVwcmVzZW50aW5nIHRoZSBtZXRhZGF0YSBzdHJ1Y3R1cmVcbiAqIEBjbGFzc1xuICogQGV4YW1wbGVcbiAqIC8vIERlZmluZSBhbmQgcmVhZCBtZXRhZGF0YSBmb3IgYSBjbGFzc1xuICogY2xhc3MgVXNlciB7IG5hbWUhOiBzdHJpbmcgfVxuICogTWV0YWRhdGEuc2V0KFVzZXIsIFwiZGVzY3JpcHRpb24uY2xhc3NcIiwgXCJBIHVzZXIgbW9kZWxcIik7XG4gKiBNZXRhZGF0YS5zZXQoVXNlciwgXCJwcm9wZXJ0aWVzLm5hbWVcIiwgU3RyaW5nKTtcbiAqIGNvbnN0IGRlc2MgPSBNZXRhZGF0YS5nZXQoVXNlciwgXCJkZXNjcmlwdGlvbi5jbGFzc1wiKTsgLy8gXCJBIHVzZXIgbW9kZWxcIlxuICogY29uc3QgdHlwZSA9IE1ldGFkYXRhLnR5cGUoVXNlciwgXCJuYW1lXCIpOyAvLyBTdHJpbmdcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQyBhcyBDb25zdHJ1Y3RvclxuICogICBwYXJ0aWNpcGFudCBTIGFzIE1ldGFkYXRhIChzdGF0aWMpXG4gKiAgIEMtPj5TOiBzZXQoVXNlciwgXCJwcm9wZXJ0aWVzLm5hbWVcIiwgU3RyaW5nKVxuICogICBDLT4+UzogZ2V0KFVzZXIsIFwicHJvcGVydGllcy5uYW1lXCIpXG4gKiAgIFMtLT4+QzogU3RyaW5nXG4gKi9cbmV4cG9ydCBjbGFzcyBNZXRhZGF0YSB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSW4tbWVtb3J5IHN0b3JhZ2Ugb2YgbWV0YWRhdGEgYnkgY29uc3RydWN0b3Igc3ltYm9sXG4gICAqIEBzdW1tYXJ5IE1hcHMgYSBTeW1ib2wgZGVyaXZlZCBmcm9tIHRoZSBjb25zdHJ1Y3RvciB0byBpdHMgbWV0YWRhdGEgb2JqZWN0LCBlbmFibGluZyBlZmZpY2llbnQgbG9va3VwLlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgX21ldGFkYXRhOiBSZWNvcmQ8c3ltYm9sLCBhbnk+ID0ge307XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQYXRoIGRlbGltaXRlciBmb3IgbmVzdGVkIG1ldGFkYXRhIGtleXNcbiAgICogQHN1bW1hcnkgVXNlZCBieSBnZXQvc2V0IG9wZXJhdGlvbnMgdG8gbmF2aWdhdGUgbmVzdGVkIHN0cnVjdHVyZXMsIGRlZmF1bHRzIHRvIE9iamVjdEtleVNwbGl0dGVyLlxuICAgKi9cbiAgc3RhdGljIHNwbGl0dGVyID0gT2JqZWN0S2V5U3BsaXR0ZXI7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3ltYm9sIGtleSB1c2VkIHRvIG1pcnJvciBtZXRhZGF0YSBvbiB0aGUgY29uc3RydWN0b3JcbiAgICogQHN1bW1hcnkgV2hlbiBtaXJyb3JpbmcgaXMgZW5hYmxlZCwgdGhlIG1ldGFkYXRhIG9iamVjdCBpcyBkZWZpbmVkIG9uIHRoZSBjb25zdHJ1Y3RvciB1bmRlciB0aGlzIG5vbi1lbnVtZXJhYmxlIGtleS5cbiAgICovXG4gIHN0YXRpYyBiYXNlS2V5ID0gRGVjb3JhdGlvbktleXMuUkVGTEVDVDtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDb250cm9scyB3aGV0aGVyIG1ldGFkYXRhIGlzIG1pcnJvcmVkIG9udG8gdGhlIGNvbnN0cnVjdG9yXG4gICAqIEBzdW1tYXJ5IFdoZW4gdHJ1ZSwgdGhlIG1ldGFkYXRhIG9iamVjdCBpcyBkZWZpbmVkIG9uIHRoZSBjb25zdHJ1Y3RvciB1bmRlciB0aGUgbm9uLWVudW1lcmFibGUgYmFzZUtleS5cbiAgICovXG4gIHN0YXRpYyBtaXJyb3I6IGJvb2xlYW4gPSB0cnVlO1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoKSB7fVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTGlzdHMga25vd24gcHJvcGVydHkga2V5cyBmb3IgYSBtb2RlbFxuICAgKiBAc3VtbWFyeSBSZWFkcyB0aGUgbWV0YWRhdGEgZW50cnkgYW5kIHJldHVybnMgdGhlIG5hbWVzIG9mIHByb3BlcnRpZXMgdGhhdCBoYXZlIHJlY29yZGVkIHR5cGUgaW5mb3JtYXRpb24uXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3J9IG1vZGVsIFRoZSB0YXJnZXQgY29uc3RydWN0b3JcbiAgICogQHJldHVybiB7c3RyaW5nW118dW5kZWZpbmVkfSBBcnJheSBvZiBwcm9wZXJ0eSBuYW1lcyBvciB1bmRlZmluZWQgaWYgbm8gbWV0YWRhdGEgZXhpc3RzXG4gICAqL1xuICBzdGF0aWMgcHJvcGVydGllcyhtb2RlbDogQ29uc3RydWN0b3IpOiBzdHJpbmdbXSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgbWV0YSA9IHRoaXMuZ2V0KG1vZGVsKTtcbiAgICBpZiAoIW1ldGEpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKG1ldGEucHJvcGVydGllcyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhIGh1bWFuLXJlYWRhYmxlIGRlc2NyaXB0aW9uIGZvciBhIGNsYXNzIG9yIGEgcHJvcGVydHlcbiAgICogQHN1bW1hcnkgTG9va3MgdXAgdGhlIGRlc2NyaXB0aW9uIHN0b3JlZCB1bmRlciB0aGUgbWV0YWRhdGEgXCJkZXNjcmlwdGlvblwiIG1hcC4gSWYgYSBwcm9wZXJ0eSBrZXkgaXMgcHJvdmlkZWQsIHJldHVybnMgdGhlIHByb3BlcnR5J3MgZGVzY3JpcHRpb247IG90aGVyd2lzZSByZXR1cm5zIHRoZSBjbGFzcyBkZXNjcmlwdGlvbi5cbiAgICogQHRlbXBsYXRlIE1cbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gbW9kZWwgVGhlIHRhcmdldCBjb25zdHJ1Y3RvciB3aG9zZSBkZXNjcmlwdGlvbiBpcyBiZWluZyByZXRyaWV2ZWRcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtwcm9wXSBPcHRpb25hbCBwcm9wZXJ0eSBrZXkgZm9yIHdoaWNoIHRvIGZldGNoIHRoZSBkZXNjcmlwdGlvblxuICAgKiBAcmV0dXJuIHtzdHJpbmd8dW5kZWZpbmVkfSBUaGUgZGVzY3JpcHRpb24gdGV4dCBpZiBwcmVzZW50LCBvdGhlcndpc2UgdW5kZWZpbmVkXG4gICAqL1xuICBzdGF0aWMgZGVzY3JpcHRpb248TT4obW9kZWw6IENvbnN0cnVjdG9yPE0+LCBwcm9wPzoga2V5b2YgTSkge1xuICAgIHJldHVybiB0aGlzLmdldChcbiAgICAgIG1vZGVsLFxuICAgICAgW0RlY29yYXRpb25LZXlzLkRFU0NSSVBUSU9OLCBwcm9wID8gcHJvcCA6IERlY29yYXRpb25LZXlzLkNMQVNTXS5qb2luKFxuICAgICAgICBPYmplY3RLZXlTcGxpdHRlclxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyB0aGUgcmVjb3JkZWQgZGVzaWduIHR5cGUgZm9yIGEgcHJvcGVydHlcbiAgICogQHN1bW1hcnkgUmVhZHMgdGhlIG1ldGFkYXRhIGVudHJ5IHVuZGVyIFwicHJvcGVydGllcy48cHJvcD5cIiB0byByZXR1cm4gdGhlIGNvbnN0cnVjdG9yIHJlY29yZGVkIGZvciB0aGUgZ2l2ZW4gcHJvcGVydHkgbmFtZS5cbiAgICogQHBhcmFtIHtDb25zdHJ1Y3Rvcn0gbW9kZWwgVGhlIHRhcmdldCBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge3N0cmluZ30gcHJvcCBUaGUgcHJvcGVydHkgbmFtZSB3aG9zZSB0eXBlIHNob3VsZCBiZSByZXR1cm5lZFxuICAgKiBAcmV0dXJuIHtDb25zdHJ1Y3Rvcnx1bmRlZmluZWR9IFRoZSBjb25zdHJ1Y3RvciByZWZlcmVuY2Ugb2YgdGhlIHByb3BlcnR5IHR5cGUgb3IgdW5kZWZpbmVkIGlmIG5vdCBhdmFpbGFibGVcbiAgICovXG4gIHN0YXRpYyB0eXBlKG1vZGVsOiBDb25zdHJ1Y3RvciwgcHJvcDogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KG1vZGVsLCBgJHtEZWNvcmF0aW9uS2V5cy5QUk9QRVJUSUVTfS4ke3Byb3B9YCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBtZXRhZGF0YSBmb3IgYSBtb2RlbCBvciBhIHNwZWNpZmljIGtleSB3aXRoaW4gaXRcbiAgICogQHN1bW1hcnkgV2hlbiBjYWxsZWQgd2l0aCBhIGNvbnN0cnVjdG9yIG9ubHksIHJldHVybnMgdGhlIGVudGlyZSBtZXRhZGF0YSBvYmplY3QgYXNzb2NpYXRlZCB3aXRoIHRoZSBtb2RlbC4gV2hlbiBhIGtleSBwYXRoIGlzIHByb3ZpZGVkLCByZXR1cm5zIHRoZSB2YWx1ZSBzdG9yZWQgYXQgdGhhdCBuZXN0ZWQga2V5LlxuICAgKiBAdGVtcGxhdGUgTVxuICAgKiBAdGVtcGxhdGUgTUVUQVxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBtb2RlbCBUaGUgdGFyZ2V0IGNvbnN0cnVjdG9yIHVzZWQgdG8gbG9jYXRlIHRoZSBtZXRhZGF0YSByZWNvcmRcbiAgICogQHJldHVybiB7TUVUQXx1bmRlZmluZWR9IFRoZSBtZXRhZGF0YSBvYmplY3QsIHRoZSB2YWx1ZSBhdCB0aGUga2V5IHBhdGgsIG9yIHVuZGVmaW5lZCBpZiBub3RoaW5nIGV4aXN0c1xuICAgKi9cbiAgc3RhdGljIGdldDxNLCBNRVRBIGV4dGVuZHMgQmFzaWNNZXRhZGF0YTxNPiA9IEJhc2ljTWV0YWRhdGE8TT4+KFxuICAgIG1vZGVsOiBDb25zdHJ1Y3RvcjxNPlxuICApOiBNRVRBIHwgdW5kZWZpbmVkO1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBtZXRhZGF0YSBmb3IgYSBtb2RlbCBvciBhIHNwZWNpZmljIGtleSB3aXRoaW4gaXRcbiAgICogQHN1bW1hcnkgV2hlbiBjYWxsZWQgd2l0aCBhIGNvbnN0cnVjdG9yIG9ubHksIHJldHVybnMgdGhlIGVudGlyZSBtZXRhZGF0YSBvYmplY3QgYXNzb2NpYXRlZCB3aXRoIHRoZSBtb2RlbC4gV2hlbiBhIGtleSBwYXRoIGlzIHByb3ZpZGVkLCByZXR1cm5zIHRoZSB2YWx1ZSBzdG9yZWQgYXQgdGhhdCBuZXN0ZWQga2V5LlxuICAgKiBAdGVtcGxhdGUgTVxuICAgKiBAdGVtcGxhdGUgTUVUQVxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBtb2RlbCBUaGUgdGFyZ2V0IGNvbnN0cnVjdG9yIHVzZWQgdG8gbG9jYXRlIHRoZSBtZXRhZGF0YSByZWNvcmRcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBuZXN0ZWQga2V5IHBhdGggdG8gZmV0Y2ggYSBzcGVjaWZpYyB2YWx1ZVxuICAgKiBAcmV0dXJuIHtNRVRBfCp8dW5kZWZpbmVkfSBUaGUgbWV0YWRhdGEgb2JqZWN0LCB0aGUgdmFsdWUgYXQgdGhlIGtleSBwYXRoLCBvciB1bmRlZmluZWQgaWYgbm90aGluZyBleGlzdHNcbiAgICovXG4gIHN0YXRpYyBnZXQobW9kZWw6IENvbnN0cnVjdG9yLCBrZXk6IHN0cmluZyk6IGFueTtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgbWV0YWRhdGEgZm9yIGEgbW9kZWwgb3IgYSBzcGVjaWZpYyBrZXkgd2l0aGluIGl0XG4gICAqIEBzdW1tYXJ5IFdoZW4gY2FsbGVkIHdpdGggYSBjb25zdHJ1Y3RvciBvbmx5LCByZXR1cm5zIHRoZSBlbnRpcmUgbWV0YWRhdGEgb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGUgbW9kZWwuIFdoZW4gYSBrZXkgcGF0aCBpcyBwcm92aWRlZCwgcmV0dXJucyB0aGUgdmFsdWUgc3RvcmVkIGF0IHRoYXQgbmVzdGVkIGtleS5cbiAgICogQHRlbXBsYXRlIE1cbiAgICogQHRlbXBsYXRlIE1FVEFcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gbW9kZWwgVGhlIHRhcmdldCBjb25zdHJ1Y3RvciB1c2VkIHRvIGxvY2F0ZSB0aGUgbWV0YWRhdGEgcmVjb3JkXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBba2V5XSBPcHRpb25hbCBuZXN0ZWQga2V5IHBhdGggdG8gZmV0Y2ggYSBzcGVjaWZpYyB2YWx1ZVxuICAgKiBAcmV0dXJuIHtNRVRBfCp8dW5kZWZpbmVkfSBUaGUgbWV0YWRhdGEgb2JqZWN0LCB0aGUgdmFsdWUgYXQgdGhlIGtleSBwYXRoLCBvciB1bmRlZmluZWQgaWYgbm90aGluZyBleGlzdHNcbiAgICovXG4gIHN0YXRpYyBnZXQobW9kZWw6IENvbnN0cnVjdG9yLCBrZXk/OiBzdHJpbmcpIHtcbiAgICBjb25zdCBzeW1ib2wgPSBTeW1ib2wuZm9yKG1vZGVsLnRvU3RyaW5nKCkpO1xuICAgIGlmICghdGhpcy5fbWV0YWRhdGFbc3ltYm9sXSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBpZiAoIWtleSkgcmV0dXJuIHRoaXMuX21ldGFkYXRhW3N5bWJvbF07XG4gICAgcmV0dXJuIGdldFZhbHVlQnlTcGxpdHRlcih0aGlzLl9tZXRhZGF0YVtzeW1ib2xdLCBrZXksIHRoaXMuc3BsaXR0ZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBXcml0ZXMgYSBtZXRhZGF0YSB2YWx1ZSBhdCBhIGdpdmVuIG5lc3RlZCBrZXkgcGF0aFxuICAgKiBAc3VtbWFyeSBFbnN1cmVzIHRoZSBtZXRhZGF0YSByZWNvcmQgZXhpc3RzIGZvciB0aGUgY29uc3RydWN0b3IsIG1pcnJvcnMgaXQgb24gdGhlIGNvbnN0cnVjdG9yIHdoZW4gZW5hYmxlZCwgYW5kIHNldHMgdGhlIHByb3ZpZGVkIHZhbHVlIG9uIHRoZSBuZXN0ZWQga2V5IHBhdGggdXNpbmcgdGhlIGNvbmZpZ3VyZWQgc3BsaXR0ZXIuXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3J9IG1vZGVsIFRoZSB0YXJnZXQgY29uc3RydWN0b3IgdG8gd2hpY2ggdGhlIG1ldGFkYXRhIGJlbG9uZ3NcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUgbmVzdGVkIGtleSBwYXRoIGF0IHdoaWNoIHRvIHN0b3JlIHRoZSB2YWx1ZVxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzdG9yZSBpbiB0aGUgbWV0YWRhdGFcbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIHN0YXRpYyBzZXQobW9kZWw6IENvbnN0cnVjdG9yLCBrZXk6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICAgIGNvbnN0IHN5bWJvbCA9IFN5bWJvbC5mb3IobW9kZWwudG9TdHJpbmcoKSk7XG4gICAgaWYgKCF0aGlzLl9tZXRhZGF0YVtzeW1ib2xdKSB0aGlzLl9tZXRhZGF0YVtzeW1ib2xdID0ge30gYXMgYW55O1xuICAgIGlmIChcbiAgICAgIE1ldGFkYXRhLm1pcnJvciAmJlxuICAgICAgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtb2RlbCwgdGhpcy5iYXNlS2V5KVxuICAgICkge1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG1vZGVsLCB0aGlzLmJhc2VLZXksIHtcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgICAgdmFsdWU6IHRoaXMuX21ldGFkYXRhW3N5bWJvbF0sXG4gICAgICB9KTtcbiAgICB9XG4gICAgc2V0VmFsdWVCeVNwbGl0dGVyKHRoaXMuX21ldGFkYXRhW3N5bWJvbF0sIGtleSwgdmFsdWUsIHRoaXMuc3BsaXR0ZXIpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBNZXRhZGF0YSB9IGZyb20gXCIuL21ldGFkYXRhL01ldGFkYXRhXCI7XG5pbXBvcnQgeyBEZWNvcmF0aW9uS2V5cywgT2JqZWN0S2V5U3BsaXR0ZXIgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQXNzaWducyBhcmJpdHJhcnkgbWV0YWRhdGEgdG8gYSB0YXJnZXQgdXNpbmcgYSBzdHJpbmcga2V5XG4gKiBAc3VtbWFyeSBEZWNvcmF0b3IgZmFjdG9yeSB0aGF0IHN0b3JlcyBhIGtleS92YWx1ZSBwYWlyIGluIHRoZSBjZW50cmFsIE1ldGFkYXRhIHN0b3JlIGZvciB0aGUgcHJvdmlkZWQgY2xhc3Mgb3IgbWVtYmVyLlxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUgbWV0YWRhdGEga2V5IHRvIGFzc29jaWF0ZSB3aXRoIHRoZSB0YXJnZXRcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIG1ldGFkYXRhIHZhbHVlIHRvIHN0b3JlIHVuZGVyIHRoZSBnaXZlbiBrZXlcbiAqIEByZXR1cm4gQSBkZWNvcmF0b3IgdGhhdCB3cml0ZXMgdGhlIG1ldGFkYXRhIHdoZW4gYXBwbGllZFxuICogQGZ1bmN0aW9uIG1ldGFkYXRhXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gbWV0YWRhdGEoa2V5OiBzdHJpbmcsIHZhbHVlOiBhbnkpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIG1ldGFkYXRhKFxuICAgIG1vZGVsOiBhbnksXG5cbiAgICBwcm9wPzogYW55LFxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICBkZXNjcmlwdG9yPzogUHJvcGVydHlEZXNjcmlwdG9yXG4gICkge1xuICAgIE1ldGFkYXRhLnNldChwcm9wID8gbW9kZWwuY29uc3RydWN0b3IgOiBtb2RlbCwga2V5LCB2YWx1ZSk7XG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENhcHR1cmVzIGFuZCBzdG9yZXMgYSBwcm9wZXJ0eSdzIGRlc2lnbiB0eXBlXG4gKiBAc3VtbWFyeSBEZWNvcmF0b3IgZmFjdG9yeSB0aGF0IHJlYWRzIHRoZSByZWZsZWN0ZWQgZGVzaWduOnR5cGUgZm9yIGEgcHJvcGVydHkgYW5kIHJlZ2lzdGVycyBpdCBpbiB0aGUgTWV0YWRhdGEgc3RvcmUgdW5kZXIgdGhlIHByb3BlcnRpZXMgbWFwLlxuICogQHJldHVybiBBIGRlY29yYXRvciB0aGF0IHJlY29yZHMgdGhlIHByb3BlcnR5J3MgdHlwZSBtZXRhZGF0YSB3aGVuIGFwcGxpZWRcbiAqIEBmdW5jdGlvbiBwcm9wXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvcCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIHByb3AobW9kZWw6IG9iamVjdCwgcHJvcDogYW55KSB7XG4gICAgY29uc3QgZGVzaWduVHlwZSA9IFJlZmxlY3QuZ2V0T3duTWV0YWRhdGEoXG4gICAgICBEZWNvcmF0aW9uS2V5cy5ERVNJR05fVFlQRSxcbiAgICAgIG1vZGVsLFxuICAgICAgcHJvcFxuICAgICk7XG4gICAgcmV0dXJuIG1ldGFkYXRhKGAke0RlY29yYXRpb25LZXlzLlBST1BFUlRJRVN9LiR7cHJvcH1gLCBkZXNpZ25UeXBlKShcbiAgICAgIG1vZGVsLFxuICAgICAgcHJvcFxuICAgICk7XG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlY29yYXRvciBmYWN0b3J5IHRoYXQgYXBwbGllcyBtdWx0aXBsZSBkZWNvcmF0b3JzIHRvIGEgc2luZ2xlIHRhcmdldFxuICogQHN1bW1hcnkgQ3JlYXRlcyBhIGNvbXBvc2l0ZSBkZWNvcmF0b3IgdGhhdCBhcHBsaWVzIG11bHRpcGxlIGRlY29yYXRvcnMgaW4gc2VxdWVuY2UsIGNvcnJlY3RseSBoYW5kbGluZyBjbGFzcywgbWV0aG9kLCBhbmQgcHJvcGVydHkgZGVjb3JhdG9ycy5cbiAqIEBwYXJhbSB7QXJyYXk8Q2xhc3NEZWNvcmF0b3IgfCBNZXRob2REZWNvcmF0b3IgfCBQcm9wZXJ0eURlY29yYXRvcj59IGRlY29yYXRvcnMgLSBBcnJheSBvZiBkZWNvcmF0b3JzIHRvIGFwcGx5XG4gKiBAcmV0dXJuIHtGdW5jdGlvbn0gQSBkZWNvcmF0b3IgZnVuY3Rpb24gdGhhdCBhcHBsaWVzIGFsbCBwcm92aWRlZCBkZWNvcmF0b3JzIHRvIHRoZSB0YXJnZXRcbiAqIEBmdW5jdGlvbiBhcHBseVxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBVIGFzIFVzZXIgQ29kZVxuICogICBwYXJ0aWNpcGFudCBBIGFzIGFwcGx5KC4uLmRlY29yYXRvcnMpXG4gKiAgIHBhcnRpY2lwYW50IEQgYXMgRGVjb3JhdG9yXG4gKiAgIFUtPj5BOiBnZXQgZGVjb3JhdG9yKC4uLmRlY29yYXRvcnMpXG4gKiAgIEEtPj5VOiByZXR1cm5zICh0YXJnZXQsIGtleT8sIGRlc2M/KSA9PiB2b2lkXG4gKiAgIFUtPj5BOiBpbnZva2Ugb24gdGFyZ2V0XG4gKiAgIGxvb3AgZm9yIGVhY2ggZGVjb3JhdG9yXG4gKiAgICAgQS0+PkQ6IGludm9rZSBhcHByb3ByaWF0ZSBkZWNvcmF0b3IgdHlwZVxuICogICBlbmRcbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseShcbiAgLi4uZGVjb3JhdG9yczogQXJyYXk8Q2xhc3NEZWNvcmF0b3IgfCBNZXRob2REZWNvcmF0b3IgfCBQcm9wZXJ0eURlY29yYXRvcj5cbikge1xuICByZXR1cm4gKFxuICAgIHRhcmdldDogb2JqZWN0LFxuICAgIHByb3BlcnR5S2V5Pzogc3RyaW5nIHwgc3ltYm9sIHwgdW5rbm93bixcbiAgICBkZXNjcmlwdG9yPzogUHJvcGVydHlEZXNjcmlwdG9yXG4gICkgPT4ge1xuICAgIGZvciAoY29uc3QgZGVjb3JhdG9yIG9mIGRlY29yYXRvcnMpIHtcbiAgICAgIGlmICh0YXJnZXQgaW5zdGFuY2VvZiBGdW5jdGlvbiAmJiAhZGVzY3JpcHRvcikge1xuICAgICAgICAoZGVjb3JhdG9yIGFzIENsYXNzRGVjb3JhdG9yKSh0YXJnZXQpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIChkZWNvcmF0b3IgYXMgTWV0aG9kRGVjb3JhdG9yIHwgUHJvcGVydHlEZWNvcmF0b3IpKFxuICAgICAgICB0YXJnZXQsXG4gICAgICAgIHByb3BlcnR5S2V5IGFzIHN0cmluZyB8IHN5bWJvbCxcbiAgICAgICAgZGVzY3JpcHRvciBhcyBUeXBlZFByb3BlcnR5RGVzY3JpcHRvcjx1bmtub3duPlxuICAgICAgKTtcbiAgICB9XG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBwcm9wZXJ0eSBtZXRhZGF0YSBkZWNvcmF0b3JcbiAqIEBzdW1tYXJ5IENvbnZlbmllbmNlIGZhY3RvcnkgdGhhdCBjb21iaW5lcyBtZXRhZGF0YShrZXksIHZhbHVlKSBhbmQgcHJvcCgpIHRvIGJvdGggc2V0IGFuIGFyYml0cmFyeSBtZXRhZGF0YSBrZXkgYW5kIHJlY29yZCB0aGUgcHJvcGVydHkncyBkZXNpZ24gdHlwZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIG1ldGFkYXRhIGtleSB0byBzZXQgZm9yIHRoZSBwcm9wZXJ0eVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgbWV0YWRhdGEgdmFsdWUgdG8gYXNzb2NpYXRlIHdpdGggdGhlIGtleVxuICogQHJldHVybiBBIGRlY29yYXRvciB0aGF0IHNldHMgdGhlIG1ldGFkYXRhIGFuZCBjYXB0dXJlcyB0aGUgcHJvcGVydHkncyB0eXBlXG4gKiBAZnVuY3Rpb24gcHJvcE1ldGFkYXRhXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvcE1ldGFkYXRhKGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSB7XG4gIHJldHVybiBhcHBseShtZXRhZGF0YShrZXksIHZhbHVlKSwgcHJvcCgpKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQXR0YWNoZXMgYSBodW1hbi1yZWFkYWJsZSBkZXNjcmlwdGlvbiB0byBhIGNsYXNzIG9yIG1lbWJlclxuICogQHN1bW1hcnkgRGVjb3JhdG9yIGZhY3RvcnkgdGhhdCBzdG9yZXMgYSB0ZXh0dWFsIGRlc2NyaXB0aW9uIGluIHRoZSBNZXRhZGF0YSBzdG9yZSB1bmRlciB0aGUgYXBwcm9wcmlhdGUgZGVzY3JpcHRpb24ga2V5IGZvciBhIGNsYXNzIG9yIGl0cyBwcm9wZXJ0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkZXNjIFRoZSBkZXNjcmlwdGl2ZSB0ZXh0IHRvIGFzc29jaWF0ZSB3aXRoIHRoZSBjbGFzcyBvciBwcm9wZXJ0eVxuICogQHJldHVybiBBIGRlY29yYXRvciB0aGF0IHJlY29yZHMgdGhlIGRlc2NyaXB0aW9uIHdoZW4gYXBwbGllZFxuICogQGZ1bmN0aW9uIGRlc2NyaXB0aW9uXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZGVzY3JpcHRpb24oZGVzYzogc3RyaW5nKSB7XG4gIHJldHVybiBmdW5jdGlvbiBkZXNjcmlwdGlvbihvcmlnaW5hbDogYW55LCBwcm9wOiBhbnksIGRlc2NyaXB0b3I/OiBhbnkpIHtcbiAgICByZXR1cm4gbWV0YWRhdGEoXG4gICAgICBbXG4gICAgICAgIERlY29yYXRpb25LZXlzLkRFU0NSSVBUSU9OLFxuICAgICAgICBwcm9wID8gcHJvcC50b1N0cmluZygpIDogRGVjb3JhdGlvbktleXMuQ0xBU1MsXG4gICAgICBdLmpvaW4oT2JqZWN0S2V5U3BsaXR0ZXIpLFxuICAgICAgZGVzY1xuICAgICkob3JpZ2luYWwsIHByb3AsIGRlc2NyaXB0b3IpO1xuICB9O1xufVxuIiwiLyoqXG4gKiBAZGVzY3JpcHRpb24gUm9vdCBlbnRyeSBwb2ludCBmb3IgdGhlIGRlY29yYXRpb24gbW9kdWxlXG4gKiBAc3VtbWFyeSBBZ2dyZWdhdGVzIGFuZCByZS1leHBvcnRzIHRoZSBwdWJsaWMgQVBJIG9mIHRoZSBkZWNvcmF0aW9uIGxpYnJhcnksIGluY2x1ZGluZyBjb3JlIGNsYXNzZXMgbGlrZSB7QGxpbmsgRGVjb3JhdGlvbn0sIHV0aWxpdHkgZGVjb3JhdG9ycywgbWV0YWRhdGEgaGVscGVycywgYW5kIGNvbnN0YW50cy4gVGhpcyBtb2R1bGUgaXMgdGhlIHByaW1hcnkgaW1wb3J0IHN1cmZhY2UgZm9yIGNvbnN1bWVycyBhbmQgZXhwb3NlczpcbiAqIC0gQ29yZSBidWlsZGVyOiB7QGxpbmsgRGVjb3JhdGlvbn1cbiAqIC0gRGVjb3JhdG9yIHV0aWxpdGllczoge0BsaW5rIG1vZHVsZTpkZWNvcmF0aW9uIHwgZGVjb3JhdG9ycyBpbiAuL2RlY29yYXRvcnN9XG4gKiAtIE1ldGFkYXRhIHV0aWxpdGllczoge0BsaW5rIE1ldGFkYXRhfVxuICogLSBDb25zdGFudHMgYW5kIGVudW1zOiB7QGxpbmsgRGVjb3JhdGlvbktleXN9LCB7QGxpbmsgRGVmYXVsdEZsYXZvdXJ9XG4gKlxuICogQG1vZHVsZSBkZWNvcmF0aW9uXG4gKi9cblxuZXhwb3J0ICogZnJvbSBcIi4vZGVjb3JhdGlvblwiO1xuZXhwb3J0ICogZnJvbSBcIi4vbWV0YWRhdGFcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vZGVjb3JhdG9yc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDdXJyZW50IHZlcnNpb24gb2YgdGhlIHJlZmxlY3Rpb24gcGFja2FnZVxuICogQHN1bW1hcnkgU3RvcmVzIHRoZSBzZW1hbnRpYyB2ZXJzaW9uIG51bWJlciBvZiB0aGUgcGFja2FnZVxuICogQGNvbnN0IFZFUlNJT05cbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdGlvblxuICovXG5leHBvcnQgY29uc3QgVkVSU0lPTiA9IFwiIyNWRVJTSU9OIyNcIjtcbiJdLCJuYW1lcyI6WyJEZWNvcmF0aW9uS2V5cyJdLCJtYXBwaW5ncyI6Ijs7Ozs7O0lBRUE7Ozs7OztJQU1HO0FBQ0ksVUFBTSxjQUFjLEdBQUc7SUFFOUI7Ozs7O0lBS0c7QUFDSSxVQUFNLGlCQUFpQixHQUFHO0lBRWpDOzs7Ozs7Ozs7SUFTRztBQUNTQTtJQUFaLENBQUEsVUFBWSxjQUFjLEVBQUE7O0lBRXhCLElBQUEsY0FBQSxDQUFBLFNBQUEsQ0FBQSxHQUFBLFNBQStCOztJQUUvQixJQUFBLGNBQUEsQ0FBQSxZQUFBLENBQUEsR0FBQSxZQUF5Qjs7SUFFekIsSUFBQSxjQUFBLENBQUEsT0FBQSxDQUFBLEdBQUEsT0FBZTs7SUFFZixJQUFBLGNBQUEsQ0FBQSxhQUFBLENBQUEsR0FBQSxhQUEyQjs7SUFFM0IsSUFBQSxjQUFBLENBQUEsYUFBQSxDQUFBLEdBQUEsYUFBMkI7O0lBRTNCLElBQUEsY0FBQSxDQUFBLGVBQUEsQ0FBQSxHQUFBLG1CQUFtQzs7SUFFbkMsSUFBQSxjQUFBLENBQUEsZUFBQSxDQUFBLEdBQUEsbUJBQW1DO0lBQ3JDLENBQUMsRUFmV0Esc0JBQWMsS0FBZEEsc0JBQWMsR0FlekIsRUFBQSxDQUFBLENBQUE7SUFFRDs7Ozs7OztJQU9HO0lBRUg7Ozs7OztJQU1HO0FBQ1UsVUFBQSxlQUFlLEdBQXVCO0lBQ2pELElBQUEsQ0FBQ0Esc0JBQWMsQ0FBQyxVQUFVLEdBQUcsRUFBRTs7O0lDckRqQzs7Ozs7OztJQU9HO0lBQ0g7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
|