UNPKG

@data-client/rest

Version:

Quickly define typed REST resources and endpoints

286 lines (278 loc) 39.8 kB
import _classPrivateFieldLooseBase from "@babel/runtime/helpers/esm/classPrivateFieldLooseBase"; import _classPrivateFieldLooseKey from "@babel/runtime/helpers/esm/classPrivateFieldLooseKey"; import { Endpoint } from '@data-client/endpoint'; import extractCollection from './extractCollection.js'; import mapCollection from './mapCollection.js'; import NetworkError from './NetworkError.js'; import { createPaginationSchema } from './paginatedCollections.js'; import paramsToString from './paramsToString.js'; import { getUrlBase, getUrlTokens, getPathRegex, isPojo } from './RestHelpers.js'; const textLikeRe = /\btext\b|\bxml\b|\bhtml\b|\bjavascript\b|\bcss\b|\bcsv\b|\burlencoded\b/; function jsonResponse(response) { return response.json().catch(error => { error.status = 400; throw error; }); } /** Simplifies endpoint definitions that follow REST patterns * * @see https://dataclient.io/rest/api/RestEndpoint */ var _hasBody = /*#__PURE__*/_classPrivateFieldLooseKey("hasBody"); export default class RestEndpoint extends Endpoint { constructor(options) { var _options$fetch; super((_options$fetch = options.fetch) != null ? _options$fetch : async function (...args) { const urlParams = _classPrivateFieldLooseBase(this, _hasBody)[_hasBody] && args.length < 2 ? {} : args[0] || {}; const body = _classPrivateFieldLooseBase(this, _hasBody)[_hasBody] ? args[args.length - 1] : undefined; return this.fetchResponse(this.url(urlParams), await this.getRequestInit(body)).then(response => this.parseResponse(response)).then(res => this.process(res, ...args)); }, options); // we want to use the prototype chain here Object.defineProperty(this, _hasBody, { writable: true, value: void 0 }); if (!('sideEffect' in this) || 'method' in options && !('sideEffect' in options)) { this.sideEffect = options.method === 'GET' || options.method === undefined ? undefined : true; } if (this.method === undefined) { this.method = this.sideEffect ? 'POST' : 'GET'; } if (this.urlPrefix === undefined) { this.urlPrefix = ''; } _classPrivateFieldLooseBase(this, _hasBody)[_hasBody] = (!('body' in this) || this.body !== undefined) && !['GET', 'DELETE'].includes(this.method); /* istanbul ignore else */ if (process.env.NODE_ENV !== 'production') { if (this.content && this.content !== 'json' && this.schema != null && typeof this.schema !== 'string' && typeof this.schema !== 'undefined') { console.error(`content '${this.content}' is incompatible with schema. Binary/text responses cannot be normalized. Use schema: undefined.`); } } Object.defineProperty(this, 'name', { get() { // using 'in' to ensure inheritance lookup if ('__name' in this) return this.__name; return this.urlPrefix + this.path; } }); } key(...args) { return `${this.method} ${this.url(_classPrivateFieldLooseBase(this, _hasBody)[_hasBody] && args.length < 2 ? {} : args[0] || {})}`; } /** Get the url */ url(urlParams = {}) { const tokens = getUrlTokens(this.path); const pathParams = {}; const searchParams = {}; Object.keys(urlParams).forEach(k => { if (tokens.has(k)) { if (urlParams[k] !== undefined) pathParams[k] = Array.isArray(urlParams[k]) ? urlParams[k].map(String) : String(urlParams[k]); } else { searchParams[k] = urlParams[k]; } }); const urlBase = getUrlBase(this.path)(pathParams); if (Object.keys(searchParams).length) { return `${this.urlPrefix}${urlBase}?${this.searchToString(searchParams)}`; } return `${this.urlPrefix}${urlBase}`; } /** Encode the url searchParams */ searchToString(searchParams) { return paramsToString(searchParams); } getHeaders(headers) { return headers; } /** Init options for fetch - run at fetch */ async getRequestInit(body) { const bodyIsPojo = isPojo(body); if (bodyIsPojo) { body = JSON.stringify(body); } const init = { ...this.requestInit, method: this.method, signal: this.signal, body }; if (!body || bodyIsPojo) { init.headers = { // default to application/json but allow user explicit overrides 'Content-Type': 'application/json', ...init.headers }; } init.headers = await this.getHeaders(init.headers); return init; } /** Perform network request and resolve with HTTP Response */ fetchResponse(input, init) { return fetch(input, init).then(response => { if (!response.ok) { throw new NetworkError(response); } return response; }).catch(error => { // ensure CORS, network down, and parse errors are still caught by NetworkErrorBoundary if (error instanceof TypeError) { error.status = 500; } throw error; }); } parseResponse(response) { if (response.status === 204) return Promise.resolve(null); if (this.content) { /* istanbul ignore else */ if (process.env.NODE_ENV !== 'production') { if (this.content !== 'json' && this.schema != null && typeof this.schema !== 'string' && typeof this.schema !== 'undefined') { const error = new NetworkError(response); error.status = 400; error.message = `content '${this.content}' is incompatible with schema. Binary/text responses cannot be normalized. Use schema: undefined.`; throw error; } } if (this.content === 'stream') return Promise.resolve(response.body); return this.content === 'json' ? jsonResponse(response) : response[this.content](); } const contentType = response.headers.get('content-type'); if (contentType != null && contentType.includes('json')) return jsonResponse(response); const isBinary = contentType && !textLikeRe.test(contentType); if (typeof this.schema === 'string' || typeof this.schema === 'undefined' || this.schema === null || this.process !== RestEndpoint.prototype.process) return isBinary ? response.blob() : response.text(); if (isBinary) { const error = new NetworkError(response); error.status = 400; error.message = `Unexpected binary content-type for schema ${this.schema}`; /* istanbul ignore else */ if (process.env.NODE_ENV !== 'production') { error.message = `Unexpected binary content-type "${contentType}" for schema ${this.schema}. Binary responses cannot be normalized. Use schema: undefined or set content: 'blob'.`; } throw error; } return response.text().then(text => { const error = new NetworkError(response); error.status = 404; error.message = `Unexpected text response for schema ${this.schema}`; /* istanbul ignore else */ if (process.env.NODE_ENV !== 'production') { if (!(contentType != null && contentType.includes('html') || text.startsWith('<!doctype html>'))) { if (tryParse(text) !== undefined) { error.message = `"content-type" header does not include "json", but JSON response found. See https://www.rfc-editor.org/rfc/rfc4627 for information on JSON responses Using parsed JSON. If text content was expected see https://dataclient.io/rest/api/RestEndpoint#parseResponse`; } } else { error.message = `Unexpected html response for schema ${this.schema} This likely means no API endpoint was configured for this request, resulting in an HTML fallback. Response (first 300 characters): ${text.substring(0, 300)}`; } } throw error; }); } process(value) { return value; } errorPolicy(error) { return error.status >= 500 ? 'soft' : undefined; } get pathRegex() { return getPathRegex(this.path); } testKey(key) { const prefix = this.method + ' ' + this.urlPrefix; if (!key.startsWith(prefix)) return false; let lastQuestion = key.lastIndexOf('?'); if (lastQuestion === -1) lastQuestion = undefined; return this.pathRegex.test(key.substring(prefix.length, lastQuestion)); } extend(options) { // make a constructor/prototype based off this // extend from it and init with options sent class E extends this.constructor {} Object.assign(E.prototype, this); return new E( // fetch get overridden by function prototype, so we must set it explicitly every time { fetch: this.fetch, ...options }); } paginated(removeCursor) { if (typeof removeCursor === 'string') { const fieldName = removeCursor; removeCursor = ({ ...params }) => { delete params[fieldName]; return [params]; }; } let found = false; const createPaginatedSchema = collection => { found = true; return createPaginationSchema(removeCursor, collection); }; const newSchema = mapCollection(this.schema, createPaginatedSchema); if (!found) throw new Error('Missing Collection'); const sup = this; return this.extend({ schema: newSchema, key(...args) { return sup.key.call(this, ...removeCursor(...args)); }, name: this.name + '.getPage' }); } get getPage() { return this.paginated(this.paginationField); } get push() { return this.extend({ method: 'POST', schema: extractCollection(this.schema, s => s.push), name: this.name + '.create' }); } get unshift() { return this.extend({ method: 'POST', schema: extractCollection(this.schema, s => s.unshift), name: this.name + '.create' }); } get assign() { return this.extend({ method: 'POST', schema: extractCollection(this.schema, s => s.assign), name: this.name + '.create' }); } get remove() { return this.extend({ method: 'PATCH', schema: extractCollection(this.schema, s => s.remove), name: this.name + '.partialUpdate' }); } get move() { const options = { method: 'PATCH', schema: extractCollection(this.schema, s => s.move), searchParams: undefined, name: this.name + '.partialUpdate' }; if (this.movePath) options.path = this.movePath; return this.extend(options); } } const tryParse = input => { try { return JSON.parse(input); } catch (e) { return undefined; } }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJFbmRwb2ludCIsImV4dHJhY3RDb2xsZWN0aW9uIiwibWFwQ29sbGVjdGlvbiIsIk5ldHdvcmtFcnJvciIsImNyZWF0ZVBhZ2luYXRpb25TY2hlbWEiLCJwYXJhbXNUb1N0cmluZyIsImdldFVybEJhc2UiLCJnZXRVcmxUb2tlbnMiLCJnZXRQYXRoUmVnZXgiLCJpc1Bvam8iLCJ0ZXh0TGlrZVJlIiwianNvblJlc3BvbnNlIiwicmVzcG9uc2UiLCJqc29uIiwiY2F0Y2giLCJlcnJvciIsInN0YXR1cyIsIl9oYXNCb2R5IiwiX2NsYXNzUHJpdmF0ZUZpZWxkTG9vc2VLZXkiLCJSZXN0RW5kcG9pbnQiLCJjb25zdHJ1Y3RvciIsIm9wdGlvbnMiLCJfb3B0aW9ucyRmZXRjaCIsImZldGNoIiwiYXJncyIsInVybFBhcmFtcyIsIl9jbGFzc1ByaXZhdGVGaWVsZExvb3NlQmFzZSIsImxlbmd0aCIsImJvZHkiLCJ1bmRlZmluZWQiLCJmZXRjaFJlc3BvbnNlIiwidXJsIiwiZ2V0UmVxdWVzdEluaXQiLCJ0aGVuIiwicGFyc2VSZXNwb25zZSIsInJlcyIsInByb2Nlc3MiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsIndyaXRhYmxlIiwidmFsdWUiLCJzaWRlRWZmZWN0IiwibWV0aG9kIiwidXJsUHJlZml4IiwiaW5jbHVkZXMiLCJlbnYiLCJOT0RFX0VOViIsImNvbnRlbnQiLCJzY2hlbWEiLCJjb25zb2xlIiwiZ2V0IiwiX19uYW1lIiwicGF0aCIsImtleSIsInRva2VucyIsInBhdGhQYXJhbXMiLCJzZWFyY2hQYXJhbXMiLCJrZXlzIiwiZm9yRWFjaCIsImsiLCJoYXMiLCJBcnJheSIsImlzQXJyYXkiLCJtYXAiLCJTdHJpbmciLCJ1cmxCYXNlIiwic2VhcmNoVG9TdHJpbmciLCJnZXRIZWFkZXJzIiwiaGVhZGVycyIsImJvZHlJc1Bvam8iLCJKU09OIiwic3RyaW5naWZ5IiwiaW5pdCIsInJlcXVlc3RJbml0Iiwic2lnbmFsIiwiaW5wdXQiLCJvayIsIlR5cGVFcnJvciIsIlByb21pc2UiLCJyZXNvbHZlIiwibWVzc2FnZSIsImNvbnRlbnRUeXBlIiwiaXNCaW5hcnkiLCJ0ZXN0IiwicHJvdG90eXBlIiwiYmxvYiIsInRleHQiLCJzdGFydHNXaXRoIiwidHJ5UGFyc2UiLCJzdWJzdHJpbmciLCJlcnJvclBvbGljeSIsInBhdGhSZWdleCIsInRlc3RLZXkiLCJwcmVmaXgiLCJsYXN0UXVlc3Rpb24iLCJsYXN0SW5kZXhPZiIsImV4dGVuZCIsIkUiLCJhc3NpZ24iLCJwYWdpbmF0ZWQiLCJyZW1vdmVDdXJzb3IiLCJmaWVsZE5hbWUiLCJwYXJhbXMiLCJmb3VuZCIsImNyZWF0ZVBhZ2luYXRlZFNjaGVtYSIsImNvbGxlY3Rpb24iLCJuZXdTY2hlbWEiLCJFcnJvciIsInN1cCIsImNhbGwiLCJuYW1lIiwiZ2V0UGFnZSIsInBhZ2luYXRpb25GaWVsZCIsInB1c2giLCJzIiwidW5zaGlmdCIsInJlbW92ZSIsIm1vdmUiLCJtb3ZlUGF0aCIsInBhcnNlIiwiZSJdLCJzb3VyY2VzIjpbIi4uL3NyYy9SZXN0RW5kcG9pbnQuanMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRW5kcG9pbnQgfSBmcm9tICdAZGF0YS1jbGllbnQvZW5kcG9pbnQnO1xuXG5pbXBvcnQgZXh0cmFjdENvbGxlY3Rpb24gZnJvbSAnLi9leHRyYWN0Q29sbGVjdGlvbi5qcyc7XG5pbXBvcnQgbWFwQ29sbGVjdGlvbiBmcm9tICcuL21hcENvbGxlY3Rpb24uanMnO1xuaW1wb3J0IE5ldHdvcmtFcnJvciBmcm9tICcuL05ldHdvcmtFcnJvci5qcyc7XG5pbXBvcnQgeyBjcmVhdGVQYWdpbmF0aW9uU2NoZW1hIH0gZnJvbSAnLi9wYWdpbmF0ZWRDb2xsZWN0aW9ucy5qcyc7XG5pbXBvcnQgcGFyYW1zVG9TdHJpbmcgZnJvbSAnLi9wYXJhbXNUb1N0cmluZy5qcyc7XG5pbXBvcnQge1xuICBnZXRVcmxCYXNlLFxuICBnZXRVcmxUb2tlbnMsXG4gIGdldFBhdGhSZWdleCxcbiAgaXNQb2pvLFxufSBmcm9tICcuL1Jlc3RIZWxwZXJzLmpzJztcblxuY29uc3QgdGV4dExpa2VSZSA9XG4gIC9cXGJ0ZXh0XFxifFxcYnhtbFxcYnxcXGJodG1sXFxifFxcYmphdmFzY3JpcHRcXGJ8XFxiY3NzXFxifFxcYmNzdlxcYnxcXGJ1cmxlbmNvZGVkXFxiLztcblxuZnVuY3Rpb24ganNvblJlc3BvbnNlKHJlc3BvbnNlKSB7XG4gIHJldHVybiByZXNwb25zZS5qc29uKCkuY2F0Y2goZXJyb3IgPT4ge1xuICAgIGVycm9yLnN0YXR1cyA9IDQwMDtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfSk7XG59XG5cbi8qKiBTaW1wbGlmaWVzIGVuZHBvaW50IGRlZmluaXRpb25zIHRoYXQgZm9sbG93IFJFU1QgcGF0dGVybnNcbiAqXG4gKiBAc2VlIGh0dHBzOi8vZGF0YWNsaWVudC5pby9yZXN0L2FwaS9SZXN0RW5kcG9pbnRcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUmVzdEVuZHBvaW50IGV4dGVuZHMgRW5kcG9pbnQge1xuICAjaGFzQm9keTtcbiAgY29uc3RydWN0b3Iob3B0aW9ucykge1xuICAgIHN1cGVyKFxuICAgICAgb3B0aW9ucy5mZXRjaCA/P1xuICAgICAgICBhc3luYyBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgICAgICAgIGNvbnN0IHVybFBhcmFtcyA9XG4gICAgICAgICAgICB0aGlzLiNoYXNCb2R5ICYmIGFyZ3MubGVuZ3RoIDwgMiA/IHt9IDogYXJnc1swXSB8fCB7fTtcbiAgICAgICAgICBjb25zdCBib2R5ID0gdGhpcy4jaGFzQm9keSA/IGFyZ3NbYXJncy5sZW5ndGggLSAxXSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICByZXR1cm4gdGhpcy5mZXRjaFJlc3BvbnNlKFxuICAgICAgICAgICAgdGhpcy51cmwodXJsUGFyYW1zKSxcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuZ2V0UmVxdWVzdEluaXQoYm9keSksXG4gICAgICAgICAgKVxuICAgICAgICAgICAgLnRoZW4ocmVzcG9uc2UgPT4gdGhpcy5wYXJzZVJlc3BvbnNlKHJlc3BvbnNlKSlcbiAgICAgICAgICAgIC50aGVuKHJlcyA9PiB0aGlzLnByb2Nlc3MocmVzLCAuLi5hcmdzKSk7XG4gICAgICAgIH0sXG4gICAgICBvcHRpb25zLFxuICAgICk7XG4gICAgLy8gd2Ugd2FudCB0byB1c2UgdGhlIHByb3RvdHlwZSBjaGFpbiBoZXJlXG4gICAgaWYgKFxuICAgICAgISgnc2lkZUVmZmVjdCcgaW4gdGhpcykgfHxcbiAgICAgICgnbWV0aG9kJyBpbiBvcHRpb25zICYmICEoJ3NpZGVFZmZlY3QnIGluIG9wdGlvbnMpKVxuICAgICkge1xuICAgICAgdGhpcy5zaWRlRWZmZWN0ID1cbiAgICAgICAgb3B0aW9ucy5tZXRob2QgPT09ICdHRVQnIHx8IG9wdGlvbnMubWV0aG9kID09PSB1bmRlZmluZWQgP1xuICAgICAgICAgIHVuZGVmaW5lZFxuICAgICAgICA6IHRydWU7XG4gICAgfVxuICAgIGlmICh0aGlzLm1ldGhvZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLm1ldGhvZCA9IHRoaXMuc2lkZUVmZmVjdCA/ICdQT1NUJyA6ICdHRVQnO1xuICAgIH1cbiAgICBpZiAodGhpcy51cmxQcmVmaXggPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy51cmxQcmVmaXggPSAnJztcbiAgICB9XG4gICAgdGhpcy4jaGFzQm9keSA9XG4gICAgICAoISgnYm9keScgaW4gdGhpcykgfHwgdGhpcy5ib2R5ICE9PSB1bmRlZmluZWQpICYmXG4gICAgICAhWydHRVQnLCAnREVMRVRFJ10uaW5jbHVkZXModGhpcy5tZXRob2QpO1xuXG4gICAgLyogaXN0YW5idWwgaWdub3JlIGVsc2UgKi9cbiAgICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgIT09ICdwcm9kdWN0aW9uJykge1xuICAgICAgaWYgKFxuICAgICAgICB0aGlzLmNvbnRlbnQgJiZcbiAgICAgICAgdGhpcy5jb250ZW50ICE9PSAnanNvbicgJiZcbiAgICAgICAgdGhpcy5zY2hlbWEgIT0gbnVsbCAmJlxuICAgICAgICB0eXBlb2YgdGhpcy5zY2hlbWEgIT09ICdzdHJpbmcnICYmXG4gICAgICAgIHR5cGVvZiB0aGlzLnNjaGVtYSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICkge1xuICAgICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICAgIGBjb250ZW50ICcke3RoaXMuY29udGVudH0nIGlzIGluY29tcGF0aWJsZSB3aXRoIHNjaGVtYS4gQmluYXJ5L3RleHQgcmVzcG9uc2VzIGNhbm5vdCBiZSBub3JtYWxpemVkLiBVc2Ugc2NoZW1hOiB1bmRlZmluZWQuYCxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ25hbWUnLCB7XG4gICAgICBnZXQoKSB7XG4gICAgICAgIC8vIHVzaW5nICdpbicgdG8gZW5zdXJlIGluaGVyaXRhbmNlIGxvb2t1cFxuICAgICAgICBpZiAoJ19fbmFtZScgaW4gdGhpcykgcmV0dXJuIHRoaXMuX19uYW1lO1xuICAgICAgICByZXR1cm4gdGhpcy51cmxQcmVmaXggKyB0aGlzLnBhdGg7XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAga2V5KC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gYCR7dGhpcy5tZXRob2R9ICR7dGhpcy51cmwoXG4gICAgICB0aGlzLiNoYXNCb2R5ICYmIGFyZ3MubGVuZ3RoIDwgMiA/IHt9IDogYXJnc1swXSB8fCB7fSxcbiAgICApfWA7XG4gIH1cblxuICAvKiogR2V0IHRoZSB1cmwgKi9cbiAgdXJsKHVybFBhcmFtcyA9IHt9KSB7XG4gICAgY29uc3QgdG9rZW5zID0gZ2V0VXJsVG9rZW5zKHRoaXMucGF0aCk7XG4gICAgY29uc3QgcGF0aFBhcmFtcyA9IHt9O1xuICAgIGNvbnN0IHNlYXJjaFBhcmFtcyA9IHt9O1xuICAgIE9iamVjdC5rZXlzKHVybFBhcmFtcykuZm9yRWFjaChrID0+IHtcbiAgICAgIGlmICh0b2tlbnMuaGFzKGspKSB7XG4gICAgICAgIGlmICh1cmxQYXJhbXNba10gIT09IHVuZGVmaW5lZClcbiAgICAgICAgICBwYXRoUGFyYW1zW2tdID1cbiAgICAgICAgICAgIEFycmF5LmlzQXJyYXkodXJsUGFyYW1zW2tdKSA/XG4gICAgICAgICAgICAgIHVybFBhcmFtc1trXS5tYXAoU3RyaW5nKVxuICAgICAgICAgICAgOiBTdHJpbmcodXJsUGFyYW1zW2tdKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNlYXJjaFBhcmFtc1trXSA9IHVybFBhcmFtc1trXTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBjb25zdCB1cmxCYXNlID0gZ2V0VXJsQmFzZSh0aGlzLnBhdGgpKHBhdGhQYXJhbXMpO1xuICAgIGlmIChPYmplY3Qua2V5cyhzZWFyY2hQYXJhbXMpLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGAke3RoaXMudXJsUHJlZml4fSR7dXJsQmFzZX0/JHt0aGlzLnNlYXJjaFRvU3RyaW5nKHNlYXJjaFBhcmFtcyl9YDtcbiAgICB9XG4gICAgcmV0dXJuIGAke3RoaXMudXJsUHJlZml4fSR7dXJsQmFzZX1gO1xuICB9XG5cbiAgLyoqIEVuY29kZSB0aGUgdXJsIHNlYXJjaFBhcmFtcyAqL1xuICBzZWFyY2hUb1N0cmluZyhzZWFyY2hQYXJhbXMpIHtcbiAgICByZXR1cm4gcGFyYW1zVG9TdHJpbmcoc2VhcmNoUGFyYW1zKTtcbiAgfVxuXG4gIGdldEhlYWRlcnMoaGVhZGVycykge1xuICAgIHJldHVybiBoZWFkZXJzO1xuICB9XG5cbiAgLyoqIEluaXQgb3B0aW9ucyBmb3IgZmV0Y2ggLSBydW4gYXQgZmV0Y2ggKi9cbiAgYXN5bmMgZ2V0UmVxdWVzdEluaXQoYm9keSkge1xuICAgIGNvbnN0IGJvZHlJc1Bvam8gPSBpc1Bvam8oYm9keSk7XG4gICAgaWYgKGJvZHlJc1Bvam8pIHtcbiAgICAgIGJvZHkgPSBKU09OLnN0cmluZ2lmeShib2R5KTtcbiAgICB9XG4gICAgY29uc3QgaW5pdCA9IHtcbiAgICAgIC4uLnRoaXMucmVxdWVzdEluaXQsXG4gICAgICBtZXRob2Q6IHRoaXMubWV0aG9kLFxuICAgICAgc2lnbmFsOiB0aGlzLnNpZ25hbCxcbiAgICAgIGJvZHksXG4gICAgfTtcbiAgICBpZiAoIWJvZHkgfHwgYm9keUlzUG9qbykge1xuICAgICAgaW5pdC5oZWFkZXJzID0ge1xuICAgICAgICAvLyBkZWZhdWx0IHRvIGFwcGxpY2F0aW9uL2pzb24gYnV0IGFsbG93IHVzZXIgZXhwbGljaXQgb3ZlcnJpZGVzXG4gICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgIC4uLmluaXQuaGVhZGVycyxcbiAgICAgIH07XG4gICAgfVxuICAgIGluaXQuaGVhZGVycyA9IGF3YWl0IHRoaXMuZ2V0SGVhZGVycyhpbml0LmhlYWRlcnMpO1xuICAgIHJldHVybiBpbml0O1xuICB9XG5cbiAgLyoqIFBlcmZvcm0gbmV0d29yayByZXF1ZXN0IGFuZCByZXNvbHZlIHdpdGggSFRUUCBSZXNwb25zZSAqL1xuICBmZXRjaFJlc3BvbnNlKGlucHV0LCBpbml0KSB7XG4gICAgcmV0dXJuIGZldGNoKGlucHV0LCBpbml0KVxuICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IE5ldHdvcmtFcnJvcihyZXNwb25zZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIC8vIGVuc3VyZSBDT1JTLCBuZXR3b3JrIGRvd24sIGFuZCBwYXJzZSBlcnJvcnMgYXJlIHN0aWxsIGNhdWdodCBieSBOZXR3b3JrRXJyb3JCb3VuZGFyeVxuICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBUeXBlRXJyb3IpIHtcbiAgICAgICAgICBlcnJvci5zdGF0dXMgPSA1MDA7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KTtcbiAgfVxuXG4gIHBhcnNlUmVzcG9uc2UocmVzcG9uc2UpIHtcbiAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSAyMDQpIHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCk7XG5cbiAgICBpZiAodGhpcy5jb250ZW50KSB7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHRoaXMuY29udGVudCAhPT0gJ2pzb24nICYmXG4gICAgICAgICAgdGhpcy5zY2hlbWEgIT0gbnVsbCAmJlxuICAgICAgICAgIHR5cGVvZiB0aGlzLnNjaGVtYSAhPT0gJ3N0cmluZycgJiZcbiAgICAgICAgICB0eXBlb2YgdGhpcy5zY2hlbWEgIT09ICd1bmRlZmluZWQnXG4gICAgICAgICkge1xuICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE5ldHdvcmtFcnJvcihyZXNwb25zZSk7XG4gICAgICAgICAgZXJyb3Iuc3RhdHVzID0gNDAwO1xuICAgICAgICAgIGVycm9yLm1lc3NhZ2UgPSBgY29udGVudCAnJHt0aGlzLmNvbnRlbnR9JyBpcyBpbmNvbXBhdGlibGUgd2l0aCBzY2hlbWEuIEJpbmFyeS90ZXh0IHJlc3BvbnNlcyBjYW5ub3QgYmUgbm9ybWFsaXplZC4gVXNlIHNjaGVtYTogdW5kZWZpbmVkLmA7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLmNvbnRlbnQgPT09ICdzdHJlYW0nKSByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlc3BvbnNlLmJvZHkpO1xuICAgICAgcmV0dXJuIHRoaXMuY29udGVudCA9PT0gJ2pzb24nID9cbiAgICAgICAgICBqc29uUmVzcG9uc2UocmVzcG9uc2UpXG4gICAgICAgIDogcmVzcG9uc2VbdGhpcy5jb250ZW50XSgpO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbnRlbnRUeXBlID0gcmVzcG9uc2UuaGVhZGVycy5nZXQoJ2NvbnRlbnQtdHlwZScpO1xuICAgIGlmIChjb250ZW50VHlwZT8uaW5jbHVkZXMoJ2pzb24nKSkgcmV0dXJuIGpzb25SZXNwb25zZShyZXNwb25zZSk7XG5cbiAgICBjb25zdCBpc0JpbmFyeSA9IGNvbnRlbnRUeXBlICYmICF0ZXh0TGlrZVJlLnRlc3QoY29udGVudFR5cGUpO1xuXG4gICAgaWYgKFxuICAgICAgdHlwZW9mIHRoaXMuc2NoZW1hID09PSAnc3RyaW5nJyB8fFxuICAgICAgdHlwZW9mIHRoaXMuc2NoZW1hID09PSAndW5kZWZpbmVkJyB8fFxuICAgICAgdGhpcy5zY2hlbWEgPT09IG51bGwgfHxcbiAgICAgIHRoaXMucHJvY2VzcyAhPT0gUmVzdEVuZHBvaW50LnByb3RvdHlwZS5wcm9jZXNzXG4gICAgKVxuICAgICAgcmV0dXJuIGlzQmluYXJ5ID8gcmVzcG9uc2UuYmxvYigpIDogcmVzcG9uc2UudGV4dCgpO1xuXG4gICAgaWYgKGlzQmluYXJ5KSB7XG4gICAgICBjb25zdCBlcnJvciA9IG5ldyBOZXR3b3JrRXJyb3IocmVzcG9uc2UpO1xuICAgICAgZXJyb3Iuc3RhdHVzID0gNDAwO1xuICAgICAgZXJyb3IubWVzc2FnZSA9IGBVbmV4cGVjdGVkIGJpbmFyeSBjb250ZW50LXR5cGUgZm9yIHNjaGVtYSAke3RoaXMuc2NoZW1hfWA7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicpIHtcbiAgICAgICAgZXJyb3IubWVzc2FnZSA9IGBVbmV4cGVjdGVkIGJpbmFyeSBjb250ZW50LXR5cGUgXCIke2NvbnRlbnRUeXBlfVwiIGZvciBzY2hlbWEgJHt0aGlzLnNjaGVtYX0uIEJpbmFyeSByZXNwb25zZXMgY2Fubm90IGJlIG5vcm1hbGl6ZWQuIFVzZSBzY2hlbWE6IHVuZGVmaW5lZCBvciBzZXQgY29udGVudDogJ2Jsb2InLmA7XG4gICAgICB9XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpLnRoZW4odGV4dCA9PiB7XG4gICAgICBjb25zdCBlcnJvciA9IG5ldyBOZXR3b3JrRXJyb3IocmVzcG9uc2UpO1xuICAgICAgZXJyb3Iuc3RhdHVzID0gNDA0O1xuICAgICAgZXJyb3IubWVzc2FnZSA9IGBVbmV4cGVjdGVkIHRleHQgcmVzcG9uc2UgZm9yIHNjaGVtYSAke3RoaXMuc2NoZW1hfWA7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICEoY29udGVudFR5cGU/LmluY2x1ZGVzKCdodG1sJykgfHwgdGV4dC5zdGFydHNXaXRoKCc8IWRvY3R5cGUgaHRtbD4nKSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgaWYgKHRyeVBhcnNlKHRleHQpICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGVycm9yLm1lc3NhZ2UgPSBgXCJjb250ZW50LXR5cGVcIiBoZWFkZXIgZG9lcyBub3QgaW5jbHVkZSBcImpzb25cIiwgYnV0IEpTT04gcmVzcG9uc2UgZm91bmQuXG5TZWUgaHR0cHM6Ly93d3cucmZjLWVkaXRvci5vcmcvcmZjL3JmYzQ2MjcgZm9yIGluZm9ybWF0aW9uIG9uIEpTT04gcmVzcG9uc2VzXG5cblVzaW5nIHBhcnNlZCBKU09OLlxuSWYgdGV4dCBjb250ZW50IHdhcyBleHBlY3RlZCBzZWUgaHR0cHM6Ly9kYXRhY2xpZW50LmlvL3Jlc3QvYXBpL1Jlc3RFbmRwb2ludCNwYXJzZVJlc3BvbnNlYDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZXJyb3IubWVzc2FnZSA9IGBVbmV4cGVjdGVkIGh0bWwgcmVzcG9uc2UgZm9yIHNjaGVtYSAke3RoaXMuc2NoZW1hfVxuVGhpcyBsaWtlbHkgbWVhbnMgbm8gQVBJIGVuZHBvaW50IHdhcyBjb25maWd1cmVkIGZvciB0aGlzIHJlcXVlc3QsIHJlc3VsdGluZyBpbiBhbiBIVE1MIGZhbGxiYWNrLlxuXG5SZXNwb25zZSAoZmlyc3QgMzAwIGNoYXJhY3RlcnMpOiAke3RleHQuc3Vic3RyaW5nKDAsIDMwMCl9YDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfSk7XG4gIH1cblxuICBwcm9jZXNzKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgZXJyb3JQb2xpY3koZXJyb3IpIHtcbiAgICByZXR1cm4gZXJyb3Iuc3RhdHVzID49IDUwMCA/ICdzb2Z0JyA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIGdldCBwYXRoUmVnZXgoKSB7XG4gICAgcmV0dXJuIGdldFBhdGhSZWdleCh0aGlzLnBhdGgpO1xuICB9XG5cbiAgdGVzdEtleShrZXkpIHtcbiAgICBjb25zdCBwcmVmaXggPSB0aGlzLm1ldGhvZCArICcgJyArIHRoaXMudXJsUHJlZml4O1xuICAgIGlmICgha2V5LnN0YXJ0c1dpdGgocHJlZml4KSkgcmV0dXJuIGZhbHNlO1xuICAgIGxldCBsYXN0UXVlc3Rpb24gPSBrZXkubGFzdEluZGV4T2YoJz8nKTtcbiAgICBpZiAobGFzdFF1ZXN0aW9uID09PSAtMSkgbGFzdFF1ZXN0aW9uID0gdW5kZWZpbmVkO1xuICAgIHJldHVybiB0aGlzLnBhdGhSZWdleC50ZXN0KGtleS5zdWJzdHJpbmcocHJlZml4Lmxlbmd0aCwgbGFzdFF1ZXN0aW9uKSk7XG4gIH1cblxuICBleHRlbmQob3B0aW9ucykge1xuICAgIC8vIG1ha2UgYSBjb25zdHJ1Y3Rvci9wcm90b3R5cGUgYmFzZWQgb2ZmIHRoaXNcbiAgICAvLyBleHRlbmQgZnJvbSBpdCBhbmQgaW5pdCB3aXRoIG9wdGlvbnMgc2VudFxuICAgIGNsYXNzIEUgZXh0ZW5kcyB0aGlzLmNvbnN0cnVjdG9yIHt9XG5cbiAgICBPYmplY3QuYXNzaWduKEUucHJvdG90eXBlLCB0aGlzKTtcblxuICAgIHJldHVybiBuZXcgRShcbiAgICAgIC8vICBmZXRjaCBnZXQgb3ZlcnJpZGRlbiBieSBmdW5jdGlvbiBwcm90b3R5cGUsIHNvIHdlIG11c3Qgc2V0IGl0IGV4cGxpY2l0bHkgZXZlcnkgdGltZVxuICAgICAgeyBmZXRjaDogdGhpcy5mZXRjaCwgLi4ub3B0aW9ucyB9LFxuICAgICk7XG4gIH1cblxuICBwYWdpbmF0ZWQocmVtb3ZlQ3Vyc29yKSB7XG4gICAgaWYgKHR5cGVvZiByZW1vdmVDdXJzb3IgPT09ICdzdHJpbmcnKSB7XG4gICAgICBjb25zdCBmaWVsZE5hbWUgPSByZW1vdmVDdXJzb3I7XG4gICAgICByZW1vdmVDdXJzb3IgPSAoeyAuLi5wYXJhbXMgfSkgPT4ge1xuICAgICAgICBkZWxldGUgcGFyYW1zW2ZpZWxkTmFtZV07XG4gICAgICAgIHJldHVybiBbcGFyYW1zXTtcbiAgICAgIH07XG4gICAgfVxuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGNvbnN0IGNyZWF0ZVBhZ2luYXRlZFNjaGVtYSA9IGNvbGxlY3Rpb24gPT4ge1xuICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgcmV0dXJuIGNyZWF0ZVBhZ2luYXRpb25TY2hlbWEocmVtb3ZlQ3Vyc29yLCBjb2xsZWN0aW9uKTtcbiAgICB9O1xuICAgIGNvbnN0IG5ld1NjaGVtYSA9IG1hcENvbGxlY3Rpb24odGhpcy5zY2hlbWEsIGNyZWF0ZVBhZ2luYXRlZFNjaGVtYSk7XG5cbiAgICBpZiAoIWZvdW5kKSB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgQ29sbGVjdGlvbicpO1xuICAgIGNvbnN0IHN1cCA9IHRoaXM7XG5cbiAgICByZXR1cm4gdGhpcy5leHRlbmQoe1xuICAgICAgc2NoZW1hOiBuZXdTY2hlbWEsXG4gICAgICBrZXkoLi4uYXJncykge1xuICAgICAgICByZXR1cm4gc3VwLmtleS5jYWxsKHRoaXMsIC4uLnJlbW92ZUN1cnNvciguLi5hcmdzKSk7XG4gICAgICB9LFxuICAgICAgbmFtZTogdGhpcy5uYW1lICsgJy5nZXRQYWdlJyxcbiAgICB9KTtcbiAgfVxuXG4gIGdldCBnZXRQYWdlKCkge1xuICAgIHJldHVybiB0aGlzLnBhZ2luYXRlZCh0aGlzLnBhZ2luYXRpb25GaWVsZCk7XG4gIH1cblxuICBnZXQgcHVzaCgpIHtcbiAgICByZXR1cm4gdGhpcy5leHRlbmQoe1xuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBzY2hlbWE6IGV4dHJhY3RDb2xsZWN0aW9uKHRoaXMuc2NoZW1hLCBzID0+IHMucHVzaCksXG4gICAgICBuYW1lOiB0aGlzLm5hbWUgKyAnLmNyZWF0ZScsXG4gICAgfSk7XG4gIH1cblxuICBnZXQgdW5zaGlmdCgpIHtcbiAgICByZXR1cm4gdGhpcy5leHRlbmQoe1xuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBzY2hlbWE6IGV4dHJhY3RDb2xsZWN0aW9uKHRoaXMuc2NoZW1hLCBzID0+IHMudW5zaGlmdCksXG4gICAgICBuYW1lOiB0aGlzLm5hbWUgKyAnLmNyZWF0ZScsXG4gICAgfSk7XG4gIH1cblxuICBnZXQgYXNzaWduKCkge1xuICAgIHJldHVybiB0aGlzLmV4dGVuZCh7XG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIHNjaGVtYTogZXh0cmFjdENvbGxlY3Rpb24odGhpcy5zY2hlbWEsIHMgPT4gcy5hc3NpZ24pLFxuICAgICAgbmFtZTogdGhpcy5uYW1lICsgJy5jcmVhdGUnLFxuICAgIH0pO1xuICB9XG5cbiAgZ2V0IHJlbW92ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5leHRlbmQoe1xuICAgICAgbWV0aG9kOiAnUEFUQ0gnLFxuICAgICAgc2NoZW1hOiBleHRyYWN0Q29sbGVjdGlvbih0aGlzLnNjaGVtYSwgcyA9PiBzLnJlbW92ZSksXG4gICAgICBuYW1lOiB0aGlzLm5hbWUgKyAnLnBhcnRpYWxVcGRhdGUnLFxuICAgIH0pO1xuICB9XG5cbiAgZ2V0IG1vdmUoKSB7XG4gICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgIG1ldGhvZDogJ1BBVENIJyxcbiAgICAgIHNjaGVtYTogZXh0cmFjdENvbGxlY3Rpb24odGhpcy5zY2hlbWEsIHMgPT4gcy5tb3ZlKSxcbiAgICAgIHNlYXJjaFBhcmFtczogdW5kZWZpbmVkLFxuICAgICAgbmFtZTogdGhpcy5uYW1lICsgJy5wYXJ0aWFsVXBkYXRlJyxcbiAgICB9O1xuICAgIGlmICh0aGlzLm1vdmVQYXRoKSBvcHRpb25zLnBhdGggPSB0aGlzLm1vdmVQYXRoO1xuICAgIHJldHVybiB0aGlzLmV4dGVuZChvcHRpb25zKTtcbiAgfVxufVxuXG5jb25zdCB0cnlQYXJzZSA9IGlucHV0ID0+IHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShpbnB1dCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59O1xuIl0sIm1hcHBpbmdzIjoiOztBQUFBLFNBQVNBLFFBQVEsUUFBUSx1QkFBdUI7QUFFaEQsT0FBT0MsaUJBQWlCLE1BQU0sd0JBQXdCO0FBQ3RELE9BQU9DLGFBQWEsTUFBTSxvQkFBb0I7QUFDOUMsT0FBT0MsWUFBWSxNQUFNLG1CQUFtQjtBQUM1QyxTQUFTQyxzQkFBc0IsUUFBUSwyQkFBMkI7QUFDbEUsT0FBT0MsY0FBYyxNQUFNLHFCQUFxQjtBQUNoRCxTQUNFQyxVQUFVLEVBQ1ZDLFlBQVksRUFDWkMsWUFBWSxFQUNaQyxNQUFNLFFBQ0Qsa0JBQWtCO0FBRXpCLE1BQU1DLFVBQVUsR0FDZCx5RUFBeUU7QUFFM0UsU0FBU0MsWUFBWUEsQ0FBQ0MsUUFBUSxFQUFFO0VBQzlCLE9BQU9BLFFBQVEsQ0FBQ0MsSUFBSSxDQUFDLENBQUMsQ0FBQ0MsS0FBSyxDQUFDQyxLQUFLLElBQUk7SUFDcENBLEtBQUssQ0FBQ0MsTUFBTSxHQUFHLEdBQUc7SUFDbEIsTUFBTUQsS0FBSztFQUNiLENBQUMsQ0FBQztBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBSEEsSUFBQUUsUUFBQSxnQkFBQUMsMEJBQUE7QUFJQSxlQUFlLE1BQU1DLFlBQVksU0FBU25CLFFBQVEsQ0FB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