angular-odata
Version:
Client side OData typescript library for Angular
439 lines • 64 kB
JavaScript
import { HttpEventType } from '@angular/common/http';
import { NEVER } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { ODataInMemoryCache } from './cache';
import { DEFAULT_VERSION } from './constants';
import { ODataCollection, ODataModel, } from './models';
import { ODataApiOptions } from './options';
import { ODataQueryOptions, ODataPathSegments, ODataRequest, ODataResponse, ODataBatchResource, ODataMetadataResource, ODataActionResource, ODataFunctionResource, ODataEntityResource, ODataEntitySetResource, ODataSingletonResource, ODataNavigationPropertyResource, } from './resources';
import { EDM_PARSERS, ODataSchema, } from './schema';
import { NONE_PARSER, PathSegment, } from './types';
/**
* Api abstraction for consuming OData services.
*/
export class ODataApi {
requester;
serviceRootUrl;
metadataUrl;
name;
version;
default;
creation;
// Options
options;
// Cache
cache;
// Error Handler
errorHandler;
// Base Parsers
parsers;
// Schemas
schemas;
constructor(config) {
this.serviceRootUrl = config.serviceRootUrl;
if (this.serviceRootUrl.includes('?'))
throw new Error("The 'serviceRootUrl' should not contain query string. Please use 'params' to add extra parameters");
if (!this.serviceRootUrl.endsWith('/'))
this.serviceRootUrl += '/';
this.metadataUrl = config.metadataUrl ?? `${this.serviceRootUrl}$metadata`;
this.name = config.name;
this.version = config.version ?? DEFAULT_VERSION;
this.default = config.default ?? false;
this.creation = config.creation ?? new Date();
this.options = new ODataApiOptions({
...config.options,
version: this.version,
});
this.cache = config.cache ?? new ODataInMemoryCache();
this.errorHandler = config.errorHandler;
this.parsers = new Map(Object.entries(config.parsers ?? EDM_PARSERS));
this.schemas = (config.schemas ?? []).map((schema) => new ODataSchema(schema, this));
}
configure(settings = {}) {
this.requester = settings.requester;
this.schemas.forEach((schema) => {
schema.configure({
options: this.options.parserOptions,
});
});
}
populate(metadata) {
const config = metadata.toConfig();
this.version = config.version ?? DEFAULT_VERSION;
const schemas = (config.schemas ?? []).map((schema) => new ODataSchema(schema, this));
this.schemas = [...this.schemas, ...schemas];
schemas.forEach((schema) => {
schema.configure({
options: this.options.parserOptions,
});
});
}
fromJson(json) {
const segments = ODataPathSegments.fromJson(json.segments);
const query = ODataQueryOptions.fromJson(json.options);
switch (segments.last()?.name) {
case PathSegment.entitySet:
if (segments.last()?.hasKey()) {
return new ODataEntityResource(this, { segments, query });
}
else {
return new ODataEntitySetResource(this, { segments, query });
}
case PathSegment.navigationProperty:
return new ODataNavigationPropertyResource(this, { segments, query });
case PathSegment.singleton:
return new ODataSingletonResource(this, { segments, query });
case PathSegment.action:
return new ODataActionResource(this, { segments, query });
case PathSegment.function:
return new ODataFunctionResource(this, { segments, query });
}
throw new Error('No Resource for json');
}
/**
* Build a metadata resource.
* @returns ODataMetadataResource
*/
metadata() {
return ODataMetadataResource.factory(this);
}
/**
* Build a batch resource.
* @returns ODataBatchResource
*/
batch() {
return ODataBatchResource.factory(this);
}
/**
* Build a singleton resource.
* @param path Name of the singleton
* @returns
*/
singleton(name) {
const singleton = this.findSingleton(name);
return ODataSingletonResource.factory(this, {
path: singleton?.name ?? name,
type: singleton?.singletonType,
});
}
/**
* Build an entity set resource.
* @param path Name of the entity set
* @returns
*/
entitySet(name) {
const entitySet = this.findEntitySet(name);
return ODataEntitySetResource.factory(this, {
path: entitySet?.name ?? name,
type: entitySet?.entityType,
});
}
/**
* Unbound Action
* @param {string} path?
* @returns ODataActionResource
*/
action(path) {
const callable = this.findCallable(path);
return ODataActionResource.factory(this, {
path,
outgoingType: callable?.type(),
incomingType: callable?.returnType(),
});
}
/**
* Unbound Function
* @param {string} path?
* @returns ODataFunctionResource
*/
function(path) {
const callable = this.findCallable(path);
return ODataFunctionResource.factory(this, {
path,
outgoingType: callable?.type(),
incomingType: callable?.returnType(),
});
}
callable(type) {
return this.findCallable(type);
}
enumType(type) {
return this.findEnumType(type);
}
structuredType(type) {
return this.findStructuredType(type);
}
//request(req: ODataRequest<any>): Observable<any> {
request(method, resource, options) {
let req = ODataRequest.factory(this, method, resource, {
body: options.body,
etag: options.etag,
context: options.context,
headers: options.headers,
params: options.params,
responseType: options.responseType,
observe: (options.observe === 'events' ? 'events' : 'response'),
withCount: options.withCount,
bodyQueryOptions: options.bodyQueryOptions,
reportProgress: options.reportProgress,
fetchPolicy: options.fetchPolicy,
parserOptions: options.parserOptions,
withCredentials: options.withCredentials,
});
let res$ = this.requester !== undefined ? this.requester(req) : NEVER;
res$ = res$.pipe(map((res) => res.type === HttpEventType.Response
? ODataResponse.fromHttpResponse(req, res)
: res));
if (this.errorHandler !== undefined)
res$ = res$.pipe(catchError(this.errorHandler));
if (options.observe === 'events') {
return res$;
}
res$ = this.cache.handleRequest(req, res$);
switch (options.observe || 'body') {
case 'body':
switch (options.responseType) {
case 'entities':
return res$.pipe(map((res) => res.entities()));
case 'entity':
return res$.pipe(map((res) => res.entity()));
case 'property':
return res$.pipe(map((res) => res.property()));
case 'value':
return res$.pipe(map((res) => res.value()));
default:
// Other responseTypes (arraybuffer, blob, json, text) return body
return res$.pipe(map((res) => res.body));
}
case 'response':
// The response stream was requested directly, so return it.
return res$;
default:
// Guard against new future observe types being added.
throw new Error(`Unreachable: unhandled observe type ${options.observe}}`);
}
}
//# region Find by Type
// Memoize
memo = {
enumTypes: new Map(),
structuredTypes: new Map(),
callables: new Map(),
entitySets: new Map(),
singletons: new Map(),
parsers: new Map(),
options: new Map(),
};
createSchema(config) {
const schema = new ODataSchema(config, this);
schema.configure({
options: this.options.parserOptions,
});
this.schemas.push(schema);
return schema;
}
findSchema(type) {
const schemas = this.schemas.filter((s) => s.isNamespaceOf(type));
if (schemas.length === 0)
return undefined;
if (schemas.length === 1)
return schemas[0];
return schemas
.sort((s1, s2) => s1.namespace.length - s2.namespace.length)
.pop();
}
//#region EnumTypes
findEnumType(value) {
if (this.memo.enumTypes.has(value)) {
return this.memo.enumTypes.get(value);
}
const enumTypes = this.schemas.reduce((acc, schema) => [...acc, ...schema.enums], []);
let enumType = enumTypes.find((e) => e.type() === value);
enumType = enumType ?? enumTypes.find((e) => e.name === value);
this.memo.enumTypes.set(value, enumType);
return enumType;
}
//#endregion
//#region StructuredTypes
findStructuredType(value) {
if (this.memo.structuredTypes.has(value)) {
return this.memo.structuredTypes.get(value);
}
const structuredTypes = this.schemas.reduce((acc, schema) => [...acc, ...schema.entities], []);
let structuredType = structuredTypes.find((e) => e.type() === value);
structuredType =
structuredType ?? structuredTypes.find((e) => e.name === value);
this.memo.structuredTypes.set(value, structuredType);
return structuredType;
}
//#endregion
//#region Callables
findCallable(value, bindingType) {
const key = bindingType !== undefined ? `${bindingType}/${value}` : value;
if (this.memo.callables.has(key)) {
return this.memo.callables.get(key);
}
const bindingStructuredType = bindingType !== undefined
? this.findStructuredType(bindingType)
: undefined;
const callables = this.schemas.reduce((acc, schema) => [...acc, ...schema.callables], []);
let callable = callables.find((c) => {
const isCallableType = c.type() == value;
const callableBindingType = c.binding()?.type;
const callableBindingStructuredType = callableBindingType !== undefined
? this.findStructuredType(callableBindingType)
: undefined;
return (isCallableType &&
(!bindingStructuredType ||
(callableBindingStructuredType &&
bindingStructuredType.isSubtypeOf(callableBindingStructuredType))));
});
callable =
callable ??
callables.find((c) => {
const isCallableType = c.name == value;
const callableBindingType = c.binding()?.type;
const callableBindingStructuredType = callableBindingType !== undefined
? this.findStructuredType(callableBindingType)
: undefined;
return (isCallableType &&
(!bindingStructuredType ||
(callableBindingStructuredType &&
bindingStructuredType.isSubtypeOf(callableBindingStructuredType))));
});
this.memo.callables.set(key, callable);
return callable;
}
//#endregion
//#region EntitySets
findEntitySet(value) {
if (this.memo.entitySets.has(value)) {
return this.memo.entitySets.get(value);
}
const entitySets = this.schemas.reduce((acc, schema) => [...acc, ...schema.entitySets], []);
let entitySet = entitySets.find((e) => e.type() === value);
entitySet = entitySet ?? entitySets.find((e) => e.name === value);
this.memo.entitySets.set(value, entitySet);
return entitySet;
}
//#endregion
//#region Singletons
findSingleton(value) {
if (this.memo.singletons.has(value)) {
return this.memo.singletons.get(value);
}
const singletons = this.schemas.reduce((acc, schema) => [...acc, ...schema.singletons], []);
let singleton = singletons.find((e) => e.type() === value);
singleton = singleton ?? singletons.find((e) => e.name === value);
this.memo.singletons.set(value, singleton);
return singleton;
}
//#endregion
findModel(type) {
return this.findStructuredType(type)?.model;
}
createModel(structured) {
if (structured.model !== undefined)
return structured.model;
// Build Ad-hoc model
const Model = class extends ODataModel {
};
// Build Meta
Model.meta = this.optionsForType(structured.type(), {
structuredType: structured,
});
if (Model.meta !== undefined) {
// Configure
Model.meta.configure({
options: this.options.parserOptions,
});
}
// Store New Model for next time
structured.model = Model;
return Model;
}
modelForType(type) {
let Model = this.findModel(type);
if (Model === undefined) {
const structured = this.findStructuredType(type);
if (structured === undefined)
throw Error(`No structured type for ${type}`);
Model = this.createModel(structured);
}
return Model;
}
findCollection(type) {
return this.findStructuredType(type)?.collection;
}
createCollection(structured, model) {
if (structured.collection !== undefined)
return structured.collection;
if (model === undefined)
model = this.createModel(structured);
const Collection = class extends ODataCollection {
static model = model;
};
structured.collection = Collection;
return Collection;
}
collectionForType(type) {
let Collection = this.findCollection(type);
if (Collection === undefined) {
const structured = this.findStructuredType(type);
if (structured === undefined)
throw Error(`No structured type for ${type}`);
const Model = this.modelForType(type);
Collection = this.createCollection(structured, Model);
}
return Collection;
}
findEntitySetForEntityType(entityType) {
if (this.memo.entitySets.has(entityType)) {
return this.memo.entitySets.get(entityType);
}
const entitySet = this.schemas
.reduce((acc, schema) => [...acc, ...schema.entitySets], [])
.find((e) => e.entityType === entityType);
this.memo.entitySets.set(entityType, entitySet);
return entitySet;
}
parserForType(type, bindingType) {
const key = bindingType !== undefined ? `${bindingType}/${type}` : type;
if (this.memo.parsers.has(key)) {
return this.memo.parsers.get(key);
}
// None Parser by default
let parser = NONE_PARSER;
if (this.parsers.has(type)) {
// Edm, Base Parsers
parser = this.parsers.get(type);
}
else if (!type.startsWith('Edm.')) {
// Callable, EnumType, StructuredType (ComplexType and EntityType) Parsers
let value = this.findCallable(type, bindingType) ??
this.findEnumType(type) ??
this.findStructuredType(type);
parser = value?.parser;
}
// Set Parser for next time
this.memo.parsers.set(key, parser);
return parser;
}
optionsForType(type, { structuredType, config, } = {}) {
// Strucutred Options
if (this.memo.options.has(type)) {
return this.memo.options.get(type);
}
let meta = undefined;
if (!type.startsWith('Edm.')) {
structuredType = this.findStructuredType(type) ?? structuredType;
if (structuredType !== undefined) {
meta = ODataModel.buildMetaOptions({ config, structuredType });
}
}
// Set Options for next time
this.memo.options.set(type, meta);
return meta;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvYW5ndWxhci1vZGF0YS9zcmMvbGliL2FwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWEsYUFBYSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDaEUsT0FBTyxFQUFFLEtBQUssRUFBYyxNQUFNLE1BQU0sQ0FBQztBQUN6QyxPQUFPLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2pELE9BQU8sRUFBYyxrQkFBa0IsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUN6RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzlDLE9BQU8sRUFFTCxlQUFlLEVBQ2YsVUFBVSxHQUVYLE1BQU0sVUFBVSxDQUFDO0FBQ2xCLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFNUMsT0FBTyxFQUNMLGlCQUFpQixFQUNqQixpQkFBaUIsRUFDakIsWUFBWSxFQUNaLGFBQWEsRUFDYixrQkFBa0IsRUFDbEIscUJBQXFCLEVBQ3JCLG1CQUFtQixFQUNuQixxQkFBcUIsRUFDckIsbUJBQW1CLEVBQ25CLHNCQUFzQixFQUN0QixzQkFBc0IsRUFDdEIsK0JBQStCLEdBQ2hDLE1BQU0sYUFBYSxDQUFDO0FBQ3JCLE9BQU8sRUFDTCxXQUFXLEVBSVgsV0FBVyxHQUdaLE1BQU0sVUFBVSxDQUFDO0FBQ2xCLE9BQU8sRUFJTCxXQUFXLEVBR1gsV0FBVyxHQUdaLE1BQU0sU0FBUyxDQUFDO0FBR2pCOztHQUVHO0FBQ0gsTUFBTSxPQUFPLFFBQVE7SUFDbkIsU0FBUyxDQUFtRDtJQUM1RCxjQUFjLENBQVM7SUFDdkIsV0FBVyxDQUFTO0lBQ3BCLElBQUksQ0FBVTtJQUNkLE9BQU8sQ0FBZTtJQUN0QixPQUFPLENBQVU7SUFDakIsUUFBUSxDQUFPO0lBQ2YsVUFBVTtJQUNWLE9BQU8sQ0FBa0I7SUFD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QztJQUNoQixDQUFDO0lBRU0sY0FBYyxDQUNuQixJQUFZLEVBQ1osRUFDRSxjQUFjLEVBQ2QsTUFBTSxNQUNnRSxFQUFFO1FBRTFFLHFCQUFxQjtRQUNyQixJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ2hDLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBcUMsQ0FBQztRQUN6RSxDQUFDO1FBRUQsSUFBSSxJQUFJLEdBQXFDLFNBQVMsQ0FBQztRQUN2RCxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQzdCLGNBQWMsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUksSUFBSSxDQUFDLElBQUksY0FBYyxDQUFDO1lBQ3BFLElBQUksY0FBYyxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUNqQyxJQUFJLEdBQUcsVUFBVSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsTUFBTSxFQUFFLGNBQWMsRUFBRSxDQUFDLENBQUM7WUFDakUsQ0FBQztRQUNILENBQUM7UUFDRCw0QkFBNEI7UUFDNUIsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNsQyxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0dHBFdmVudCwgSHR0cEV2ZW50VHlwZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IE5FVkVSLCBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBjYXRjaEVycm9yLCBtYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBPRGF0YUNhY2hlLCBPRGF0YUluTWVtb3J5Q2FjaGUgfSBmcm9tICcuL2NhY2hlJztcbmltcG9ydCB7IERFRkFVTFRfVkVSU0lPTiB9IGZyb20gJy4vY29uc3RhbnRzJztcbmltcG9ydCB7XG4gIE1vZGVsT3B0aW9ucyxcbiAgT0RhdGFDb2xsZWN0aW9uLFxuICBPRGF0YU1vZGVsLFxuICBPRGF0YU1vZGVsT3B0aW9ucyxcbn0gZnJvbSAnLi9tb2RlbHMnO1xuaW1wb3J0IHsgT0RhdGFBcGlPcHRpb25zIH0gZnJvbSAnLi9vcHRpb25zJztcbmltcG9ydCB7IE9EYXRhT3B0aW9ucywgT0RhdGFSZXNvdXJjZSwgT0RhdGFTZWdtZW50IH0gZnJvbSAnLi9yZXNvdXJjZXMnO1xuaW1wb3J0IHtcbiAgT0RhdGFRdWVyeU9wdGlvbnMsXG4gIE9EYXRhUGF0aFNlZ21lbnRzLFxuICBPRGF0YVJlcXVlc3QsXG4gIE9EYXRhUmVzcG9uc2UsXG4gIE9EYXRhQmF0Y2hSZXNvdXJjZSxcbiAgT0RhdGFNZXRhZGF0YVJlc291cmNlLFxuICBPRGF0YUFjdGlvblJlc291cmNlLFxuICBPRGF0YUZ1bmN0aW9uUmVzb3VyY2UsXG4gIE9EYXRhRW50aXR5UmVzb3VyY2UsXG4gIE9EYXRhRW50aXR5U2V0UmVzb3VyY2UsXG4gIE9EYXRhU2luZ2xldG9uUmVzb3VyY2UsXG4gIE9EYXRhTmF2aWdhdGlvblByb3BlcnR5UmVzb3VyY2UsXG59IGZyb20gJy4vcmVzb3VyY2VzJztcbmltcG9ydCB7XG4gIEVETV9QQVJTRVJTLFxuICBPRGF0YUNhbGxhYmxlLFxuICBPRGF0YUVudGl0eVNldCxcbiAgT0RhdGFFbnVtVHlwZSxcbiAgT0RhdGFTY2hlbWEsXG4gIE9EYXRhU2luZ2xldG9uLFxuICBPRGF0YVN0cnVjdHVyZWRUeXBlLFxufSBmcm9tICcuL3NjaGVtYSc7XG5pbXBvcnQge1xuICBBcGlDb25maWcsXG4gIEFwaU9wdGlvbnMsXG4gIEVkbVR5cGUsXG4gIE5PTkVfUEFSU0VSLFxuICBPRGF0YVZlcnNpb24sXG4gIFBhcnNlcixcbiAgUGF0aFNlZ21lbnQsXG4gIFF1ZXJ5T3B0aW9uLFxuICBTY2hlbWFDb25maWcsXG59IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgT0RhdGFNZXRhZGF0YSB9IGZyb20gJy4vbWV0YWRhdGEvbWV0YWRhdGEnO1xuXG4vKipcbiAqIEFwaSBhYnN0cmFjdGlvbiBmb3IgY29uc3VtaW5nIE9EYXRhIHNlcnZpY2VzLlxuICovXG5leHBvcnQgY2xhc3MgT0RhdGFBcGkge1xuICByZXF1ZXN0ZXI/OiAocmVxdWVzdDogT0RhdGFSZXF1ZXN0PGFueT4pID0+IE9ic2VydmFibGU8YW55PjtcbiAgc2VydmljZVJvb3RVcmw6IHN0cmluZztcbiAgbWV0YWRhdGFVcmw6IHN0cmluZztcbiAgbmFtZT86IHN0cmluZztcbiAgdmVyc2lvbjogT0RhdGFWZXJzaW9uO1xuICBkZWZhdWx0OiBib29sZWFuO1xuICBjcmVhdGlvbjogRGF0ZTtcbiAgLy8gT3B0aW9uc1xuICBvcHRpb25zOiBPRGF0YUFwaU9wdGlvbnM7XG4gIC8vIENhY2hlXG4gIGNhY2hlITogT0RhdGFDYWNoZTtcbiAgLy8gRXJyb3IgSGFuZGxlclxuICBlcnJvckhhbmRsZXI/OiAoZXJyb3I6IGFueSwgY2F1Z2h0OiBPYnNlcnZhYmxlPGFueT4pID0+IE9ic2VydmFibGU8bmV2ZXI+O1xuICAvLyBCYXNlIFBhcnNlcnNcbiAgcGFyc2VyczogTWFwPHN0cmluZywgUGFyc2VyPGFueT4+O1xuICAvLyBTY2hlbWFzXG4gIHNjaGVtYXM6IE9EYXRhU2NoZW1hW107XG5cbiAgY29uc3RydWN0b3IoY29uZmlnOiBBcGlDb25maWcpIHtcbiAgICB0aGlzLnNlcnZpY2VSb290VXJsID0gY29uZmlnLnNlcnZpY2VSb290VXJsO1xuICAgIGlmICh0aGlzLnNlcnZpY2VSb290VXJsLmluY2x1ZGVzKCc/JykpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiVGhlICdzZXJ2aWNlUm9vdFVybCcgc2hvdWxkIG5vdCBjb250YWluIHF1ZXJ5IHN0cmluZy4gUGxlYXNlIHVzZSAncGFyYW1zJyB0byBhZGQgZXh0cmEgcGFyYW1ldGVyc1wiLFxuICAgICAgKTtcbiAgICBpZiAoIXRoaXMuc2VydmljZVJvb3RVcmwuZW5kc1dpdGgoJy8nKSkgdGhpcy5zZXJ2aWNlUm9vdFVybCArPSAnLyc7XG4gICAgdGhpcy5tZXRhZGF0YVVybCA9IGNvbmZpZy5tZXRhZGF0YVVybCA/PyBgJHt0aGlzLnNlcnZpY2VSb290VXJsfSRtZXRhZGF0YWA7XG4gICAgdGhpcy5uYW1lID0gY29uZmlnLm5hbWU7XG4gICAgdGhpcy52ZXJzaW9uID0gY29uZmlnLnZlcnNpb24gPz8gREVGQVVMVF9WRVJTSU9OO1xuICAgIHRoaXMuZGVmYXVsdCA9IGNvbmZpZy5kZWZhdWx0ID8/IGZhbHNlO1xuICAgIHRoaXMuY3JlYXRpb24gPSBjb25maWcuY3JlYXRpb24gPz8gbmV3IERhdGUoKTtcbiAgICB0aGlzLm9wdGlvbnMgPSBuZXcgT0RhdGFBcGlPcHRpb25zKHtcbiAgICAgIC4uLmNvbmZpZy5vcHRpb25zLFxuICAgICAgdmVyc2lvbjogdGhpcy52ZXJzaW9uLFxuICAgIH0pO1xuXG4gICAgdGhpcy5jYWNoZSA9IChjb25maWcuY2FjaGUgYXMgT0RhdGFDYWNoZSkgPz8gbmV3IE9EYXRhSW5NZW1vcnlDYWNoZSgpO1xuICAgIHRoaXMuZXJyb3JIYW5kbGVyID0gY29uZmlnLmVycm9ySGFuZGxlcjtcbiAgICB0aGlzLnBhcnNlcnMgPSBuZXcgTWFwKE9iamVjdC5lbnRyaWVzKGNvbmZpZy5wYXJzZXJzID8/IEVETV9QQVJTRVJTKSk7XG5cbiAgICB0aGlzLnNjaGVtYXMgPSAoY29uZmlnLnNjaGVtYXMgPz8gW10pLm1hcChcbiAgICAgIChzY2hlbWEpID0+IG5ldyBPRGF0YVNjaGVtYShzY2hlbWEsIHRoaXMpLFxuICAgICk7XG4gIH1cblxuICBjb25maWd1cmUoXG4gICAgc2V0dGluZ3M6IHtcbiAgICAgIHJlcXVlc3Rlcj86IChyZXF1ZXN0OiBPRGF0YVJlcXVlc3Q8YW55PikgPT4gT2JzZXJ2YWJsZTxhbnk+O1xuICAgIH0gPSB7fSxcbiAgKSB7XG4gICAgdGhpcy5yZXF1ZXN0ZXIgPSBzZXR0aW5ncy5yZXF1ZXN0ZXI7XG4gICAgdGhpcy5zY2hlbWFzLmZvckVhY2goKHNjaGVtYSkgPT4ge1xuICAgICAgc2NoZW1hLmNvbmZpZ3VyZSh7XG4gICAgICAgIG9wdGlvbnM6IHRoaXMub3B0aW9ucy5wYXJzZXJPcHRpb25zLFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBwb3B1bGF0ZShtZXRhZGF0YTogT0RhdGFNZXRhZGF0YSkge1xuICAgIGNvbnN0IGNvbmZpZyA9IG1ldGFkYXRhLnRvQ29uZmlnKCk7XG4gICAgdGhpcy52ZXJzaW9uID0gY29uZmlnLnZlcnNpb24gPz8gREVGQVVMVF9WRVJTSU9OO1xuICAgIGNvbnN0IHNjaGVtYXMgPSAoY29uZmlnLnNjaGVtYXMgPz8gW10pLm1hcChcbiAgICAgIChzY2hlbWEpID0+IG5ldyBPRGF0YVNjaGVtYShzY2hlbWEsIHRoaXMpLFxuICAgICk7XG4gICAgdGhpcy5zY2hlbWFzID0gWy4uLnRoaXMuc2NoZW1hcywgLi4uc2NoZW1hc107XG4gICAgc2NoZW1hcy5mb3JFYWNoKChzY2hlbWEpID0+IHtcbiAgICAgIHNjaGVtYS5jb25maWd1cmUoe1xuICAgICAgICBvcHRpb25zOiB0aGlzLm9wdGlvbnMucGFyc2VyT3B0aW9ucyxcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgZnJvbUpzb248UCwgUj4oanNvbjoge1xuICAgIHNlZ21lbnRzOiBPRGF0YVNlZ21lbnRbXTtcbiAgICBvcHRpb25zOiB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfTtcbiAgfSk6IE9EYXRhQWN0aW9uUmVzb3VyY2U8UCwgUj4gfCBPRGF0YUZ1bmN0aW9uUmVzb3VyY2U8UCwgUj47XG4gIGZyb21Kc29uPEU+KGpzb246IHtcbiAgICBzZWdtZW50czogT0RhdGFTZWdtZW50W107XG4gICAgb3B0aW9uczogeyBbbmFtZTogc3RyaW5nXTogYW55IH07XG4gIH0pOlxuICAgIHwgT0RhdGFFbnRpdHlSZXNvdXJjZTxFPlxuICAgIHwgT0RhdGFFbnRpdHlTZXRSZXNvdXJjZTxFPlxuICAgIHwgT0RhdGFOYXZpZ2F0aW9uUHJvcGVydHlSZXNvdXJjZTxFPlxuICAgIHwgT0RhdGFTaW5nbGV0b25SZXNvdXJjZTxFPjtcbiAgZnJvbUpzb24oanNvbjoge1xuICAgIHNlZ21lbnRzOiBPRGF0YVNlZ21lbnRbXTtcbiAgICBvcHRpb25zOiB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfTtcbiAgfSkge1xuICAgIGNvbnN0IHNlZ21lbnRzID0gT0RhdGFQYXRoU2VnbWVudHMuZnJvbUpzb24oanNvbi5zZWdtZW50cyk7XG4gICAgY29uc3QgcXVlcnkgPSBPRGF0YVF1ZXJ5T3B0aW9ucy5mcm9tSnNvbjxhbnk+KGpzb24ub3B0aW9ucyk7XG4gICAgc3dpdGNoIChzZWdtZW50cy5sYXN0KCk/Lm5hbWUgYXMgUGF0aFNlZ21lbnQpIHtcbiAgICAgIGNhc2UgUGF0aFNlZ21lbnQuZW50aXR5U2V0OlxuICAgICAgICBpZiAoc2VnbWVudHMubGFzdCgpPy5oYXNLZXkoKSkge1xuICAgICAgICAgIHJldHVybiBuZXcgT0RhdGFFbnRpdHlSZXNvdXJjZSh0aGlzLCB7IHNlZ21lbnRzLCBxdWVyeSB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gbmV3IE9EYXRhRW50aXR5U2V0UmVzb3VyY2UodGhpcywgeyBzZWdtZW50cywgcXVlcnkgfSk7XG4gICAgICAgIH1cbiAgICAgIGNhc2UgUGF0aFNlZ21lbnQubmF2aWdhdGlvblByb3BlcnR5OlxuICAgICAgICByZXR1cm4gbmV3IE9EYXRhTmF2aWdhdGlvblByb3BlcnR5UmVzb3VyY2UodGhpcywgeyBzZWdtZW50cywgcXVlcnkgfSk7XG4gICAgICBjYXNlIFBhdGhTZWdtZW50LnNpbmdsZXRvbjpcbiAgICAgICAgcmV0dXJuIG5ldyBPRGF0YVNpbmdsZXRvblJlc291cmNlKHRoaXMsIHsgc2VnbWVudHMsIHF1ZXJ5IH0pO1xuICAgICAgY2FzZSBQYXRoU2VnbWVudC5hY3Rpb246XG4gICAgICAgIHJldHVybiBuZXcgT0RhdGFBY3Rpb25SZXNvdXJjZSh0aGlzLCB7IHNlZ21lbnRzLCBxdWVyeSB9KTtcbiAgICAgIGNhc2UgUGF0aFNlZ21lbnQuZnVuY3Rpb246XG4gICAgICAgIHJldHVybiBuZXcgT0RhdGFGdW5jdGlvblJlc291cmNlKHRoaXMsIHsgc2VnbWVudHMsIHF1ZXJ5IH0pO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIFJlc291cmNlIGZvciBqc29uJyk7XG4gIH1cblxuICAvKipcbiAgICogQnVpbGQgYSBtZXRhZGF0YSByZXNvdXJjZS5cbiAgICogQHJldHVybnMgT0RhdGFNZXRhZGF0YVJlc291cmNlXG4gICAqL1xuICBtZXRhZGF0YSgpOiBPRGF0YU1ldGFkYXRhUmVzb3VyY2Uge1xuICAgIHJldHVybiBPRGF0YU1ldGFkYXRhUmVzb3VyY2UuZmFjdG9yeSh0aGlzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBhIGJhdGNoIHJlc291cmNlLlxuICAgKiBAcmV0dXJucyBPRGF0YUJhdGNoUmVzb3VyY2VcbiAgICovXG4gIGJhdGNoKCk6IE9EYXRhQmF0Y2hSZXNvdXJjZSB7XG4gICAgcmV0dXJuIE9EYXRhQmF0Y2hSZXNvdXJjZS5mYWN0b3J5KHRoaXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIGEgc2luZ2xldG9uIHJlc291cmNlLlxuICAgKiBAcGFyYW0gcGF0aCBOYW1lIG9mIHRoZSBzaW5nbGV0b25cbiAgICogQHJldHVybnNcbiAgICovXG4gIHNpbmdsZXRvbjxUPihuYW1lOiBzdHJpbmcpIHtcbiAgICBjb25zdCBzaW5nbGV0b24gPSB0aGlzLmZpbmRTaW5nbGV0b24obmFtZSk7XG4gICAgcmV0dXJuIE9EYXRhU2luZ2xldG9uUmVzb3VyY2UuZmFjdG9yeTxUPih0aGlzLCB7XG4gICAgICBwYXRoOiBzaW5nbGV0b24/Lm5hbWUgPz8gbmFtZSxcbiAgICAgIHR5cGU6IHNpbmdsZXRvbj8uc2luZ2xldG9uVHlwZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBhbiBlbnRpdHkgc2V0IHJlc291cmNlLlxuICAgKiBAcGFyYW0gcGF0aCBOYW1lIG9mIHRoZSBlbnRpdHkgc2V0XG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBlbnRpdHlTZXQ8VD4obmFtZTogc3RyaW5nKTogT0RhdGFFbnRpdHlTZXRSZXNvdXJjZTxUPiB7XG4gICAgY29uc3QgZW50aXR5U2V0ID0gdGhpcy5maW5kRW50aXR5U2V0KG5hbWUpO1xuICAgIHJldHVybiBPRGF0YUVudGl0eVNldFJlc291cmNlLmZhY3Rvcnk8VD4odGhpcywge1xuICAgICAgcGF0aDogZW50aXR5U2V0Py5uYW1lID8/IG5hbWUsXG4gICAgICB0eXBlOiBlbnRpdHlTZXQ/LmVudGl0eVR5cGUsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVW5ib3VuZCBBY3Rpb25cbiAgICogQHBhcmFtICB7c3RyaW5nfSBwYXRoP1xuICAgKiBAcmV0dXJucyBPRGF0YUFjdGlvblJlc291cmNlXG4gICAqL1xuICBhY3Rpb248UCwgUj4ocGF0aDogc3RyaW5nKTogT0RhdGFBY3Rpb25SZXNvdXJjZTxQLCBSPiB7XG4gICAgY29uc3QgY2FsbGFibGUgPSB0aGlzLmZpbmRDYWxsYWJsZTxSPihwYXRoKTtcbiAgICByZXR1cm4gT0RhdGFBY3Rpb25SZXNvdXJjZS5mYWN0b3J5PFAsIFI+KHRoaXMsIHtcbiAgICAgIHBhdGgsXG4gICAgICBvdXRnb2luZ1R5cGU6IGNhbGxhYmxlPy50eXBlKCksXG4gICAgICBpbmNvbWluZ1R5cGU6IGNhbGxhYmxlPy5yZXR1cm5UeXBlKCksXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVW5ib3VuZCBGdW5jdGlvblxuICAgKiBAcGFyYW0gIHtzdHJpbmd9IHBhdGg/XG4gICAqIEByZXR1cm5zIE9EYXRhRnVuY3Rpb25SZXNvdXJjZVxuICAgKi9cbiAgZnVuY3Rpb248UCwgUj4ocGF0aDogc3RyaW5nKTogT0RhdGFGdW5jdGlvblJlc291cmNlPFAsIFI+IHtcbiAgICBjb25zdCBjYWxsYWJsZSA9IHRoaXMuZmluZENhbGxhYmxlPFI+KHBhdGgpO1xuICAgIHJldHVybiBPRGF0YUZ1bmN0aW9uUmVzb3VyY2UuZmFjdG9yeTxQLCBSPih0aGlzLCB7XG4gICAgICBwYXRoLFxuICAgICAgb3V0Z29pbmdUeXBlOiBjYWxsYWJsZT8udHlwZSgpLFxuICAgICAgaW5jb21pbmdUeXBlOiBjYWxsYWJsZT8ucmV0dXJuVHlwZSgpLFxuICAgIH0pO1xuICB9XG5cbiAgY2FsbGFibGU8VD4odHlwZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuZmluZENhbGxhYmxlPFQ+KHR5cGUpO1xuICB9XG5cbiAgZW51bVR5cGU8VD4odHlwZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuZmluZEVudW1UeXBlPFQ+KHR5cGUpO1xuICB9XG5cbiAgc3RydWN0dXJlZFR5cGU8VD4odHlwZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuZmluZFN0cnVjdHVyZWRUeXBlPFQ+KHR5cGUpO1xuICB9XG5cbiAgLy9yZXF1ZXN0KHJlcTogT0RhdGFSZXF1ZXN0PGFueT4pOiBPYnNlcnZhYmxlPGFueT4ge1xuICByZXF1ZXN0PFQ+KFxuICAgIG1ldGhvZDogc3RyaW5nLFxuICAgIHJlc291cmNlOiBPRGF0YVJlc291cmNlPGFueT4sXG4gICAgb3B0aW9uczogT0RhdGFPcHRpb25zICYge1xuICAgICAgYm9keT86IGFueTtcbiAgICAgIGV0YWc/OiBzdHJpbmc7XG4gICAgICByZXNwb25zZVR5cGU/OlxuICAgICAgICB8ICdhcnJheWJ1ZmZlcidcbiAgICAgICAgfCAnYmxvYidcbiAgICAgICAgfCAnanNvbidcbiAgICAgICAgfCAndGV4dCdcbiAgICAgICAgfCAndmFsdWUnXG4gICAgICAgIHwgJ3Byb3BlcnR5J1xuICAgICAgICB8ICdlbnRpdHknXG4gICAgICAgIHwgJ2VudGl0aWVzJztcbiAgICAgIG9ic2VydmU/OiAnYm9keScgfCAnZXZlbnRzJyB8ICdyZXNwb25zZSc7XG4gICAgICB3aXRoQ291bnQ/OiBib29sZWFuO1xuICAgICAgYm9keVF1ZXJ5T3B0aW9ucz86IFF1ZXJ5T3B0aW9uW107XG4gICAgfSxcbiAgKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICBsZXQgcmVxID0gT0RhdGFSZXF1ZXN0LmZhY3RvcnkodGhpcywgbWV0aG9kLCByZXNvdXJjZSwge1xuICAgICAgYm9keTogb3B0aW9ucy5ib2R5LFxuICAgICAgZXRhZzogb3B0aW9ucy5ldGFnLFxuICAgICAgY29udGV4dDogb3B0aW9ucy5jb250ZXh0LFxuICAgICAgaGVhZGVyczogb3B0aW9ucy5oZWFkZXJzLFxuICAgICAgcGFyYW1zOiBvcHRpb25zLnBhcmFtcyxcbiAgICAgIHJlc3BvbnNlVHlwZTogb3B0aW9ucy5yZXNwb25zZVR5cGUsXG4gICAgICBvYnNlcnZlOiAob3B0aW9ucy5vYnNlcnZlID09PSAnZXZlbnRzJyA/ICdldmVudHMnIDogJ3Jlc3BvbnNlJykgYXNcbiAgICAgICAgfCAnZXZlbnRzJ1xuICAgICAgICB8ICdyZXNwb25zZScsXG4gICAgICB3aXRoQ291bnQ6IG9wdGlvbnMud2l0aENvdW50LFxuICAgICAgYm9keVF1ZXJ5T3B0aW9uczogb3B0aW9ucy5ib2R5UXVlcnlPcHRpb25zLFxuICAgICAgcmVwb3J0UHJvZ3Jlc3M6IG9wdGlvbnMucmVwb3J0UHJvZ3Jlc3MsXG4gICAgICBmZXRjaFBvbGljeTogb3B0aW9ucy5mZXRjaFBvbGljeSxcbiAgICAgIHBhcnNlck9wdGlvbnM6IG9wdGlvbnMucGFyc2VyT3B0aW9ucyxcbiAgICAgIHdpdGhDcmVkZW50aWFsczogb3B0aW9ucy53aXRoQ3JlZGVudGlhbHMsXG4gICAgfSk7XG5cbiAgICBsZXQgcmVzJCA9IHRoaXMucmVxdWVzdGVyICE9PSB1bmRlZmluZWQgPyB0aGlzLnJlcXVlc3RlcihyZXEpIDogTkVWRVI7XG5cbiAgICByZXMkID0gcmVzJC5waXBlKFxuICAgICAgbWFwKChyZXM6IEh0dHBFdmVudDxhbnk+KSA9PlxuICAgICAgICByZXMudHlwZSA9PT0gSHR0cEV2ZW50VHlwZS5SZXNwb25zZVxuICAgICAgICAgID8gT0RhdGFSZXNwb25zZS5mcm9tSHR0cFJlc3BvbnNlPGFueT4ocmVxLCByZXMpXG4gICAgICAgICAgOiByZXMsXG4gICAgICApLFxuICAgICk7XG5cbiAgICBpZiAodGhpcy5lcnJvckhhbmRsZXIgIT09IHVuZGVmaW5lZClcbiAgICAgIHJlcyQgPSByZXMkLnBpcGUoY2F0Y2hFcnJvcih0aGlzLmVycm9ySGFuZGxlcikpO1xuXG4gICAgaWYgKG9wdGlvbnMub2JzZXJ2ZSA9PT0gJ2V2ZW50cycpIHtcbiAgICAgIHJldHVybiByZXMkO1xuICAgIH1cblxuICAgIHJlcyQgPSB0aGlzLmNhY2hlLmhhbmRsZVJlcXVlc3QocmVxLCByZXMkKTtcblxuICAgIHN3aXRjaCAob3B0aW9ucy5vYnNlcnZlIHx8ICdib2R5Jykge1xuICAgICAgY2FzZSAnYm9keSc6XG4gICAgICAgIHN3aXRjaCAob3B0aW9ucy5yZXNwb25zZVR5cGUpIHtcbiAgICAgICAgICBjYXNlICdlbnRpdGllcyc6XG4gICAgICAgICAgICByZXR1cm4gcmVzJC5waXBlKG1hcCgocmVzOiBPRGF0YVJlc3BvbnNlPFQ+KSA9PiByZXMuZW50aXRpZXMoKSkpO1xuICAgICAgICAgIGNhc2UgJ2VudGl0eSc6XG4gICAgICAgICAgICByZXR1cm4gcmVzJC5waXBlKG1hcCgocmVzOiBPRGF0YVJlc3BvbnNlPFQ+KSA9PiByZXMuZW5