@decaf-ts/for-http 0.2.10 → 0.2.12
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/README.md +23 -3
- package/dist/for-http.cjs +2 -712
- package/dist/for-http.cjs.map +1 -0
- package/dist/for-http.js +2 -0
- package/dist/for-http.js.map +1 -0
- package/lib/RestRepository.cjs +1 -1
- package/lib/RestRepository.js.map +1 -0
- package/lib/RestService.cjs +1 -1
- package/lib/RestService.js.map +1 -0
- package/lib/adapter.cjs +1 -1
- package/lib/adapter.js.map +1 -0
- package/lib/axios/axios.cjs +1 -1
- package/lib/axios/axios.js.map +1 -0
- package/lib/axios/constants.cjs +1 -1
- package/lib/axios/constants.js.map +1 -0
- package/lib/axios/index.cjs +1 -1
- package/lib/axios/index.js.map +1 -0
- package/lib/axios/types.cjs +1 -1
- package/lib/axios/types.js.map +1 -0
- package/lib/esm/RestRepository.js +1 -1
- package/lib/esm/RestRepository.js.map +1 -0
- package/lib/esm/RestService.js +1 -1
- package/lib/esm/RestService.js.map +1 -0
- package/lib/esm/adapter.js +1 -1
- package/lib/esm/adapter.js.map +1 -0
- package/lib/esm/axios/axios.js +1 -1
- package/lib/esm/axios/axios.js.map +1 -0
- package/lib/esm/axios/constants.js +1 -1
- package/lib/esm/axios/constants.js.map +1 -0
- package/lib/esm/axios/index.js +1 -1
- package/lib/esm/axios/index.js.map +1 -0
- package/lib/esm/axios/types.js +1 -1
- package/lib/esm/axios/types.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/types.js +1 -1
- package/lib/esm/types.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/types.cjs +1 -1
- package/lib/types.js.map +1 -0
- package/package.json +11 -22
- package/dist/for-http.esm.cjs +0 -705
package/dist/for-http.cjs
CHANGED
|
@@ -1,712 +1,2 @@
|
|
|
1
|
-
(
|
|
2
|
-
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports', '@decaf-ts/core', '@decaf-ts/db-decorators', '@decaf-ts/decorator-validation', '@decaf-ts/logging', 'axios'], factory) :
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["for-http"] = {}, global.core, global.dbDecorators, global.decoratorValidation, global.logging, global.axios));
|
|
5
|
-
})(this, (function (exports, core, dbDecorators, decoratorValidation, logging, axios) { 'use strict';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @description Service class for REST API operations
|
|
9
|
-
* @summary Provides a comprehensive implementation for interacting with REST APIs.
|
|
10
|
-
* This class implements CRUD operations for single and bulk operations, as well as
|
|
11
|
-
* the Observable pattern to notify observers of changes. It works with HTTP adapters
|
|
12
|
-
* to perform the actual API requests and handles model conversion.
|
|
13
|
-
* @template M - The model type, extending Model
|
|
14
|
-
* @template Q - The query type used by the adapter
|
|
15
|
-
* @template A - The HTTP adapter type, extending HttpAdapter
|
|
16
|
-
* @template F - The HTTP flags type, extending HttpFlags
|
|
17
|
-
* @template C - The context type, extending Context<F>
|
|
18
|
-
* @param {A} adapter - The HTTP adapter instance
|
|
19
|
-
* @param {Constructor<M>} [clazz] - Optional constructor for the model class
|
|
20
|
-
* @class RestService
|
|
21
|
-
* @example
|
|
22
|
-
* ```typescript
|
|
23
|
-
* // Create a service for User model with Axios adapter
|
|
24
|
-
* const axiosAdapter = new AxiosAdapter({
|
|
25
|
-
* protocol: 'https',
|
|
26
|
-
* host: 'api.example.com'
|
|
27
|
-
* });
|
|
28
|
-
* const userService = new RestService(axiosAdapter, User);
|
|
29
|
-
*
|
|
30
|
-
* // Create a new user
|
|
31
|
-
* const user = new User({ name: 'John Doe', email: 'john@example.com' });
|
|
32
|
-
* const createdUser = await userService.create(user);
|
|
33
|
-
*
|
|
34
|
-
* // Update a user
|
|
35
|
-
* createdUser.name = 'Jane Doe';
|
|
36
|
-
* const updatedUser = await userService.update(createdUser);
|
|
37
|
-
*
|
|
38
|
-
* // Delete a user
|
|
39
|
-
* await userService.delete(updatedUser.id);
|
|
40
|
-
* ```
|
|
41
|
-
* @mermaid
|
|
42
|
-
* sequenceDiagram
|
|
43
|
-
* participant Client
|
|
44
|
-
* participant Service as RestService
|
|
45
|
-
* participant Adapter as HttpAdapter
|
|
46
|
-
* participant API
|
|
47
|
-
* Client->>Service: create(model)
|
|
48
|
-
* Service->>Adapter: prepare(model, pk)
|
|
49
|
-
* Service->>Adapter: create(table, id, record)
|
|
50
|
-
* Adapter->>API: HTTP POST
|
|
51
|
-
* API-->>Adapter: 201 Created
|
|
52
|
-
* Adapter-->>Service: record
|
|
53
|
-
* Service-->>Client: revert(record)
|
|
54
|
-
*/
|
|
55
|
-
class RestService extends logging.LoggedClass {
|
|
56
|
-
/**
|
|
57
|
-
* @description Gets the model class constructor
|
|
58
|
-
* @summary Retrieves the model class constructor associated with this service.
|
|
59
|
-
* Throws an error if no class definition is found.
|
|
60
|
-
* @return {Constructor<M>} The model class constructor
|
|
61
|
-
* @throws {InternalError} If no class definition is found
|
|
62
|
-
*/
|
|
63
|
-
get class() {
|
|
64
|
-
if (!this._class)
|
|
65
|
-
throw new dbDecorators.InternalError("No class definition found for this repository");
|
|
66
|
-
return this._class;
|
|
67
|
-
}
|
|
68
|
-
get log() {
|
|
69
|
-
if (!this.logger)
|
|
70
|
-
this.logger = this.adapter["log"].for(this.toString());
|
|
71
|
-
return this.logger;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* @description Gets the primary key property name
|
|
75
|
-
* @summary Retrieves the name of the primary key property for the model.
|
|
76
|
-
* If not already determined, it finds the primary key using the model class.
|
|
77
|
-
* @return The primary key property name
|
|
78
|
-
*/
|
|
79
|
-
get pk() {
|
|
80
|
-
if (!this._pk)
|
|
81
|
-
this._pk = dbDecorators.findPrimaryKey(new this.class()).id;
|
|
82
|
-
return this._pk;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* @description Gets the HTTP adapter
|
|
86
|
-
* @summary Retrieves the HTTP adapter associated with this service.
|
|
87
|
-
* Throws an error if no adapter is found.
|
|
88
|
-
* @return {A} The HTTP adapter instance
|
|
89
|
-
* @throws {InternalError} If no adapter is found
|
|
90
|
-
*/
|
|
91
|
-
get adapter() {
|
|
92
|
-
if (!this._adapter)
|
|
93
|
-
throw new dbDecorators.InternalError("No adapter found for this repository. did you use the @uses decorator or pass it in the constructor?");
|
|
94
|
-
return this._adapter;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* @description Gets the table name for the model
|
|
98
|
-
* @summary Retrieves the table name associated with the model class.
|
|
99
|
-
* If not already determined, it gets the table name from the Repository utility.
|
|
100
|
-
* @return {string} The table name
|
|
101
|
-
*/
|
|
102
|
-
get tableName() {
|
|
103
|
-
if (!this._tableName)
|
|
104
|
-
this._tableName = core.Repository.table(this.class);
|
|
105
|
-
return this._tableName;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* @description Initializes a new RestService instance
|
|
109
|
-
* @summary Creates a new service instance with the specified adapter and optional model class.
|
|
110
|
-
* The constructor stores the adapter and model class for later use in CRUD operations.
|
|
111
|
-
* @param {A} adapter - The HTTP adapter instance to use for API requests
|
|
112
|
-
* @param {Constructor<M>} [clazz] - Optional constructor for the model class
|
|
113
|
-
*/
|
|
114
|
-
constructor(adapter, clazz) {
|
|
115
|
-
super();
|
|
116
|
-
this.observers = [];
|
|
117
|
-
this._adapter = adapter;
|
|
118
|
-
if (clazz)
|
|
119
|
-
this._class = clazz;
|
|
120
|
-
}
|
|
121
|
-
url(path, queryParams) {
|
|
122
|
-
return this.adapter.url(path, queryParams);
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* @description Creates a new resource
|
|
126
|
-
* @summary Creates a new resource in the REST API using the provided model.
|
|
127
|
-
* The method prepares the model for the adapter, sends the create request,
|
|
128
|
-
* and then converts the response back to a model instance.
|
|
129
|
-
* @param {M} model - The model instance to create
|
|
130
|
-
* @param {...any[]} args - Additional arguments to pass to the adapter
|
|
131
|
-
* @return {Promise<M>} A promise that resolves with the created model instance
|
|
132
|
-
*/
|
|
133
|
-
async create(model, ...args) {
|
|
134
|
-
// eslint-disable-next-line prefer-const
|
|
135
|
-
let { record, id } = this.adapter.prepare(model, this.pk);
|
|
136
|
-
record = await this.adapter.create(this.tableName, id, record, ...args);
|
|
137
|
-
return this.adapter.revert(record, this.class, this.pk, id);
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* @description Retrieves a resource by ID
|
|
141
|
-
* @summary Fetches a resource from the REST API using the provided ID.
|
|
142
|
-
* The method sends the read request and converts the response to a model instance.
|
|
143
|
-
* @param {string|number} id - The identifier of the resource to retrieve
|
|
144
|
-
* @param {...any[]} args - Additional arguments to pass to the adapter
|
|
145
|
-
* @return {Promise<M>} A promise that resolves with the retrieved model instance
|
|
146
|
-
*/
|
|
147
|
-
async read(id, ...args) {
|
|
148
|
-
const m = await this.adapter.read(this.tableName, id, ...args);
|
|
149
|
-
return this.adapter.revert(m, this.class, this.pk, id);
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* @description Updates an existing resource
|
|
153
|
-
* @summary Updates an existing resource in the REST API using the provided model.
|
|
154
|
-
* The method prepares the model for the adapter, sends the update request,
|
|
155
|
-
* and then converts the response back to a model instance.
|
|
156
|
-
* @param {M} model - The model instance with updated data
|
|
157
|
-
* @param {...any[]} args - Additional arguments to pass to the adapter
|
|
158
|
-
* @return {Promise<M>} A promise that resolves with the updated model instance
|
|
159
|
-
*/
|
|
160
|
-
async update(model, ...args) {
|
|
161
|
-
// eslint-disable-next-line prefer-const
|
|
162
|
-
let { record, id } = this.adapter.prepare(model, this.pk);
|
|
163
|
-
record = await this.adapter.update(this.tableName, id, record, ...args);
|
|
164
|
-
return this.adapter.revert(record, this.class, this.pk, id);
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* @description Deletes a resource by ID
|
|
168
|
-
* @summary Removes a resource from the REST API using the provided ID.
|
|
169
|
-
* The method sends the delete request and converts the response to a model instance.
|
|
170
|
-
* @param {string|number} id - The identifier of the resource to delete
|
|
171
|
-
* @param {...any[]} args - Additional arguments to pass to the adapter
|
|
172
|
-
* @return {Promise<M>} A promise that resolves with the deleted model instance
|
|
173
|
-
*/
|
|
174
|
-
async delete(id, ...args) {
|
|
175
|
-
const m = await this.adapter.delete(this.tableName, id, ...args);
|
|
176
|
-
return this.adapter.revert(m, this.class, this.pk, id);
|
|
177
|
-
}
|
|
178
|
-
async request(details) {
|
|
179
|
-
return this.adapter.request(details);
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* @description Creates multiple resources
|
|
183
|
-
* @summary Creates multiple resources in the REST API using the provided models.
|
|
184
|
-
* The method prepares each model for the adapter, sends a bulk create request,
|
|
185
|
-
* and then converts the responses back to model instances.
|
|
186
|
-
* @param {M[]} models - The model instances to create
|
|
187
|
-
* @param {...any[]} args - Additional arguments to pass to the adapter
|
|
188
|
-
* @return {Promise<M[]>} A promise that resolves with an array of created model instances
|
|
189
|
-
* @mermaid
|
|
190
|
-
* sequenceDiagram
|
|
191
|
-
* participant Client
|
|
192
|
-
* participant Service as RestService
|
|
193
|
-
* participant Adapter as HttpAdapter
|
|
194
|
-
* Client->>Service: createAll(models)
|
|
195
|
-
* Service->>Adapter: prepare(model, pk) x N
|
|
196
|
-
* Service->>Adapter: createAll(table, ids[], records[])
|
|
197
|
-
* Adapter-->>Service: records[]
|
|
198
|
-
* Service-->>Client: revert(records[])
|
|
199
|
-
*/
|
|
200
|
-
async createAll(models, ...args) {
|
|
201
|
-
if (!models.length)
|
|
202
|
-
return models;
|
|
203
|
-
const prepared = models.map((m) => this.adapter.prepare(m, this.pk));
|
|
204
|
-
const ids = prepared.map((p) => p.id);
|
|
205
|
-
let records = prepared.map((p) => p.record);
|
|
206
|
-
records = await this.adapter.createAll(this.tableName, ids, records, ...args);
|
|
207
|
-
return records.map((r, i) => this.adapter.revert(r, this.class, this.pk, ids[i]));
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* @description Deletes multiple resources by IDs
|
|
211
|
-
* @summary Removes multiple resources from the REST API using the provided IDs.
|
|
212
|
-
* The method sends a bulk delete request and converts the responses to model instances.
|
|
213
|
-
* @param {string[]|number[]} keys - The identifiers of the resources to delete
|
|
214
|
-
* @param {...any[]} args - Additional arguments to pass to the adapter
|
|
215
|
-
* @return {Promise<M[]>} A promise that resolves with an array of deleted model instances
|
|
216
|
-
*/
|
|
217
|
-
async deleteAll(keys, ...args) {
|
|
218
|
-
const results = await this.adapter.deleteAll(this.tableName, keys, ...args);
|
|
219
|
-
return results.map((r, i) => this.adapter.revert(r, this.class, this.pk, keys[i]));
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* @description Retrieves multiple resources by IDs
|
|
223
|
-
* @summary Fetches multiple resources from the REST API using the provided IDs.
|
|
224
|
-
* The method sends a bulk read request and converts the responses to model instances.
|
|
225
|
-
* @param {string[]|number[]} keys - The identifiers of the resources to retrieve
|
|
226
|
-
* @param {...any[]} args - Additional arguments to pass to the adapter
|
|
227
|
-
* @return {Promise<M[]>} A promise that resolves with an array of retrieved model instances
|
|
228
|
-
*/
|
|
229
|
-
async readAll(keys, ...args) {
|
|
230
|
-
const records = await this.adapter.readAll(this.tableName, keys, ...args);
|
|
231
|
-
return records.map((r, i) => this.adapter.revert(r, this.class, this.pk, keys[i]));
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* @description Updates multiple resources
|
|
235
|
-
* @summary Updates multiple resources in the REST API using the provided models.
|
|
236
|
-
* The method prepares each model for the adapter, sends a bulk update request,
|
|
237
|
-
* and then converts the responses back to model instances.
|
|
238
|
-
* @param {M[]} models - The model instances with updated data
|
|
239
|
-
* @param {...any[]} args - Additional arguments to pass to the adapter
|
|
240
|
-
* @return {Promise<M[]>} A promise that resolves with an array of updated model instances
|
|
241
|
-
*/
|
|
242
|
-
async updateAll(models, ...args) {
|
|
243
|
-
const records = models.map((m) => this.adapter.prepare(m, this.pk));
|
|
244
|
-
const updated = await this.adapter.updateAll(this.tableName, records.map((r) => r.id), records.map((r) => r.record), ...args);
|
|
245
|
-
return updated.map((u, i) => this.adapter.revert(u, this.class, this.pk, records[i].id));
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* @description Registers an observer
|
|
249
|
-
* @summary Adds an observer to the list of observers that will be notified of changes.
|
|
250
|
-
* Throws an error if the observer is already registered.
|
|
251
|
-
* @param {Observer} observer - The observer to register
|
|
252
|
-
* @return {void}
|
|
253
|
-
* @throws {InternalError} If the observer is already registered
|
|
254
|
-
*/
|
|
255
|
-
observe(observer) {
|
|
256
|
-
const index = this.observers.indexOf(observer);
|
|
257
|
-
if (index !== -1)
|
|
258
|
-
throw new dbDecorators.InternalError("Observer already registered");
|
|
259
|
-
this.observers.push(observer);
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* @description Unregisters an observer
|
|
263
|
-
* @summary Removes an observer from the list of observers.
|
|
264
|
-
* Throws an error if the observer is not found.
|
|
265
|
-
* @param {Observer} observer - The observer to unregister
|
|
266
|
-
* @return {void}
|
|
267
|
-
* @throws {InternalError} If the observer is not found
|
|
268
|
-
*/
|
|
269
|
-
unObserve(observer) {
|
|
270
|
-
const index = this.observers.indexOf(observer);
|
|
271
|
-
if (index === -1)
|
|
272
|
-
throw new dbDecorators.InternalError("Failed to find Observer");
|
|
273
|
-
this.observers.splice(index, 1);
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* @description Notifies all registered observers
|
|
277
|
-
* @summary Calls the refresh method on all registered observers to update themselves.
|
|
278
|
-
* Any errors during observer refresh are logged as warnings but don't stop the process.
|
|
279
|
-
* @param {...any[]} [args] - Optional arguments to pass to the observer refresh method
|
|
280
|
-
* @return {Promise<void>} A promise that resolves when all observers have been updated
|
|
281
|
-
*/
|
|
282
|
-
async updateObservers(...args) {
|
|
283
|
-
const results = await Promise.allSettled(this.observers.map((o) => o.refresh(...args)));
|
|
284
|
-
results.forEach((result, i) => {
|
|
285
|
-
if (result.status === "rejected")
|
|
286
|
-
console.warn(`Failed to update observable ${this.observers[i]}: ${result.reason}`);
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
toString() {
|
|
290
|
-
return `${this.class.name} rest service`;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* @description Abstract HTTP adapter for REST API interactions
|
|
296
|
-
* @summary Provides a base implementation for HTTP adapters with methods for CRUD operations,
|
|
297
|
-
* URL construction, and error handling. This class extends the core Adapter class and
|
|
298
|
-
* implements the necessary methods for HTTP communication. Concrete implementations
|
|
299
|
-
* must provide specific HTTP client functionality.
|
|
300
|
-
* @template Y - The native HTTP client type
|
|
301
|
-
* @template Q - The query type used by the adapter
|
|
302
|
-
* @template F - The HTTP flags type, extending HttpFlags
|
|
303
|
-
* @template C - The context type, extending Context<F>
|
|
304
|
-
* @param {Y} native - The native HTTP client instance
|
|
305
|
-
* @param {HttpConfig} config - Configuration for the HTTP adapter
|
|
306
|
-
* @param {string} flavour - The adapter flavor identifier
|
|
307
|
-
* @param {string} [alias] - Optional alias for the adapter
|
|
308
|
-
* @class HttpAdapter
|
|
309
|
-
* @example
|
|
310
|
-
* ```typescript
|
|
311
|
-
* // Example implementation with Axios
|
|
312
|
-
* class AxiosAdapter extends HttpAdapter<AxiosInstance, AxiosRequestConfig> {
|
|
313
|
-
* constructor(config: HttpConfig) {
|
|
314
|
-
* super(axios.create(), config, 'axios');
|
|
315
|
-
* }
|
|
316
|
-
*
|
|
317
|
-
* async request<V>(details: AxiosRequestConfig): Promise<V> {
|
|
318
|
-
* const response = await this.native.request(details);
|
|
319
|
-
* return response.data;
|
|
320
|
-
* }
|
|
321
|
-
*
|
|
322
|
-
* // Implement other abstract methods...
|
|
323
|
-
* }
|
|
324
|
-
* ```
|
|
325
|
-
*/
|
|
326
|
-
class HttpAdapter extends core.Adapter {
|
|
327
|
-
constructor(config, flavour, alias) {
|
|
328
|
-
super(config, flavour, alias);
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* @description Generates operation flags with HTTP headers
|
|
332
|
-
* @summary Extends the base flags method to include HTTP-specific headers for operations.
|
|
333
|
-
* This method adds an empty headers object to the flags returned by the parent class.
|
|
334
|
-
* @template F - The Repository Flags type
|
|
335
|
-
* @template M - The model type
|
|
336
|
-
* @param {OperationKeys.CREATE|OperationKeys.READ|OperationKeys.UPDATE|OperationKeys.DELETE} operation - The operation type
|
|
337
|
-
* @param {Constructor<M>} model - The model constructor
|
|
338
|
-
* @param {Partial<F>} overrides - Optional flag overrides
|
|
339
|
-
* @return {F} The flags object with headers
|
|
340
|
-
*/
|
|
341
|
-
flags(operation, model, overrides) {
|
|
342
|
-
return Object.assign(super.flags(operation, model, overrides), {
|
|
343
|
-
headers: {},
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
|
-
/**
|
|
347
|
-
* @description Returns the repository constructor for this adapter
|
|
348
|
-
* @summary Provides the RestService class as the repository implementation for this HTTP adapter.
|
|
349
|
-
* This method is used to create repository instances that work with this adapter type.
|
|
350
|
-
* @template M - The model type
|
|
351
|
-
* @return {Constructor<Repository<M, Q, HttpAdapter<Y, Q, F, C>, F, C>>} The repository constructor
|
|
352
|
-
*/
|
|
353
|
-
repository() {
|
|
354
|
-
return RestService;
|
|
355
|
-
}
|
|
356
|
-
/**
|
|
357
|
-
* @description Prepares a model for persistence
|
|
358
|
-
* @summary Converts a model instance into a format suitable for database storage,
|
|
359
|
-
* handling column mapping and separating transient properties
|
|
360
|
-
* @template M - The model type
|
|
361
|
-
* @param {M} model - The model instance to prepare
|
|
362
|
-
* @param pk - The primary key property name
|
|
363
|
-
* @return The prepared data
|
|
364
|
-
*/
|
|
365
|
-
prepare(model, pk) {
|
|
366
|
-
const log = this.log.for(this.prepare);
|
|
367
|
-
const result = Object.assign({}, model);
|
|
368
|
-
if (model[core.PersistenceKeys.METADATA]) {
|
|
369
|
-
log.silly(`Passing along persistence metadata for ${model[core.PersistenceKeys.METADATA]}`);
|
|
370
|
-
Object.defineProperty(result, core.PersistenceKeys.METADATA, {
|
|
371
|
-
enumerable: false,
|
|
372
|
-
writable: false,
|
|
373
|
-
configurable: true,
|
|
374
|
-
value: model[core.PersistenceKeys.METADATA],
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
return {
|
|
378
|
-
record: model,
|
|
379
|
-
id: model[pk],
|
|
380
|
-
};
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* @description Converts database data back into a model instance
|
|
384
|
-
* @summary Reconstructs a model instance from database data, handling column mapping
|
|
385
|
-
* and reattaching transient properties
|
|
386
|
-
* @template M - The model type
|
|
387
|
-
* @param obj - The database record
|
|
388
|
-
* @param {string|Constructor<M>} clazz - The model class or name
|
|
389
|
-
* @param pk - The primary key property name
|
|
390
|
-
* @param {string|number|bigint} id - The primary key value
|
|
391
|
-
* @return {M} The reconstructed model instance
|
|
392
|
-
*/
|
|
393
|
-
revert(obj, clazz, pk, id) {
|
|
394
|
-
const log = this.log.for(this.revert);
|
|
395
|
-
const ob = {};
|
|
396
|
-
const m = (typeof clazz === "string" ? decoratorValidation.Model.build(ob, clazz) : new clazz(ob));
|
|
397
|
-
log.silly(`Rebuilding model ${m.constructor.name} id ${id}`);
|
|
398
|
-
const constr = typeof clazz === "string" ? decoratorValidation.Model.get(clazz) : clazz;
|
|
399
|
-
if (!constr)
|
|
400
|
-
throw new dbDecorators.InternalError(`Failed to retrieve model constructor for ${clazz}`);
|
|
401
|
-
const result = new constr(obj);
|
|
402
|
-
const metadata = obj[core.PersistenceKeys.METADATA];
|
|
403
|
-
if (metadata) {
|
|
404
|
-
log.silly(`Passing along ${this.flavour} persistence metadata for ${m.constructor.name} id ${id}: ${metadata}`);
|
|
405
|
-
Object.defineProperty(result, core.PersistenceKeys.METADATA, {
|
|
406
|
-
enumerable: false,
|
|
407
|
-
configurable: false,
|
|
408
|
-
writable: false,
|
|
409
|
-
value: metadata,
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
return result;
|
|
413
|
-
}
|
|
414
|
-
/**
|
|
415
|
-
* @description Constructs a URL for API requests
|
|
416
|
-
* @summary Builds a complete URL for API requests using the configured protocol and host,
|
|
417
|
-
* the specified table name, and optional query parameters. The method handles URL encoding.
|
|
418
|
-
* @param {string} tableName - The name of the table or endpoint
|
|
419
|
-
* @param {Record<string, string | number>} [queryParams] - Optional query parameters
|
|
420
|
-
* @return {string} The encoded URL string
|
|
421
|
-
*/
|
|
422
|
-
url(tableName, queryParams) {
|
|
423
|
-
const url = new URL(`${this.config.protocol}://${this.config.host}/${tableName}`);
|
|
424
|
-
if (queryParams)
|
|
425
|
-
Object.entries(queryParams).forEach(([key, value]) => url.searchParams.append(key, value.toString()));
|
|
426
|
-
// ensure spaces are encoded as %20 (not '+') to match expectations
|
|
427
|
-
return encodeURI(url.toString()).replace(/\+/g, "%20");
|
|
428
|
-
}
|
|
429
|
-
/**
|
|
430
|
-
* @description Executes a raw query
|
|
431
|
-
* @summary Method for executing raw queries directly with the HTTP client.
|
|
432
|
-
* This method is not supported by default in HTTP adapters and throws an UnsupportedError.
|
|
433
|
-
* Subclasses can override this method to provide implementation.
|
|
434
|
-
* @template R - The result type
|
|
435
|
-
* @param {Q} rawInput - The raw query input
|
|
436
|
-
* @param {boolean} process - Whether to process the result
|
|
437
|
-
* @param {...any[]} args - Additional arguments
|
|
438
|
-
* @return {Promise<R>} A promise that resolves with the query result
|
|
439
|
-
* @throws {UnsupportedError} Always throws as this method is not supported by default
|
|
440
|
-
*/
|
|
441
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
442
|
-
raw(rawInput, process, ...args) {
|
|
443
|
-
return Promise.reject(new core.UnsupportedError("Api is not natively available for HttpAdapters. If required, please extends this class"));
|
|
444
|
-
}
|
|
445
|
-
/**
|
|
446
|
-
* @description Creates a sequence
|
|
447
|
-
* @summary Method for creating a sequence for generating unique identifiers.
|
|
448
|
-
* This method is not supported by default in HTTP adapters and throws an UnsupportedError.
|
|
449
|
-
* Subclasses can override this method to provide implementation.
|
|
450
|
-
* @param {SequenceOptions} options - Options for creating the sequence
|
|
451
|
-
* @return {Promise<Sequence>} A promise that resolves with the created sequence
|
|
452
|
-
* @throws {UnsupportedError} Always throws as this method is not supported by default
|
|
453
|
-
*/
|
|
454
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
455
|
-
Sequence(options) {
|
|
456
|
-
return Promise.reject(new core.UnsupportedError("Api is not natively available for HttpAdapters. If required, please extends this class"));
|
|
457
|
-
}
|
|
458
|
-
/**
|
|
459
|
-
* @description Creates a statement for querying
|
|
460
|
-
* @summary Method for creating a statement for building and executing queries.
|
|
461
|
-
* This method is not supported by default in HTTP adapters and throws an UnsupportedError.
|
|
462
|
-
* Subclasses can override this method to provide implementation.
|
|
463
|
-
* @template M - The model type
|
|
464
|
-
* @template ! - The raw query type
|
|
465
|
-
* @return {Statement<Q, M, any>} A statement object for building queries
|
|
466
|
-
* @throws {UnsupportedError} Always throws as this method is not supported by default
|
|
467
|
-
*/
|
|
468
|
-
Statement() {
|
|
469
|
-
throw new core.UnsupportedError("Api is not natively available for HttpAdapters. If required, please extends this class");
|
|
470
|
-
}
|
|
471
|
-
/**
|
|
472
|
-
* @description Parses a condition into a query
|
|
473
|
-
* @summary Method for parsing a condition object into a query format understood by the HTTP client.
|
|
474
|
-
* This method is not supported by default in HTTP adapters and throws an UnsupportedError.
|
|
475
|
-
* Subclasses can override this method to provide implementation.
|
|
476
|
-
* @param {Condition<any>} condition - The condition to parse
|
|
477
|
-
* @return {Q} The parsed query
|
|
478
|
-
* @throws {UnsupportedError} Always throws as this method is not supported by default
|
|
479
|
-
*/
|
|
480
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
481
|
-
parseCondition(condition) {
|
|
482
|
-
throw new core.UnsupportedError("Api is not natively available for HttpAdapters. If required, please extends this class");
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
/**
|
|
487
|
-
* @description Axios adapter flavor identifier
|
|
488
|
-
* @summary Constant string identifier used to identify the Axios implementation of the HTTP adapter
|
|
489
|
-
* @const {string} AxiosFlavour
|
|
490
|
-
* @memberOf module:for-http.axios
|
|
491
|
-
*/
|
|
492
|
-
const AxiosFlavour = "axios";
|
|
493
|
-
|
|
494
|
-
/**
|
|
495
|
-
* @description Axios implementation of the HTTP adapter
|
|
496
|
-
* @summary Concrete implementation of HttpAdapter using Axios as the HTTP client.
|
|
497
|
-
* This adapter provides CRUD operations for RESTful APIs using Axios for HTTP requests.
|
|
498
|
-
* @template Axios - The Axios client type
|
|
499
|
-
* @template AxiosRequestConfig - The Axios request configuration type
|
|
500
|
-
* @template AxiosFlags - The flags type extending HttpFlags
|
|
501
|
-
* @template Context<AxiosFlags> - The context type for this adapter
|
|
502
|
-
* @param {Axios} native - The Axios instance
|
|
503
|
-
* @param {HttpConfig} config - Configuration for the HTTP adapter
|
|
504
|
-
* @param {string} [alias] - Optional alias for the adapter
|
|
505
|
-
* @class
|
|
506
|
-
* @example
|
|
507
|
-
* ```typescript
|
|
508
|
-
* import axios from 'axios';
|
|
509
|
-
* import { AxiosHttpAdapter } from '@decaf-ts/for-http';
|
|
510
|
-
*
|
|
511
|
-
* const config = { protocol: 'https', host: 'api.example.com' };
|
|
512
|
-
* const adapter = new AxiosHttpAdapter(axios.create(), config);
|
|
513
|
-
*
|
|
514
|
-
* // Use the adapter with a repository
|
|
515
|
-
* const userRepo = adapter.getRepository(User);
|
|
516
|
-
* const user = await userRepo.findById('123');
|
|
517
|
-
* ```
|
|
518
|
-
* @mermaid
|
|
519
|
-
* sequenceDiagram
|
|
520
|
-
* participant Client
|
|
521
|
-
* participant AxiosHttpAdapter
|
|
522
|
-
* participant Axios
|
|
523
|
-
* participant API
|
|
524
|
-
*
|
|
525
|
-
* Client->>AxiosHttpAdapter: create(table, id, data)
|
|
526
|
-
* AxiosHttpAdapter->>AxiosHttpAdapter: url(table)
|
|
527
|
-
* AxiosHttpAdapter->>Axios: post(url, data)
|
|
528
|
-
* Axios->>API: HTTP POST Request
|
|
529
|
-
* API-->>Axios: Response
|
|
530
|
-
* Axios-->>AxiosHttpAdapter: Response Data
|
|
531
|
-
* AxiosHttpAdapter-->>Client: Created Resource
|
|
532
|
-
*
|
|
533
|
-
* Client->>AxiosHttpAdapter: read(table, id)
|
|
534
|
-
* AxiosHttpAdapter->>AxiosHttpAdapter: url(table, {id})
|
|
535
|
-
* AxiosHttpAdapter->>Axios: get(url)
|
|
536
|
-
* Axios->>API: HTTP GET Request
|
|
537
|
-
* API-->>Axios: Response
|
|
538
|
-
* Axios-->>AxiosHttpAdapter: Response Data
|
|
539
|
-
* AxiosHttpAdapter-->>Client: Resource Data
|
|
540
|
-
*/
|
|
541
|
-
class AxiosHttpAdapter extends HttpAdapter {
|
|
542
|
-
constructor(config, alias) {
|
|
543
|
-
super(config, AxiosFlavour, alias);
|
|
544
|
-
}
|
|
545
|
-
getClient() {
|
|
546
|
-
return new axios.Axios();
|
|
547
|
-
}
|
|
548
|
-
/**
|
|
549
|
-
* @description Sends an HTTP request using Axios
|
|
550
|
-
* @summary Implementation of the abstract request method from HttpAdapter.
|
|
551
|
-
* This method uses the Axios instance to send HTTP requests with the provided configuration.
|
|
552
|
-
* @template V - The response value type
|
|
553
|
-
* @param {AxiosRequestConfig} details - The Axios request configuration
|
|
554
|
-
* @return {Promise<V>} A promise that resolves with the response data
|
|
555
|
-
*/
|
|
556
|
-
async request(details) {
|
|
557
|
-
return this.client.request(details);
|
|
558
|
-
}
|
|
559
|
-
/**
|
|
560
|
-
* @description Creates a new resource via HTTP POST
|
|
561
|
-
* @summary Implementation of the abstract create method from HttpAdapter.
|
|
562
|
-
* This method sends a POST request to the specified endpoint with the model data.
|
|
563
|
-
* @param {string} tableName - The name of the table or endpoint
|
|
564
|
-
* @param {string|number} id - The identifier for the resource (not used in URL for POST)
|
|
565
|
-
* @param {Record<string, any>} model - The data model to create
|
|
566
|
-
* @return {Promise<Record<string, any>>} A promise that resolves with the created resource
|
|
567
|
-
*/
|
|
568
|
-
async create(tableName, id, model) {
|
|
569
|
-
try {
|
|
570
|
-
const url = this.url(tableName);
|
|
571
|
-
return this.client.post(url, model);
|
|
572
|
-
}
|
|
573
|
-
catch (e) {
|
|
574
|
-
throw this.parseError(e);
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
/**
|
|
578
|
-
* @description Retrieves a resource by ID via HTTP GET
|
|
579
|
-
* @summary Implementation of the abstract read method from HttpAdapter.
|
|
580
|
-
* This method sends a GET request to the specified endpoint with the ID as a query parameter.
|
|
581
|
-
* @param {string} tableName - The name of the table or endpoint
|
|
582
|
-
* @param {string|number|bigint} id - The identifier for the resource to retrieve
|
|
583
|
-
* @return {Promise<Record<string, any>>} A promise that resolves with the retrieved resource
|
|
584
|
-
*/
|
|
585
|
-
async read(tableName, id) {
|
|
586
|
-
try {
|
|
587
|
-
const url = this.url(tableName, { id: id });
|
|
588
|
-
return this.client.get(url);
|
|
589
|
-
}
|
|
590
|
-
catch (e) {
|
|
591
|
-
throw this.parseError(e);
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
/**
|
|
595
|
-
* @description Updates an existing resource via HTTP PUT
|
|
596
|
-
* @summary Implementation of the abstract update method from HttpAdapter.
|
|
597
|
-
* This method sends a PUT request to the specified endpoint with the updated model data.
|
|
598
|
-
* @param {string} tableName - The name of the table or endpoint
|
|
599
|
-
* @param {string|number} id - The identifier for the resource (not used in URL for PUT)
|
|
600
|
-
* @param {Record<string, any>} model - The updated data model
|
|
601
|
-
* @return {Promise<Record<string, any>>} A promise that resolves with the updated resource
|
|
602
|
-
*/
|
|
603
|
-
async update(tableName, id, model) {
|
|
604
|
-
try {
|
|
605
|
-
const url = this.url(tableName);
|
|
606
|
-
return this.client.put(url, model);
|
|
607
|
-
}
|
|
608
|
-
catch (e) {
|
|
609
|
-
throw this.parseError(e);
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
/**
|
|
613
|
-
* @description Deletes a resource by ID via HTTP DELETE
|
|
614
|
-
* @summary Implementation of the abstract delete method from HttpAdapter.
|
|
615
|
-
* This method sends a DELETE request to the specified endpoint with the ID as a query parameter.
|
|
616
|
-
* @param {string} tableName - The name of the table or endpoint
|
|
617
|
-
* @param {string|number|bigint} id - The identifier for the resource to delete
|
|
618
|
-
* @return {Promise<Record<string, any>>} A promise that resolves with the deletion result
|
|
619
|
-
*/
|
|
620
|
-
async delete(tableName, id) {
|
|
621
|
-
try {
|
|
622
|
-
const url = this.url(tableName, { id: id });
|
|
623
|
-
return this.client.delete(url);
|
|
624
|
-
}
|
|
625
|
-
catch (e) {
|
|
626
|
-
throw this.parseError(e);
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
parseError(err) {
|
|
630
|
-
const errs = [
|
|
631
|
-
dbDecorators.InternalError,
|
|
632
|
-
core.AuthorizationError,
|
|
633
|
-
dbDecorators.ConflictError,
|
|
634
|
-
dbDecorators.NotFoundError,
|
|
635
|
-
core.UnsupportedError,
|
|
636
|
-
];
|
|
637
|
-
for (const error of errs) {
|
|
638
|
-
if (err.message.includes(error.name))
|
|
639
|
-
return new error(err.message);
|
|
640
|
-
}
|
|
641
|
-
return new dbDecorators.InternalError(err.message);
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
/**
|
|
646
|
-
* @description HTTP client module for REST API interactions
|
|
647
|
-
* @summary This module provides classes and utilities for interacting with REST APIs.
|
|
648
|
-
* It exposes repository and service classes for making HTTP requests, along with
|
|
649
|
-
* type definitions and adapters for different HTTP clients. The module includes
|
|
650
|
-
* {@link RestRepository} and {@link RestService} for API interactions.
|
|
651
|
-
* @namespace axios
|
|
652
|
-
* @memberOf module:for-http
|
|
653
|
-
*/
|
|
654
|
-
AxiosHttpAdapter.decoration();
|
|
655
|
-
|
|
656
|
-
/**
|
|
657
|
-
* @description Repository for REST API interactions
|
|
658
|
-
* @summary A specialized repository implementation for interacting with REST APIs.
|
|
659
|
-
* This class extends the core Repository class and works with HTTP adapters to
|
|
660
|
-
* provide CRUD operations for models via REST endpoints.
|
|
661
|
-
* This Is NOT the default repository for the HTTP adapter. That would be {@link RestService}.
|
|
662
|
-
* Use this only in the specific case of needing to run the CURD model logic (decoration) before submitting to the backend
|
|
663
|
-
* @template M - The model type, extending Model
|
|
664
|
-
* @template Q - The query type used by the adapter
|
|
665
|
-
* @template A - The HTTP adapter type, extending HttpAdapter
|
|
666
|
-
* @template F - The HTTP flags type, extending HttpFlags
|
|
667
|
-
* @template C - The context type, extending Context<F>
|
|
668
|
-
* @param {A} adapter - The HTTP adapter instance
|
|
669
|
-
* @param {Constructor<M>} [clazz] - Optional constructor for the model class
|
|
670
|
-
* @class RestRepository
|
|
671
|
-
* @example
|
|
672
|
-
* ```typescript
|
|
673
|
-
* // Create a repository for User model with Axios adapter
|
|
674
|
-
* const axiosAdapter = new AxiosAdapter({
|
|
675
|
-
* protocol: 'https',
|
|
676
|
-
* host: 'api.example.com'
|
|
677
|
-
* });
|
|
678
|
-
* const userRepository = new RestRepository(axiosAdapter, User);
|
|
679
|
-
*
|
|
680
|
-
* // Use the repository for CRUD operations
|
|
681
|
-
* const user = await userRepository.findById('123');
|
|
682
|
-
* ```
|
|
683
|
-
* @see {@link RestService}
|
|
684
|
-
*/
|
|
685
|
-
class RestRepository extends core.Repository {
|
|
686
|
-
constructor(adapter, clazz) {
|
|
687
|
-
super(adapter, clazz);
|
|
688
|
-
}
|
|
689
|
-
url(path, queryParams) {
|
|
690
|
-
return this.adapter.url(path, queryParams);
|
|
691
|
-
}
|
|
692
|
-
async request(details) {
|
|
693
|
-
return this.adapter.request(details);
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
/**
|
|
698
|
-
* @description Current version of the for-http module
|
|
699
|
-
* @summary Version identifier for the module
|
|
700
|
-
* @const VERSION
|
|
701
|
-
*/
|
|
702
|
-
const VERSION = "0.2.9";
|
|
703
|
-
|
|
704
|
-
exports.AxiosFlavour = AxiosFlavour;
|
|
705
|
-
exports.AxiosHttpAdapter = AxiosHttpAdapter;
|
|
706
|
-
exports.HttpAdapter = HttpAdapter;
|
|
707
|
-
exports.RestRepository = RestRepository;
|
|
708
|
-
exports.RestService = RestService;
|
|
709
|
-
exports.VERSION = VERSION;
|
|
710
|
-
|
|
711
|
-
}));
|
|
712
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yLWh0dHAuY2pzIiwic291cmNlcyI6WyIuLi9zcmMvUmVzdFNlcnZpY2UudHMiLCIuLi9zcmMvYWRhcHRlci50cyIsIi4uL3NyYy9heGlvcy9jb25zdGFudHMudHMiLCIuLi9zcmMvYXhpb3MvYXhpb3MudHMiLCIuLi9zcmMvYXhpb3MvaW5kZXgudHMiLCIuLi9zcmMvUmVzdFJlcG9zaXRvcnkudHMiLCIuLi9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQnVsa0NydWRPcGVyYXRvcixcbiAgQ29udGV4dCxcbiAgQ3J1ZE9wZXJhdG9yLFxuICBmaW5kUHJpbWFyeUtleSxcbiAgSW50ZXJuYWxFcnJvcixcbn0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciwgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBPYnNlcnZlciwgUmVwb3NpdG9yeSB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgSHR0cEFkYXB0ZXIgfSBmcm9tIFwiLi9hZGFwdGVyXCI7XG5pbXBvcnQgeyBIdHRwRmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgTG9nZ2VkQ2xhc3MsIExvZ2dlciB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTZXJ2aWNlIGNsYXNzIGZvciBSRVNUIEFQSSBvcGVyYXRpb25zXG4gKiBAc3VtbWFyeSBQcm92aWRlcyBhIGNvbXByZWhlbnNpdmUgaW1wbGVtZW50YXRpb24gZm9yIGludGVyYWN0aW5nIHdpdGggUkVTVCBBUElzLlxuICogVGhpcyBjbGFzcyBpbXBsZW1lbnRzIENSVUQgb3BlcmF0aW9ucyBmb3Igc2luZ2xlIGFuZCBidWxrIG9wZXJhdGlvbnMsIGFzIHdlbGwgYXNcbiAqIHRoZSBPYnNlcnZhYmxlIHBhdHRlcm4gdG8gbm90aWZ5IG9ic2VydmVycyBvZiBjaGFuZ2VzLiBJdCB3b3JrcyB3aXRoIEhUVFAgYWRhcHRlcnNcbiAqIHRvIHBlcmZvcm0gdGhlIGFjdHVhbCBBUEkgcmVxdWVzdHMgYW5kIGhhbmRsZXMgbW9kZWwgY29udmVyc2lvbi5cbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUsIGV4dGVuZGluZyBNb2RlbFxuICogQHRlbXBsYXRlIFEgLSBUaGUgcXVlcnkgdHlwZSB1c2VkIGJ5IHRoZSBhZGFwdGVyXG4gKiBAdGVtcGxhdGUgQSAtIFRoZSBIVFRQIGFkYXB0ZXIgdHlwZSwgZXh0ZW5kaW5nIEh0dHBBZGFwdGVyXG4gKiBAdGVtcGxhdGUgRiAtIFRoZSBIVFRQIGZsYWdzIHR5cGUsIGV4dGVuZGluZyBIdHRwRmxhZ3NcbiAqIEB0ZW1wbGF0ZSBDIC0gVGhlIGNvbnRleHQgdHlwZSwgZXh0ZW5kaW5nIENvbnRleHQ8Rj5cbiAqIEBwYXJhbSB7QX0gYWRhcHRlciAtIFRoZSBIVFRQIGFkYXB0ZXIgaW5zdGFuY2VcbiAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IFtjbGF6el0gLSBPcHRpb25hbCBjb25zdHJ1Y3RvciBmb3IgdGhlIG1vZGVsIGNsYXNzXG4gKiBAY2xhc3MgUmVzdFNlcnZpY2VcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBDcmVhdGUgYSBzZXJ2aWNlIGZvciBVc2VyIG1vZGVsIHdpdGggQXhpb3MgYWRhcHRlclxuICogY29uc3QgYXhpb3NBZGFwdGVyID0gbmV3IEF4aW9zQWRhcHRlcih7XG4gKiAgIHByb3RvY29sOiAnaHR0cHMnLFxuICogICBob3N0OiAnYXBpLmV4YW1wbGUuY29tJ1xuICogfSk7XG4gKiBjb25zdCB1c2VyU2VydmljZSA9IG5ldyBSZXN0U2VydmljZShheGlvc0FkYXB0ZXIsIFVzZXIpO1xuICpcbiAqIC8vIENyZWF0ZSBhIG5ldyB1c2VyXG4gKiBjb25zdCB1c2VyID0gbmV3IFVzZXIoeyBuYW1lOiAnSm9obiBEb2UnLCBlbWFpbDogJ2pvaG5AZXhhbXBsZS5jb20nIH0pO1xuICogY29uc3QgY3JlYXRlZFVzZXIgPSBhd2FpdCB1c2VyU2VydmljZS5jcmVhdGUodXNlcik7XG4gKlxuICogLy8gVXBkYXRlIGEgdXNlclxuICogY3JlYXRlZFVzZXIubmFtZSA9ICdKYW5lIERvZSc7XG4gKiBjb25zdCB1cGRhdGVkVXNlciA9IGF3YWl0IHVzZXJTZXJ2aWNlLnVwZGF0ZShjcmVhdGVkVXNlcik7XG4gKlxuICogLy8gRGVsZXRlIGEgdXNlclxuICogYXdhaXQgdXNlclNlcnZpY2UuZGVsZXRlKHVwZGF0ZWRVc2VyLmlkKTtcbiAqIGBgYFxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgU2VydmljZSBhcyBSZXN0U2VydmljZVxuICogICBwYXJ0aWNpcGFudCBBZGFwdGVyIGFzIEh0dHBBZGFwdGVyXG4gKiAgIHBhcnRpY2lwYW50IEFQSVxuICogICBDbGllbnQtPj5TZXJ2aWNlOiBjcmVhdGUobW9kZWwpXG4gKiAgIFNlcnZpY2UtPj5BZGFwdGVyOiBwcmVwYXJlKG1vZGVsLCBwaylcbiAqICAgU2VydmljZS0+PkFkYXB0ZXI6IGNyZWF0ZSh0YWJsZSwgaWQsIHJlY29yZClcbiAqICAgQWRhcHRlci0+PkFQSTogSFRUUCBQT1NUXG4gKiAgIEFQSS0tPj5BZGFwdGVyOiAyMDEgQ3JlYXRlZFxuICogICBBZGFwdGVyLS0+PlNlcnZpY2U6IHJlY29yZFxuICogICBTZXJ2aWNlLS0+PkNsaWVudDogcmV2ZXJ0KHJlY29yZClcbiAqL1xuZXhwb3J0IGNsYXNzIFJlc3RTZXJ2aWNlPFxuICAgIE0gZXh0ZW5kcyBNb2RlbCxcbiAgICBRLFxuICAgIEEgZXh0ZW5kcyBIdHRwQWRhcHRlcjxhbnksIGFueSwgUSwgRiwgQz4sXG4gICAgRiBleHRlbmRzIEh0dHBGbGFncyA9IEh0dHBGbGFncyxcbiAgICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4gID5cbiAgZXh0ZW5kcyBMb2dnZWRDbGFzc1xuICBpbXBsZW1lbnRzIENydWRPcGVyYXRvcjxNPiwgQnVsa0NydWRPcGVyYXRvcjxNPiwgT2JzZXJ2YWJsZVxue1xuICBwcml2YXRlIHJlYWRvbmx5IF9jbGFzcyE6IENvbnN0cnVjdG9yPE0+O1xuICBwcml2YXRlIF9wayE6IGtleW9mIE07XG5cbiAgcHJpdmF0ZSBsb2dnZXI/OiBMb2dnZXI7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXRzIHRoZSBtb2RlbCBjbGFzcyBjb25zdHJ1Y3RvclxuICAgKiBAc3VtbWFyeSBSZXRyaWV2ZXMgdGhlIG1vZGVsIGNsYXNzIGNvbnN0cnVjdG9yIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHNlcnZpY2UuXG4gICAqIFRocm93cyBhbiBlcnJvciBpZiBubyBjbGFzcyBkZWZpbml0aW9uIGlzIGZvdW5kLlxuICAgKiBAcmV0dXJuIHtDb25zdHJ1Y3RvcjxNPn0gVGhlIG1vZGVsIGNsYXNzIGNvbnN0cnVjdG9yXG4gICAqIEB0aHJvd3Mge0ludGVybmFsRXJyb3J9IElmIG5vIGNsYXNzIGRlZmluaXRpb24gaXMgZm91bmRcbiAgICovXG4gIGdldCBjbGFzcygpIHtcbiAgICBpZiAoIXRoaXMuX2NsYXNzKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJObyBjbGFzcyBkZWZpbml0aW9uIGZvdW5kIGZvciB0aGlzIHJlcG9zaXRvcnlcIik7XG4gICAgcmV0dXJuIHRoaXMuX2NsYXNzO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGdldCBsb2coKTogTG9nZ2VyIHtcbiAgICBpZiAoIXRoaXMubG9nZ2VyKVxuICAgICAgdGhpcy5sb2dnZXIgPSAoXG4gICAgICAgIHRoaXMuYWRhcHRlcltcImxvZ1wiIGFzIGtleW9mIHR5cGVvZiB0aGlzLmFkYXB0ZXJdIGFzIExvZ2dlclxuICAgICAgKS5mb3IodGhpcy50b1N0cmluZygpKTtcbiAgICByZXR1cm4gdGhpcy5sb2dnZXI7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIHByaW1hcnkga2V5IHByb3BlcnR5IG5hbWVcbiAgICogQHN1bW1hcnkgUmV0cmlldmVzIHRoZSBuYW1lIG9mIHRoZSBwcmltYXJ5IGtleSBwcm9wZXJ0eSBmb3IgdGhlIG1vZGVsLlxuICAgKiBJZiBub3QgYWxyZWFkeSBkZXRlcm1pbmVkLCBpdCBmaW5kcyB0aGUgcHJpbWFyeSBrZXkgdXNpbmcgdGhlIG1vZGVsIGNsYXNzLlxuICAgKiBAcmV0dXJuIFRoZSBwcmltYXJ5IGtleSBwcm9wZXJ0eSBuYW1lXG4gICAqL1xuICBnZXQgcGsoKSB7XG4gICAgaWYgKCF0aGlzLl9waykgdGhpcy5fcGsgPSBmaW5kUHJpbWFyeUtleShuZXcgdGhpcy5jbGFzcygpKS5pZDtcbiAgICByZXR1cm4gdGhpcy5fcGs7XG4gIH1cblxuICBwcm90ZWN0ZWQgb2JzZXJ2ZXJzOiBPYnNlcnZlcltdID0gW107XG5cbiAgcHJpdmF0ZSByZWFkb25seSBfYWRhcHRlciE6IEE7XG4gIHByaXZhdGUgX3RhYmxlTmFtZSE6IHN0cmluZztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIEhUVFAgYWRhcHRlclxuICAgKiBAc3VtbWFyeSBSZXRyaWV2ZXMgdGhlIEhUVFAgYWRhcHRlciBhc3NvY2lhdGVkIHdpdGggdGhpcyBzZXJ2aWNlLlxuICAgKiBUaHJvd3MgYW4gZXJyb3IgaWYgbm8gYWRhcHRlciBpcyBmb3VuZC5cbiAgICogQHJldHVybiB7QX0gVGhlIEhUVFAgYWRhcHRlciBpbnN0YW5jZVxuICAgKiBAdGhyb3dzIHtJbnRlcm5hbEVycm9yfSBJZiBubyBhZGFwdGVyIGlzIGZvdW5kXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0IGFkYXB0ZXIoKTogQSB7XG4gICAgaWYgKCF0aGlzLl9hZGFwdGVyKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIFwiTm8gYWRhcHRlciBmb3VuZCBmb3IgdGhpcyByZXBvc2l0b3J5LiBkaWQgeW91IHVzZSB0aGUgQHVzZXMgZGVjb3JhdG9yIG9yIHBhc3MgaXQgaW4gdGhlIGNvbnN0cnVjdG9yP1wiXG4gICAgICApO1xuICAgIHJldHVybiB0aGlzLl9hZGFwdGVyO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXRzIHRoZSB0YWJsZSBuYW1lIGZvciB0aGUgbW9kZWxcbiAgICogQHN1bW1hcnkgUmV0cmlldmVzIHRoZSB0YWJsZSBuYW1lIGFzc29jaWF0ZWQgd2l0aCB0aGUgbW9kZWwgY2xhc3MuXG4gICAqIElmIG5vdCBhbHJlYWR5IGRldGVybWluZWQsIGl0IGdldHMgdGhlIHRhYmxlIG5hbWUgZnJvbSB0aGUgUmVwb3NpdG9yeSB1dGlsaXR5LlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSB0YWJsZSBuYW1lXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0IHRhYmxlTmFtZSgpIHtcbiAgICBpZiAoIXRoaXMuX3RhYmxlTmFtZSkgdGhpcy5fdGFibGVOYW1lID0gUmVwb3NpdG9yeS50YWJsZSh0aGlzLmNsYXNzKTtcbiAgICByZXR1cm4gdGhpcy5fdGFibGVOYW1lO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplcyBhIG5ldyBSZXN0U2VydmljZSBpbnN0YW5jZVxuICAgKiBAc3VtbWFyeSBDcmVhdGVzIGEgbmV3IHNlcnZpY2UgaW5zdGFuY2Ugd2l0aCB0aGUgc3BlY2lmaWVkIGFkYXB0ZXIgYW5kIG9wdGlvbmFsIG1vZGVsIGNsYXNzLlxuICAgKiBUaGUgY29uc3RydWN0b3Igc3RvcmVzIHRoZSBhZGFwdGVyIGFuZCBtb2RlbCBjbGFzcyBmb3IgbGF0ZXIgdXNlIGluIENSVUQgb3BlcmF0aW9ucy5cbiAgICogQHBhcmFtIHtBfSBhZGFwdGVyIC0gVGhlIEhUVFAgYWRhcHRlciBpbnN0YW5jZSB0byB1c2UgZm9yIEFQSSByZXF1ZXN0c1xuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBbY2xhenpdIC0gT3B0aW9uYWwgY29uc3RydWN0b3IgZm9yIHRoZSBtb2RlbCBjbGFzc1xuICAgKi9cbiAgY29uc3RydWN0b3IoYWRhcHRlcjogQSwgY2xheno/OiBDb25zdHJ1Y3RvcjxNPikge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5fYWRhcHRlciA9IGFkYXB0ZXI7XG4gICAgaWYgKGNsYXp6KSB0aGlzLl9jbGFzcyA9IGNsYXp6O1xuICB9XG5cbiAgdXJsKHBhdGg6IHN0cmluZywgcXVlcnlQYXJhbXM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBudW1iZXI+KSB7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci51cmwocGF0aCwgcXVlcnlQYXJhbXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbmV3IHJlc291cmNlXG4gICAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBuZXcgcmVzb3VyY2UgaW4gdGhlIFJFU1QgQVBJIHVzaW5nIHRoZSBwcm92aWRlZCBtb2RlbC5cbiAgICogVGhlIG1ldGhvZCBwcmVwYXJlcyB0aGUgbW9kZWwgZm9yIHRoZSBhZGFwdGVyLCBzZW5kcyB0aGUgY3JlYXRlIHJlcXVlc3QsXG4gICAqIGFuZCB0aGVuIGNvbnZlcnRzIHRoZSByZXNwb25zZSBiYWNrIHRvIGEgbW9kZWwgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2UgdG8gY3JlYXRlXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBhZGFwdGVyXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGNyZWF0ZWQgbW9kZWwgaW5zdGFuY2VcbiAgICovXG4gIGFzeW5jIGNyZWF0ZShtb2RlbDogTSwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE0+IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcHJlZmVyLWNvbnN0XG4gICAgbGV0IHsgcmVjb3JkLCBpZCB9ID0gdGhpcy5hZGFwdGVyLnByZXBhcmUobW9kZWwsIHRoaXMucGspO1xuICAgIHJlY29yZCA9IGF3YWl0IHRoaXMuYWRhcHRlci5jcmVhdGUodGhpcy50YWJsZU5hbWUsIGlkLCByZWNvcmQsIC4uLmFyZ3MpO1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmV2ZXJ0KHJlY29yZCwgdGhpcy5jbGFzcywgdGhpcy5waywgaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgYSByZXNvdXJjZSBieSBJRFxuICAgKiBAc3VtbWFyeSBGZXRjaGVzIGEgcmVzb3VyY2UgZnJvbSB0aGUgUkVTVCBBUEkgdXNpbmcgdGhlIHByb3ZpZGVkIElELlxuICAgKiBUaGUgbWV0aG9kIHNlbmRzIHRoZSByZWFkIHJlcXVlc3QgYW5kIGNvbnZlcnRzIHRoZSByZXNwb25zZSB0byBhIG1vZGVsIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIC0gVGhlIGlkZW50aWZpZXIgb2YgdGhlIHJlc291cmNlIHRvIHJldHJpZXZlXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBhZGFwdGVyXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHJldHJpZXZlZCBtb2RlbCBpbnN0YW5jZVxuICAgKi9cbiAgYXN5bmMgcmVhZChpZDogc3RyaW5nIHwgbnVtYmVyLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TT4ge1xuICAgIGNvbnN0IG0gPSBhd2FpdCB0aGlzLmFkYXB0ZXIucmVhZCh0aGlzLnRhYmxlTmFtZSwgaWQsIC4uLmFyZ3MpO1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmV2ZXJ0KG0sIHRoaXMuY2xhc3MsIHRoaXMucGssIGlkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVXBkYXRlcyBhbiBleGlzdGluZyByZXNvdXJjZVxuICAgKiBAc3VtbWFyeSBVcGRhdGVzIGFuIGV4aXN0aW5nIHJlc291cmNlIGluIHRoZSBSRVNUIEFQSSB1c2luZyB0aGUgcHJvdmlkZWQgbW9kZWwuXG4gICAqIFRoZSBtZXRob2QgcHJlcGFyZXMgdGhlIG1vZGVsIGZvciB0aGUgYWRhcHRlciwgc2VuZHMgdGhlIHVwZGF0ZSByZXF1ZXN0LFxuICAgKiBhbmQgdGhlbiBjb252ZXJ0cyB0aGUgcmVzcG9uc2UgYmFjayB0byBhIG1vZGVsIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHdpdGggdXBkYXRlZCBkYXRhXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBhZGFwdGVyXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHVwZGF0ZWQgbW9kZWwgaW5zdGFuY2VcbiAgICovXG4gIGFzeW5jIHVwZGF0ZShtb2RlbDogTSwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE0+IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcHJlZmVyLWNvbnN0XG4gICAgbGV0IHsgcmVjb3JkLCBpZCB9ID0gdGhpcy5hZGFwdGVyLnByZXBhcmUobW9kZWwsIHRoaXMucGspO1xuICAgIHJlY29yZCA9IGF3YWl0IHRoaXMuYWRhcHRlci51cGRhdGUodGhpcy50YWJsZU5hbWUsIGlkLCByZWNvcmQsIC4uLmFyZ3MpO1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmV2ZXJ0KHJlY29yZCwgdGhpcy5jbGFzcywgdGhpcy5waywgaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWxldGVzIGEgcmVzb3VyY2UgYnkgSURcbiAgICogQHN1bW1hcnkgUmVtb3ZlcyBhIHJlc291cmNlIGZyb20gdGhlIFJFU1QgQVBJIHVzaW5nIHRoZSBwcm92aWRlZCBJRC5cbiAgICogVGhlIG1ldGhvZCBzZW5kcyB0aGUgZGVsZXRlIHJlcXVlc3QgYW5kIGNvbnZlcnRzIHRoZSByZXNwb25zZSB0byBhIG1vZGVsIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIC0gVGhlIGlkZW50aWZpZXIgb2YgdGhlIHJlc291cmNlIHRvIGRlbGV0ZVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgYWRhcHRlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPE0+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBkZWxldGVkIG1vZGVsIGluc3RhbmNlXG4gICAqL1xuICBhc3luYyBkZWxldGUoaWQ6IHN0cmluZyB8IG51bWJlciwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE0+IHtcbiAgICBjb25zdCBtID0gYXdhaXQgdGhpcy5hZGFwdGVyLmRlbGV0ZSh0aGlzLnRhYmxlTmFtZSwgaWQsIC4uLmFyZ3MpO1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmV2ZXJ0KG0sIHRoaXMuY2xhc3MsIHRoaXMucGssIGlkKTtcbiAgfVxuXG4gIGFzeW5jIHJlcXVlc3Q8Vj4oZGV0YWlsczogUSkge1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmVxdWVzdDxWPihkZXRhaWxzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBtdWx0aXBsZSByZXNvdXJjZXNcbiAgICogQHN1bW1hcnkgQ3JlYXRlcyBtdWx0aXBsZSByZXNvdXJjZXMgaW4gdGhlIFJFU1QgQVBJIHVzaW5nIHRoZSBwcm92aWRlZCBtb2RlbHMuXG4gICAqIFRoZSBtZXRob2QgcHJlcGFyZXMgZWFjaCBtb2RlbCBmb3IgdGhlIGFkYXB0ZXIsIHNlbmRzIGEgYnVsayBjcmVhdGUgcmVxdWVzdCxcbiAgICogYW5kIHRoZW4gY29udmVydHMgdGhlIHJlc3BvbnNlcyBiYWNrIHRvIG1vZGVsIGluc3RhbmNlcy5cbiAgICogQHBhcmFtIHtNW119IG1vZGVscyAtIFRoZSBtb2RlbCBpbnN0YW5jZXMgdG8gY3JlYXRlXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBhZGFwdGVyXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCBhbiBhcnJheSBvZiBjcmVhdGVkIG1vZGVsIGluc3RhbmNlc1xuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAgICogICBwYXJ0aWNpcGFudCBTZXJ2aWNlIGFzIFJlc3RTZXJ2aWNlXG4gICAqICAgcGFydGljaXBhbnQgQWRhcHRlciBhcyBIdHRwQWRhcHRlclxuICAgKiAgIENsaWVudC0+PlNlcnZpY2U6IGNyZWF0ZUFsbChtb2RlbHMpXG4gICAqICAgU2VydmljZS0+PkFkYXB0ZXI6IHByZXBhcmUobW9kZWwsIHBrKSB4IE5cbiAgICogICBTZXJ2aWNlLT4+QWRhcHRlcjogY3JlYXRlQWxsKHRhYmxlLCBpZHNbXSwgcmVjb3Jkc1tdKVxuICAgKiAgIEFkYXB0ZXItLT4+U2VydmljZTogcmVjb3Jkc1tdXG4gICAqICAgU2VydmljZS0tPj5DbGllbnQ6IHJldmVydChyZWNvcmRzW10pXG4gICAqL1xuICBhc3luYyBjcmVhdGVBbGwobW9kZWxzOiBNW10sIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxNW10+IHtcbiAgICBpZiAoIW1vZGVscy5sZW5ndGgpIHJldHVybiBtb2RlbHM7XG4gICAgY29uc3QgcHJlcGFyZWQgPSBtb2RlbHMubWFwKChtKSA9PiB0aGlzLmFkYXB0ZXIucHJlcGFyZShtLCB0aGlzLnBrKSk7XG4gICAgY29uc3QgaWRzID0gcHJlcGFyZWQubWFwKChwKSA9PiBwLmlkKTtcbiAgICBsZXQgcmVjb3JkcyA9IHByZXBhcmVkLm1hcCgocCkgPT4gcC5yZWNvcmQpO1xuICAgIHJlY29yZHMgPSBhd2FpdCB0aGlzLmFkYXB0ZXIuY3JlYXRlQWxsKFxuICAgICAgdGhpcy50YWJsZU5hbWUsXG4gICAgICBpZHMgYXMgKHN0cmluZyB8IG51bWJlcilbXSxcbiAgICAgIHJlY29yZHMsXG4gICAgICAuLi5hcmdzXG4gICAgKTtcbiAgICByZXR1cm4gcmVjb3Jkcy5tYXAoKHIsIGkpID0+XG4gICAgICB0aGlzLmFkYXB0ZXIucmV2ZXJ0KHIsIHRoaXMuY2xhc3MsIHRoaXMucGssIGlkc1tpXSBhcyBzdHJpbmcgfCBudW1iZXIpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRGVsZXRlcyBtdWx0aXBsZSByZXNvdXJjZXMgYnkgSURzXG4gICAqIEBzdW1tYXJ5IFJlbW92ZXMgbXVsdGlwbGUgcmVzb3VyY2VzIGZyb20gdGhlIFJFU1QgQVBJIHVzaW5nIHRoZSBwcm92aWRlZCBJRHMuXG4gICAqIFRoZSBtZXRob2Qgc2VuZHMgYSBidWxrIGRlbGV0ZSByZXF1ZXN0IGFuZCBjb252ZXJ0cyB0aGUgcmVzcG9uc2VzIHRvIG1vZGVsIGluc3RhbmNlcy5cbiAgICogQHBhcmFtIHtzdHJpbmdbXXxudW1iZXJbXX0ga2V5cyAtIFRoZSBpZGVudGlmaWVycyBvZiB0aGUgcmVzb3VyY2VzIHRvIGRlbGV0ZVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgYWRhcHRlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPE1bXT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggYW4gYXJyYXkgb2YgZGVsZXRlZCBtb2RlbCBpbnN0YW5jZXNcbiAgICovXG4gIGFzeW5jIGRlbGV0ZUFsbChrZXlzOiBzdHJpbmdbXSB8IG51bWJlcltdLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TVtdPiB7XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IHRoaXMuYWRhcHRlci5kZWxldGVBbGwodGhpcy50YWJsZU5hbWUsIGtleXMsIC4uLmFyZ3MpO1xuICAgIHJldHVybiByZXN1bHRzLm1hcCgociwgaSkgPT5cbiAgICAgIHRoaXMuYWRhcHRlci5yZXZlcnQociwgdGhpcy5jbGFzcywgdGhpcy5waywga2V5c1tpXSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgbXVsdGlwbGUgcmVzb3VyY2VzIGJ5IElEc1xuICAgKiBAc3VtbWFyeSBGZXRjaGVzIG11bHRpcGxlIHJlc291cmNlcyBmcm9tIHRoZSBSRVNUIEFQSSB1c2luZyB0aGUgcHJvdmlkZWQgSURzLlxuICAgKiBUaGUgbWV0aG9kIHNlbmRzIGEgYnVsayByZWFkIHJlcXVlc3QgYW5kIGNvbnZlcnRzIHRoZSByZXNwb25zZXMgdG8gbW9kZWwgaW5zdGFuY2VzLlxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfG51bWJlcltdfSBrZXlzIC0gVGhlIGlkZW50aWZpZXJzIG9mIHRoZSByZXNvdXJjZXMgdG8gcmV0cmlldmVcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIGFkYXB0ZXJcbiAgICogQHJldHVybiB7UHJvbWlzZTxNW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIGFuIGFycmF5IG9mIHJldHJpZXZlZCBtb2RlbCBpbnN0YW5jZXNcbiAgICovXG4gIGFzeW5jIHJlYWRBbGwoa2V5czogc3RyaW5nW10gfCBudW1iZXJbXSwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE1bXT4ge1xuICAgIGNvbnN0IHJlY29yZHMgPSBhd2FpdCB0aGlzLmFkYXB0ZXIucmVhZEFsbCh0aGlzLnRhYmxlTmFtZSwga2V5cywgLi4uYXJncyk7XG4gICAgcmV0dXJuIHJlY29yZHMubWFwKChyLCBpKSA9PlxuICAgICAgdGhpcy5hZGFwdGVyLnJldmVydChyLCB0aGlzLmNsYXNzLCB0aGlzLnBrLCBrZXlzW2ldKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgbXVsdGlwbGUgcmVzb3VyY2VzXG4gICAqIEBzdW1tYXJ5IFVwZGF0ZXMgbXVsdGlwbGUgcmVzb3VyY2VzIGluIHRoZSBSRVNUIEFQSSB1c2luZyB0aGUgcHJvdmlkZWQgbW9kZWxzLlxuICAgKiBUaGUgbWV0aG9kIHByZXBhcmVzIGVhY2ggbW9kZWwgZm9yIHRoZSBhZGFwdGVyLCBzZW5kcyBhIGJ1bGsgdXBkYXRlIHJlcXVlc3QsXG4gICAqIGFuZCB0aGVuIGNvbnZlcnRzIHRoZSByZXNwb25zZXMgYmFjayB0byBtb2RlbCBpbnN0YW5jZXMuXG4gICAqIEBwYXJhbSB7TVtdfSBtb2RlbHMgLSBUaGUgbW9kZWwgaW5zdGFuY2VzIHdpdGggdXBkYXRlZCBkYXRhXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBhZGFwdGVyXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCBhbiBhcnJheSBvZiB1cGRhdGVkIG1vZGVsIGluc3RhbmNlc1xuICAgKi9cbiAgYXN5bmMgdXBkYXRlQWxsKG1vZGVsczogTVtdLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TVtdPiB7XG4gICAgY29uc3QgcmVjb3JkcyA9IG1vZGVscy5tYXAoKG0pID0+IHRoaXMuYWRhcHRlci5wcmVwYXJlKG0sIHRoaXMucGspKTtcbiAgICBjb25zdCB1cGRhdGVkID0gYXdhaXQgdGhpcy5hZGFwdGVyLnVwZGF0ZUFsbChcbiAgICAgIHRoaXMudGFibGVOYW1lLFxuICAgICAgcmVjb3Jkcy5tYXAoKHIpID0+IHIuaWQpLFxuICAgICAgcmVjb3Jkcy5tYXAoKHIpID0+IHIucmVjb3JkKSxcbiAgICAgIC4uLmFyZ3NcbiAgICApO1xuICAgIHJldHVybiB1cGRhdGVkLm1hcCgodSwgaSkgPT5cbiAgICAgIHRoaXMuYWRhcHRlci5yZXZlcnQodSwgdGhpcy5jbGFzcywgdGhpcy5waywgcmVjb3Jkc1tpXS5pZClcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWdpc3RlcnMgYW4gb2JzZXJ2ZXJcbiAgICogQHN1bW1hcnkgQWRkcyBhbiBvYnNlcnZlciB0byB0aGUgbGlzdCBvZiBvYnNlcnZlcnMgdGhhdCB3aWxsIGJlIG5vdGlmaWVkIG9mIGNoYW5nZXMuXG4gICAqIFRocm93cyBhbiBlcnJvciBpZiB0aGUgb2JzZXJ2ZXIgaXMgYWxyZWFkeSByZWdpc3RlcmVkLlxuICAgKiBAcGFyYW0ge09ic2VydmVyfSBvYnNlcnZlciAtIFRoZSBvYnNlcnZlciB0byByZWdpc3RlclxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKiBAdGhyb3dzIHtJbnRlcm5hbEVycm9yfSBJZiB0aGUgb2JzZXJ2ZXIgaXMgYWxyZWFkeSByZWdpc3RlcmVkXG4gICAqL1xuICBvYnNlcnZlKG9ic2VydmVyOiBPYnNlcnZlcik6IHZvaWQge1xuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5vYnNlcnZlcnMuaW5kZXhPZihvYnNlcnZlcik7XG4gICAgaWYgKGluZGV4ICE9PSAtMSkgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJPYnNlcnZlciBhbHJlYWR5IHJlZ2lzdGVyZWRcIik7XG4gICAgdGhpcy5vYnNlcnZlcnMucHVzaChvYnNlcnZlcik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFVucmVnaXN0ZXJzIGFuIG9ic2VydmVyXG4gICAqIEBzdW1tYXJ5IFJlbW92ZXMgYW4gb2JzZXJ2ZXIgZnJvbSB0aGUgbGlzdCBvZiBvYnNlcnZlcnMuXG4gICAqIFRocm93cyBhbiBlcnJvciBpZiB0aGUgb2JzZXJ2ZXIgaXMgbm90IGZvdW5kLlxuICAgKiBAcGFyYW0ge09ic2VydmVyfSBvYnNlcnZlciAtIFRoZSBvYnNlcnZlciB0byB1bnJlZ2lzdGVyXG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqIEB0aHJvd3Mge0ludGVybmFsRXJyb3J9IElmIHRoZSBvYnNlcnZlciBpcyBub3QgZm91bmRcbiAgICovXG4gIHVuT2JzZXJ2ZShvYnNlcnZlcjogT2JzZXJ2ZXIpOiB2b2lkIHtcbiAgICBjb25zdCBpbmRleCA9IHRoaXMub2JzZXJ2ZXJzLmluZGV4T2Yob2JzZXJ2ZXIpO1xuICAgIGlmIChpbmRleCA9PT0gLTEpIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiRmFpbGVkIHRvIGZpbmQgT2JzZXJ2ZXJcIik7XG4gICAgdGhpcy5vYnNlcnZlcnMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTm90aWZpZXMgYWxsIHJlZ2lzdGVyZWQgb2JzZXJ2ZXJzXG4gICAqIEBzdW1tYXJ5IENhbGxzIHRoZSByZWZyZXNoIG1ldGhvZCBvbiBhbGwgcmVnaXN0ZXJlZCBvYnNlcnZlcnMgdG8gdXBkYXRlIHRoZW1zZWx2ZXMuXG4gICAqIEFueSBlcnJvcnMgZHVyaW5nIG9ic2VydmVyIHJlZnJlc2ggYXJlIGxvZ2dlZCBhcyB3YXJuaW5ncyBidXQgZG9uJ3Qgc3RvcCB0aGUgcHJvY2Vzcy5cbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gW2FyZ3NdIC0gT3B0aW9uYWwgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIG9ic2VydmVyIHJlZnJlc2ggbWV0aG9kXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gYWxsIG9ic2VydmVycyBoYXZlIGJlZW4gdXBkYXRlZFxuICAgKi9cbiAgYXN5bmMgdXBkYXRlT2JzZXJ2ZXJzKC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChcbiAgICAgIHRoaXMub2JzZXJ2ZXJzLm1hcCgobykgPT4gby5yZWZyZXNoKC4uLmFyZ3MpKVxuICAgICk7XG4gICAgcmVzdWx0cy5mb3JFYWNoKChyZXN1bHQsIGkpID0+IHtcbiAgICAgIGlmIChyZXN1bHQuc3RhdHVzID09PSBcInJlamVjdGVkXCIpXG4gICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICBgRmFpbGVkIHRvIHVwZGF0ZSBvYnNlcnZhYmxlICR7dGhpcy5vYnNlcnZlcnNbaV19OiAke3Jlc3VsdC5yZWFzb259YFxuICAgICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgb3ZlcnJpZGUgdG9TdHJpbmcoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYCR7dGhpcy5jbGFzcy5uYW1lfSByZXN0IHNlcnZpY2VgO1xuICB9XG59XG4iLCJpbXBvcnQge1xuICBBZGFwdGVyLFxuICBDb25kaXRpb24sXG4gIFBlcnNpc3RlbmNlS2V5cyxcbiAgUmVwb3NpdG9yeSxcbiAgU2VxdWVuY2UsXG4gIFNlcXVlbmNlT3B0aW9ucyxcbiAgVW5zdXBwb3J0ZWRFcnJvcixcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBDb250ZXh0LCBJbnRlcm5hbEVycm9yLCBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBIdHRwQ29uZmlnLCBIdHRwRmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgUmVzdFNlcnZpY2UgfSBmcm9tIFwiLi9SZXN0U2VydmljZVwiO1xuaW1wb3J0IHsgU3RhdGVtZW50IH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEFic3RyYWN0IEhUVFAgYWRhcHRlciBmb3IgUkVTVCBBUEkgaW50ZXJhY3Rpb25zXG4gKiBAc3VtbWFyeSBQcm92aWRlcyBhIGJhc2UgaW1wbGVtZW50YXRpb24gZm9yIEhUVFAgYWRhcHRlcnMgd2l0aCBtZXRob2RzIGZvciBDUlVEIG9wZXJhdGlvbnMsXG4gKiBVUkwgY29uc3RydWN0aW9uLCBhbmQgZXJyb3IgaGFuZGxpbmcuIFRoaXMgY2xhc3MgZXh0ZW5kcyB0aGUgY29yZSBBZGFwdGVyIGNsYXNzIGFuZFxuICogaW1wbGVtZW50cyB0aGUgbmVjZXNzYXJ5IG1ldGhvZHMgZm9yIEhUVFAgY29tbXVuaWNhdGlvbi4gQ29uY3JldGUgaW1wbGVtZW50YXRpb25zXG4gKiBtdXN0IHByb3ZpZGUgc3BlY2lmaWMgSFRUUCBjbGllbnQgZnVuY3Rpb25hbGl0eS5cbiAqIEB0ZW1wbGF0ZSBZIC0gVGhlIG5hdGl2ZSBIVFRQIGNsaWVudCB0eXBlXG4gKiBAdGVtcGxhdGUgUSAtIFRoZSBxdWVyeSB0eXBlIHVzZWQgYnkgdGhlIGFkYXB0ZXJcbiAqIEB0ZW1wbGF0ZSBGIC0gVGhlIEhUVFAgZmxhZ3MgdHlwZSwgZXh0ZW5kaW5nIEh0dHBGbGFnc1xuICogQHRlbXBsYXRlIEMgLSBUaGUgY29udGV4dCB0eXBlLCBleHRlbmRpbmcgQ29udGV4dDxGPlxuICogQHBhcmFtIHtZfSBuYXRpdmUgLSBUaGUgbmF0aXZlIEhUVFAgY2xpZW50IGluc3RhbmNlXG4gKiBAcGFyYW0ge0h0dHBDb25maWd9IGNvbmZpZyAtIENvbmZpZ3VyYXRpb24gZm9yIHRoZSBIVFRQIGFkYXB0ZXJcbiAqIEBwYXJhbSB7c3RyaW5nfSBmbGF2b3VyIC0gVGhlIGFkYXB0ZXIgZmxhdm9yIGlkZW50aWZpZXJcbiAqIEBwYXJhbSB7c3RyaW5nfSBbYWxpYXNdIC0gT3B0aW9uYWwgYWxpYXMgZm9yIHRoZSBhZGFwdGVyXG4gKiBAY2xhc3MgSHR0cEFkYXB0ZXJcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBFeGFtcGxlIGltcGxlbWVudGF0aW9uIHdpdGggQXhpb3NcbiAqIGNsYXNzIEF4aW9zQWRhcHRlciBleHRlbmRzIEh0dHBBZGFwdGVyPEF4aW9zSW5zdGFuY2UsIEF4aW9zUmVxdWVzdENvbmZpZz4ge1xuICogICBjb25zdHJ1Y3Rvcihjb25maWc6IEh0dHBDb25maWcpIHtcbiAqICAgICBzdXBlcihheGlvcy5jcmVhdGUoKSwgY29uZmlnLCAnYXhpb3MnKTtcbiAqICAgfVxuICpcbiAqICAgYXN5bmMgcmVxdWVzdDxWPihkZXRhaWxzOiBBeGlvc1JlcXVlc3RDb25maWcpOiBQcm9taXNlPFY+IHtcbiAqICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMubmF0aXZlLnJlcXVlc3QoZGV0YWlscyk7XG4gKiAgICAgcmV0dXJuIHJlc3BvbnNlLmRhdGE7XG4gKiAgIH1cbiAqXG4gKiAgIC8vIEltcGxlbWVudCBvdGhlciBhYnN0cmFjdCBtZXRob2RzLi4uXG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEh0dHBBZGFwdGVyPFxuICBZIGV4dGVuZHMgSHR0cENvbmZpZyxcbiAgQ09OLFxuICBRLFxuICBGIGV4dGVuZHMgSHR0cEZsYWdzID0gSHR0cEZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4+IGV4dGVuZHMgQWRhcHRlcjxZLCBDT04sIFEsIEYsIEM+IHtcbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKGNvbmZpZzogWSwgZmxhdm91cjogc3RyaW5nLCBhbGlhcz86IHN0cmluZykge1xuICAgIHN1cGVyKGNvbmZpZywgZmxhdm91ciwgYWxpYXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZW5lcmF0ZXMgb3BlcmF0aW9uIGZsYWdzIHdpdGggSFRUUCBoZWFkZXJzXG4gICAqIEBzdW1tYXJ5IEV4dGVuZHMgdGhlIGJhc2UgZmxhZ3MgbWV0aG9kIHRvIGluY2x1ZGUgSFRUUC1zcGVjaWZpYyBoZWFkZXJzIGZvciBvcGVyYXRpb25zLlxuICAgKiBUaGlzIG1ldGhvZCBhZGRzIGFuIGVtcHR5IGhlYWRlcnMgb2JqZWN0IHRvIHRoZSBmbGFncyByZXR1cm5lZCBieSB0aGUgcGFyZW50IGNsYXNzLlxuICAgKiBAdGVtcGxhdGUgRiAtIFRoZSBSZXBvc2l0b3J5IEZsYWdzIHR5cGVcbiAgICogQHRlbXBsYXRlIE0gLSBUaGUgbW9kZWwgdHlwZVxuICAgKiBAcGFyYW0ge09wZXJhdGlvbktleXMuQ1JFQVRFfE9wZXJhdGlvbktleXMuUkVBRHxPcGVyYXRpb25LZXlzLlVQREFURXxPcGVyYXRpb25LZXlzLkRFTEVURX0gb3BlcmF0aW9uIC0gVGhlIG9wZXJhdGlvbiB0eXBlXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IG1vZGVsIC0gVGhlIG1vZGVsIGNvbnN0cnVjdG9yXG4gICAqIEBwYXJhbSB7UGFydGlhbDxGPn0gb3ZlcnJpZGVzIC0gT3B0aW9uYWwgZmxhZyBvdmVycmlkZXNcbiAgICogQHJldHVybiB7Rn0gVGhlIGZsYWdzIG9iamVjdCB3aXRoIGhlYWRlcnNcbiAgICovXG4gIG92ZXJyaWRlIGZsYWdzPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgb3BlcmF0aW9uOlxuICAgICAgfCBPcGVyYXRpb25LZXlzLkNSRUFURVxuICAgICAgfCBPcGVyYXRpb25LZXlzLlJFQURcbiAgICAgIHwgT3BlcmF0aW9uS2V5cy5VUERBVEVcbiAgICAgIHwgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gICAgbW9kZWw6IENvbnN0cnVjdG9yPE0+LFxuICAgIG92ZXJyaWRlczogUGFydGlhbDxGPlxuICApIHtcbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihzdXBlci5mbGFnczxNPihvcGVyYXRpb24sIG1vZGVsLCBvdmVycmlkZXMpLCB7XG4gICAgICBoZWFkZXJzOiB7fSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0dXJucyB0aGUgcmVwb3NpdG9yeSBjb25zdHJ1Y3RvciBmb3IgdGhpcyBhZGFwdGVyXG4gICAqIEBzdW1tYXJ5IFByb3ZpZGVzIHRoZSBSZXN0U2VydmljZSBjbGFzcyBhcyB0aGUgcmVwb3NpdG9yeSBpbXBsZW1lbnRhdGlvbiBmb3IgdGhpcyBIVFRQIGFkYXB0ZXIuXG4gICAqIFRoaXMgbWV0aG9kIGlzIHVzZWQgdG8gY3JlYXRlIHJlcG9zaXRvcnkgaW5zdGFuY2VzIHRoYXQgd29yayB3aXRoIHRoaXMgYWRhcHRlciB0eXBlLlxuICAgKiBAdGVtcGxhdGUgTSAtIFRoZSBtb2RlbCB0eXBlXG4gICAqIEByZXR1cm4ge0NvbnN0cnVjdG9yPFJlcG9zaXRvcnk8TSwgUSwgSHR0cEFkYXB0ZXI8WSwgUSwgRiwgQz4sIEYsIEM+Pn0gVGhlIHJlcG9zaXRvcnkgY29uc3RydWN0b3JcbiAgICovXG4gIG92ZXJyaWRlIHJlcG9zaXRvcnk8TSBleHRlbmRzIE1vZGVsPigpOiBDb25zdHJ1Y3RvcjxcbiAgICBSZXBvc2l0b3J5PE0sIFEsIEh0dHBBZGFwdGVyPFksIENPTiwgUSwgRiwgQz4sIEYsIEM+XG4gID4ge1xuICAgIHJldHVybiBSZXN0U2VydmljZSBhcyB1bmtub3duIGFzIENvbnN0cnVjdG9yPFxuICAgICAgUmVwb3NpdG9yeTxNLCBRLCBIdHRwQWRhcHRlcjxZLCBDT04sIFEsIEYsIEM+LCBGLCBDPlxuICAgID47XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmVzIGEgbW9kZWwgZm9yIHBlcnNpc3RlbmNlXG4gICAqIEBzdW1tYXJ5IENvbnZlcnRzIGEgbW9kZWwgaW5zdGFuY2UgaW50byBhIGZvcm1hdCBzdWl0YWJsZSBmb3IgZGF0YWJhc2Ugc3RvcmFnZSxcbiAgICogaGFuZGxpbmcgY29sdW1uIG1hcHBpbmcgYW5kIHNlcGFyYXRpbmcgdHJhbnNpZW50IHByb3BlcnRpZXNcbiAgICogQHRlbXBsYXRlIE0gLSBUaGUgbW9kZWwgdHlwZVxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHRvIHByZXBhcmVcbiAgICogQHBhcmFtIHBrIC0gVGhlIHByaW1hcnkga2V5IHByb3BlcnR5IG5hbWVcbiAgICogQHJldHVybiBUaGUgcHJlcGFyZWQgZGF0YVxuICAgKi9cbiAgb3ZlcnJpZGUgcHJlcGFyZTxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG1vZGVsOiBNLFxuICAgIHBrOiBrZXlvZiBNXG4gICk6IHtcbiAgICByZWNvcmQ6IFJlY29yZDxzdHJpbmcsIGFueT47XG4gICAgaWQ6IHN0cmluZztcbiAgICB0cmFuc2llbnQ/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICB9IHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5wcmVwYXJlKTtcbiAgICBjb25zdCByZXN1bHQgPSBPYmplY3QuYXNzaWduKHt9LCBtb2RlbCk7XG4gICAgaWYgKChtb2RlbCBhcyBhbnkpW1BlcnNpc3RlbmNlS2V5cy5NRVRBREFUQV0pIHtcbiAgICAgIGxvZy5zaWxseShcbiAgICAgICAgYFBhc3NpbmcgYWxvbmcgcGVyc2lzdGVuY2UgbWV0YWRhdGEgZm9yICR7KG1vZGVsIGFzIGFueSlbUGVyc2lzdGVuY2VLZXlzLk1FVEFEQVRBXX1gXG4gICAgICApO1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHJlc3VsdCwgUGVyc2lzdGVuY2VLZXlzLk1FVEFEQVRBLCB7XG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgdmFsdWU6IChtb2RlbCBhcyBhbnkpW1BlcnNpc3RlbmNlS2V5cy5NRVRBREFUQV0sXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgcmVjb3JkOiBtb2RlbCxcbiAgICAgIGlkOiBtb2RlbFtwa10gYXMgc3RyaW5nLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENvbnZlcnRzIGRhdGFiYXNlIGRhdGEgYmFjayBpbnRvIGEgbW9kZWwgaW5zdGFuY2VcbiAgICogQHN1bW1hcnkgUmVjb25zdHJ1Y3RzIGEgbW9kZWwgaW5zdGFuY2UgZnJvbSBkYXRhYmFzZSBkYXRhLCBoYW5kbGluZyBjb2x1bW4gbWFwcGluZ1xuICAgKiBhbmQgcmVhdHRhY2hpbmcgdHJhbnNpZW50IHByb3BlcnRpZXNcbiAgICogQHRlbXBsYXRlIE0gLSBUaGUgbW9kZWwgdHlwZVxuICAgKiBAcGFyYW0gb2JqIC0gVGhlIGRhdGFiYXNlIHJlY29yZFxuICAgKiBAcGFyYW0ge3N0cmluZ3xDb25zdHJ1Y3RvcjxNPn0gY2xhenogLSBUaGUgbW9kZWwgY2xhc3Mgb3IgbmFtZVxuICAgKiBAcGFyYW0gcGsgLSBUaGUgcHJpbWFyeSBrZXkgcHJvcGVydHkgbmFtZVxuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ8YmlnaW50fSBpZCAtIFRoZSBwcmltYXJ5IGtleSB2YWx1ZVxuICAgKiBAcmV0dXJuIHtNfSBUaGUgcmVjb25zdHJ1Y3RlZCBtb2RlbCBpbnN0YW5jZVxuICAgKi9cbiAgb3ZlcnJpZGUgcmV2ZXJ0PE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgb2JqOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIGNsYXp6OiBzdHJpbmcgfCBDb25zdHJ1Y3RvcjxNPixcbiAgICBwazoga2V5b2YgTSxcbiAgICBpZDogc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50XG4gICk6IE0ge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLnJldmVydCk7XG4gICAgY29uc3Qgb2I6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcbiAgICBjb25zdCBtID0gKFxuICAgICAgdHlwZW9mIGNsYXp6ID09PSBcInN0cmluZ1wiID8gTW9kZWwuYnVpbGQob2IsIGNsYXp6KSA6IG5ldyBjbGF6eihvYilcbiAgICApIGFzIE07XG4gICAgbG9nLnNpbGx5KGBSZWJ1aWxkaW5nIG1vZGVsICR7bS5jb25zdHJ1Y3Rvci5uYW1lfSBpZCAke2lkfWApO1xuICAgIGNvbnN0IGNvbnN0ciA9IHR5cGVvZiBjbGF6eiA9PT0gXCJzdHJpbmdcIiA/IE1vZGVsLmdldChjbGF6eikgOiBjbGF6ejtcbiAgICBpZiAoIWNvbnN0cilcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICBgRmFpbGVkIHRvIHJldHJpZXZlIG1vZGVsIGNvbnN0cnVjdG9yIGZvciAke2NsYXp6fWBcbiAgICAgICk7XG4gICAgY29uc3QgcmVzdWx0ID0gbmV3IChjb25zdHIgYXMgQ29uc3RydWN0b3I8TT4pKG9iaik7XG4gICAgY29uc3QgbWV0YWRhdGEgPSBvYmpbUGVyc2lzdGVuY2VLZXlzLk1FVEFEQVRBXTtcbiAgICBpZiAobWV0YWRhdGEpIHtcbiAgICAgIGxvZy5zaWxseShcbiAgICAgICAgYFBhc3NpbmcgYWxvbmcgJHt0aGlzLmZsYXZvdXJ9IHBlcnNpc3RlbmNlIG1ldGFkYXRhIGZvciAke20uY29uc3RydWN0b3IubmFtZX0gaWQgJHtpZH06ICR7bWV0YWRhdGF9YFxuICAgICAgKTtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShyZXN1bHQsIFBlcnNpc3RlbmNlS2V5cy5NRVRBREFUQSwge1xuICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiBmYWxzZSxcbiAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgICB2YWx1ZTogbWV0YWRhdGEsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDb25zdHJ1Y3RzIGEgVVJMIGZvciBBUEkgcmVxdWVzdHNcbiAgICogQHN1bW1hcnkgQnVpbGRzIGEgY29tcGxldGUgVVJMIGZvciBBUEkgcmVxdWVzdHMgdXNpbmcgdGhlIGNvbmZpZ3VyZWQgcHJvdG9jb2wgYW5kIGhvc3QsXG4gICAqIHRoZSBzcGVjaWZpZWQgdGFibGUgbmFtZSwgYW5kIG9wdGlvbmFsIHF1ZXJ5IHBhcmFtZXRlcnMuIFRoZSBtZXRob2QgaGFuZGxlcyBVUkwgZW5jb2RpbmcuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUgb3IgZW5kcG9pbnRcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBudW1iZXI+fSBbcXVlcnlQYXJhbXNdIC0gT3B0aW9uYWwgcXVlcnkgcGFyYW1ldGVyc1xuICAgKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBlbmNvZGVkIFVSTCBzdHJpbmdcbiAgICovXG4gIHVybCh0YWJsZU5hbWU6IHN0cmluZywgcXVlcnlQYXJhbXM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBudW1iZXI+KSB7XG4gICAgY29uc3QgdXJsID0gbmV3IFVSTChcbiAgICAgIGAke3RoaXMuY29uZmlnLnByb3RvY29sfTovLyR7dGhpcy5jb25maWcuaG9zdH0vJHt0YWJsZU5hbWV9YFxuICAgICk7XG4gICAgaWYgKHF1ZXJ5UGFyYW1zKVxuICAgICAgT2JqZWN0LmVudHJpZXMocXVlcnlQYXJhbXMpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT5cbiAgICAgICAgdXJsLnNlYXJjaFBhcmFtcy5hcHBlbmQoa2V5LCB2YWx1ZS50b1N0cmluZygpKVxuICAgICAgKTtcblxuICAgIC8vIGVuc3VyZSBzcGFjZXMgYXJlIGVuY29kZWQgYXMgJTIwIChub3QgJysnKSB0byBtYXRjaCBleHBlY3RhdGlvbnNcbiAgICByZXR1cm4gZW5jb2RlVVJJKHVybC50b1N0cmluZygpKS5yZXBsYWNlKC9cXCsvZywgXCIlMjBcIik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNlbmRzIGFuIEhUVFAgcmVxdWVzdFxuICAgKiBAc3VtbWFyeSBBYnN0cmFjdCBtZXRob2QgdGhhdCBtdXN0IGJlIGltcGxlbWVudGVkIGJ5IHN1YmNsYXNzZXMgdG8gc2VuZCBIVFRQIHJlcXVlc3RzXG4gICAqIHVzaW5nIHRoZSBuYXRpdmUgSFRUUCBjbGllbnQuIFRoaXMgaXMgdGhlIGNvcmUgbWV0aG9kIGZvciBtYWtpbmcgQVBJIGNhbGxzLlxuICAgKiBAdGVtcGxhdGUgViAtIFRoZSByZXNwb25zZSB2YWx1ZSB0eXBlXG4gICAqIEBwYXJhbSB7UX0gZGV0YWlscyAtIFRoZSByZXF1ZXN0IGRldGFpbHMgc3BlY2lmaWMgdG8gdGhlIEhUVFAgY2xpZW50XG4gICAqIEByZXR1cm4ge1Byb21pc2U8Vj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHJlc3BvbnNlIGRhdGFcbiAgICovXG4gIGFic3RyYWN0IHJlcXVlc3Q8Vj4oZGV0YWlsczogUSk6IFByb21pc2U8Vj47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbmV3IHJlc291cmNlXG4gICAqIEBzdW1tYXJ5IEFic3RyYWN0IG1ldGhvZCB0aGF0IG11c3QgYmUgaW1wbGVtZW50ZWQgYnkgc3ViY2xhc3NlcyB0byBjcmVhdGUgYSBuZXcgcmVzb3VyY2VcbiAgICogdmlhIEhUVFAuIFRoaXMgdHlwaWNhbGx5IGNvcnJlc3BvbmRzIHRvIGEgUE9TVCByZXF1ZXN0LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlIG9yIGVuZHBvaW50XG4gICAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gaWQgLSBUaGUgaWRlbnRpZmllciBmb3IgdGhlIHJlc291cmNlXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gbW9kZWwgLSBUaGUgZGF0YSBtb2RlbCB0byBjcmVhdGVcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge1Byb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGNyZWF0ZWQgcmVzb3VyY2VcbiAgICovXG4gIGFic3RyYWN0IG92ZXJyaWRlIGNyZWF0ZShcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZDogc3RyaW5nIHwgbnVtYmVyLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgYSByZXNvdXJjZSBieSBJRFxuICAgKiBAc3VtbWFyeSBBYnN0cmFjdCBtZXRob2QgdGhhdCBtdXN0IGJlIGltcGxlbWVudGVkIGJ5IHN1YmNsYXNzZXMgdG8gcmV0cmlldmUgYSByZXNvdXJjZVxuICAgKiB2aWEgSFRUUC4gVGhpcyB0eXBpY2FsbHkgY29ycmVzcG9uZHMgdG8gYSBHRVQgcmVxdWVzdC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZSBvciBlbmRwb2ludFxuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ8YmlnaW50fSBpZCAtIFRoZSBpZGVudGlmaWVyIGZvciB0aGUgcmVzb3VyY2VcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge1Byb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHJldHJpZXZlZCByZXNvdXJjZVxuICAgKi9cbiAgYWJzdHJhY3Qgb3ZlcnJpZGUgcmVhZChcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZDogc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50LFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVcGRhdGVzIGFuIGV4aXN0aW5nIHJlc291cmNlXG4gICAqIEBzdW1tYXJ5IEFic3RyYWN0IG1ldGhvZCB0aGF0IG11c3QgYmUgaW1wbGVtZW50ZWQgYnkgc3ViY2xhc3NlcyB0byB1cGRhdGUgYSByZXNvdXJjZVxuICAgKiB2aWEgSFRUUC4gVGhpcyB0eXBpY2FsbHkgY29ycmVzcG9uZHMgdG8gYSBQVVQgb3IgUEFUQ0ggcmVxdWVzdC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZSBvciBlbmRwb2ludFxuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIC0gVGhlIGlkZW50aWZpZXIgZm9yIHRoZSByZXNvdXJjZVxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IG1vZGVsIC0gVGhlIHVwZGF0ZWQgZGF0YSBtb2RlbFxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgdXBkYXRlZCByZXNvdXJjZVxuICAgKi9cbiAgYWJzdHJhY3Qgb3ZlcnJpZGUgdXBkYXRlKFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIGlkOiBzdHJpbmcgfCBudW1iZXIsXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERlbGV0ZXMgYSByZXNvdXJjZSBieSBJRFxuICAgKiBAc3VtbWFyeSBBYnN0cmFjdCBtZXRob2QgdGhhdCBtdXN0IGJlIGltcGxlbWVudGVkIGJ5IHN1YmNsYXNzZXMgdG8gZGVsZXRlIGEgcmVzb3VyY2VcbiAgICogdmlhIEhUVFAuIFRoaXMgdHlwaWNhbGx5IGNvcnJlc3BvbmRzIHRvIGEgREVMRVRFIHJlcXVlc3QuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUgb3IgZW5kcG9pbnRcbiAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfGJpZ2ludH0gaWQgLSBUaGUgaWRlbnRpZmllciBmb3IgdGhlIHJlc291cmNlIHRvIGRlbGV0ZVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgZGVsZXRpb24gcmVzdWx0XG4gICAqL1xuICBhYnN0cmFjdCBvdmVycmlkZSBkZWxldGUoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IHN0cmluZyB8IG51bWJlciB8IGJpZ2ludCxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXhlY3V0ZXMgYSByYXcgcXVlcnlcbiAgICogQHN1bW1hcnkgTWV0aG9kIGZvciBleGVjdXRpbmcgcmF3IHF1ZXJpZXMgZGlyZWN0bHkgd2l0aCB0aGUgSFRUUCBjbGllbnQuXG4gICAqIFRoaXMgbWV0aG9kIGlzIG5vdCBzdXBwb3J0ZWQgYnkgZGVmYXVsdCBpbiBIVFRQIGFkYXB0ZXJzIGFuZCB0aHJvd3MgYW4gVW5zdXBwb3J0ZWRFcnJvci5cbiAgICogU3ViY2xhc3NlcyBjYW4gb3ZlcnJpZGUgdGhpcyBtZXRob2QgdG8gcHJvdmlkZSBpbXBsZW1lbnRhdGlvbi5cbiAgICogQHRlbXBsYXRlIFIgLSBUaGUgcmVzdWx0IHR5cGVcbiAgICogQHBhcmFtIHtRfSByYXdJbnB1dCAtIFRoZSByYXcgcXVlcnkgaW5wdXRcbiAgICogQHBhcmFtIHtib29sZWFufSBwcm9jZXNzIC0gV2hldGhlciB0byBwcm9jZXNzIHRoZSByZXN1bHRcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge1Byb21pc2U8Uj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHF1ZXJ5IHJlc3VsdFxuICAgKiBAdGhyb3dzIHtVbnN1cHBvcnRlZEVycm9yfSBBbHdheXMgdGhyb3dzIGFzIHRoaXMgbWV0aG9kIGlzIG5vdCBzdXBwb3J0ZWQgYnkgZGVmYXVsdFxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICByYXc8Uj4ocmF3SW5wdXQ6IFEsIHByb2Nlc3M6IGJvb2xlYW4sIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxSPiB7XG4gICAgcmV0dXJuIFByb21pc2UucmVqZWN0KFxuICAgICAgbmV3IFVuc3VwcG9ydGVkRXJyb3IoXG4gICAgICAgIFwiQXBpIGlzIG5vdCBuYXRpdmVseSBhdmFpbGFibGUgZm9yIEh0dHBBZGFwdGVycy4gSWYgcmVxdWlyZWQsIHBsZWFzZSBleHRlbmRzIHRoaXMgY2xhc3NcIlxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBzZXF1ZW5jZVxuICAgKiBAc3VtbWFyeSBNZXRob2QgZm9yIGNyZWF0aW5nIGEgc2VxdWVuY2UgZm9yIGdlbmVyYXRpbmcgdW5pcXVlIGlkZW50aWZpZXJzLlxuICAgKiBUaGlzIG1ldGhvZCBpcyBub3Qgc3VwcG9ydGVkIGJ5IGRlZmF1bHQgaW4gSFRUUCBhZGFwdGVycyBhbmQgdGhyb3dzIGFuIFVuc3VwcG9ydGVkRXJyb3IuXG4gICAqIFN1YmNsYXNzZXMgY2FuIG92ZXJyaWRlIHRoaXMgbWV0aG9kIHRvIHByb3ZpZGUgaW1wbGVtZW50YXRpb24uXG4gICAqIEBwYXJhbSB7U2VxdWVuY2VPcHRpb25zfSBvcHRpb25zIC0gT3B0aW9ucyBmb3IgY3JlYXRpbmcgdGhlIHNlcXVlbmNlXG4gICAqIEByZXR1cm4ge1Byb21pc2U8U2VxdWVuY2U+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBjcmVhdGVkIHNlcXVlbmNlXG4gICAqIEB0aHJvd3Mge1Vuc3VwcG9ydGVkRXJyb3J9IEFsd2F5cyB0aHJvd3MgYXMgdGhpcyBtZXRob2QgaXMgbm90IHN1cHBvcnRlZCBieSBkZWZhdWx0XG4gICAqL1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIFNlcXVlbmNlKG9wdGlvbnM6IFNlcXVlbmNlT3B0aW9ucyk6IFByb21pc2U8U2VxdWVuY2U+IHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoXG4gICAgICBuZXcgVW5zdXBwb3J0ZWRFcnJvcihcbiAgICAgICAgXCJBcGkgaXMgbm90IG5hdGl2ZWx5IGF2YWlsYWJsZSBmb3IgSHR0cEFkYXB0ZXJzLiBJZiByZXF1aXJlZCwgcGxlYXNlIGV4dGVuZHMgdGhpcyBjbGFzc1wiXG4gICAgICApXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIHN0YXRlbWVudCBmb3IgcXVlcnlpbmdcbiAgICogQHN1bW1hcnkgTWV0aG9kIGZvciBjcmVhdGluZyBhIHN0YXRlbWVudCBmb3IgYnVpbGRpbmcgYW5kIGV4ZWN1dGluZyBxdWVyaWVzLlxuICAgKiBUaGlzIG1ldGhvZCBpcyBub3Qgc3VwcG9ydGVkIGJ5IGRlZmF1bHQgaW4gSFRUUCBhZGFwdGVycyBhbmQgdGhyb3dzIGFuIFVuc3VwcG9ydGVkRXJyb3IuXG4gICAqIFN1YmNsYXNzZXMgY2FuIG92ZXJyaWRlIHRoaXMgbWV0aG9kIHRvIHByb3ZpZGUgaW1wbGVtZW50YXRpb24uXG4gICAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGVcbiAgICogQHRlbXBsYXRlICEgLSBUaGUgcmF3IHF1ZXJ5IHR5cGVcbiAgICogQHJldHVybiB7U3RhdGVtZW50PFEsIE0sIGFueT59IEEgc3RhdGVtZW50IG9iamVjdCBmb3IgYnVpbGRpbmcgcXVlcmllc1xuICAgKiBAdGhyb3dzIHtVbnN1cHBvcnRlZEVycm9yfSBBbHdheXMgdGhyb3dzIGFzIHRoaXMgbWV0aG9kIGlzIG5vdCBzdXBwb3J0ZWQgYnkgZGVmYXVsdFxuICAgKi9cbiAgb3ZlcnJpZGUgU3RhdGVtZW50PE0gZXh0ZW5kcyBNb2RlbD4oKTogU3RhdGVtZW50PFEsIE0sIGFueT4ge1xuICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKFxuICAgICAgXCJBcGkgaXMgbm90IG5hdGl2ZWx5IGF2YWlsYWJsZSBmb3IgSHR0cEFkYXB0ZXJzLiBJZiByZXF1aXJlZCwgcGxlYXNlIGV4dGVuZHMgdGhpcyBjbGFzc1wiXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUGFyc2VzIGEgY29uZGl0aW9uIGludG8gYSBxdWVyeVxuICAgKiBAc3VtbWFyeSBNZXRob2QgZm9yIHBhcnNpbmcgYSBjb25kaXRpb24gb2JqZWN0IGludG8gYSBxdWVyeSBmb3JtYXQgdW5kZXJzdG9vZCBieSB0aGUgSFRUUCBjbGllbnQuXG4gICAqIFRoaXMgbWV0aG9kIGlzIG5vdCBzdXBwb3J0ZWQgYnkgZGVmYXVsdCBpbiBIVFRQIGFkYXB0ZXJzIGFuZCB0aHJvd3MgYW4gVW5zdXBwb3J0ZWRFcnJvci5cbiAgICogU3ViY2xhc3NlcyBjYW4gb3ZlcnJpZGUgdGhpcyBtZXRob2QgdG8gcHJvdmlkZSBpbXBsZW1lbnRhdGlvbi5cbiAgICogQHBhcmFtIHtDb25kaXRpb248YW55Pn0gY29uZGl0aW9uIC0gVGhlIGNvbmRpdGlvbiB0byBwYXJzZVxuICAgKiBAcmV0dXJuIHtRfSBUaGUgcGFyc2VkIHF1ZXJ5XG4gICAqIEB0aHJvd3Mge1Vuc3VwcG9ydGVkRXJyb3J9IEFsd2F5cyB0aHJvd3MgYXMgdGhpcyBtZXRob2QgaXMgbm90IHN1cHBvcnRlZCBieSBkZWZhdWx0XG4gICAqL1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIHBhcnNlQ29uZGl0aW9uKGNvbmRpdGlvbjogQ29uZGl0aW9uPGFueT4pOiBRIHtcbiAgICB0aHJvdyBuZXcgVW5zdXBwb3J0ZWRFcnJvcihcbiAgICAgIFwiQXBpIGlzIG5vdCBuYXRpdmVseSBhdmFpbGFibGUgZm9yIEh0dHBBZGFwdGVycy4gSWYgcmVxdWlyZWQsIHBsZWFzZSBleHRlbmRzIHRoaXMgY2xhc3NcIlxuICAgICk7XG4gIH1cbn1cbiIsIi8qKlxuICogQGRlc2NyaXB0aW9uIEF4aW9zIGFkYXB0ZXIgZmxhdm9yIGlkZW50aWZpZXJcbiAqIEBzdW1tYXJ5IENvbnN0YW50IHN0cmluZyBpZGVudGlmaWVyIHVzZWQgdG8gaWRlbnRpZnkgdGhlIEF4aW9zIGltcGxlbWVudGF0aW9uIG9mIHRoZSBIVFRQIGFkYXB0ZXJcbiAqIEBjb25zdCB7c3RyaW5nfSBBeGlvc0ZsYXZvdXJcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWh0dHAuYXhpb3NcbiAqL1xuZXhwb3J0IGNvbnN0IEF4aW9zRmxhdm91ciA9IFwiYXhpb3NcIjtcbiIsImltcG9ydCB7IEh0dHBBZGFwdGVyIH0gZnJvbSBcIi4uL2FkYXB0ZXJcIjtcbmltcG9ydCB7IEF4aW9zLCBBeGlvc1JlcXVlc3RDb25maWcgfSBmcm9tIFwiYXhpb3NcIjtcbmltcG9ydCB7IEh0dHBDb25maWcgfSBmcm9tIFwiLi4vdHlwZXNcIjtcbmltcG9ydCB7IEF4aW9zRmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHtcbiAgQmFzZUVycm9yLFxuICBDb25mbGljdEVycm9yLFxuICBDb250ZXh0LFxuICBJbnRlcm5hbEVycm9yLFxuICBOb3RGb3VuZEVycm9yLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IEF4aW9zRmxhdm91ciB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgQXV0aG9yaXphdGlvbkVycm9yLCBVbnN1cHBvcnRlZEVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEF4aW9zIGltcGxlbWVudGF0aW9uIG9mIHRoZSBIVFRQIGFkYXB0ZXJcbiAqIEBzdW1tYXJ5IENvbmNyZXRlIGltcGxlbWVudGF0aW9uIG9mIEh0dHBBZGFwdGVyIHVzaW5nIEF4aW9zIGFzIHRoZSBIVFRQIGNsaWVudC5cbiAqIFRoaXMgYWRhcHRlciBwcm92aWRlcyBDUlVEIG9wZXJhdGlvbnMgZm9yIFJFU1RmdWwgQVBJcyB1c2luZyBBeGlvcyBmb3IgSFRUUCByZXF1ZXN0cy5cbiAqIEB0ZW1wbGF0ZSBBeGlvcyAtIFRoZSBBeGlvcyBjbGllbnQgdHlwZVxuICogQHRlbXBsYXRlIEF4aW9zUmVxdWVzdENvbmZpZyAtIFRoZSBBeGlvcyByZXF1ZXN0IGNvbmZpZ3VyYXRpb24gdHlwZVxuICogQHRlbXBsYXRlIEF4aW9zRmxhZ3MgLSBUaGUgZmxhZ3MgdHlwZSBleHRlbmRpbmcgSHR0cEZsYWdzXG4gKiBAdGVtcGxhdGUgQ29udGV4dDxBeGlvc0ZsYWdzPiAtIFRoZSBjb250ZXh0IHR5cGUgZm9yIHRoaXMgYWRhcHRlclxuICogQHBhcmFtIHtBeGlvc30gbmF0aXZlIC0gVGhlIEF4aW9zIGluc3RhbmNlXG4gKiBAcGFyYW0ge0h0dHBDb25maWd9IGNvbmZpZyAtIENvbmZpZ3VyYXRpb24gZm9yIHRoZSBIVFRQIGFkYXB0ZXJcbiAqIEBwYXJhbSB7c3RyaW5nfSBbYWxpYXNdIC0gT3B0aW9uYWwgYWxpYXMgZm9yIHRoZSBhZGFwdGVyXG4gKiBAY2xhc3NcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgYXhpb3MgZnJvbSAnYXhpb3MnO1xuICogaW1wb3J0IHsgQXhpb3NIdHRwQWRhcHRlciB9IGZyb20gJ0BkZWNhZi10cy9mb3ItaHR0cCc7XG4gKlxuICogY29uc3QgY29uZmlnID0geyBwcm90b2NvbDogJ2h0dHBzJywgaG9zdDogJ2FwaS5leGFtcGxlLmNvbScgfTtcbiAqIGNvbnN0IGFkYXB0ZXIgPSBuZXcgQXhpb3NIdHRwQWRhcHRlcihheGlvcy5jcmVhdGUoKSwgY29uZmlnKTtcbiAqXG4gKiAvLyBVc2UgdGhlIGFkYXB0ZXIgd2l0aCBhIHJlcG9zaXRvcnlcbiAqIGNvbnN0IHVzZXJSZXBvID0gYWRhcHRlci5nZXRSZXBvc2l0b3J5KFVzZXIpO1xuICogY29uc3QgdXNlciA9IGF3YWl0IHVzZXJSZXBvLmZpbmRCeUlkKCcxMjMnKTtcbiAqIGBgYFxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgQXhpb3NIdHRwQWRhcHRlclxuICogICBwYXJ0aWNpcGFudCBBeGlvc1xuICogICBwYXJ0aWNpcGFudCBBUElcbiAqXG4gKiAgIENsaWVudC0+PkF4aW9zSHR0cEFkYXB0ZXI6IGNyZWF0ZSh0YWJsZSwgaWQsIGRhdGEpXG4gKiAgIEF4aW9zSHR0cEFkYXB0ZXItPj5BeGlvc0h0dHBBZGFwdGVyOiB1cmwodGFibGUpXG4gKiAgIEF4aW9zSHR0cEFkYXB0ZXItPj5BeGlvczogcG9zdCh1cmwsIGRhdGEpXG4gKiAgIEF4aW9zLT4+QVBJOiBIVFRQIFBPU1QgUmVxdWVzdFxuICogICBBUEktLT4+QXhpb3M6IFJlc3BvbnNlXG4gKiAgIEF4aW9zLS0+PkF4aW9zSHR0cEFkYXB0ZXI6IFJlc3BvbnNlIERhdGFcbiAqICAgQXhpb3NIdHRwQWRhcHRlci0tPj5DbGllbnQ6IENyZWF0ZWQgUmVzb3VyY2VcbiAqXG4gKiAgIENsaWVudC0+PkF4aW9zSHR0cEFkYXB0ZXI6IHJlYWQodGFibGUsIGlkKVxuICogICBBeGlvc0h0dHBBZGFwdGVyLT4+QXhpb3NIdHRwQWRhcHRlcjogdXJsKHRhYmxlLCB7aWR9KVxuICogICBBeGlvc0h0dHBBZGFwdGVyLT4+QXhpb3M6IGdldCh1cmwpXG4gKiAgIEF4aW9zLT4+QVBJOiBIVFRQIEdFVCBSZXF1ZXN0XG4gKiAgIEFQSS0tPj5BeGlvczogUmVzcG9uc2VcbiAqICAgQXhpb3MtLT4+QXhpb3NIdHRwQWRhcHRlcjogUmVzcG9uc2UgRGF0YVxuICogICBBeGlvc0h0dHBBZGFwdGVyLS0+PkNsaWVudDogUmVzb3VyY2UgRGF0YVxuICovXG5leHBvcnQgY2xhc3MgQXhpb3NIdHRwQWRhcHRlciBleHRlbmRzIEh0dHBBZGFwdGVyPFxuICBIdHRwQ29uZmlnLFxuICBBeGlvcyxcbiAgQXhpb3NSZXF1ZXN0Q29uZmlnLFxuICBBeGlvc0ZsYWdzLFxuICBDb250ZXh0PEF4aW9zRmxhZ3M+XG4+IHtcbiAgY29uc3RydWN0b3IoY29uZmlnOiBIdHRwQ29uZmlnLCBhbGlhcz86IHN0cmluZykge1xuICAgIHN1cGVyKGNvbmZpZywgQXhpb3NGbGF2b3VyLCBhbGlhcyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgZ2V0Q2xpZW50KCk6IEF4aW9zIHtcbiAgICByZXR1cm4gbmV3IEF4aW9zKCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNlbmRzIGFuIEhUVFAgcmVxdWVzdCB1c2luZyBBeGlvc1xuICAgKiBAc3VtbWFyeSBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgYWJzdHJhY3QgcmVxdWVzdCBtZXRob2QgZnJvbSBIdHRwQWRhcHRlci5cbiAgICogVGhpcyBtZXRob2QgdXNlcyB0aGUgQXhpb3MgaW5zdGFuY2UgdG8gc2VuZCBIVFRQIHJlcXVlc3RzIHdpdGggdGhlIHByb3ZpZGVkIGNvbmZpZ3VyYXRpb24uXG4gICAqIEB0ZW1wbGF0ZSBWIC0gVGhlIHJlc3BvbnNlIHZhbHVlIHR5cGVcbiAgICogQHBhcmFtIHtBeGlvc1JlcXVlc3RDb25maWd9IGRldGFpbHMgLSBUaGUgQXhpb3MgcmVxdWVzdCBjb25maWd1cmF0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8Vj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHJlc3BvbnNlIGRhdGFcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIHJlcXVlc3Q8Vj4oZGV0YWlsczogQXhpb3NSZXF1ZXN0Q29uZmlnKTogUHJvbWlzZTxWPiB7XG4gICAgcmV0dXJuIHRoaXMuY2xpZW50LnJlcXVlc3QoZGV0YWlscyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgcmVzb3VyY2UgdmlhIEhUVFAgUE9TVFxuICAgKiBAc3VtbWFyeSBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgYWJzdHJhY3QgY3JlYXRlIG1ldGhvZCBmcm9tIEh0dHBBZGFwdGVyLlxuICAgKiBUaGlzIG1ldGhvZCBzZW5kcyBhIFBPU1QgcmVxdWVzdCB0byB0aGUgc3BlY2lmaWVkIGVuZHBvaW50IHdpdGggdGhlIG1vZGVsIGRhdGEuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUgb3IgZW5kcG9pbnRcbiAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBpZCAtIFRoZSBpZGVudGlmaWVyIGZvciB0aGUgcmVzb3VyY2UgKG5vdCB1c2VkIGluIFVSTCBmb3IgUE9TVClcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBtb2RlbCAtIFRoZSBkYXRhIG1vZGVsIHRvIGNyZWF0ZVxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBjcmVhdGVkIHJlc291cmNlXG4gICAqL1xuICBhc3luYyBjcmVhdGUoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IHN0cmluZyB8IG51bWJlcixcbiAgICBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PlxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgdXJsID0gdGhpcy51cmwodGFibGVOYW1lKTtcbiAgICAgIHJldHVybiB0aGlzLmNsaWVudC5wb3N0KHVybCwgbW9kZWwpO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUpO1xuICAgIH1cbiAgfVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhIHJlc291cmNlIGJ5IElEIHZpYSBIVFRQIEdFVFxuICAgKiBAc3VtbWFyeSBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgYWJzdHJhY3QgcmVhZCBtZXRob2QgZnJvbSBIdHRwQWRhcHRlci5cbiAgICogVGhpcyBtZXRob2Qgc2VuZHMgYSBHRVQgcmVxdWVzdCB0byB0aGUgc3BlY2lmaWVkIGVuZHBvaW50IHdpdGggdGhlIElEIGFzIGEgcXVlcnkgcGFyYW1ldGVyLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlIG9yIGVuZHBvaW50XG4gICAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcnxiaWdpbnR9IGlkIC0gVGhlIGlkZW50aWZpZXIgZm9yIHRoZSByZXNvdXJjZSB0byByZXRyaWV2ZVxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSByZXRyaWV2ZWQgcmVzb3VyY2VcbiAgICovXG4gIGFzeW5jIHJlYWQoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IHN0cmluZyB8IG51bWJlciB8IGJpZ2ludFxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgdXJsID0gdGhpcy51cmwodGFibGVOYW1lLCB7IGlkOiBpZCBhcyBzdHJpbmcgfCBudW1iZXIgfSk7XG4gICAgICByZXR1cm4gdGhpcy5jbGllbnQuZ2V0KHVybCk7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVcGRhdGVzIGFuIGV4aXN0aW5nIHJlc291cmNlIHZpYSBIVFRQIFBVVFxuICAgKiBAc3VtbWFyeSBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgYWJzdHJhY3QgdXBkYXRlIG1ldGhvZCBmcm9tIEh0dHBBZGFwdGVyLlxuICAgKiBUaGlzIG1ldGhvZCBzZW5kcyBhIFBVVCByZXF1ZXN0IHRvIHRoZSBzcGVjaWZpZWQgZW5kcG9pbnQgd2l0aCB0aGUgdXBkYXRlZCBtb2RlbCBkYXRhLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlIG9yIGVuZHBvaW50XG4gICAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gaWQgLSBUaGUgaWRlbnRpZmllciBmb3IgdGhlIHJlc291cmNlIChub3QgdXNlZCBpbiBVUkwgZm9yIFBVVClcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBtb2RlbCAtIFRoZSB1cGRhdGVkIGRhdGEgbW9kZWxcbiAgICogQHJldHVybiB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgdXBkYXRlZCByZXNvdXJjZVxuICAgKi9cbiAgYXN5bmMgdXBkYXRlKFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIGlkOiBzdHJpbmcgfCBudW1iZXIsXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT5cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHVybCA9IHRoaXMudXJsKHRhYmxlTmFtZSk7XG4gICAgICByZXR1cm4gdGhpcy5jbGllbnQucHV0KHVybCwgbW9kZWwpO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRGVsZXRlcyBhIHJlc291cmNlIGJ5IElEIHZpYSBIVFRQIERFTEVURVxuICAgKiBAc3VtbWFyeSBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgYWJzdHJhY3QgZGVsZXRlIG1ldGhvZCBmcm9tIEh0dHBBZGFwdGVyLlxuICAgKiBUaGlzIG1ldGhvZCBzZW5kcyBhIERFTEVURSByZXF1ZXN0IHRvIHRoZSBzcGVjaWZpZWQgZW5kcG9pbnQgd2l0aCB0aGUgSUQgYXMgYSBxdWVyeSBwYXJhbWV0ZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUgb3IgZW5kcG9pbnRcbiAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfGJpZ2ludH0gaWQgLSBUaGUgaWRlbnRpZmllciBmb3IgdGhlIHJlc291cmNlIHRvIGRlbGV0ZVxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBkZWxldGlvbiByZXN1bHRcbiAgICovXG4gIGFzeW5jIGRlbGV0ZShcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZDogc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50XG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB1cmwgPSB0aGlzLnVybCh0YWJsZU5hbWUsIHsgaWQ6IGlkIGFzIHN0cmluZyB8IG51bWJlciB9KTtcbiAgICAgIHJldHVybiB0aGlzLmNsaWVudC5kZWxldGUodXJsKTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIHRocm93IHRoaXMucGFyc2VFcnJvcihlKTtcbiAgICB9XG4gIH1cblxuICBvdmVycmlkZSBwYXJzZUVycm9yKGVycjogRXJyb3IpOiBCYXNlRXJyb3Ige1xuICAgIGNvbnN0IGVycnMgPSBbXG4gICAgICBJbnRlcm5hbEVycm9yLFxuICAgICAgQXV0aG9yaXphdGlvbkVycm9yLFxuICAgICAgQ29uZmxpY3RFcnJvcixcbiAgICAgIE5vdEZvdW5kRXJyb3IsXG4gICAgICBVbnN1cHBvcnRlZEVycm9yLFxuICAgIF07XG4gICAgZm9yIChjb25zdCBlcnJvciBvZiBlcnJzKSB7XG4gICAgICBpZiAoKGVyciBhcyBFcnJvcikubWVzc2FnZS5pbmNsdWRlcyhlcnJvci5uYW1lKSlcbiAgICAgICAgcmV0dXJuIG5ldyBlcnJvcihlcnIubWVzc2FnZSk7XG4gICAgfVxuICAgIHJldHVybiBuZXcgSW50ZXJuYWxFcnJvcihlcnIubWVzc2FnZSk7XG4gIH1cbn1cbiIsImltcG9ydCB7IEF4aW9zSHR0cEFkYXB0ZXIgfSBmcm9tIFwiLi9heGlvc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBIVFRQIGNsaWVudCBtb2R1bGUgZm9yIFJFU1QgQVBJIGludGVyYWN0aW9uc1xuICogQHN1bW1hcnkgVGhpcyBtb2R1bGUgcHJvdmlkZXMgY2xhc3NlcyBhbmQgdXRpbGl0aWVzIGZvciBpbnRlcmFjdGluZyB3aXRoIFJFU1QgQVBJcy5cbiAqIEl0IGV4cG9zZXMgcmVwb3NpdG9yeSBhbmQgc2VydmljZSBjbGFzc2VzIGZvciBtYWtpbmcgSFRUUCByZXF1ZXN0cywgYWxvbmcgd2l0aFxuICogdHlwZSBkZWZpbml0aW9ucyBhbmQgYWRhcHRlcnMgZm9yIGRpZmZlcmVudCBIVFRQIGNsaWVudHMuIFRoZSBtb2R1bGUgaW5jbHVkZXNcbiAqIHtAbGluayBSZXN0UmVwb3NpdG9yeX0gYW5kIHtAbGluayBSZXN0U2VydmljZX0gZm9yIEFQSSBpbnRlcmFjdGlvbnMuXG4gKiBAbmFtZXNwYWNlIGF4aW9zXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1odHRwXG4gKi9cblxuQXhpb3NIdHRwQWRhcHRlci5kZWNvcmF0aW9uKCk7XG5cbmV4cG9ydCAqIGZyb20gXCIuL2F4aW9zXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3R5cGVzXCI7XG4iLCJpbXBvcnQgeyBSZXBvc2l0b3J5IH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciwgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBIdHRwQWRhcHRlciB9IGZyb20gXCIuL2FkYXB0ZXJcIjtcbmltcG9ydCB7IENvbnRleHQgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IEh0dHBGbGFncyB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlcG9zaXRvcnkgZm9yIFJFU1QgQVBJIGludGVyYWN0aW9uc1xuICogQHN1bW1hcnkgQSBzcGVjaWFsaXplZCByZXBvc2l0b3J5IGltcGxlbWVudGF0aW9uIGZvciBpbnRlcmFjdGluZyB3aXRoIFJFU1QgQVBJcy5cbiAqIFRoaXMgY2xhc3MgZXh0ZW5kcyB0aGUgY29yZSBSZXBvc2l0b3J5IGNsYXNzIGFuZCB3b3JrcyB3aXRoIEhUVFAgYWRhcHRlcnMgdG9cbiAqIHByb3ZpZGUgQ1JVRCBvcGVyYXRpb25zIGZvciBtb2RlbHMgdmlhIFJFU1QgZW5kcG9pbnRzLlxuICogVGhpcyBJcyBOT1QgdGhlIGRlZmF1bHQgcmVwb3NpdG9yeSBmb3IgdGhlIEhUVFAgYWRhcHRlci4gVGhhdCB3b3VsZCBiZSB7QGxpbmsgUmVzdFNlcnZpY2V9LlxuICogVXNlIHRoaXMgb25seSBpbiB0aGUgc3BlY2lmaWMgY2FzZSBvZiBuZWVkaW5nIHRvIHJ1biB0aGUgQ1VSRCBtb2RlbCBsb2dpYyAoZGVjb3JhdGlvbikgYmVmb3JlIHN1Ym1pdHRpbmcgdG8gdGhlIGJhY2tlbmRcbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUsIGV4dGVuZGluZyBNb2RlbFxuICogQHRlbXBsYXRlIFEgLSBUaGUgcXVlcnkgdHlwZSB1c2VkIGJ5IHRoZSBhZGFwdGVyXG4gKiBAdGVtcGxhdGUgQSAtIFRoZSBIVFRQIGFkYXB0ZXIgdHlwZSwgZXh0ZW5kaW5nIEh0dHBBZGFwdGVyXG4gKiBAdGVtcGxhdGUgRiAtIFRoZSBIVFRQIGZsYWdzIHR5cGUsIGV4dGVuZGluZyBIdHRwRmxhZ3NcbiAqIEB0ZW1wbGF0ZSBDIC0gVGhlIGNvbnRleHQgdHlwZSwgZXh0ZW5kaW5nIENvbnRleHQ8Rj5cbiAqIEBwYXJhbSB7QX0gYWRhcHRlciAtIFRoZSBIVFRQIGFkYXB0ZXIgaW5zdGFuY2VcbiAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IFtjbGF6el0gLSBPcHRpb25hbCBjb25zdHJ1Y3RvciBmb3IgdGhlIG1vZGVsIGNsYXNzXG4gKiBAY2xhc3MgUmVzdFJlcG9zaXRvcnlcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBDcmVhdGUgYSByZXBvc2l0b3J5IGZvciBVc2VyIG1vZGVsIHdpdGggQXhpb3MgYWRhcHRlclxuICogY29uc3QgYXhpb3NBZGFwdGVyID0gbmV3IEF4aW9zQWRhcHRlcih7XG4gKiAgIHByb3RvY29sOiAnaHR0cHMnLFxuICogICBob3N0OiAnYXBpLmV4YW1wbGUuY29tJ1xuICogfSk7XG4gKiBjb25zdCB1c2VyUmVwb3NpdG9yeSA9IG5ldyBSZXN0UmVwb3NpdG9yeShheGlvc0FkYXB0ZXIsIFVzZXIpO1xuICpcbiAqIC8vIFVzZSB0aGUgcmVwb3NpdG9yeSBmb3IgQ1JVRCBvcGVyYXRpb25zXG4gKiBjb25zdCB1c2VyID0gYXdhaXQgdXNlclJlcG9zaXRvcnkuZmluZEJ5SWQoJzEyMycpO1xuICogYGBgXG4gKiBAc2VlIHtAbGluayBSZXN0U2VydmljZX1cbiAqL1xuZXhwb3J0IGNsYXNzIFJlc3RSZXBvc2l0b3J5PFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFEsXG4gIEEgZXh0ZW5kcyBIdHRwQWRhcHRlcjxhbnksIGFueSwgUSwgRiwgQz4sXG4gIEYgZXh0ZW5kcyBIdHRwRmxhZ3MgPSBIdHRwRmxhZ3MsXG4gIEMgZXh0ZW5kcyBDb250ZXh0PEY+ID0gQ29udGV4dDxGPixcbj4gZXh0ZW5kcyBSZXBvc2l0b3J5PE0sIFEsIEE+IHtcbiAgY29uc3RydWN0b3IoYWRhcHRlcjogQSwgY2xheno/OiBDb25zdHJ1Y3RvcjxNPikge1xuICAgIHN1cGVyKGFkYXB0ZXIsIGNsYXp6KTtcbiAgfVxuXG4gIHVybChwYXRoOiBzdHJpbmcsIHF1ZXJ5UGFyYW1zPzogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgbnVtYmVyPikge1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIudXJsKHBhdGgsIHF1ZXJ5UGFyYW1zKTtcbiAgfVxuXG4gIGFzeW5jIHJlcXVlc3Q8Vj4oZGV0YWlsczogUSkge1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmVxdWVzdDxWPihkZXRhaWxzKTtcbiAgfVxufVxuIiwiaW1wb3J0IFwiQGRlY2FmLXRzL2NvcmVcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSFRUUCBjbGllbnQgbW9kdWxlIGZvciBSRVNUIEFQSSBpbnRlcmFjdGlvbnNcbiAqIEBzdW1tYXJ5IFRoaXMgbW9kdWxlIHByb3ZpZGVzIGNsYXNzZXMgYW5kIHV0aWxpdGllcyBmb3IgaW50ZXJhY3Rpbmcgd2l0aCBSRVNUIEFQSXMuXG4gKiBJdCBleHBvc2VzIHJlcG9zaXRvcnkgYW5kIHNlcnZpY2UgY2xhc3NlcyBmb3IgbWFraW5nIEhUVFAgcmVxdWVzdHMsIGFsb25nIHdpdGhcbiAqIHR5cGUgZGVmaW5pdGlvbnMgYW5kIGFkYXB0ZXJzIGZvciBkaWZmZXJlbnQgSFRUUCBjbGllbnRzLiBUaGUgbW9kdWxlIGluY2x1ZGVzXG4gKiB7QGxpbmsgUmVzdFJlcG9zaXRvcnl9IGFuZCB7QGxpbmsgUmVzdFNlcnZpY2V9IGZvciBBUEkgaW50ZXJhY3Rpb25zLlxuICogQG1vZHVsZSBmb3ItaHR0cFxuICovXG5leHBvcnQgKiBmcm9tIFwiLi9heGlvc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vYWRhcHRlclwiO1xuZXhwb3J0ICogZnJvbSBcIi4vUmVzdFJlcG9zaXRvcnlcIjtcbmV4cG9ydCAqIGZyb20gXCIuL1Jlc3RTZXJ2aWNlXCI7XG5leHBvcnQgKiBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDdXJyZW50IHZlcnNpb24gb2YgdGhlIGZvci1odHRwIG1vZHVsZVxuICogQHN1bW1hcnkgVmVyc2lvbiBpZGVudGlmaWVyIGZvciB0aGUgbW9kdWxlXG4gKiBAY29uc3QgVkVSU0lPTlxuICovXG5leHBvcnQgY29uc3QgVkVSU0lPTiA9IFwiIyNWRVJTSU9OIyNcIjtcbiJdLCJuYW1lcyI6WyJMb2dnZWRDbGFzcyIsIkludGVybmFsRXJyb3IiLCJmaW5kUHJpbWFyeUtleSIsIlJlcG9zaXRvcnkiLCJBZGFwdGVyIiwiUGVyc2lzdGVuY2VLZXlzIiwiTW9kZWwiLCJVbnN1cHBvcnRlZEVycm9yIiwiQXhp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
|
|
1
|
+
var e,t;e=this,t=function(e,t,r,s,a,i){"use strict";class o extends a.LoggedClass{get class(){if(!this._class)throw new r.InternalError("No class definition found for this repository");return this._class}get log(){return this.logger||(this.logger=this.adapter.log.for(this.toString())),this.logger}get pk(){return this._pk||(this._pk=r.findPrimaryKey(new this.class).id),this._pk}get adapter(){if(!this._adapter)throw new r.InternalError("No adapter found for this repository. did you use the @uses decorator or pass it in the constructor?");return this._adapter}get tableName(){return this._tableName||(this._tableName=t.Repository.table(this.class)),this._tableName}constructor(e,t){super(),this.observers=[],this._adapter=e,t&&(this._class=t)}url(e,t){return this.adapter.url(e,t)}async create(e,...t){let{record:r,id:s}=this.adapter.prepare(e,this.pk);return r=await this.adapter.create(this.tableName,s,r,...t),this.adapter.revert(r,this.class,this.pk,s)}async read(e,...t){const r=await this.adapter.read(this.tableName,e,...t);return this.adapter.revert(r,this.class,this.pk,e)}async update(e,...t){let{record:r,id:s}=this.adapter.prepare(e,this.pk);return r=await this.adapter.update(this.tableName,s,r,...t),this.adapter.revert(r,this.class,this.pk,s)}async delete(e,...t){const r=await this.adapter.delete(this.tableName,e,...t);return this.adapter.revert(r,this.class,this.pk,e)}async request(e){return this.adapter.request(e)}async createAll(e,...t){if(!e.length)return e;const r=e.map(e=>this.adapter.prepare(e,this.pk)),s=r.map(e=>e.id);let a=r.map(e=>e.record);return a=await this.adapter.createAll(this.tableName,s,a,...t),a.map((e,t)=>this.adapter.revert(e,this.class,this.pk,s[t]))}async deleteAll(e,...t){return(await this.adapter.deleteAll(this.tableName,e,...t)).map((t,r)=>this.adapter.revert(t,this.class,this.pk,e[r]))}async readAll(e,...t){return(await this.adapter.readAll(this.tableName,e,...t)).map((t,r)=>this.adapter.revert(t,this.class,this.pk,e[r]))}async updateAll(e,...t){const r=e.map(e=>this.adapter.prepare(e,this.pk));return(await this.adapter.updateAll(this.tableName,r.map(e=>e.id),r.map(e=>e.record),...t)).map((e,t)=>this.adapter.revert(e,this.class,this.pk,r[t].id))}observe(e){if(-1!==this.observers.indexOf(e))throw new r.InternalError("Observer already registered");this.observers.push(e)}unObserve(e){const t=this.observers.indexOf(e);if(-1===t)throw new r.InternalError("Failed to find Observer");this.observers.splice(t,1)}async updateObservers(...e){(await Promise.allSettled(this.observers.map(t=>t.refresh(...e)))).forEach((e,t)=>{e.status})}toString(){return this.class.name+" rest service"}}class n extends t.Adapter{constructor(e,t,r){super(e,t,r)}flags(e,t,r){return Object.assign(super.flags(e,t,r),{headers:{}})}repository(){return o}prepare(e,r){const s=this.log.for(this.prepare),a=Object.assign({},e);return e[t.PersistenceKeys.METADATA]&&(s.silly("Passing along persistence metadata for "+e[t.PersistenceKeys.METADATA]),Object.defineProperty(a,t.PersistenceKeys.METADATA,{enumerable:!1,writable:!1,configurable:!0,value:e[t.PersistenceKeys.METADATA]})),{record:e,id:e[r]}}revert(e,a,i,o){const n=this.log.for(this.revert),l={},c="string"==typeof a?s.Model.build(l,a):new a(l);n.silly(`Rebuilding model ${c.constructor.name} id ${o}`);const d="string"==typeof a?s.Model.get(a):a;if(!d)throw new r.InternalError("Failed to retrieve model constructor for "+a);const p=new d(e),h=e[t.PersistenceKeys.METADATA];return h&&(n.silly(`Passing along ${this.flavour} persistence metadata for ${c.constructor.name} id ${o}: ${h}`),Object.defineProperty(p,t.PersistenceKeys.METADATA,{enumerable:!1,configurable:!1,writable:!1,value:h})),p}url(e,t){const r=new URL(`${this.config.protocol}://${this.config.host}/${e}`);return t&&Object.entries(t).forEach(([e,t])=>r.searchParams.append(e,t.toString())),encodeURI(r.toString()).replace(/\+/g,"%20")}raw(e,r,...s){return Promise.reject(new t.UnsupportedError("Api is not natively available for HttpAdapters. If required, please extends this class"))}Sequence(e){return Promise.reject(new t.UnsupportedError("Api is not natively available for HttpAdapters. If required, please extends this class"))}Statement(){throw new t.UnsupportedError("Api is not natively available for HttpAdapters. If required, please extends this class")}parseCondition(e){throw new t.UnsupportedError("Api is not natively available for HttpAdapters. If required, please extends this class")}}const l="axios";class c extends n{constructor(e,t){super(e,l,t)}getClient(){return new i.Axios}async request(e){return this.client.request(e)}async create(e,t,r){try{const t=this.url(e);return this.client.post(t,r)}catch(e){throw this.parseError(e)}}async read(e,t){try{const r=this.url(e,{id:t});return this.client.get(r)}catch(e){throw this.parseError(e)}}async update(e,t,r){try{const t=this.url(e);return this.client.put(t,r)}catch(e){throw this.parseError(e)}}async delete(e,t){try{const r=this.url(e,{id:t});return this.client.delete(r)}catch(e){throw this.parseError(e)}}parseError(e){const s=[r.InternalError,t.AuthorizationError,r.ConflictError,r.NotFoundError,t.UnsupportedError];for(const t of s)if(e.message.includes(t.name))return new t(e.message);return new r.InternalError(e.message)}}c.decoration();class d extends t.Repository{constructor(e,t){super(e,t)}url(e,t){return this.adapter.url(e,t)}async request(e){return this.adapter.request(e)}}e.AxiosFlavour=l,e.AxiosHttpAdapter=c,e.HttpAdapter=n,e.RestRepository=d,e.RestService=o,e.VERSION="##VERSION##"},"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@decaf-ts/core"),require("@decaf-ts/db-decorators"),require("@decaf-ts/decorator-validation"),require("@decaf-ts/logging"),require("axios")):"function"==typeof define&&define.amd?define(["exports","@decaf-ts/core","@decaf-ts/db-decorators","@decaf-ts/decorator-validation","@decaf-ts/logging","axios"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self)["for-http"]={},e.decafTsCore,e.decafTsDbDecorators,e.decafTsDecoratorValidation,e.decafTsLogging,e.axios);
|
|
2
|
+
//# sourceMappingURL=for-http.cjs.map
|