@orbit/records
Version:
A flexible data access and synchronization layer.
216 lines • 26.4 kB
JavaScript
import { QueryTerm } from '@orbit/data';
import { isObject } from '@orbit/utils';
import { ValidationError } from './record-exceptions';
import { StandardRecordValidators } from './record-validators/standard-record-validators';
function isFilterSpecifier(param) {
return param.kind !== undefined;
}
function isAttributeFilterParam(param) {
return param.attribute !== undefined;
}
function isRelatedRecordFilterParam(param) {
return (param.relation !== undefined &&
param.record !== undefined);
}
function isRelatedRecordsFilterParam(param) {
return (param.relation !== undefined &&
param.records !== undefined);
}
export class BaseRecordQueryTerm extends QueryTerm {
constructor(queryBuilder, expression) {
super(expression);
this.$queryBuilder = queryBuilder;
}
toQueryExpression() {
const expression = super.toQueryExpression();
const validatorFor = this.$queryBuilder.$validatorFor;
if (validatorFor) {
const schema = this.$queryBuilder.$schema;
const validateRecordQueryExpression = validatorFor(StandardRecordValidators.RecordQueryExpression);
const issues = validateRecordQueryExpression(expression, {
validatorFor,
schema
});
if (issues !== undefined) {
throw new ValidationError('Validation isssues encountered while building a query expression', issues);
}
}
return expression;
}
}
/**
* A query term representing a single record.
*/
export class FindRecordTerm extends BaseRecordQueryTerm {
constructor(queryBuilder, record) {
super(queryBuilder, {
op: 'findRecord',
record
});
}
}
export class FindRelatedRecordTerm extends BaseRecordQueryTerm {
constructor(queryBuilder, record, relationship) {
super(queryBuilder, {
op: 'findRelatedRecord',
record,
relationship
});
}
}
export class FindRecordsTerm extends BaseRecordQueryTerm {
/**
* Applies sorting to a collection query.
*
* Sort specifiers can be expressed in object form, like:
*
* ```ts
* { attribute: 'name', order: 'descending' }
* { attribute: 'name', order: 'ascending' }
* ```
*
* Or in string form, like:
*
* ```ts
* '-name' // descending order
* 'name' // ascending order
* ```
*/
sort(...params) {
var _a;
const specifiers = params.map((p) => this.$sortParamToSpecifier(p));
this._expression.sort = ((_a = this._expression.sort) !== null && _a !== void 0 ? _a : []).concat(specifiers);
return this;
}
/**
* Applies pagination to a collection query.
*/
page(param) {
this._expression.page = this.$pageParamToSpecifier(param);
return this;
}
/**
* Apply a filter expression.
*
* For example:
*
* ```ts
* oqb
* .records('planet')
* .filter({ attribute: 'atmosphere', value: true },
* { attribute: 'classification', value: 'terrestrial' });
* ```
*/
filter(...params) {
var _a;
const specifiers = params.map((p) => this.$filterParamToSpecifier(p));
this._expression.filter = ((_a = this._expression.filter) !== null && _a !== void 0 ? _a : []).concat(specifiers);
return this;
}
$filterParamToSpecifier(param) {
var _a;
let specifier;
if (isFilterSpecifier(param)) {
specifier = param;
}
else {
const op = (_a = param.op) !== null && _a !== void 0 ? _a : 'equal';
if (isAttributeFilterParam(param)) {
const { attribute, value } = param;
specifier = {
kind: 'attribute',
op,
attribute,
value
};
}
else if (isRelatedRecordFilterParam(param)) {
const { relation } = param;
let record;
if (Array.isArray(param.record)) {
record = param.record.map((ri) => this.$queryBuilder.$normalizeRecordIdentity(ri));
}
else if (param.record) {
record = this.$queryBuilder.$normalizeRecordIdentity(param.record);
}
else {
record = null;
}
specifier = {
kind: 'relatedRecord',
op,
relation,
record
};
}
else if (isRelatedRecordsFilterParam(param)) {
const { relation } = param;
let records = param.records.map((ri) => this.$queryBuilder.$normalizeRecordIdentity(ri));
specifier = {
kind: 'relatedRecords',
op,
relation,
records
};
}
}
if (specifier === undefined) {
throw new ValidationError('Unrecognized `filter` param encountered while building query expression');
}
return specifier;
}
$pageParamToSpecifier(param) {
let specifier;
if (param.hasOwnProperty('offset') || param.hasOwnProperty('limit')) {
specifier = {
kind: 'offsetLimit',
offset: param.offset,
limit: param.limit
};
}
if (specifier === undefined) {
throw new ValidationError('Unrecognized `page` param encountered while building query expression');
}
return specifier;
}
$sortParamToSpecifier(param) {
let specifier;
if (isObject(param)) {
if (param.hasOwnProperty('kind')) {
specifier = param;
}
else if (param.hasOwnProperty('attribute')) {
specifier = {
kind: 'attribute',
attribute: param.attribute,
order: param.order || 'ascending'
};
}
}
else if (typeof param === 'string') {
specifier = this.$parseSortParamString(param);
}
if (specifier === undefined) {
throw new ValidationError('Unrecognized `sort` param encountered while building query expression');
}
return specifier;
}
$parseSortParamString(sortSpecifier) {
let attribute;
let order;
if (sortSpecifier[0] === '-') {
attribute = sortSpecifier.slice(1);
order = 'descending';
}
else {
attribute = sortSpecifier;
order = 'ascending';
}
return {
kind: 'attribute',
attribute,
order
};
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb3JkLXF1ZXJ5LXRlcm0uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVjb3JkLXF1ZXJ5LXRlcm0udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN4QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRXhDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQXFCdEQsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sZ0RBQWdELENBQUM7QUFzQzFGLFNBQVMsaUJBQWlCLENBQ3hCLEtBQXNCO0lBRXRCLE9BQVEsS0FBeUIsQ0FBQyxJQUFJLEtBQUssU0FBUyxDQUFDO0FBQ3ZELENBQUM7QUFFRCxTQUFTLHNCQUFzQixDQUM3QixLQUFzQjtJQUV0QixPQUFRLEtBQThCLENBQUMsU0FBUyxLQUFLLFNBQVMsQ0FBQztBQUNqRSxDQUFDO0FBRUQsU0FBUywwQkFBMEIsQ0FDakMsS0FBc0I7SUFFdEIsT0FBTyxDQUNKLEtBQXNDLENBQUMsUUFBUSxLQUFLLFNBQVM7UUFDN0QsS0FBc0MsQ0FBQyxNQUFNLEtBQUssU0FBUyxDQUM3RCxDQUFDO0FBQ0osQ0FBQztBQUVELFNBQVMsMkJBQTJCLENBQ2xDLEtBQXNCO0lBRXRCLE9BQU8sQ0FDSixLQUF1QyxDQUFDLFFBQVEsS0FBSyxTQUFTO1FBQzlELEtBQXVDLENBQUMsT0FBTyxLQUFLLFNBQVMsQ0FDL0QsQ0FBQztBQUNKLENBQUM7QUFFRCxNQUFNLE9BQU8sbUJBSVgsU0FBUSxTQUFhO0lBR3JCLFlBQVksWUFBd0MsRUFBRSxVQUFjO1FBQ2xFLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNsQixJQUFJLENBQUMsYUFBYSxHQUFHLFlBQVksQ0FBQztJQUNwQyxDQUFDO0lBRUQsaUJBQWlCO1FBQ2YsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLGlCQUFpQixFQUFF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QUssQ0FBQyxDQUFDO1NBQy9DO1FBRUQsSUFBSSxTQUFTLEtBQUssU0FBUyxFQUFFO1lBQzNCLE1BQU0sSUFBSSxlQUFlLENBQ3ZCLHVFQUF1RSxDQUN4RSxDQUFDO1NBQ0g7UUFFRCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRUQscUJBQXFCLENBQUMsYUFBcUI7UUFDekMsSUFBSSxTQUFpQixDQUFDO1FBQ3RCLElBQUksS0FBZ0IsQ0FBQztRQUVyQixJQUFJLGFBQWEsQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLEVBQUU7WUFDNUIsU0FBUyxHQUFHLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDbkMsS0FBSyxHQUFHLFlBQVksQ0FBQztTQUN0QjthQUFNO1lBQ0wsU0FBUyxHQUFHLGFBQWEsQ0FBQztZQUMxQixLQUFLLEdBQUcsV0FBVyxDQUFDO1NBQ3JCO1FBRUQsT0FBTztZQUNMLElBQUksRUFBRSxXQUFXO1lBQ2pCLFNBQVM7WUFDVCxLQUFLO1NBQ04sQ0FBQztJQUNKLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFF1ZXJ5VGVybSB9IGZyb20gJ0BvcmJpdC9kYXRhJztcbmltcG9ydCB7IGlzT2JqZWN0IH0gZnJvbSAnQG9yYml0L3V0aWxzJztcbmltcG9ydCB7IFJlY29yZElkZW50aXR5IH0gZnJvbSAnLi9yZWNvcmQnO1xuaW1wb3J0IHsgVmFsaWRhdGlvbkVycm9yIH0gZnJvbSAnLi9yZWNvcmQtZXhjZXB0aW9ucyc7XG5pbXBvcnQgeyBSZWNvcmRRdWVyeUJ1aWxkZXIgfSBmcm9tICcuL3JlY29yZC1xdWVyeS1idWlsZGVyJztcbmltcG9ydCB7XG4gIEF0dHJpYnV0ZUZpbHRlclNwZWNpZmllcixcbiAgQXR0cmlidXRlU29ydFNwZWNpZmllcixcbiAgRmlsdGVyU3BlY2lmaWVyLFxuICBGaW5kUmVjb3JkLFxuICBGaW5kUmVjb3JkcyxcbiAgRmluZFJlbGF0ZWRSZWNvcmQsXG4gIEZpbmRSZWxhdGVkUmVjb3JkcyxcbiAgUGFnZVNwZWNpZmllcixcbiAgUmVjb3JkUXVlcnlFeHByZXNzaW9uLFxuICBSZWxhdGVkUmVjb3JkRmlsdGVyU3BlY2lmaWVyLFxuICBSZWxhdGVkUmVjb3Jkc0ZpbHRlclNwZWNpZmllcixcbiAgU2V0Q29tcGFyaXNvbk9wZXJhdG9yLFxuICBTb3J0T3JkZXIsXG4gIFNvcnRTcGVjaWZpZXIsXG4gIFZhbHVlQ29tcGFyaXNvbk9wZXJhdG9yXG59IGZyb20gJy4vcmVjb3JkLXF1ZXJ5LWV4cHJlc3Npb24nO1xuaW1wb3J0IHsgUmVjb3JkU2NoZW1hIH0gZnJvbSAnLi9yZWNvcmQtc2NoZW1hJztcbmltcG9ydCB7IFJlY29yZFF1ZXJ5RXhwcmVzc2lvblZhbGlkYXRvciB9IGZyb20gJy4vcmVjb3JkLXZhbGlkYXRvcnMvcmVjb3JkLXF1ZXJ5LWV4cHJlc3Npb24tdmFsaWRhdG9yJztcbmltcG9ydCB7IFN0YW5kYXJkUmVjb3JkVmFsaWRhdG9ycyB9IGZyb20gJy4vcmVjb3JkLXZhbGlkYXRvcnMvc3RhbmRhcmQtcmVjb3JkLXZhbGlkYXRvcnMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEF0dHJpYnV0ZVNvcnRQYXJhbSB7XG4gIGF0dHJpYnV0ZTogc3RyaW5nO1xuICBvcmRlcj86IFNvcnRPcmRlcjtcbn1cblxuZXhwb3J0IHR5cGUgU29ydFBhcmFtID0gU29ydFNwZWNpZmllciB8IEF0dHJpYnV0ZVNvcnRQYXJhbSB8IHN0cmluZztcblxuZXhwb3J0IGludGVyZmFjZSBQYWdlUGFyYW0ge1xuICBvZmZzZXQ/OiBudW1iZXI7XG4gIGxpbWl0PzogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEF0dHJpYnV0ZUZpbHRlclBhcmFtIHtcbiAgb3A/OiBWYWx1ZUNvbXBhcmlzb25PcGVyYXRvcjtcbiAgYXR0cmlidXRlOiBzdHJpbmc7XG4gIHZhbHVlOiBhbnk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVsYXRlZFJlY29yZEZpbHRlclBhcmFtPFJJID0gUmVjb3JkSWRlbnRpdHk+IHtcbiAgb3A/OiBTZXRDb21wYXJpc29uT3BlcmF0b3I7XG4gIHJlbGF0aW9uOiBzdHJpbmc7XG4gIHJlY29yZDogUkkgfCBSSVtdIHwgbnVsbDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZWxhdGVkUmVjb3Jkc0ZpbHRlclBhcmFtPFJJID0gUmVjb3JkSWRlbnRpdHk+IHtcbiAgb3A/OiBTZXRDb21wYXJpc29uT3BlcmF0b3I7XG4gIHJlbGF0aW9uOiBzdHJpbmc7XG4gIHJlY29yZHM6IFJJW107XG59XG5cbmV4cG9ydCB0eXBlIEZpbHRlclBhcmFtPFJJID0gUmVjb3JkSWRlbnRpdHk+ID1cbiAgfCBGaWx0ZXJTcGVjaWZpZXJcbiAgfCBBdHRyaWJ1dGVGaWx0ZXJQYXJhbVxuICB8IFJlbGF0ZWRSZWNvcmRGaWx0ZXJQYXJhbTxSST5cbiAgfCBSZWxhdGVkUmVjb3Jkc0ZpbHRlclBhcmFtPFJJPjtcblxuZnVuY3Rpb24gaXNGaWx0ZXJTcGVjaWZpZXI8UkkgPSBSZWNvcmRJZGVudGl0eT4oXG4gIHBhcmFtOiBGaWx0ZXJQYXJhbTxSST5cbik6IHBhcmFtIGlzIEZpbHRlclNwZWNpZmllciB7XG4gIHJldHVybiAocGFyYW0gYXMgRmlsdGVyU3BlY2lmaWVyKS5raW5kICE9PSB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIGlzQXR0cmlidXRlRmlsdGVyUGFyYW08UkkgPSBSZWNvcmRJZGVudGl0eT4oXG4gIHBhcmFtOiBGaWx0ZXJQYXJhbTxSST5cbik6IHBhcmFtIGlzIEF0dHJpYnV0ZUZpbHRlclBhcmFtIHtcbiAgcmV0dXJuIChwYXJhbSBhcyBBdHRyaWJ1dGVGaWx0ZXJQYXJhbSkuYXR0cmlidXRlICE9PSB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIGlzUmVsYXRlZFJlY29yZEZpbHRlclBhcmFtPFJJID0gUmVjb3JkSWRlbnRpdHk+KFxuICBwYXJhbTogRmlsdGVyUGFyYW08Ukk+XG4pOiBwYXJhbSBpcyBSZWxhdGVkUmVjb3JkRmlsdGVyUGFyYW08Ukk+IHtcbiAgcmV0dXJuIChcbiAgICAocGFyYW0gYXMgUmVsYXRlZFJlY29yZEZpbHRlclBhcmFtPFJJPikucmVsYXRpb24gIT09IHVuZGVmaW5lZCAmJlxuICAgIChwYXJhbSBhcyBSZWxhdGVkUmVjb3JkRmlsdGVyUGFyYW08Ukk+KS5yZWNvcmQgIT09IHVuZGVmaW5lZFxuICApO1xufVxuXG5mdW5jdGlvbiBpc1JlbGF0ZWRSZWNvcmRzRmlsdGVyUGFyYW08UkkgPSBSZWNvcmRJZGVudGl0eT4oXG4gIHBhcmFtOiBGaWx0ZXJQYXJhbTxSST5cbik6IHBhcmFtIGlzIFJlbGF0ZWRSZWNvcmRzRmlsdGVyUGFyYW08Ukk+IHtcbiAgcmV0dXJuIChcbiAgICAocGFyYW0gYXMgUmVsYXRlZFJlY29yZHNGaWx0ZXJQYXJhbTxSST4pLnJlbGF0aW9uICE9PSB1bmRlZmluZWQgJiZcbiAgICAocGFyYW0gYXMgUmVsYXRlZFJlY29yZHNGaWx0ZXJQYXJhbTxSST4pLnJlY29yZHMgIT09IHVuZGVmaW5lZFxuICApO1xufVxuXG5leHBvcnQgY2xhc3MgQmFzZVJlY29yZFF1ZXJ5VGVybTxcbiAgUUUgZXh0ZW5kcyBSZWNvcmRRdWVyeUV4cHJlc3Npb24sXG4gIFJUID0gc3RyaW5nLFxuICBSSSA9IFJlY29yZElkZW50aXR5XG4+IGV4dGVuZHMgUXVlcnlUZXJtPFFFPiB7XG4gICRxdWVyeUJ1aWxkZXI6IFJlY29yZFF1ZXJ5QnVpbGRlcjxSVCwgUkk+O1xuXG4gIGNvbnN0cnVjdG9yKHF1ZXJ5QnVpbGRlcjogUmVjb3JkUXVlcnlCdWlsZGVyPFJULCBSST4sIGV4cHJlc3Npb246IFFFKSB7XG4gICAgc3VwZXIoZXhwcmVzc2lvbik7XG4gICAgdGhpcy4kcXVlcnlCdWlsZGVyID0gcXVlcnlCdWlsZGVyO1xuICB9XG5cbiAgdG9RdWVyeUV4cHJlc3Npb24oKTogUUUge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBzdXBlci50b1F1ZXJ5RXhwcmVzc2lvbigpO1xuXG4gICAgY29uc3QgdmFsaWRhdG9yRm9yID0gdGhpcy4kcXVlcnlCdWlsZGVyLiR2YWxpZGF0b3JGb3I7XG4gICAgaWYgKHZhbGlkYXRvckZvcikge1xuICAgICAgY29uc3Qgc2NoZW1hID0gdGhpcy4kcXVlcnlCdWlsZGVyLiRzY2hlbWEgYXMgUmVjb3JkU2NoZW1hO1xuICAgICAgY29uc3QgdmFsaWRhdGVSZWNvcmRRdWVyeUV4cHJlc3Npb24gPSB2YWxpZGF0b3JGb3IoXG4gICAgICAgIFN0YW5kYXJkUmVjb3JkVmFsaWRhdG9ycy5SZWNvcmRRdWVyeUV4cHJlc3Npb25cbiAgICAgICkgYXMgUmVjb3JkUXVlcnlFeHByZXNzaW9uVmFsaWRhdG9yO1xuXG4gICAgICBjb25zdCBpc3N1ZXMgPSB2YWxpZGF0ZVJlY29yZFF1ZXJ5RXhwcmVzc2lvbihleHByZXNzaW9uLCB7XG4gICAgICAgIHZhbGlkYXRvckZvcixcbiAgICAgICAgc2NoZW1hXG4gICAgICB9KTtcblxuICAgICAgaWYgKGlzc3VlcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICAgICAgJ1ZhbGlkYXRpb24gaXNzc3VlcyBlbmNvdW50ZXJlZCB3aGlsZSBidWlsZGluZyBhIHF1ZXJ5IGV4cHJlc3Npb24nLFxuICAgICAgICAgIGlzc3Vlc1xuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBleHByZXNzaW9uO1xuICB9XG59XG5cbi8qKlxuICogQSBxdWVyeSB0ZXJtIHJlcHJlc2VudGluZyBhIHNpbmdsZSByZWNvcmQuXG4gKi9cbmV4cG9ydCBjbGFzcyBGaW5kUmVjb3JkVGVybTxcbiAgUlQgPSBzdHJpbmcsXG4gIFJJID0gUmVjb3JkSWRlbnRpdHlcbj4gZXh0ZW5kcyBCYXNlUmVjb3JkUXVlcnlUZXJtPEZpbmRSZWNvcmQsIFJULCBSST4ge1xuICBjb25zdHJ1Y3RvcihcbiAgICBxdWVyeUJ1aWxkZXI6IFJlY29yZFF1ZXJ5QnVpbGRlcjxSVCwgUkk+LFxuICAgIHJlY29yZDogUmVjb3JkSWRlbnRpdHlcbiAgKSB7XG4gICAgc3VwZXIocXVlcnlCdWlsZGVyLCB7XG4gICAgICBvcDogJ2ZpbmRSZWNvcmQnLFxuICAgICAgcmVjb3JkXG4gICAgfSk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEZpbmRSZWxhdGVkUmVjb3JkVGVybTxcbiAgUlQgPSBzdHJpbmcsXG4gIFJJID0gUmVjb3JkSWRlbnRpdHlcbj4gZXh0ZW5kcyBCYXNlUmVjb3JkUXVlcnlUZXJtPEZpbmRSZWxhdGVkUmVjb3JkLCBSVCwgUkk+IHtcbiAgY29uc3RydWN0b3IoXG4gICAgcXVlcnlCdWlsZGVyOiBSZWNvcmRRdWVyeUJ1aWxkZXI8UlQsIFJJPixcbiAgICByZWNvcmQ6IFJlY29yZElkZW50aXR5LFxuICAgIHJlbGF0aW9uc2hpcDogc3RyaW5nXG4gICkge1xuICAgIHN1cGVyKHF1ZXJ5QnVpbGRlciwge1xuICAgICAgb3A6ICdmaW5kUmVsYXRlZFJlY29yZCcsXG4gICAgICByZWNvcmQsXG4gICAgICByZWxhdGlvbnNoaXBcbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgRmluZFJlY29yZHNUZXJtPFxuICBSVCA9IHN0cmluZyxcbiAgUkkgPSBSZWNvcmRJZGVudGl0eVxuPiBleHRlbmRzIEJhc2VSZWNvcmRRdWVyeVRlcm08RmluZFJlY29yZHMgfCBGaW5kUmVsYXRlZFJlY29yZHMsIFJULCBSST4ge1xuICAvKipcbiAgICogQXBwbGllcyBzb3J0aW5nIHRvIGEgY29sbGVjdGlvbiBxdWVyeS5cbiAgICpcbiAgICogU29ydCBzcGVjaWZpZXJzIGNhbiBiZSBleHByZXNzZWQgaW4gb2JqZWN0IGZvcm0sIGxpa2U6XG4gICAqXG4gICAqIGBgYHRzXG4gICAqIHsgYXR0cmlidXRlOiAnbmFtZScsIG9yZGVyOiAnZGVzY2VuZGluZycgfVxuICAgKiB7IGF0dHJpYnV0ZTogJ25hbWUnLCBvcmRlcjogJ2FzY2VuZGluZycgfVxuICAgKiBgYGBcbiAgICpcbiAgICogT3IgaW4gc3RyaW5nIGZvcm0sIGxpa2U6XG4gICAqXG4gICAqIGBgYHRzXG4gICAqICctbmFtZScgLy8gZGVzY2VuZGluZyBvcmRlclxuICAgKiAnbmFtZScgIC8vIGFzY2VuZGluZyBvcmRlclxuICAgKiBgYGBcbiAgICovXG4gIHNvcnQoLi4ucGFyYW1zOiBTb3J0UGFyYW1bXSk6IHRoaXMge1xuICAgIGNvbnN0IHNwZWNpZmllcnMgPSBwYXJhbXMubWFwKChwKSA9PiB0aGlzLiRzb3J0UGFyYW1Ub1NwZWNpZmllcihwKSk7XG4gICAgdGhpcy5fZXhwcmVzc2lvbi5zb3J0ID0gKHRoaXMuX2V4cHJlc3Npb24uc29ydCA/PyBbXSkuY29uY2F0KHNwZWNpZmllcnMpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEFwcGxpZXMgcGFnaW5hdGlvbiB0byBhIGNvbGxlY3Rpb24gcXVlcnkuXG4gICAqL1xuICBwYWdlKHBhcmFtOiBQYWdlUGFyYW0pOiB0aGlzIHtcbiAgICB0aGlzLl9leHByZXNzaW9uLnBhZ2UgPSB0aGlzLiRwYWdlUGFyYW1Ub1NwZWNpZmllcihwYXJhbSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQXBwbHkgYSBmaWx0ZXIgZXhwcmVzc2lvbi5cbiAgICpcbiAgICogRm9yIGV4YW1wbGU6XG4gICAqXG4gICAqIGBgYHRzXG4gICAqIG9xYlxuICAgKiAgIC5yZWNvcmRzKCdwbGFuZXQnKVxuICAgKiAgIC5maWx0ZXIoeyBhdHRyaWJ1dGU6ICdhdG1vc3BoZXJlJywgdmFsdWU6IHRydWUgfSxcbiAgICogICAgICAgICAgIHsgYXR0cmlidXRlOiAnY2xhc3NpZmljYXRpb24nLCB2YWx1ZTogJ3RlcnJlc3RyaWFsJyB9KTtcbiAgICogYGBgXG4gICAqL1xuICBmaWx0ZXIoLi4ucGFyYW1zOiBGaWx0ZXJQYXJhbTxSST5bXSk6IHRoaXMge1xuICAgIGNvbnN0IHNwZWNpZmllcnMgPSBwYXJhbXMubWFwKChwKSA9PiB0aGlzLiRmaWx0ZXJQYXJhbVRvU3BlY2lmaWVyKHApKTtcbiAgICB0aGlzLl9leHByZXNzaW9uLmZpbHRlciA9ICh0aGlzLl9leHByZXNzaW9uLmZpbHRlciA/PyBbXSkuY29uY2F0KFxuICAgICAgc3BlY2lmaWVyc1xuICAgICk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAkZmlsdGVyUGFyYW1Ub1NwZWNpZmllcihwYXJhbTogRmlsdGVyUGFyYW08Ukk+KTogRmlsdGVyU3BlY2lmaWVyIHtcbiAgICBsZXQgc3BlY2lmaWVyOiBGaWx0ZXJTcGVjaWZpZXIgfCB1bmRlZmluZWQ7XG5cbiAgICBpZiAoaXNGaWx0ZXJTcGVjaWZpZXI8Ukk+KHBhcmFtKSkge1xuICAgICAgc3BlY2lmaWVyID0gcGFyYW07XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IG9wID0gcGFyYW0ub3AgPz8gJ2VxdWFsJztcbiAgICAgIGlmIChpc0F0dHJpYnV0ZUZpbHRlclBhcmFtKHBhcmFtKSkge1xuICAgICAgICBjb25zdCB7IGF0dHJpYnV0ZSwgdmFsdWUgfSA9IHBhcmFtO1xuICAgICAgICBzcGVjaWZpZXIgPSB7XG4gICAgICAgICAga2luZDogJ2F0dHJpYnV0ZScsXG4gICAgICAgICAgb3AsXG4gICAgICAgICAgYXR0cmlidXRlLFxuICAgICAgICAgIHZhbHVlXG4gICAgICAgIH0gYXMgQXR0cmlidXRlRmlsdGVyU3BlY2lmaWVyO1xuICAgICAgfSBlbHNlIGlmIChpc1JlbGF0ZWRSZWNvcmRGaWx0ZXJQYXJhbTxSST4ocGFyYW0pKSB7XG4gICAgICAgIGNvbnN0IHsgcmVsYXRpb24gfSA9IHBhcmFtO1xuICAgICAgICBsZXQgcmVjb3JkOiBSZWNvcmRJZGVudGl0eVtdIHwgUmVjb3JkSWRlbnRpdHkgfCBudWxsO1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShwYXJhbS5yZWNvcmQpKSB7XG4gICAgICAgICAgcmVjb3JkID0gcGFyYW0ucmVjb3JkLm1hcCgocmkpID0+XG4gICAgICAgICAgICB0aGlzLiRxdWVyeUJ1aWxkZXIuJG5vcm1hbGl6ZVJlY29yZElkZW50aXR5KHJpKVxuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAocGFyYW0ucmVjb3JkKSB7XG4gICAgICAgICAgcmVjb3JkID0gdGhpcy4kcXVlcnlCdWlsZGVyLiRub3JtYWxpemVSZWNvcmRJZGVudGl0eShwYXJhbS5yZWNvcmQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlY29yZCA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgc3BlY2lmaWVyID0ge1xuICAgICAgICAgIGtpbmQ6ICdyZWxhdGVkUmVjb3JkJyxcbiAgICAgICAgICBvcCxcbiAgICAgICAgICByZWxhdGlvbixcbiAgICAgICAgICByZWNvcmRcbiAgICAgICAgfSBhcyBSZWxhdGVkUmVjb3JkRmlsdGVyU3BlY2lmaWVyO1xuICAgICAgfSBlbHNlIGlmIChpc1JlbGF0ZWRSZWNvcmRzRmlsdGVyUGFyYW08Ukk+KHBhcmFtKSkge1xuICAgICAgICBjb25zdCB7IHJlbGF0aW9uIH0gPSBwYXJhbTtcbiAgICAgICAgbGV0IHJlY29yZHMgPSBwYXJhbS5yZWNvcmRzLm1hcCgocmkpID0+XG4gICAgICAgICAgdGhpcy4kcXVlcnlCdWlsZGVyLiRub3JtYWxpemVSZWNvcmRJZGVudGl0eShyaSlcbiAgICAgICAgKTtcbiAgICAgICAgc3BlY2lmaWVyID0ge1xuICAgICAgICAgIGtpbmQ6ICdyZWxhdGVkUmVjb3JkcycsXG4gICAgICAgICAgb3AsXG4gICAgICAgICAgcmVsYXRpb24sXG4gICAgICAgICAgcmVjb3Jkc1xuICAgICAgICB9IGFzIFJlbGF0ZWRSZWNvcmRzRmlsdGVyU3BlY2lmaWVyO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzcGVjaWZpZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgICAgJ1VucmVjb2duaXplZCBgZmlsdGVyYCBwYXJhbSBlbmNvdW50ZXJlZCB3aGlsZSBidWlsZGluZyBxdWVyeSBleHByZXNzaW9uJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc3BlY2lmaWVyO1xuICB9XG5cbiAgJHBhZ2VQYXJhbVRvU3BlY2lmaWVyKHBhcmFtOiBQYWdlUGFyYW0pOiBQYWdlU3BlY2lmaWVyIHtcbiAgICBsZXQgc3BlY2lmaWVyOiBQYWdlU3BlY2lmaWVyIHwgdW5kZWZpbmVkO1xuXG4gICAgaWYgKHBhcmFtLmhhc093blByb3BlcnR5KCdvZmZzZXQnKSB8fCBwYXJhbS5oYXNPd25Qcm9wZXJ0eSgnbGltaXQnKSkge1xuICAgICAgc3BlY2lmaWVyID0ge1xuICAgICAgICBraW5kOiAnb2Zmc2V0TGltaXQnLFxuICAgICAgICBvZmZzZXQ6IHBhcmFtLm9mZnNldCxcbiAgICAgICAgbGltaXQ6IHBhcmFtLmxpbWl0XG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmIChzcGVjaWZpZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgICAgJ1VucmVjb2duaXplZCBgcGFnZWAgcGFyYW0gZW5jb3VudGVyZWQgd2hpbGUgYnVpbGRpbmcgcXVlcnkgZXhwcmVzc2lvbidcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNwZWNpZmllcjtcbiAgfVxuXG4gICRzb3J0UGFyYW1Ub1NwZWNpZmllcihwYXJhbTogU29ydFBhcmFtKTogU29ydFNwZWNpZmllciB7XG4gICAgbGV0IHNwZWNpZmllcjogU29ydFNwZWNpZmllciB8IHVuZGVmaW5lZDtcblxuICAgIGlmIChpc09iamVjdChwYXJhbSkpIHtcbiAgICAgIGlmIChwYXJhbS5oYXNPd25Qcm9wZXJ0eSgna2luZCcpKSB7XG4gICAgICAgIHNwZWNpZmllciA9IHBhcmFtIGFzIFNvcnRTcGVjaWZpZXI7XG4gICAgICB9IGVsc2UgaWYgKHBhcmFtLmhhc093blByb3BlcnR5KCdhdHRyaWJ1dGUnKSkge1xuICAgICAgICBzcGVjaWZpZXIgPSB7XG4gICAgICAgICAga2luZDogJ2F0dHJpYnV0ZScsXG4gICAgICAgICAgYXR0cmlidXRlOiAocGFyYW0gYXMgQXR0cmlidXRlU29ydFBhcmFtKS5hdHRyaWJ1dGUsXG4gICAgICAgICAgb3JkZXI6IChwYXJhbSBhcyBBdHRyaWJ1dGVTb3J0UGFyYW0pLm9yZGVyIHx8ICdhc2NlbmRpbmcnXG4gICAgICAgIH0gYXMgQXR0cmlidXRlU29ydFNwZWNpZmllcjtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBwYXJhbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHNwZWNpZmllciA9IHRoaXMuJHBhcnNlU29ydFBhcmFtU3RyaW5nKHBhcmFtKTtcbiAgICB9XG5cbiAgICBpZiAoc3BlY2lmaWVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICAgICdVbnJlY29nbml6ZWQgYHNvcnRgIHBhcmFtIGVuY291bnRlcmVkIHdoaWxlIGJ1aWxkaW5nIHF1ZXJ5IGV4cHJlc3Npb24nXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBzcGVjaWZpZXI7XG4gIH1cblxuICAkcGFyc2VTb3J0UGFyYW1TdHJpbmcoc29ydFNwZWNpZmllcjogc3RyaW5nKTogQXR0cmlidXRlU29ydFNwZWNpZmllciB7XG4gICAgbGV0IGF0dHJpYnV0ZTogc3RyaW5nO1xuICAgIGxldCBvcmRlcjogU29ydE9yZGVyO1xuXG4gICAgaWYgKHNvcnRTcGVjaWZpZXJbMF0gPT09ICctJykge1xuICAgICAgYXR0cmlidXRlID0gc29ydFNwZWNpZmllci5zbGljZSgxKTtcbiAgICAgIG9yZGVyID0gJ2Rlc2NlbmRpbmcnO1xuICAgIH0gZWxzZSB7XG4gICAgICBhdHRyaWJ1dGUgPSBzb3J0U3BlY2lmaWVyO1xuICAgICAgb3JkZXIgPSAnYXNjZW5kaW5nJztcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAga2luZDogJ2F0dHJpYnV0ZScsXG4gICAgICBhdHRyaWJ1dGUsXG4gICAgICBvcmRlclxuICAgIH07XG4gIH1cbn1cblxuZXhwb3J0IHR5cGUgUmVjb3JkUXVlcnlUZXJtPFJUID0gc3RyaW5nLCBSSSA9IFJlY29yZElkZW50aXR5PiA9XG4gIHwgRmluZFJlY29yZFRlcm08UlQsIFJJPlxuICB8IEZpbmRSZWxhdGVkUmVjb3JkVGVybTxSVCwgUkk+XG4gIHwgRmluZFJlY29yZHNUZXJtPFJULCBSST47XG4iXX0=