UNPKG

@orbit/records

Version:

A flexible data access and synchronization layer.

223 lines 26.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FindRecordsTerm = exports.FindRelatedRecordTerm = exports.FindRecordTerm = exports.BaseRecordQueryTerm = void 0; const data_1 = require("@orbit/data"); const utils_1 = require("@orbit/utils"); const record_exceptions_1 = require("./record-exceptions"); const standard_record_validators_1 = require("./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); } class BaseRecordQueryTerm extends data_1.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(standard_record_validators_1.StandardRecordValidators.RecordQueryExpression); const issues = validateRecordQueryExpression(expression, { validatorFor, schema }); if (issues !== undefined) { throw new record_exceptions_1.ValidationError('Validation isssues encountered while building a query expression', issues); } } return expression; } } exports.BaseRecordQueryTerm = BaseRecordQueryTerm; /** * A query term representing a single record. */ class FindRecordTerm extends BaseRecordQueryTerm { constructor(queryBuilder, record) { super(queryBuilder, { op: 'findRecord', record }); } } exports.FindRecordTerm = FindRecordTerm; class FindRelatedRecordTerm extends BaseRecordQueryTerm { constructor(queryBuilder, record, relationship) { super(queryBuilder, { op: 'findRelatedRecord', record, relationship }); } } exports.FindRelatedRecordTerm = FindRelatedRecordTerm; 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 record_exceptions_1.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 record_exceptions_1.ValidationError('Unrecognized `page` param encountered while building query expression'); } return specifier; } $sortParamToSpecifier(param) { let specifier; if ((0, utils_1.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 record_exceptions_1.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 }; } } exports.FindRecordsTerm = FindRecordsTerm; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb3JkLXF1ZXJ5LXRlcm0uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVjb3JkLXF1ZXJ5LXRlcm0udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsc0NBQXdDO0FBQ3hDLHdDQUF3QztBQUV4QywyREFBc0Q7QUFxQnRELCtGQUEwRjtBQXNDMUYsU0FBUyxpQkFBaUIsQ0FDeEIsS0FBc0I7SUFFdEIsT0FBUSxLQUF5QixDQUFDLElBQUksS0FBSyxTQUFTLENBQUM7QUFDdkQsQ0FBQztBQUVELFNBQVMsc0JBQXNCLENBQzdCLEtBQXNCO0lBRXRCLE9BQVEsS0FBOEIsQ0FBQyxTQUFTLEtBQUssU0FBUyxDQUFDO0FBQ2pFLENBQUM7QUFFRCxTQUFTLDBCQUEwQixDQUNqQyxLQUFzQjtJQUV0QixPQUFPLENBQ0osS0FBc0MsQ0FBQyxRQUFRLEtBQUssU0FBUztRQUM3RCxLQUFzQyxDQUFDLE1BQU0sS0FBSyxTQUFTLENBQzdELENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUywyQkFBMkIsQ0FDbEMsS0FBc0I7SUFFdEIsT0FBTyxDQUNKLEtBQXVDLENBQUMsUUFBUSxLQUFLLFNBQVM7UUFDOUQsS0FBdUMsQ0FBQyxPQUFPLEtBQUssU0FBUyxDQUMvRCxDQUFDO0FBQ0osQ0FBQztBQUVELE1BQWEsbUJBSVgsU0FBUSxnQkFBYTtJQUdyQixZQUFZLFlBQXdDLEVBQUUsVUFBYztRQUNsRSxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDbEIsSUFBSSxDQUFDLGFBQWEsR0FBRyxZQUFZLENBQUM7SUFDcEMsQ0FBQztJQUVELGlCQUFpQjtRQUNmLE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBRTdDLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDO1FBQ3RELElBQUksWUFBWSxFQUFFO1lBQ2hCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMs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Q0FBQztTQUNIO1FBRUQsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVELHFCQUFxQixDQUFDLGFBQXFCO1FBQ3pDLElBQUksU0FBaUIsQ0FBQztRQUN0QixJQUFJLEtBQWdCLENBQUM7UUFFckIsSUFBSSxhQUFhLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxFQUFFO1lBQzVCLFNBQVMsR0FBRyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ25DLEtBQUssR0FBRyxZQUFZLENBQUM7U0FDdEI7YUFBTTtZQUNMLFNBQVMsR0FBRyxhQUFhLENBQUM7WUFDMUIsS0FBSyxHQUFHLFdBQVcsQ0FBQztTQUNyQjtRQUVELE9BQU87WUFDTCxJQUFJLEVBQUUsV0FBVztZQUNqQixTQUFTO1lBQ1QsS0FBSztTQUNOLENBQUM7SUFDSixDQUFDO0NBQ0Y7QUEvS0QsMENBK0tDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUXVlcnlUZXJtIH0gZnJvbSAnQG9yYml0L2RhdGEnO1xuaW1wb3J0IHsgaXNPYmplY3QgfSBmcm9tICdAb3JiaXQvdXRpbHMnO1xuaW1wb3J0IHsgUmVjb3JkSWRlbnRpdHkgfSBmcm9tICcuL3JlY29yZCc7XG5pbXBvcnQgeyBWYWxpZGF0aW9uRXJyb3IgfSBmcm9tICcuL3JlY29yZC1leGNlcHRpb25zJztcbmltcG9ydCB7IFJlY29yZFF1ZXJ5QnVpbGRlciB9IGZyb20gJy4vcmVjb3JkLXF1ZXJ5LWJ1aWxkZXInO1xuaW1wb3J0IHtcbiAgQXR0cmlidXRlRmlsdGVyU3BlY2lmaWVyLFxuICBBdHRyaWJ1dGVTb3J0U3BlY2lmaWVyLFxuICBGaWx0ZXJTcGVjaWZpZXIsXG4gIEZpbmRSZWNvcmQsXG4gIEZpbmRSZWNvcmRzLFxuICBGaW5kUmVsYXRlZFJlY29yZCxcbiAgRmluZFJlbGF0ZWRSZWNvcmRzLFxuICBQYWdlU3BlY2lmaWVyLFxuICBSZWNvcmRRdWVyeUV4cHJlc3Npb24sXG4gIFJlbGF0ZWRSZWNvcmRGaWx0ZXJTcGVjaWZpZXIsXG4gIFJlbGF0ZWRSZWNvcmRzRmlsdGVyU3BlY2lmaWVyLFxuICBTZXRDb21wYXJpc29uT3BlcmF0b3IsXG4gIFNvcnRPcmRlcixcbiAgU29ydFNwZWNpZmllcixcbiAgVmFsdWVDb21wYXJpc29uT3BlcmF0b3Jcbn0gZnJvbSAnLi9yZWNvcmQtcXVlcnktZXhwcmVzc2lvbic7XG5pbXBvcnQgeyBSZWNvcmRTY2hlbWEgfSBmcm9tICcuL3JlY29yZC1zY2hlbWEnO1xuaW1wb3J0IHsgUmVjb3JkUXVlcnlFeHByZXNzaW9uVmFsaWRhdG9yIH0gZnJvbSAnLi9yZWNvcmQtdmFsaWRhdG9ycy9yZWNvcmQtcXVlcnktZXhwcmVzc2lvbi12YWxpZGF0b3InO1xuaW1wb3J0IHsgU3RhbmRhcmRSZWNvcmRWYWxpZGF0b3JzIH0gZnJvbSAnLi9yZWNvcmQtdmFsaWRhdG9ycy9zdGFuZGFyZC1yZWNvcmQtdmFsaWRhdG9ycyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXR0cmlidXRlU29ydFBhcmFtIHtcbiAgYXR0cmlidXRlOiBzdHJpbmc7XG4gIG9yZGVyPzogU29ydE9yZGVyO1xufVxuXG5leHBvcnQgdHlwZSBTb3J0UGFyYW0gPSBTb3J0U3BlY2lmaWVyIHwgQXR0cmlidXRlU29ydFBhcmFtIHwgc3RyaW5nO1xuXG5leHBvcnQgaW50ZXJmYWNlIFBhZ2VQYXJhbSB7XG4gIG9mZnNldD86IG51bWJlcjtcbiAgbGltaXQ/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXR0cmlidXRlRmlsdGVyUGFyYW0ge1xuICBvcD86IFZhbHVlQ29tcGFyaXNvbk9wZXJhdG9yO1xuICBhdHRyaWJ1dGU6IHN0cmluZztcbiAgdmFsdWU6IGFueTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZWxhdGVkUmVjb3JkRmlsdGVyUGFyYW08UkkgPSBSZWNvcmRJZGVudGl0eT4ge1xuICBvcD86IFNldENvbXBhcmlzb25PcGVyYXRvcjtcbiAgcmVsYXRpb246IHN0cmluZztcbiAgcmVjb3JkOiBSSSB8IFJJW10gfCBudWxsO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlbGF0ZWRSZWNvcmRzRmlsdGVyUGFyYW08UkkgPSBSZWNvcmRJZGVudGl0eT4ge1xuICBvcD86IFNldENvbXBhcmlzb25PcGVyYXRvcjtcbiAgcmVsYXRpb246IHN0cmluZztcbiAgcmVjb3JkczogUklbXTtcbn1cblxuZXhwb3J0IHR5cGUgRmlsdGVyUGFyYW08UkkgPSBSZWNvcmRJZGVudGl0eT4gPVxuICB8IEZpbHRlclNwZWNpZmllclxuICB8IEF0dHJpYnV0ZUZpbHRlclBhcmFtXG4gIHwgUmVsYXRlZFJlY29yZEZpbHRlclBhcmFtPFJJPlxuICB8IFJlbGF0ZWRSZWNvcmRzRmlsdGVyUGFyYW08Ukk+O1xuXG5mdW5jdGlvbiBpc0ZpbHRlclNwZWNpZmllcjxSSSA9IFJlY29yZElkZW50aXR5PihcbiAgcGFyYW06IEZpbHRlclBhcmFtPFJJPlxuKTogcGFyYW0gaXMgRmlsdGVyU3BlY2lmaWVyIHtcbiAgcmV0dXJuIChwYXJhbSBhcyBGaWx0ZXJTcGVjaWZpZXIpLmtpbmQgIT09IHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gaXNBdHRyaWJ1dGVGaWx0ZXJQYXJhbTxSSSA9IFJlY29yZElkZW50aXR5PihcbiAgcGFyYW06IEZpbHRlclBhcmFtPFJJPlxuKTogcGFyYW0gaXMgQXR0cmlidXRlRmlsdGVyUGFyYW0ge1xuICByZXR1cm4gKHBhcmFtIGFzIEF0dHJpYnV0ZUZpbHRlclBhcmFtKS5hdHRyaWJ1dGUgIT09IHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gaXNSZWxhdGVkUmVjb3JkRmlsdGVyUGFyYW08UkkgPSBSZWNvcmRJZGVudGl0eT4oXG4gIHBhcmFtOiBGaWx0ZXJQYXJhbTxSST5cbik6IHBhcmFtIGlzIFJlbGF0ZWRSZWNvcmRGaWx0ZXJQYXJhbTxSST4ge1xuICByZXR1cm4gKFxuICAgIChwYXJhbSBhcyBSZWxhdGVkUmVjb3JkRmlsdGVyUGFyYW08Ukk+KS5yZWxhdGlvbiAhPT0gdW5kZWZpbmVkICYmXG4gICAgKHBhcmFtIGFzIFJlbGF0ZWRSZWNvcmRGaWx0ZXJQYXJhbTxSST4pLnJlY29yZCAhPT0gdW5kZWZpbmVkXG4gICk7XG59XG5cbmZ1bmN0aW9uIGlzUmVsYXRlZFJlY29yZHNGaWx0ZXJQYXJhbTxSSSA9IFJlY29yZElkZW50aXR5PihcbiAgcGFyYW06IEZpbHRlclBhcmFtPFJJPlxuKTogcGFyYW0gaXMgUmVsYXRlZFJlY29yZHNGaWx0ZXJQYXJhbTxSST4ge1xuICByZXR1cm4gKFxuICAgIChwYXJhbSBhcyBSZWxhdGVkUmVjb3Jkc0ZpbHRlclBhcmFtPFJJPikucmVsYXRpb24gIT09IHVuZGVmaW5lZCAmJlxuICAgIChwYXJhbSBhcyBSZWxhdGVkUmVjb3Jkc0ZpbHRlclBhcmFtPFJJPikucmVjb3JkcyAhPT0gdW5kZWZpbmVkXG4gICk7XG59XG5cbmV4cG9ydCBjbGFzcyBCYXNlUmVjb3JkUXVlcnlUZXJtPFxuICBRRSBleHRlbmRzIFJlY29yZFF1ZXJ5RXhwcmVzc2lvbixcbiAgUlQgPSBzdHJpbmcsXG4gIFJJID0gUmVjb3JkSWRlbnRpdHlcbj4gZXh0ZW5kcyBRdWVyeVRlcm08UUU+IHtcbiAgJHF1ZXJ5QnVpbGRlcjogUmVjb3JkUXVlcnlCdWlsZGVyPFJULCBSST47XG5cbiAgY29uc3RydWN0b3IocXVlcnlCdWlsZGVyOiBSZWNvcmRRdWVyeUJ1aWxkZXI8UlQsIFJJPiwgZXhwcmVzc2lvbjogUUUpIHtcbiAgICBzdXBlcihleHByZXNzaW9uKTtcbiAgICB0aGlzLiRxdWVyeUJ1aWxkZXIgPSBxdWVyeUJ1aWxkZXI7XG4gIH1cblxuICB0b1F1ZXJ5RXhwcmVzc2lvbigpOiBRRSB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IHN1cGVyLnRvUXVlcnlFeHByZXNzaW9uKCk7XG5cbiAgICBjb25zdCB2YWxpZGF0b3JGb3IgPSB0aGlzLiRxdWVyeUJ1aWxkZXIuJHZhbGlkYXRvckZvcjtcbiAgICBpZiAodmFsaWRhdG9yRm9yKSB7XG4gICAgICBjb25zdCBzY2hlbWEgPSB0aGlzLiRxdWVyeUJ1aWxkZXIuJHNjaGVtYSBhcyBSZWNvcmRTY2hlbWE7XG4gICAgICBjb25zdCB2YWxpZGF0ZVJlY29yZFF1ZXJ5RXhwcmVzc2lvbiA9IHZhbGlkYXRvckZvcihcbiAgICAgICAgU3RhbmRhcmRSZWNvcmRWYWxpZGF0b3JzLlJlY29yZFF1ZXJ5RXhwcmVzc2lvblxuICAgICAgKSBhcyBSZWNvcmRRdWVyeUV4cHJlc3Npb25WYWxpZGF0b3I7XG5cbiAgICAgIGNvbnN0IGlzc3VlcyA9IHZhbGlkYXRlUmVjb3JkUXVlcnlFeHByZXNzaW9uKGV4cHJlc3Npb24sIHtcbiAgICAgICAgdmFsaWRhdG9yRm9yLFxuICAgICAgICBzY2hlbWFcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoaXNzdWVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgICAgICAnVmFsaWRhdGlvbiBpc3NzdWVzIGVuY291bnRlcmVkIHdoaWxlIGJ1aWxkaW5nIGEgcXVlcnkgZXhwcmVzc2lvbicsXG4gICAgICAgICAgaXNzdWVzXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGV4cHJlc3Npb247XG4gIH1cbn1cblxuLyoqXG4gKiBBIHF1ZXJ5IHRlcm0gcmVwcmVzZW50aW5nIGEgc2luZ2xlIHJlY29yZC5cbiAqL1xuZXhwb3J0IGNsYXNzIEZpbmRSZWNvcmRUZXJtPFxuICBSVCA9IHN0cmluZyxcbiAgUkkgPSBSZWNvcmRJZGVudGl0eVxuPiBleHRlbmRzIEJhc2VSZWNvcmRRdWVyeVRlcm08RmluZFJlY29yZCwgUlQsIFJJPiB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHF1ZXJ5QnVpbGRlcjogUmVjb3JkUXVlcnlCdWlsZGVyPFJULCBSST4sXG4gICAgcmVjb3JkOiBSZWNvcmRJZGVudGl0eVxuICApIHtcbiAgICBzdXBlcihxdWVyeUJ1aWxkZXIsIHtcbiAgICAgIG9wOiAnZmluZFJlY29yZCcsXG4gICAgICByZWNvcmRcbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgRmluZFJlbGF0ZWRSZWNvcmRUZXJtPFxuICBSVCA9IHN0cmluZyxcbiAgUkkgPSBSZWNvcmRJZGVudGl0eVxuPiBleHRlbmRzIEJhc2VSZWNvcmRRdWVyeVRlcm08RmluZFJlbGF0ZWRSZWNvcmQsIFJULCBSST4ge1xuICBjb25zdHJ1Y3RvcihcbiAgICBxdWVyeUJ1aWxkZXI6IFJlY29yZFF1ZXJ5QnVpbGRlcjxSVCwgUkk+LFxuICAgIHJlY29yZDogUmVjb3JkSWRlbnRpdHksXG4gICAgcmVsYXRpb25zaGlwOiBzdHJpbmdcbiAgKSB7XG4gICAgc3VwZXIocXVlcnlCdWlsZGVyLCB7XG4gICAgICBvcDogJ2ZpbmRSZWxhdGVkUmVjb3JkJyxcbiAgICAgIHJlY29yZCxcbiAgICAgIHJlbGF0aW9uc2hpcFxuICAgIH0pO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBGaW5kUmVjb3Jkc1Rlcm08XG4gIFJUID0gc3RyaW5nLFxuICBSSSA9IFJlY29yZElkZW50aXR5XG4+IGV4dGVuZHMgQmFzZVJlY29yZFF1ZXJ5VGVybTxGaW5kUmVjb3JkcyB8IEZpbmRSZWxhdGVkUmVjb3JkcywgUlQsIFJJPiB7XG4gIC8qKlxuICAgKiBBcHBsaWVzIHNvcnRpbmcgdG8gYSBjb2xsZWN0aW9uIHF1ZXJ5LlxuICAgKlxuICAgKiBTb3J0IHNwZWNpZmllcnMgY2FuIGJlIGV4cHJlc3NlZCBpbiBvYmplY3QgZm9ybSwgbGlrZTpcbiAgICpcbiAgICogYGBgdHNcbiAgICogeyBhdHRyaWJ1dGU6ICduYW1lJywgb3JkZXI6ICdkZXNjZW5kaW5nJyB9XG4gICAqIHsgYXR0cmlidXRlOiAnbmFtZScsIG9yZGVyOiAnYXNjZW5kaW5nJyB9XG4gICAqIGBgYFxuICAgKlxuICAgKiBPciBpbiBzdHJpbmcgZm9ybSwgbGlrZTpcbiAgICpcbiAgICogYGBgdHNcbiAgICogJy1uYW1lJyAvLyBkZXNjZW5kaW5nIG9yZGVyXG4gICAqICduYW1lJyAgLy8gYXNjZW5kaW5nIG9yZGVyXG4gICAqIGBgYFxuICAgKi9cbiAgc29ydCguLi5wYXJhbXM6IFNvcnRQYXJhbVtdKTogdGhpcyB7XG4gICAgY29uc3Qgc3BlY2lmaWVycyA9IHBhcmFtcy5tYXAoKHApID0+IHRoaXMuJHNvcnRQYXJhbVRvU3BlY2lmaWVyKHApKTtcbiAgICB0aGlzLl9leHByZXNzaW9uLnNvcnQgPSAodGhpcy5fZXhwcmVzc2lvbi5zb3J0ID8/IFtdKS5jb25jYXQoc3BlY2lmaWVycyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQXBwbGllcyBwYWdpbmF0aW9uIHRvIGEgY29sbGVjdGlvbiBxdWVyeS5cbiAgICovXG4gIHBhZ2UocGFyYW06IFBhZ2VQYXJhbSk6IHRoaXMge1xuICAgIHRoaXMuX2V4cHJlc3Npb24ucGFnZSA9IHRoaXMuJHBhZ2VQYXJhbVRvU3BlY2lmaWVyKHBhcmFtKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBseSBhIGZpbHRlciBleHByZXNzaW9uLlxuICAgKlxuICAgKiBGb3IgZXhhbXBsZTpcbiAgICpcbiAgICogYGBgdHNcbiAgICogb3FiXG4gICAqICAgLnJlY29yZHMoJ3BsYW5ldCcpXG4gICAqICAgLmZpbHRlcih7IGF0dHJpYnV0ZTogJ2F0bW9zcGhlcmUnLCB2YWx1ZTogdHJ1ZSB9LFxuICAgKiAgICAgICAgICAgeyBhdHRyaWJ1dGU6ICdjbGFzc2lmaWNhdGlvbicsIHZhbHVlOiAndGVycmVzdHJpYWwnIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIGZpbHRlciguLi5wYXJhbXM6IEZpbHRlclBhcmFtPFJJPltdKTogdGhpcyB7XG4gICAgY29uc3Qgc3BlY2lmaWVycyA9IHBhcmFtcy5tYXAoKHApID0+IHRoaXMuJGZpbHRlclBhcmFtVG9TcGVjaWZpZXIocCkpO1xuICAgIHRoaXMuX2V4cHJlc3Npb24uZmlsdGVyID0gKHRoaXMuX2V4cHJlc3Npb24uZmlsdGVyID8/IFtdKS5jb25jYXQoXG4gICAgICBzcGVjaWZpZXJzXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gICRmaWx0ZXJQYXJhbVRvU3BlY2lmaWVyKHBhcmFtOiBGaWx0ZXJQYXJhbTxSST4pOiBGaWx0ZXJTcGVjaWZpZXIge1xuICAgIGxldCBzcGVjaWZpZXI6IEZpbHRlclNwZWNpZmllciB8IHVuZGVmaW5lZDtcblxuICAgIGlmIChpc0ZpbHRlclNwZWNpZmllcjxSST4ocGFyYW0pKSB7XG4gICAgICBzcGVjaWZpZXIgPSBwYXJhbTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3Qgb3AgPSBwYXJhbS5vcCA/PyAnZXF1YWwnO1xuICAgICAgaWYgKGlzQXR0cmlidXRlRmlsdGVyUGFyYW0ocGFyYW0pKSB7XG4gICAgICAgIGNvbnN0IHsgYXR0cmlidXRlLCB2YWx1ZSB9ID0gcGFyYW07XG4gICAgICAgIHNwZWNpZmllciA9IHtcbiAgICAgICAgICBraW5kOiAnYXR0cmlidXRlJyxcbiAgICAgICAgICBvcCxcbiAgICAgICAgICBhdHRyaWJ1dGUsXG4gICAgICAgICAgdmFsdWVcbiAgICAgICAgfSBhcyBBdHRyaWJ1dGVGaWx0ZXJTcGVjaWZpZXI7XG4gICAgICB9IGVsc2UgaWYgKGlzUmVsYXRlZFJlY29yZEZpbHRlclBhcmFtPFJJPihwYXJhbSkpIHtcbiAgICAgICAgY29uc3QgeyByZWxhdGlvbiB9ID0gcGFyYW07XG4gICAgICAgIGxldCByZWNvcmQ6IFJlY29yZElkZW50aXR5W10gfCBSZWNvcmRJZGVudGl0eSB8IG51bGw7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHBhcmFtLnJlY29yZCkpIHtcbiAgICAgICAgICByZWNvcmQgPSBwYXJhbS5yZWNvcmQubWFwKChyaSkgPT5cbiAgICAgICAgICAgIHRoaXMuJHF1ZXJ5QnVpbGRlci4kbm9ybWFsaXplUmVjb3JkSWRlbnRpdHkocmkpXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmIChwYXJhbS5yZWNvcmQpIHtcbiAgICAgICAgICByZWNvcmQgPSB0aGlzLiRxdWVyeUJ1aWxkZXIuJG5vcm1hbGl6ZVJlY29yZElkZW50aXR5KHBhcmFtLnJlY29yZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVjb3JkID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBzcGVjaWZpZXIgPSB7XG4gICAgICAgICAga2luZDogJ3JlbGF0ZWRSZWNvcmQnLFxuICAgICAgICAgIG9wLFxuICAgICAgICAgIHJlbGF0aW9uLFxuICAgICAgICAgIHJlY29yZFxuICAgICAgICB9IGFzIFJlbGF0ZWRSZWNvcmRGaWx0ZXJTcGVjaWZpZXI7XG4gICAgICB9IGVsc2UgaWYgKGlzUmVsYXRlZFJlY29yZHNGaWx0ZXJQYXJhbTxSST4ocGFyYW0pKSB7XG4gICAgICAgIGNvbnN0IHsgcmVsYXRpb24gfSA9IHBhcmFtO1xuICAgICAgICBsZXQgcmVjb3JkcyA9IHBhcmFtLnJlY29yZHMubWFwKChyaSkgPT5cbiAgICAgICAgICB0aGlzLiRxdWVyeUJ1aWxkZXIuJG5vcm1hbGl6ZVJlY29yZElkZW50aXR5KHJpKVxuICAgICAgICApO1xuICAgICAgICBzcGVjaWZpZXIgPSB7XG4gICAgICAgICAga2luZDogJ3JlbGF0ZWRSZWNvcmRzJyxcbiAgICAgICAgICBvcCxcbiAgICAgICAgICByZWxhdGlvbixcbiAgICAgICAgICByZWNvcmRzXG4gICAgICAgIH0gYXMgUmVsYXRlZFJlY29yZHNGaWx0ZXJTcGVjaWZpZXI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHNwZWNpZmllciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgICAnVW5yZWNvZ25pemVkIGBmaWx0ZXJgIHBhcmFtIGVuY291bnRlcmVkIHdoaWxlIGJ1aWxkaW5nIHF1ZXJ5IGV4cHJlc3Npb24nXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBzcGVjaWZpZXI7XG4gIH1cblxuICAkcGFnZVBhcmFtVG9TcGVjaWZpZXIocGFyYW06IFBhZ2VQYXJhbSk6IFBhZ2VTcGVjaWZpZXIge1xuICAgIGxldCBzcGVjaWZpZXI6IFBhZ2VTcGVjaWZpZXIgfCB1bmRlZmluZWQ7XG5cbiAgICBpZiAocGFyYW0uaGFzT3duUHJvcGVydHkoJ29mZnNldCcpIHx8IHBhcmFtLmhhc093blByb3BlcnR5KCdsaW1pdCcpKSB7XG4gICAgICBzcGVjaWZpZXIgPSB7XG4gICAgICAgIGtpbmQ6ICdvZmZzZXRMaW1pdCcsXG4gICAgICAgIG9mZnNldDogcGFyYW0ub2Zmc2V0LFxuICAgICAgICBsaW1pdDogcGFyYW0ubGltaXRcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKHNwZWNpZmllciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgICAnVW5yZWNvZ25pemVkIGBwYWdlYCBwYXJhbSBlbmNvdW50ZXJlZCB3aGlsZSBidWlsZGluZyBxdWVyeSBleHByZXNzaW9uJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc3BlY2lmaWVyO1xuICB9XG5cbiAgJHNvcnRQYXJhbVRvU3BlY2lmaWVyKHBhcmFtOiBTb3J0UGFyYW0pOiBTb3J0U3BlY2lmaWVyIHtcbiAgICBsZXQgc3BlY2lmaWVyOiBTb3J0U3BlY2lmaWVyIHwgdW5kZWZpbmVkO1xuXG4gICAgaWYgKGlzT2JqZWN0KHBhcmFtKSkge1xuICAgICAgaWYgKHBhcmFtLmhhc093blByb3BlcnR5KCdraW5kJykpIHtcbiAgICAgICAgc3BlY2lmaWVyID0gcGFyYW0gYXMgU29ydFNwZWNpZmllcjtcbiAgICAgIH0gZWxzZSBpZiAocGFyYW0uaGFzT3duUHJvcGVydHkoJ2F0dHJpYnV0ZScpKSB7XG4gICAgICAgIHNwZWNpZmllciA9IHtcbiAgICAgICAgICBraW5kOiAnYXR0cmlidXRlJyxcbiAgICAgICAgICBhdHRyaWJ1dGU6IChwYXJhbSBhcyBBdHRyaWJ1dGVTb3J0UGFyYW0pLmF0dHJpYnV0ZSxcbiAgICAgICAgICBvcmRlcjogKHBhcmFtIGFzIEF0dHJpYnV0ZVNvcnRQYXJhbSkub3JkZXIgfHwgJ2FzY2VuZGluZydcbiAgICAgICAgfSBhcyBBdHRyaWJ1dGVTb3J0U3BlY2lmaWVyO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodHlwZW9mIHBhcmFtID09PSAnc3RyaW5nJykge1xuICAgICAgc3BlY2lmaWVyID0gdGhpcy4kcGFyc2VTb3J0UGFyYW1TdHJpbmcocGFyYW0pO1xuICAgIH1cblxuICAgIGlmIChzcGVjaWZpZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgICAgJ1VucmVjb2duaXplZCBgc29ydGAgcGFyYW0gZW5jb3VudGVyZWQgd2hpbGUgYnVpbGRpbmcgcXVlcnkgZXhwcmVzc2lvbidcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNwZWNpZmllcjtcbiAgfVxuXG4gICRwYXJzZVNvcnRQYXJhbVN0cmluZyhzb3J0U3BlY2lmaWVyOiBzdHJpbmcpOiBBdHRyaWJ1dGVTb3J0U3BlY2lmaWVyIHtcbiAgICBsZXQgYXR0cmlidXRlOiBzdHJpbmc7XG4gICAgbGV0IG9yZGVyOiBTb3J0T3JkZXI7XG5cbiAgICBpZiAoc29ydFNwZWNpZmllclswXSA9PT0gJy0nKSB7XG4gICAgICBhdHRyaWJ1dGUgPSBzb3J0U3BlY2lmaWVyLnNsaWNlKDEpO1xuICAgICAgb3JkZXIgPSAnZGVzY2VuZGluZyc7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF0dHJpYnV0ZSA9IHNvcnRTcGVjaWZpZXI7XG4gICAgICBvcmRlciA9ICdhc2NlbmRpbmcnO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBraW5kOiAnYXR0cmlidXRlJyxcbiAgICAgIGF0dHJpYnV0ZSxcbiAgICAgIG9yZGVyXG4gICAgfTtcbiAgfVxufVxuXG5leHBvcnQgdHlwZSBSZWNvcmRRdWVyeVRlcm08UlQgPSBzdHJpbmcsIFJJID0gUmVjb3JkSWRlbnRpdHk+ID1cbiAgfCBGaW5kUmVjb3JkVGVybTxSVCwgUkk+XG4gIHwgRmluZFJlbGF0ZWRSZWNvcmRUZXJtPFJULCBSST5cbiAgfCBGaW5kUmVjb3Jkc1Rlcm08UlQsIFJJPjtcbiJdfQ==