angular-odata
Version:
Client side OData typescript library for Angular
428 lines • 59.3 kB
JavaScript
import { HttpErrorResponse, HttpHeaders, HttpResponse, } from '@angular/common/http';
import { map, Subject } from 'rxjs';
import { $BATCH, ACCEPT, APPLICATION_HTTP, APPLICATION_JSON, BATCH_PREFIX, BINARY, BOUNDARY_PREFIX_SUFFIX, CHANGESET_PREFIX, CONTENT_ID, CONTENT_TRANSFER_ENCODING, CONTENT_TYPE, HTTP11, MULTIPART_MIXED, MULTIPART_MIXED_BOUNDARY, NEWLINE, NEWLINE_REGEXP, ODATA_VERSION, VERSION_4_0, XSSI_PREFIX, } from '../../constants';
import { PathSegment } from '../../types';
import { Arrays } from '../../utils/arrays';
import { Http } from '../../utils/http';
import { Strings } from '../../utils/strings';
import { ODataPathSegments } from '../path';
import { ODataResource } from '../resource';
export class ODataBatchRequest extends Subject {
request;
id;
group;
constructor(request) {
super();
this.request = request;
this.id = Strings.uniqueId({ prefix: 'r' });
this.group = Strings.uniqueId({ prefix: 'g' });
}
toString() {
return this.toLegacy();
}
toLegacy({ relativeUrls } = {}) {
//TODO: Relative or Absolute url ?
let res = [
`${this.request.method} ${relativeUrls ? this.request.pathWithParams : this.request.urlWithParams} ${HTTP11}`,
];
if (this.request.method === 'POST' ||
this.request.method === 'PATCH' ||
this.request.method === 'PUT') {
res.push(`${CONTENT_TYPE}: ${APPLICATION_JSON}`);
}
if (this.request.headers instanceof HttpHeaders) {
let headers = this.request.headers;
res = [
...res,
...headers
.keys()
.map((key) => `${key}: ${(headers.getAll(key) || []).join(',')}`),
];
}
if (this.request.method === 'GET' || this.request.method === 'DELETE') {
res.push(NEWLINE);
}
else {
res.push(`${NEWLINE}${JSON.stringify(this.request.body)}`);
}
return res.join(NEWLINE);
}
toJson({ relativeUrls } = {}) {
let res = {
id: this.id,
method: this.request.method,
url: relativeUrls
? this.request.pathWithParams
: this.request.urlWithParams,
//'atomicityGroup': this.group
//"dependsOn": ["g1", "g2", "r2"]
};
if (this.request.headers instanceof HttpHeaders) {
let headers = this.request.headers;
res['headers'] = headers
.keys()
.map((key) => `${key}: ${(headers.getAll(key) || []).join(',')}`);
}
if (!(this.request.method === 'GET' || this.request.method === 'DELETE')) {
res['body'] = this.request.body;
}
return res;
}
onLoad(response) {
if (response.ok) {
this.next(response);
this.complete();
}
else {
// An unsuccessful request is delivered on the error channel.
this.error(response);
}
}
onError(response) {
this.error(response);
}
}
/**
* OData Batch Resource
* https://www.odata.org/getting-started/advanced-tutorial/#batch
*/
export class ODataBatchResource extends ODataResource {
// VARIABLES
_requests = [];
requests() {
return this._requests.map((r) => r.request);
}
_responses = null;
responses() {
return this._responses;
}
//#region Factory
static factory(api) {
let segments = new ODataPathSegments();
segments.add(PathSegment.batch, $BATCH);
return new ODataBatchResource(api, { segments });
}
clone() {
const batch = super.clone();
batch._requests = [...this._requests];
return batch;
}
//#endregion
storeRequester() {
const current = this.api.requester;
// Switch to the batch requester
this.api.requester = (req) => {
if (req.api !== this.api)
throw new Error('Batch Request are for the same api.');
if (req.observe === 'events')
throw new Error("Batch Request does not allows observe == 'events'.");
this._requests.push(new ODataBatchRequest(req));
return this._requests[this._requests.length - 1];
};
return current;
}
restoreRequester(handler) {
this.api.requester = handler;
}
/**
* Add to batch request
* @param ctx The context for the request
* @returns The result of execute the context
*/
add(ctx) {
// Store original requester
var handler = this.storeRequester();
// Execute the context
const result = ctx(this);
// Restore original requester
this.restoreRequester(handler);
return result;
}
send(options) {
if (this.api.options.jsonBatchFormat) {
return this.sendJson(options);
}
else {
return this.sendLegacy(options);
}
}
sendJson(options) {
const headers = Http.mergeHttpHeaders((options && options.headers) || {}, {
[ODATA_VERSION]: VERSION_4_0,
});
return this.api
.request('POST', this, {
body: ODataBatchResource.buildJsonBody(this._requests, this.api.options),
responseType: 'json',
observe: 'response',
headers: headers,
params: options ? options.params : undefined,
withCredentials: options ? options.withCredentials : undefined,
})
.pipe(map((response) => {
if (this._responses == null) {
this._responses = [];
}
this._responses = [
...this._responses,
...ODataBatchResource.parseJsonResponse(this._requests, response),
];
//HACK: tuple[1] === undefined
Arrays.zip(this._requests, this._responses).forEach((tuple) => {
if (!tuple[0].isStopped && tuple[1])
tuple[0].onLoad(tuple[1]);
});
return response;
}));
}
sendLegacy(options) {
const bound = Strings.uniqueId({ prefix: BATCH_PREFIX });
const headers = Http.mergeHttpHeaders((options && options.headers) || {}, {
[ODATA_VERSION]: VERSION_4_0,
[CONTENT_TYPE]: MULTIPART_MIXED_BOUNDARY + bound,
[ACCEPT]: MULTIPART_MIXED,
});
return this.api
.request('POST', this, {
body: ODataBatchResource.buildLegacyBody(bound, this._requests, this.api.options),
responseType: 'text',
observe: 'response',
headers: headers,
params: options ? options.params : undefined,
withCredentials: options ? options.withCredentials : undefined,
})
.pipe(map((response) => {
if (this._responses == null) {
this._responses = [];
}
this._responses = [
...this._responses,
...ODataBatchResource.parseLegacyResponse(this._requests, response),
];
Arrays.zip(this._requests, this._responses).forEach((tuple) => {
if (!tuple[0].isStopped && tuple[1])
tuple[0].onLoad(tuple[1]);
});
return response;
}));
}
/**
* Execute the batch request
* @param ctx The context for the request
* @param options The options of the batch request
* @returns The result of execute the context
*/
exec(ctx, options) {
let result = this.add(ctx);
return this.send(options).pipe(map((response) => [result, response]));
}
body() {
return ODataBatchResource.buildLegacyBody(Strings.uniqueId({ prefix: BATCH_PREFIX }), this._requests, this.api.options);
}
json() {
return ODataBatchResource.buildJsonBody(this._requests, this.api.options);
}
static buildLegacyBody(batchBoundary, requests, options) {
let res = [];
let changesetBoundary = null;
let changesetId = 1;
for (const request of requests) {
// if method is GET and there is a changeset boundary open then close it
if (request.request.method === 'GET' && changesetBoundary !== null) {
res.push(`${BOUNDARY_PREFIX_SUFFIX}${changesetBoundary}${BOUNDARY_PREFIX_SUFFIX}`);
changesetBoundary = null;
}
// if there is no changeset boundary open then open a batch boundary
if (changesetBoundary === null) {
res.push(`${BOUNDARY_PREFIX_SUFFIX}${batchBoundary}`);
}
// if method is not GET and there is no changeset boundary open then open a changeset boundary
if (request.request.method !== 'GET') {
if (changesetBoundary === null) {
changesetBoundary = Strings.uniqueId({ prefix: CHANGESET_PREFIX });
res.push(`${CONTENT_TYPE}: ${MULTIPART_MIXED_BOUNDARY}${changesetBoundary}`);
res.push(NEWLINE);
}
res.push(`${BOUNDARY_PREFIX_SUFFIX}${changesetBoundary}`);
}
res.push(`${CONTENT_TYPE}: ${APPLICATION_HTTP}`);
res.push(`${CONTENT_TRANSFER_ENCODING}: ${BINARY}`);
if (request.request.method !== 'GET') {
res.push(`${CONTENT_ID}: ${changesetId++}`);
}
res.push(NEWLINE);
res.push(`${request.toLegacy(options)}`);
}
if (res.length) {
if (changesetBoundary !== null) {
res.push(`${BOUNDARY_PREFIX_SUFFIX}${changesetBoundary}${BOUNDARY_PREFIX_SUFFIX}`);
changesetBoundary = null;
}
res.push(`${BOUNDARY_PREFIX_SUFFIX}${batchBoundary}${BOUNDARY_PREFIX_SUFFIX}`);
}
return res.join(NEWLINE);
}
static buildJsonBody(requests, options) {
return {
requests: requests.map((request) => request.toJson(options)),
};
}
static parseLegacyResponse(requests, response) {
let chunks = [];
const contentType = response.headers.get(CONTENT_TYPE) || '';
const batchBoundary = Http.boundaryDelimiter(contentType);
const endLine = Http.boundaryEnd(batchBoundary);
const lines = (response.body || '').split(NEWLINE_REGEXP);
let changesetResponses = null;
let contentId = null;
let changesetBoundary = null;
let changesetEndLine = null;
let startIndex = null;
for (let index = 0; index < lines.length; index++) {
const line = lines[index];
if (line.startsWith(CONTENT_TYPE)) {
const contentTypeValue = Http.headerValue(line);
if (contentTypeValue === MULTIPART_MIXED) {
changesetResponses = [];
contentId = null;
changesetBoundary = Http.boundaryDelimiter(line);
changesetEndLine = Http.boundaryEnd(changesetBoundary);
startIndex = null;
}
continue;
}
else if (changesetResponses !== null && line.startsWith(CONTENT_ID)) {
contentId = Number(Http.headerValue(line));
}
else if (line.startsWith(HTTP11)) {
startIndex = index;
}
else if (line === batchBoundary ||
line === changesetBoundary ||
line === endLine ||
line === changesetEndLine) {
if (!startIndex) {
continue;
}
const chunk = lines.slice(startIndex, index);
if (changesetResponses !== null && contentId !== null) {
changesetResponses[contentId] = chunk;
}
else {
chunks.push(chunk);
}
if (line === batchBoundary || line === changesetBoundary) {
startIndex = index + 1;
}
else if (line === endLine || line === changesetEndLine) {
if (changesetResponses !== null) {
for (const response of changesetResponses) {
if (response) {
chunks.push(response);
}
}
}
changesetResponses = null;
changesetBoundary = null;
changesetEndLine = null;
startIndex = null;
}
}
}
return chunks.map((chunk, index) => {
let request = requests[index].request;
let { code, message } = Http.parseResponseStatus(chunk[0]);
chunk = chunk.slice(1);
let headers = new HttpHeaders();
var index = 1;
for (; index < chunk.length; index++) {
const batchBodyLine = chunk[index];
if (batchBodyLine === '') {
break;
}
const batchBodyLineParts = batchBodyLine.split(': ');
headers = headers.append(batchBodyLineParts[0].trim(), batchBodyLineParts[1].trim());
}
let body = '';
for (; index < chunk.length; index++) {
body += chunk[index];
}
if (code === 0) {
code = !!body ? 200 : 0;
}
let ok = code >= 200 && code < 300;
if (request.responseType === 'json' && typeof body === 'string') {
const originalBody = body;
body = body.replace(XSSI_PREFIX, '');
try {
body = body !== '' ? JSON.parse(body) : null;
}
catch (error) {
body = originalBody;
if (ok) {
ok = false;
body = { error, text: body };
}
}
}
return ok
? new HttpResponse({
body,
headers,
status: code,
statusText: message,
url: request.urlWithParams,
})
: new HttpErrorResponse({
// The error in this case is the response body (error from the server).
error: body,
headers,
status: code,
statusText: message,
url: request.urlWithParams,
});
});
}
static parseJsonResponse(requests, response) {
const responses = (response.body ? response.body : {})['responses'] ?? [];
return responses.map((response, index) => {
let request = requests[index].request;
let code = response['status'];
let headers = new HttpHeaders(response['headers']);
let body = response['body'];
if (code === 0) {
code = !!body ? 200 : 0;
}
let ok = code >= 200 && code < 300;
if (request.responseType === 'json' && typeof body === 'string') {
const originalBody = body;
body = body.replace(XSSI_PREFIX, '');
try {
body = body !== '' ? JSON.parse(body) : null;
}
catch (error) {
body = originalBody;
if (ok) {
ok = false;
body = { error, text: body };
}
}
}
return ok
? new HttpResponse({
body,
headers,
status: code,
url: request.urlWithParams,
})
: new HttpErrorResponse({
// The error in this case is the response body (error from the server).
error: body,
headers,
status: code,
url: request.urlWithParams,
});
});
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmF0Y2guanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLW9kYXRhL3NyYy9saWIvcmVzb3VyY2VzL3R5cGVzL2JhdGNoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxpQkFBaUIsRUFDakIsV0FBVyxFQUNYLFlBQVksR0FFYixNQUFNLHNCQUFzQixDQUFDO0FBRTlCLE9BQU8sRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRXBDLE9BQU8sRUFDTCxNQUFNLEVBQ04sTUFBTSxFQUNOLGdCQUFnQixFQUNoQixnQkFBZ0IsRUFDaEIsWUFBWSxFQUNaLE1BQU0sRUFDTixzQkFBc0IsRUFDdEIsZ0JBQWdCLEVBQ2hCLFVBQVUsRUFDVix5QkFBeUIsRUFDekIsWUFBWSxFQUNaLE1BQU0sRUFDTixlQUFlLEVBQ2Ysd0JBQXdCLEVBQ3hCLE9BQU8sRUFDUCxjQUFjLEVBQ2QsYUFBYSxFQUNiLFdBQVcsRUFDWCxXQUFXLEdBQ1osTUFBTSxpQkFBaUIsQ0FBQztBQUN6QixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDeEMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUU1QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBSzVDLE1BQU0sT0FBTyxpQkFBcUIsU0FBUSxPQUF5QjtJQUc5QztJQUZuQixFQUFFLENBQVM7SUFDWCxLQUFLLENBQVM7SUFDZCxZQUFtQixPQUEwQjtRQUMzQyxLQUFLLEVBQUUsQ0FBQztRQURTLFlBQU8sR0FBUCxPQUFPLENB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QUFDO1lBQ25DLElBQUksT0FBTyxDQUFDLFlBQVksS0FBSyxNQUFNLElBQUksT0FBTyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQ2hFLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQztnQkFDMUIsSUFBSSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUNyQyxJQUFJLENBQUM7b0JBQ0gsSUFBSSxHQUFHLElBQUksS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztnQkFDL0MsQ0FBQztnQkFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO29CQUNmLElBQUksR0FBRyxZQUFZLENBQUM7b0JBRXBCLElBQUksRUFBRSxFQUFFLENBQUM7d0JBQ1AsRUFBRSxHQUFHLEtBQUssQ0FBQzt3QkFDWCxJQUFJLEdBQUcsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDO29CQUMvQixDQUFDO2dCQUNILENBQUM7WUFDSCxDQUFDO1lBRUQsT0FBTyxFQUFFO2dCQUNQLENBQUMsQ0FBQyxJQUFJLFlBQVksQ0FBTTtvQkFDcEIsSUFBSTtvQkFDSixPQUFPO29CQUNQLE1BQU0sRUFBRSxJQUFJO29CQUNaLEdBQUcsRUFBRSxPQUFPLENBQUMsYUFBYTtpQkFDM0IsQ0FBQztnQkFDSixDQUFDLENBQUMsSUFBSSxpQkFBaUIsQ0FBQztvQkFDcEIsdUVBQXVFO29CQUN2RSxLQUFLLEVBQUUsSUFBSTtvQkFDWCxPQUFPO29CQUNQLE1BQU0sRUFBRSxJQUFJO29CQUNaLEdBQUcsRUFBRSxPQUFPLENBQUMsYUFBYTtpQkFDM0IsQ0FBQyxDQUFDO1FBQ1QsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBIdHRwRXJyb3JSZXNwb25zZSxcbiAgSHR0cEhlYWRlcnMsXG4gIEh0dHBSZXNwb25zZSxcbiAgSHR0cFJlc3BvbnNlQmFzZSxcbn0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwLCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBPRGF0YUFwaSB9IGZyb20gJy4uLy4uL2FwaSc7XG5pbXBvcnQge1xuICAkQkFUQ0gsXG4gIEFDQ0VQVCxcbiAgQVBQTElDQVRJT05fSFRUUCxcbiAgQVBQTElDQVRJT05fSlNPTixcbiAgQkFUQ0hfUFJFRklYLFxuICBCSU5BUlksXG4gIEJPVU5EQVJZX1BSRUZJWF9TVUZGSVgsXG4gIENIQU5HRVNFVF9QUkVGSVgsXG4gIENPTlRFTlRfSUQsXG4gIENPTlRFTlRfVFJBTlNGRVJfRU5DT0RJTkcsXG4gIENPTlRFTlRfVFlQRSxcbiAgSFRUUDExLFxuICBNVUxUSVBBUlRfTUlYRUQsXG4gIE1VTFRJUEFSVF9NSVhFRF9CT1VOREFSWSxcbiAgTkVXTElORSxcbiAgTkVXTElORV9SRUdFWFAsXG4gIE9EQVRBX1ZFUlNJT04sXG4gIFZFUlNJT05fNF8wLFxuICBYU1NJX1BSRUZJWCxcbn0gZnJvbSAnLi4vLi4vY29uc3RhbnRzJztcbmltcG9ydCB7IFBhdGhTZWdtZW50IH0gZnJvbSAnLi4vLi4vdHlwZXMnO1xuaW1wb3J0IHsgQXJyYXlzIH0gZnJvbSAnLi4vLi4vdXRpbHMvYXJyYXlzJztcbmltcG9ydCB7IEh0dHAgfSBmcm9tICcuLi8uLi91dGlscy9odHRwJztcbmltcG9ydCB7IFN0cmluZ3MgfSBmcm9tICcuLi8uLi91dGlscy9zdHJpbmdzJztcbmltcG9ydCB7IE9EYXRhUGF0aFNlZ21lbnRzIH0gZnJvbSAnLi4vcGF0aCc7XG5pbXBvcnQgeyBPRGF0YVJlcXVlc3QgfSBmcm9tICcuLi9yZXF1ZXN0JztcbmltcG9ydCB7IE9EYXRhUmVzb3VyY2UgfSBmcm9tICcuLi9yZXNvdXJjZSc7XG5pbXBvcnQgeyBPRGF0YU9wdGlvbnMgfSBmcm9tICcuL29wdGlvbnMnO1xuaW1wb3J0IHsgT0RhdGFBcGlPcHRpb25zIH0gZnJvbSAnLi4vLi4vb3B0aW9ucyc7XG5pbXBvcnQgeyBPRGF0YVJlc3BvbnNlIH0gZnJvbSAnLi4vcmVzcG9uc2UnO1xuXG5leHBvcnQgY2xhc3MgT0RhdGFCYXRjaFJlcXVlc3Q8VD4gZXh0ZW5kcyBTdWJqZWN0PEh0dHBSZXNwb25zZUJhc2U+IHtcbiAgaWQ6IHN0cmluZztcbiAgZ3JvdXA6IHN0cmluZztcbiAgY29uc3RydWN0b3IocHVibGljIHJlcXVlc3Q6IE9EYXRhUmVxdWVzdDxhbnk+KSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLmlkID0gU3RyaW5ncy51bmlxdWVJZCh7IHByZWZpeDogJ3InIH0pO1xuICAgIHRoaXMuZ3JvdXAgPSBTdHJpbmdzLnVuaXF1ZUlkKHsgcHJlZml4OiAnZycgfSk7XG4gIH1cblxuICBvdmVycmlkZSB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gdGhpcy50b0xlZ2FjeSgpO1xuICB9XG5cbiAgdG9MZWdhY3koeyByZWxhdGl2ZVVybHMgfTogeyByZWxhdGl2ZVVybHM/OiBib29sZWFuIH0gPSB7fSk6IHN0cmluZyB7XG4gICAgLy9UT0RPOiBSZWxhdGl2ZSBvciBBYnNvbHV0ZSB1cmwgP1xuICAgIGxldCByZXMgPSBbXG4gICAgICBgJHt0aGlzLnJlcXVlc3QubWV0aG9kfSAke1xuICAgICAgICByZWxhdGl2ZVVybHMgPyB0aGlzLnJlcXVlc3QucGF0aFdpdGhQYXJhbXMgOiB0aGlzLnJlcXVlc3QudXJsV2l0aFBhcmFtc1xuICAgICAgfSAke0hUVFAxMX1gLFxuICAgIF07XG4gICAgaWYgKFxuICAgICAgdGhpcy5yZXF1ZXN0Lm1ldGhvZCA9PT0gJ1BPU1QnIHx8XG4gICAgICB0aGlzLnJlcXVlc3QubWV0aG9kID09PSAnUEFUQ0gnIHx8XG4gICAgICB0aGlzLnJlcXVlc3QubWV0aG9kID09PSAnUFVUJ1xuICAgICkge1xuICAgICAgcmVzLnB1c2goYCR7Q09OVEVOVF9UWVBFfTogJHtBUFBMSUNBVElPTl9KU09OfWApO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnJlcXVlc3QuaGVhZGVycyBpbnN0YW5jZW9mIEh0dHBIZWFkZXJzKSB7XG4gICAgICBsZXQgaGVhZGVycyA9IHRoaXMucmVxdWVzdC5oZWFkZXJzO1xuICAgICAgcmVzID0gW1xuICAgICAgICAuLi5yZXMsXG4gICAgICAgIC4uLmhlYWRlcnNcbiAgICAgICAgICAua2V5cygpXG4gICAgICAgICAgLm1hcCgoa2V5KSA9PiBgJHtrZXl9OiAkeyhoZWFkZXJzLmdldEFsbChrZXkpIHx8IFtdKS5qb2luKCcsJyl9YCksXG4gICAgICBdO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnJlcXVlc3QubWV0aG9kID09PSAnR0VUJyB8fCB0aGlzLnJlcXVlc3QubWV0aG9kID09PSAnREVMRVRFJykge1xuICAgICAgcmVzLnB1c2goTkVXTElORSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlcy5wdXNoKGAke05FV0xJTkV9JHtKU09OLnN0cmluZ2lmeSh0aGlzLnJlcXVlc3QuYm9keSl9YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlcy5qb2luKE5FV0xJTkUpO1xuICB9XG5cbiAgdG9Kc29uKHsgcmVsYXRpdmVVcmxzIH06IHsgcmVsYXRpdmVVcmxzPzogYm9vbGVhbiB9ID0ge30pIHtcbiAgICBsZXQgcmVzOiB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfSA9IHtcbiAgICAgIGlkOiB0aGlzLmlkLFxuICAgICAgbWV0aG9kOiB0aGlzLnJlcXVlc3QubWV0aG9kLFxuICAgICAgdXJsOiByZWxhdGl2ZVVybHNcbiAgICAgICAgPyB0aGlzLnJlcXVlc3QucGF0aFdpdGhQYXJhbXNcbiAgICAgICAgOiB0aGlzLnJlcXVlc3QudXJsV2l0aFBhcmFtcyxcbiAgICAgIC8vJ2F0b21pY2l0eUdyb3VwJzogdGhpcy5ncm91cFxuICAgICAgLy9cImRlcGVuZHNPblwiOiBbXCJnMVwiLCBcImcyXCIsIFwicjJcIl1cbiAgICB9O1xuICAgIGlmICh0aGlzLnJlcXVlc3QuaGVhZGVycyBpbnN0YW5jZW9mIEh0dHBIZWFkZXJzKSB7XG4gICAgICBsZXQgaGVhZGVycyA9IHRoaXMucmVxdWVzdC5oZWFkZXJzO1xuICAgICAgcmVzWydoZWFkZXJzJ10gPSBoZWFkZXJzXG4gICAgICAgIC5rZXlzKClcbiAgICAgICAgLm1hcCgoa2V5KSA9PiBgJHtrZXl9OiAkeyhoZWFkZXJzLmdldEFsbChrZXkpIHx8IFtdKS5qb2luKCcsJyl9YCk7XG4gICAgfVxuICAgIGlmICghKHRoaXMucmVxdWVzdC5tZXRob2QgPT09ICdHRVQnIHx8IHRoaXMucmVxdWVzdC5tZXRob2QgPT09ICdERUxFVEUnKSkge1xuICAgICAgcmVzWydib2R5J10gPSB0aGlzLnJlcXVlc3QuYm9keTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzO1xuICB9XG5cbiAgb25Mb2FkKHJlc3BvbnNlOiBIdHRwUmVzcG9uc2VCYXNlKSB7XG4gICAgaWYgKHJlc3BvbnNlLm9rKSB7XG4gICAgICB0aGlzLm5leHQocmVzcG9uc2UpO1xuICAgICAgdGhpcy5jb21wbGV0ZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBBbiB1bnN1Y2Nlc3NmdWwgcmVxdWVzdCBpcyBkZWxpdmVyZWQgb24gdGhlIGVycm9yIGNoYW5uZWwuXG4gICAgICB0aGlzLmVycm9yKHJlc3BvbnNlIGFzIEh0dHBFcnJvclJlc3BvbnNlKTtcbiAgICB9XG4gIH1cblxuICBvbkVycm9yKHJlc3BvbnNlOiBIdHRwRXJyb3JSZXNwb25zZSkge1xuICAgIHRoaXMuZXJyb3IocmVzcG9uc2UpO1xuICB9XG59XG5cbi8qKlxuICogT0RhdGEgQmF0Y2ggUmVzb3VyY2VcbiAqIGh0dHBzOi8vd3d3Lm9kYXRhLm9yZy9nZXR0aW5nLXN0YXJ0ZWQvYWR2YW5jZWQtdHV0b3JpYWwvI2JhdGNoXG4gKi9cbmV4cG9ydCBjbGFzcyBPRGF0YUJhdGNoUmVzb3VyY2UgZXh0ZW5kcyBPRGF0YVJlc291cmNlPGFueT4ge1xuICAvLyBWQVJJQUJMRVNcbiAgcHJpdmF0ZSBfcmVxdWVzdHM6IE9EYXRhQmF0Y2hSZXF1ZXN0PGFueT5bXSA9IFtdO1xuICByZXF1ZXN0cygpIHtcbiAgICByZXR1cm4gdGhpcy5fcmVxdWVzdHMubWFwKChyKSA9PiByLnJlcXVlc3QpO1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVzcG9uc2VzOiBIdHRwUmVzcG9uc2VCYXNlW10gfCBudWxsID0gbnVsbDtcbiAgcmVzcG9uc2VzKCkge1xuICAgIHJldHVybiB0aGlzLl9yZXNwb25zZXM7XG4gIH1cblxuICAvLyNyZWdpb24gRmFjdG9yeVxuICBzdGF0aWMgZmFjdG9yeShhcGk6IE9EYXRhQXBpKSB7XG4gICAgbGV0IHNlZ21lbnRzID0gbmV3IE9EYXRhUGF0aFNlZ21lbnRzKCk7XG4gICAgc2VnbWVudHMuYWRkKFBhdGhTZWdtZW50LmJhdGNoLCAkQkFUQ0gpO1xuICAgIHJldHVybiBuZXcgT0RhdGFCYXRjaFJlc291cmNlKGFwaSwgeyBzZWdtZW50cyB9KTtcbiAgfVxuXG4gIG92ZXJyaWRlIGNsb25lKCk6IE9EYXRhQmF0Y2hSZXNvdXJjZSB7XG4gICAgY29uc3QgYmF0Y2ggPSBzdXBlci5jbG9uZSgpIGFzIE9EYXRhQmF0Y2hSZXNvdXJjZTtcbiAgICBiYXRjaC5fcmVxdWVzdHMgPSBbLi4udGhpcy5fcmVxdWVzdHNdO1xuICAgIHJldHVybiBiYXRjaDtcbiAgfVxuICAvLyNlbmRyZWdpb25cblxuICBwcml2YXRlIHN0b3JlUmVxdWVzdGVyKCkge1xuICAgIGNvbnN0IGN1cnJlbnQgPSB0aGlzLmFwaS5yZXF1ZXN0ZXI7XG4gICAgLy8gU3dpdGNoIHRvIHRoZSBiYXRjaCByZXF1ZXN0ZXJcbiAgICB0aGlzLmFwaS5yZXF1ZXN0ZXIgPSAocmVxOiBPRGF0YVJlcXVlc3Q8YW55Pik6IE9ic2VydmFibGU8YW55PiA9PiB7XG4gICAgICBpZiAocmVxLmFwaSAhPT0gdGhpcy5hcGkpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQmF0Y2ggUmVxdWVzdCBhcmUgZm9yIHRoZSBzYW1lIGFwaS4nKTtcbiAgICAgIGlmIChyZXEub2JzZXJ2ZSA9PT0gJ2V2ZW50cycpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkJhdGNoIFJlcXVlc3QgZG9lcyBub3QgYWxsb3dzIG9ic2VydmUgPT0gJ2V2ZW50cycuXCIpO1xuICAgICAgdGhpcy5fcmVxdWVzdHMucHVzaChuZXcgT0RhdGFCYXRjaFJlcXVlc3Q8YW55PihyZXEpKTtcbiAgICAgIHJldHVybiB0aGlzLl9yZXF1ZXN0c1t0aGlzLl9yZXF1ZXN0cy5sZW5ndGggLSAxXTtcbiAgICB9O1xuICAgIHJldHVybiBjdXJyZW50O1xuICB9XG5cbiAgcHJpdmF0ZSByZXN0b3JlUmVxdWVzdGVyKFxuICAgIGhhbmRsZXI6ICgocmVxOiBPRGF0YVJlcXVlc3Q8YW55PikgPT4gT2JzZXJ2YWJsZTxhbnk+KSB8IHVuZGVmaW5lZCxcbiAgKSB7XG4gICAgdGhpcy5hcGkucmVxdWVzdGVyID0gaGFuZGxlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgdG8gYmF0Y2ggcmVxdWVzdFxuICAgKiBAcGFyYW0gY3R4IFRoZSBjb250ZXh0IGZvciB0aGUgcmVxdWVzdFxuICAgKiBAcmV0dXJucyBUaGUgcmVzdWx0IG9mIGV4ZWN1dGUgdGhlIGNvbnRleHRcbiAgICovXG4gIGFkZDxSPihjdHg6IChiYXRjaDogdGhpcykgPT4gUik6IFIge1xuICAgIC8vIFN0b3JlIG9yaWdpbmFsIHJlcXVlc3RlclxuICAgIHZhciBoYW5kbGVyID0gdGhpcy5zdG9yZVJlcXVlc3RlcigpO1xuICAgIC8vIEV4ZWN1dGUgdGhlIGNvbnRleHRcbiAgICBjb25zdCByZXN1bHQgPSBjdHgodGhpcyk7XG4gICAgLy8gUmVzdG9yZSBvcmlnaW5hbCByZXF1ZXN0ZXJcbiAgICB0aGlzLnJlc3RvcmVSZXF1ZXN0ZXIoaGFuZGxlcik7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgc2VuZChvcHRpb25zPzogT0RhdGFPcHRpb25zKTogT2JzZXJ2YWJsZTxPRGF0YVJlc3BvbnNlPGFueT4+IHtcbiAgICBpZiAodGhpcy5hcGkub3B0aW9ucy5qc29uQmF0Y2hGb3JtYXQpIHtcbiAgICAgIHJldHVybiB0aGlzLnNlbmRKc29uKG9wdGlvbnMpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5zZW5kTGVnYWN5KG9wdGlvbnMpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc2VuZEpzb24ob3B0aW9ucz86IE9EYXRhT3B0aW9ucyk6IE9ic2VydmFibGU8T0RhdGFSZXNwb25zZTxPYmplY3Q+PiB7XG4gICAgY29uc3QgaGVhZGVycyA9IEh0dHAubWVyZ2VIdHRwSGVhZGVycygob3B0aW9ucyAmJiBvcHRpb25zLmhlYWRlcnMpIHx8IHt9LCB7XG4gICAgICBbT0RBVEFfVkVSU0lPTl06IFZFUlNJT05fNF8wLFxuICAgIH0pO1xuICAgIHJldHVybiB0aGlzLmFwaVxuICAgICAgLnJlcXVlc3Q8b2JqZWN0PignUE9TVCcsIHRoaXMsIHtcbiAgICAgICAgYm9keTogT0RhdGFCYXRjaFJlc291cmNlLmJ1aWxkSnNvbkJvZHkoXG4gICAgICAgICAgdGhpcy5fcmVxdWVzdHMsXG4gICAgICAgICAgdGhpcy5hcGkub3B0aW9ucyxcbiAgICAgICAgKSxcbiAgICAgICAgcmVzcG9uc2VUeXBlOiAnanNvbicsXG4gICAgICAgIG9ic2VydmU6ICdyZXNwb25zZScsXG4gICAgICAgIGhlYWRlcnM6IGhlYWRlcnMsXG4gICAgICAgIHBhcmFtczogb3B0aW9ucyA/IG9wdGlvbnMucGFyYW1zIDogdW5kZWZpbmVkLFxuICAgICAgICB3aXRoQ3JlZGVudGlhbHM6IG9wdGlvbnMgPyBvcHRpb25zLndpdGhDcmVkZW50aWFscyA6IHVuZGVmaW5lZCxcbiAgICAgIH0pXG4gICAgICAucGlwZShcbiAgICAgICAgbWFwKChyZXNwb25zZTogT0RhdGFSZXNwb25zZTxPYmplY3Q+KSA9PiB7XG4gICAgICAgICAgaWYgKHRoaXMuX3Jlc3BvbnNlcyA9PSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLl9yZXNwb25zZXMgPSBbXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5fcmVzcG9uc2VzID0gW1xuICAgICAgICAgICAgLi4udGhpcy5fcmVzcG9uc2VzLFxuICAgICAgICAgICAgLi4uT0RhdGFCYXRjaFJlc291cmNlLnBhcnNlSnNvblJlc3BvbnNlKHRoaXMuX3JlcXVlc3RzLCByZXNwb25zZSksXG4gICAgICAgICAgXTtcbiAgICAgICAgICAvL0hBQ0s6IHR1cGxlWzFdID09PSB1bmRlZmluZWRcbiAgICAgICAgICBBcnJheXMuemlwKHRoaXMuX3JlcXVlc3RzLCB0aGlzLl9yZXNwb25zZXMpLmZvckVhY2goKHR1cGxlKSA9PiB7XG4gICAgICAgICAgICBpZiAoIXR1cGxlWzBdLmlzU3RvcHBlZCAmJiB0dXBsZVsxXSkgdHVwbGVbMF0ub25Mb2FkKHR1cGxlWzFdKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc2VuZExlZ2FjeShcbiAgICBvcHRpb25zPzogT0RhdGFPcHRpb25zLFxuICApOiBPYnNlcnZhYmxlPE9EYXRhUmVzcG9uc2U8c3RyaW5nPj4ge1xuICAgIGNvbnN0IGJvdW5kID0gU3RyaW5ncy51bmlxdWVJZCh7IHByZWZpeDogQkFUQ0hfUFJFRklYIH0pO1xuICAgIGNvbnN0IGhlYWRlcnMgPSBIdHRwLm1lcmdlSHR0cEhlYWRlcnMoKG9wdGlvbnMgJiYgb3B0aW9ucy5oZWFkZXJzKSB8fCB7fSwge1xuICAgICAgW09EQVRBX1ZFUlNJT05dOiBWRVJTSU9OXzRfMCxcbiAgICAgIFtDT05URU5UX1RZUEVdOiBNVUxUSVBBUlRfTUlYRURfQk9VTkRBUlkgKyBib3VuZCxcbiAgICAgIFtBQ0NFUFRdOiBNVUxUSVBBUlRfTUlYRUQsXG4gICAgfSk7XG4gICAgcmV0dXJuIHRoaXMuYXBpXG4gICAgICAucmVxdWVzdDxPRGF0YVJlc3BvbnNlPHN0cmluZz4+KCdQT1NUJywgdGhpcywge1xuICAgICAgICBib2R5OiBPRGF0YUJhdGNoUmVzb3VyY2UuYnVpbGRMZWdhY3lCb2R5KFxuICAgICAgICAgIGJvdW5kLFxuICAgICAgICAgIHRoaXMuX3JlcXVlc3RzLFxuICAgICAgICAgIHRoaXMuYXBpLm9wdGlvbnMsXG4gICAgICAgICksXG4gICAgICAgIHJlc3BvbnNlVHlwZTogJ3RleHQnLFxuICAgICAgICBvYnNlcnZlOiAncmVzcG9uc2UnLFxuICAgICAgICBoZWFkZXJzOiBoZWFkZXJzLFxuICAgICAgICBwYXJhbXM6IG9wdGlvbnMgPyBvcHRpb25zLnBhcmFtcyA6IHVuZGVmaW5lZCxcbiAgICAgICAgd2l0aENyZWRlbnRpYWxzOiBvcHRpb25zID8gb3B0aW9ucy53aXRoQ3JlZGVudGlhbHMgOiB1bmRlZmluZWQsXG4gICAgICB9KVxuICAgICAgLnBpcGUoXG4gICAgICAgIG1hcCgocmVzcG9uc2U6IE9EYXRhUmVzcG9uc2U8c3RyaW5nPikgPT4ge1xuICAgICAgICAgIGlmICh0aGlzLl9yZXNwb25zZXMgPT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5fcmVzcG9uc2VzID0gW107XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMuX3Jlc3BvbnNlcyA9IFtcbiAgICAgICAgICAgIC4uLnRoaXMuX3Jlc3BvbnNlcyxcbiAgICAgICAgICAgIC4uLk9EYXRhQmF0Y2hSZXNvdXJjZS5wYXJzZUxlZ2FjeVJlc3BvbnNlKHRoaXMuX3JlcXVlc3RzLCByZXNwb25zZSksXG4gICAgICAgICAgXTtcbiAgICAgICAgICBBcnJheXMuemlwKHRoaXMuX3JlcXVlc3RzLCB0aGlzLl9yZXNwb25zZXMpLmZvckVhY2goKHR1cGxlKSA9PiB7XG4gICAgICAgICAgICBpZiAoIXR1cGxlWzBdLmlzU3RvcHBlZCAmJiB0dXBsZVsxXSkgdHVwbGVbMF0ub25Mb2FkKHR1cGxlWzFdKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeGVjdXRlIHRoZSBiYXRjaCByZXF1ZXN0XG4gICAqIEBwYXJhbSBjdHggVGhlIGNvbnRleHQgZm9yIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSBvcHRpb25zIFRoZSBvcHRpb25zIG9mIHRoZSBiYXRjaCByZXF1ZXN0XG4gICAqIEByZXR1cm5zIFRoZSByZXN1bHQgb2YgZXhlY3V0ZSB0aGUgY29udGV4dFxuICAgKi9cbiAgZXhlYzxSPihcbiAgICBjdHg6IChiYXRjaDogdGhpcykgPT4gUixcbiAgICBvcHRpb25zPzogT0RhdGFPcHRpb25zLFxuICApOiBPYnNlcnZhYmxlPFtSLCBPRGF0YVJlc3BvbnNlPHN0cmluZz5dPiB7XG4gICAgbGV0IHJlc3VsdCA9IHRoaXMuYWRkKGN0eCk7XG4gICAgcmV0dXJuIHRoaXMuc2VuZChvcHRpb25zKS5waXBlKG1hcCgocmVzcG9uc2UpID0+IFtyZXN1bHQsIHJlc3BvbnNlXSkpO1xuICB9XG5cbiAgYm9keSgpIHtcbiAgICByZXR1cm4gT0RhdGFCYXRjaFJlc291cmNlLmJ1aWxkTGVnYWN5Qm9keShcbiAgICAgIFN0cmluZ3MudW5pcXVlSWQoeyBwcmVmaXg6IEJBVENIX1BSRUZJWCB9KSxcbiAgICAgIHRoaXMuX3JlcXVlc3RzLFxuICAgICAgdGhpcy5hcGkub3B0aW9ucyxcbiAgICApO1xuICB9XG5cbiAganNvbigpIHtcbiAgICByZXR1cm4gT0RhdGFCYXRjaFJlc291cmNlLmJ1aWxkSnNvbkJvZHkodGhpcy5fcmVxdWVzdHMsIHRoaXMuYXBpLm9wdGlvbnMpO1xuICB9XG5cbiAgc3RhdGljIGJ1aWxkTGVnYWN5Qm9keShcbiAgICBiYXRjaEJvdW5kYXJ5OiBzdHJpbmcsXG4gICAgcmVxdWVzdHM6IE9EYXRhQmF0Y2hSZXF1ZXN0PGFueT5bXSxcbiAgICBvcHRpb25zOiBPRGF0YUFwaU9wdGlvbnMsXG4gICk6IHN0cmluZyB7XG4gICAgbGV0IHJlcyA9IFtdO1xuICAgIGxldCBjaGFuZ2VzZXRCb3VuZGFyeTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gICAgbGV0IGNoYW5nZXNldElkID0gMTtcblxuICAgIGZvciAoY29uc3QgcmVxdWVzdCBvZiByZXF1ZXN0cykge1xuICAgICAgLy8gaWYgbWV0aG9kIGlzIEdFVCBhbmQgdGhlcmUgaXMgYSBjaGFuZ2VzZXQgYm91bmRhcnkgb3BlbiB0aGVuIGNsb3NlIGl0XG4gICAgICBpZiAocmVxdWVzdC5yZXF1ZXN0Lm1ldGhvZCA9PT0gJ0dFVCcgJiYgY2hhbmdlc2V0Qm91bmRhcnkgIT09IG51bGwpIHtcbiAgICAgICAgcmVzLnB1c2goXG4gICAgICAgICAgYCR7Qk9VTkRBUllfUFJFRklYX1NVRkZJWH0ke2NoYW5nZXNldEJvdW5kYXJ5fSR7Qk9VTkRBUllfUFJFRklYX1NVRkZJWH1gLFxuICAgICAgICApO1xuICAgICAgICBjaGFuZ2VzZXRCb3VuZGFyeSA9IG51bGw7XG4gICAgICB9XG5cbiAgICAgIC8vIGlmIHRoZXJlIGlzIG5vIGNoYW5nZXNldCBib3VuZGFyeSBvcGVuIHRoZW4gb3BlbiBhIGJhdGNoIGJvdW5kYXJ5XG4gICAgICBpZiAoY2hhbmdlc2V0Qm91bmRhcnkgPT09IG51bGwpIHtcbiAgICAgICAgcmVzLnB1c2goYCR7Qk9VTkRBUllfUFJFRklYX1NVRkZJWH0ke2JhdGNoQm91bmRhcnl9YCk7XG4gICAgICB9XG5cbiAgICAgIC8vIGlmIG1ldGhvZCBpcyBub3QgR0VUIGFuZCB0aGVyZSBpcyBubyBjaGFuZ2VzZXQgYm91bmRhcnkgb3BlbiB0aGVuIG9wZW4gYSBjaGFuZ2VzZXQgYm91bmRhcnlcbiAgICAgIGlmIChyZXF1ZXN0LnJlcXVlc3QubWV0aG9kICE9PSAnR0VUJykge1xuICAgICAgICBpZiAoY2hhbmdlc2V0Qm91bmRhcnkgPT09IG51bGwpIHt