UNPKG

rentdynamics

Version:

Package to help facilitate communicating with the Rent Dynamics API

243 lines 32 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ClientHelpers = exports.ClientOptions = exports.BASE_URL = exports.Client = void 0; /** * Client is a convenience class for interacting with the Rent Dynamics services. * * Note if this class does not suit your needs, it may be wise to roll your own implementation using * the {@linkcode ClientHelpers} class. */ class Client { constructor(options) { this.helpers = new ClientHelpers(options); } /** * get wraps a request library to work with the Rent Dynamics API. * @param endpoint the path following the baseUrl. * @example get('/foo'); */ async get(endpoint) { const fullUrl = this.helpers.baseUrl + endpoint; const headers = await this.helpers.getHeaders(endpoint, undefined, this.authToken); return fetch(fullUrl.replace(/\|/g, '%7C'), { method: 'GET', headers: Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json' }) }); } /** * put wraps a request library to work with the Rent Dynamics API. * @param endpoint the path following the baseUrl. * @param payload a JSON serializable object. * @example put('/foo', { bar: 1 }); */ async put(endpoint, payload) { const fullUrl = this.helpers.baseUrl + endpoint; const headers = await this.helpers.getHeaders(endpoint, payload, this.authToken); return fetch(fullUrl, { method: 'PUT', headers: Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json' }), body: JSON.stringify(payload) }); } /** * post wraps a request library to work with the Rent Dynamics API. * @param endpoint the path following the baseUrl. * @param payload a JSON serializable object. * @example post('/foo', { bar: 1 }); */ async post(endpoint, payload) { const fullUrl = this.helpers.baseUrl + endpoint; const headers = await this.helpers.getHeaders(endpoint, payload, this.authToken); return fetch(fullUrl, { method: 'POST', headers: Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json' }), body: JSON.stringify(payload) }); } /** * delete wraps a request library to work with the Rent Dynamics API. * @param endpoint the path following the baseUrl. * @example delete('/foo/1'); */ async delete(endpoint) { const fullUrl = this.helpers.baseUrl + endpoint; const headers = await this.helpers.getHeaders(endpoint, undefined, this.authToken); return fetch(fullUrl, { method: 'DELETE', headers: Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json' }) }); } /** * login enables an instance of {@linkcode Client} to make authenticated requests to the Rent * Dynamics API. */ async login(username, password) { const _password = await this.helpers.encryptPassword(password); const endpoint = '/auth/login'; const result = await this.post(endpoint, { username, password: _password }); if (!result.ok) { return result; } const { token } = await result.json(); this.authToken = token; return result; } /** logout invalidates the users session generated by {@linkcode login}. */ async logout() { const endpoint = '/auth/logout'; const result = await this.post(endpoint, { authToken: this.authToken }); if (!result.ok) { return result; } this.authToken = undefined; return result; } } exports.Client = Client; /** BASE_URL is a collection of base urls for each dev/prod Rent Dynamics service. */ var BASE_URL; (function (BASE_URL) { BASE_URL["DEV_RD"] = "https://api.rentdynamics.dev"; BASE_URL["PROD_RD"] = "https://api.rentdynamics.com"; BASE_URL["DEV_RP"] = "https://api-dev.rentplus.com"; BASE_URL["PROD_RP"] = "https://api.rentplus.com"; })(BASE_URL = exports.BASE_URL || (exports.BASE_URL = {})); /** ClientOptions is consumed and updated by {@linkcode ClientHelpers}. */ class ClientOptions { constructor() { /** * baseUrl is the base request url. The default is the development rentdynamics api. A custom * string may be provided beyond the {@linkcode BASE_URL} options. */ this.baseUrl = BASE_URL.DEV_RD; /** * getEncoder is used to encode text. The encoder can be overridden as needed. For example in a * node environment. * @example * const options = new ClientOptions(); * options.getEncoder = async () => new (await import('util')).TextEncoder(); */ this.getEncoder = async () => new TextEncoder(); /** * getCryptographer is used for cryptography. The cryptographer can be overridden as needed. For * example in a node environment. * @example * const options = new ClientOptions(); * options.getCryptographer = async () => (await import('crypto')).subtle; */ this.getCryptographer = async () => crypto.subtle; } } exports.ClientOptions = ClientOptions; /** * ClientHelpers is a collection of utilities consumed by {@linkcode Client}. ClientHelpers can be * used to calculate headers in case a consumer wants to build their own API client. */ class ClientHelpers { constructor(options) { this.options = options; } /** * baseUrl is the base url used throughout the {@linkcode ClientHelpers} instance. It is initially * configured through {@linkcode ClientOptions}. */ get baseUrl() { return this.options.baseUrl; } /** * getTimestamp is used to calculate the timestamp header. This method is not likely to be called * on it's own. Instead, it is typically used to mock the current time. */ getTimestamp() { return Date.now(); } /** * getHeaders creates headers for the given params. If an auth token is included, this method will * generate an `Authorization` header. */ async getHeaders(endpoint, payload, authToken) { const headers = {}; if (this.options.apiKey && this.options.apiSecretKey) { if (!payload || !Object.keys(payload).length) { payload = undefined; } if (typeof payload !== 'undefined') { payload = JSON.stringify(this.formatPayload(payload)); } const timestamp = this.getTimestamp(); const nonce = await this.getNonce(timestamp, endpoint, payload); if (authToken) { headers.Authorization = 'TOKEN ' + authToken; } headers['x-rd-api-key'] = this.options.apiKey; headers['x-rd-api-nonce'] = nonce; headers['x-rd-timestamp'] = timestamp.toString(); return headers; } return headers; } /** formatPayload formats the payload for nonce calculation. */ formatPayload(payload) { let formattedPayload = {}; if (payload === undefined || payload === null) { formattedPayload = null; } else if (payload !== Object(payload)) { formattedPayload = payload; } else if (Array.isArray(payload)) { formattedPayload = []; payload.forEach((_, index) => { formattedPayload[index] = this.formatPayload(payload[index]); }); } else { Object.keys(payload) .sort() .forEach(k => { if (typeof payload[k] === 'object') { formattedPayload[k] = this.formatPayload(payload[k]); } else if (typeof payload[k] === 'string') { formattedPayload[k] = payload[k].replace(/ /g, ''); } else { formattedPayload[k] = payload[k]; } }); } return formattedPayload; } /** getNonce calculates the nonce for the given params. */ async getNonce(timestamp, url, payloadStr) { if (!this.options.apiSecretKey) return Promise.resolve(''); const encodedUrl = encodeURI(url) .replace(/%7[Cc]/g, '|') .replace(/%20/g, ' '); const nonceStr = typeof payloadStr !== 'undefined' ? timestamp + encodedUrl + payloadStr : timestamp + encodedUrl; const cryptographer = await this.options.getCryptographer(); const encoder = await this.options.getEncoder(); const key = encoder.encode(this.options.apiSecretKey); const data = encoder.encode(nonceStr); const algorithm = { name: 'HMAC', hash: 'SHA-1' }; const hmac = await cryptographer.importKey('raw', key, algorithm, false, ['sign']); const signed = await cryptographer.sign(algorithm.name, hmac, data); return _hexDigest(signed); } /** encryptPassword encrypts the password for login. */ async encryptPassword(password) { const cryptographer = await this.options.getCryptographer(); const encoder = await this.options.getEncoder(); const encodedPassword = encoder.encode(password); const digestedPassword = await cryptographer.digest('SHA-1', encodedPassword); return _hexDigest(digestedPassword); } } exports.ClientHelpers = ClientHelpers; const _hexDigest = (buf) => Array.from(new Uint8Array(buf)) .map(b => b.toString(16).padStart(2, '0')) .join(''); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9saWIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBSUE7Ozs7O0dBS0c7QUFDSCxNQUFhLE1BQU07SUFRakIsWUFBWSxPQUFzQjtRQUNoQyxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksS0FBSyxDQUFDLEdBQUcsQ0FBQyxRQUFnQjtRQUMvQixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sR0FBRyxRQUFRLENBQUM7UUFDaEQsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNuRixPQUFPLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsRUFBRTtZQUMxQyxNQUFNLEVBQUUsS0FBSztZQUNiLE9BQU8sa0NBQ0YsT0FBTyxLQUNWLGNBQWMsRUFBRSxrQkFBa0IsR0FDbkM7U0FDRixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxLQUFLLENBQUMsR0FBRyxDQUFDLFFBQWdCLEVBQUUsT0FBZ0I7UUFDakQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEdBQUcsUUFBUSxDQUFDO1FBQ2hELE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDakYsT0FBTyxLQUFLLENBQUMsT0FBTyxFQUFFO1lBQ3BCLE1BQU0sRUFBRSxLQUFLO1lBQ2IsT0FBTyxrQ0FDRixPQUFPLEtBQ1YsY0FBYyxFQUFFLGtCQUFrQixH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LENBQUMsSUFBSSxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUM7S0FDNUIsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0tBQ3pDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBQYXlsb2FkIGlzIGtub3duIGFzIHRoZSBcImJvZHlcIiBvZiBhIFJlcXVlc3QuIFRoZSBwYXlsb2FkIG11c3QgYmUgSlNPTiBzZXJpYWxpemFibGUuICovXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxudHlwZSBQYXlsb2FkID0gYW55O1xuXG4vKipcbiAqIENsaWVudCBpcyBhIGNvbnZlbmllbmNlIGNsYXNzIGZvciBpbnRlcmFjdGluZyB3aXRoIHRoZSBSZW50IER5bmFtaWNzIHNlcnZpY2VzLlxuICpcbiAqIE5vdGUgaWYgdGhpcyBjbGFzcyBkb2VzIG5vdCBzdWl0IHlvdXIgbmVlZHMsIGl0IG1heSBiZSB3aXNlIHRvIHJvbGwgeW91ciBvd24gaW1wbGVtZW50YXRpb24gdXNpbmdcbiAqIHRoZSB7QGxpbmtjb2RlIENsaWVudEhlbHBlcnN9IGNsYXNzLlxuICovXG5leHBvcnQgY2xhc3MgQ2xpZW50IHtcbiAgLyoqXG4gICAqIGF1dGhUb2tlbiBpZiBkZWZpbmVkLCBhdXRoVG9rZW4gaXMgdXNlZCB0byBtYWtlIGF1dGhlbnRpY2F0ZWQgcmVxdWVzdHMuIE5vdGUgYXV0aFRva2VuIGlzIG5vdFxuICAgKiB0eXBpY2FsbHkgZ2V0L3NldCBtYW51YWxseSwgYnV0IGluc3RlYWQgaXMgbWFuYWdlZCB0aHJvdWdoIHRoZSBsb2dpbi9sb2dvdXQgbWV0aG9kcy5cbiAgICovXG4gIHB1YmxpYyBhdXRoVG9rZW46IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSByZWFkb25seSBoZWxwZXJzOiBDbGllbnRIZWxwZXJzO1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IENsaWVudE9wdGlvbnMpIHtcbiAgICB0aGlzLmhlbHBlcnMgPSBuZXcgQ2xpZW50SGVscGVycyhvcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBnZXQgd3JhcHMgYSByZXF1ZXN0IGxpYnJhcnkgdG8gd29yayB3aXRoIHRoZSBSZW50IER5bmFtaWNzIEFQSS5cbiAgICogQHBhcmFtIGVuZHBvaW50IHRoZSBwYXRoIGZvbGxvd2luZyB0aGUgYmFzZVVybC5cbiAgICogQGV4YW1wbGUgZ2V0KCcvZm9vJyk7XG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZ2V0KGVuZHBvaW50OiBzdHJpbmcpIHtcbiAgICBjb25zdCBmdWxsVXJsID0gdGhpcy5oZWxwZXJzLmJhc2VVcmwgKyBlbmRwb2ludDtcbiAgICBjb25zdCBoZWFkZXJzID0gYXdhaXQgdGhpcy5oZWxwZXJzLmdldEhlYWRlcnMoZW5kcG9pbnQsIHVuZGVmaW5lZCwgdGhpcy5hdXRoVG9rZW4pO1xuICAgIHJldHVybiBmZXRjaChmdWxsVXJsLnJlcGxhY2UoL1xcfC9nLCAnJTdDJyksIHtcbiAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIC4uLmhlYWRlcnMsXG4gICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbidcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBwdXQgd3JhcHMgYSByZXF1ZXN0IGxpYnJhcnkgdG8gd29yayB3aXRoIHRoZSBSZW50IER5bmFtaWNzIEFQSS5cbiAgICogQHBhcmFtIGVuZHBvaW50IHRoZSBwYXRoIGZvbGxvd2luZyB0aGUgYmFzZVVybC5cbiAgICogQHBhcmFtIHBheWxvYWQgYSBKU09OIHNlcmlhbGl6YWJsZSBvYmplY3QuXG4gICAqIEBleGFtcGxlIHB1dCgnL2ZvbycsIHsgYmFyOiAxIH0pO1xuICAgKi9cbiAgcHVibGljIGFzeW5jIHB1dChlbmRwb2ludDogc3RyaW5nLCBwYXlsb2FkOiBQYXlsb2FkKSB7XG4gICAgY29uc3QgZnVsbFVybCA9IHRoaXMuaGVscGVycy5iYXNlVXJsICsgZW5kcG9pbnQ7XG4gICAgY29uc3QgaGVhZGVycyA9IGF3YWl0IHRoaXMuaGVscGVycy5nZXRIZWFkZXJzKGVuZHBvaW50LCBwYXlsb2FkLCB0aGlzLmF1dGhUb2tlbik7XG4gICAgcmV0dXJuIGZldGNoKGZ1bGxVcmwsIHtcbiAgICAgIG1ldGhvZDogJ1BVVCcsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIC4uLmhlYWRlcnMsXG4gICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbidcbiAgICAgIH0sXG4gICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShwYXlsb2FkKVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIHBvc3Qgd3JhcHMgYSByZXF1ZXN0IGxpYnJhcnkgdG8gd29yayB3aXRoIHRoZSBSZW50IER5bmFtaWNzIEFQSS5cbiAgICogQHBhcmFtIGVuZHBvaW50IHRoZSBwYXRoIGZvbGxvd2luZyB0aGUgYmFzZVVybC5cbiAgICogQHBhcmFtIHBheWxvYWQgYSBKU09OIHNlcmlhbGl6YWJsZSBvYmplY3QuXG4gICAqIEBleGFtcGxlIHBvc3QoJy9mb28nLCB7IGJhcjogMSB9KTtcbiAgICovXG4gIHB1YmxpYyBhc3luYyBwb3N0KGVuZHBvaW50OiBzdHJpbmcsIHBheWxvYWQ6IFBheWxvYWQpIHtcbiAgICBjb25zdCBmdWxsVXJsID0gdGhpcy5oZWxwZXJzLmJhc2VVcmwgKyBlbmRwb2ludDtcbiAgICBjb25zdCBoZWFkZXJzID0gYXdhaXQgdGhpcy5oZWxwZXJzLmdldEhlYWRlcnMoZW5kcG9pbnQsIHBheWxvYWQsIHRoaXMuYXV0aFRva2VuKTtcbiAgICByZXR1cm4gZmV0Y2goZnVsbFVybCwge1xuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIC4uLmhlYWRlcnMsXG4gICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbidcbiAgICAgIH0sXG4gICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShwYXlsb2FkKVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIGRlbGV0ZSB3cmFwcyBhIHJlcXVlc3QgbGlicmFyeSB0byB3b3JrIHdpdGggdGhlIFJlbnQgRHluYW1pY3MgQVBJLlxuICAgKiBAcGFyYW0gZW5kcG9pbnQgdGhlIHBhdGggZm9sbG93aW5nIHRoZSBiYXNlVXJsLlxuICAgKiBAZXhhbXBsZSBkZWxldGUoJy9mb28vMScpO1xuICAgKi9cbiAgcHVibGljIGFzeW5jIGRlbGV0ZShlbmRwb2ludDogc3RyaW5nKSB7XG4gICAgY29uc3QgZnVsbFVybCA9IHRoaXMuaGVscGVycy5iYXNlVXJsICsgZW5kcG9pbnQ7XG4gICAgY29uc3QgaGVhZGVycyA9IGF3YWl0IHRoaXMuaGVscGVycy5nZXRIZWFkZXJzKGVuZHBvaW50LCB1bmRlZmluZWQsIHRoaXMuYXV0aFRva2VuKTtcbiAgICByZXR1cm4gZmV0Y2goZnVsbFVybCwge1xuICAgICAgbWV0aG9kOiAnREVMRVRFJyxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgLi4uaGVhZGVycyxcbiAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJ1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIGxvZ2luIGVuYWJsZXMgYW4gaW5zdGFuY2Ugb2Yge0BsaW5rY29kZSBDbGllbnR9IHRvIG1ha2UgYXV0aGVudGljYXRlZCByZXF1ZXN0cyB0byB0aGUgUmVudFxuICAgKiBEeW5hbWljcyBBUEkuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgbG9naW4odXNlcm5hbWU6IHN0cmluZywgcGFzc3dvcmQ6IHN0cmluZykge1xuICAgIGNvbnN0IF9wYXNzd29yZCA9IGF3YWl0IHRoaXMuaGVscGVycy5lbmNyeXB0UGFzc3dvcmQocGFzc3dvcmQpO1xuICAgIGNvbnN0IGVuZHBvaW50ID0gJy9hdXRoL2xvZ2luJztcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnBvc3QoZW5kcG9pbnQsIHsgdXNlcm5hbWUsIHBhc3N3b3JkOiBfcGFzc3dvcmQgfSk7XG4gICAgaWYgKCFyZXN1bHQub2spIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICAgIGNvbnN0IHsgdG9rZW4gfSA9IGF3YWl0IHJlc3VsdC5qc29uKCk7XG4gICAgdGhpcy5hdXRoVG9rZW4gPSB0b2tlbjtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqIGxvZ291dCBpbnZhbGlkYXRlcyB0aGUgdXNlcnMgc2Vzc2lvbiBnZW5lcmF0ZWQgYnkge0BsaW5rY29kZSBsb2dpbn0uICovXG4gIHB1YmxpYyBhc3luYyBsb2dvdXQoKSB7XG4gICAgY29uc3QgZW5kcG9pbnQgPSAnL2F1dGgvbG9nb3V0JztcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnBvc3QoZW5kcG9pbnQsIHsgYXV0aFRva2VuOiB0aGlzLmF1dGhUb2tlbiB9KTtcbiAgICBpZiAoIXJlc3VsdC5vaykge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gICAgdGhpcy5hdXRoVG9rZW4gPSB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuXG4vKiogQkFTRV9VUkwgaXMgYSBjb2xsZWN0aW9uIG9mIGJhc2UgdXJscyBmb3IgZWFjaCBkZXYvcHJvZCBSZW50IER5bmFtaWNzIHNlcnZpY2UuICovXG5leHBvcnQgZW51bSBCQVNFX1VSTCB7XG4gIERFVl9SRCA9ICdodHRwczovL2FwaS5yZW50ZHluYW1pY3MuZGV2JyxcbiAgUFJPRF9SRCA9ICdodHRwczovL2FwaS5yZW50ZHluYW1pY3MuY29tJyxcbiAgREVWX1JQID0gJ2h0dHBzOi8vYXBpLWRldi5yZW50cGx1cy5jb20nLFxuICBQUk9EX1JQID0gJ2h0dHBzOi8vYXBpLnJlbnRwbHVzLmNvbSdcbn1cblxuZXhwb3J0IHR5cGUgUmRFbmNvZGVyID0gUGljazxUZXh0RW5jb2RlciwgJ2VuY29kZSc+O1xuXG5leHBvcnQgdHlwZSBSZENyeXB0b2dyYXBoZXIgPSBQaWNrPFN1YnRsZUNyeXB0bywgJ2ltcG9ydEtleSc+ICZcbiAgUGljazxTdWJ0bGVDcnlwdG8sICdzaWduJz4gJlxuICBQaWNrPFN1YnRsZUNyeXB0bywgJ2RpZ2VzdCc+O1xuXG4vKiogQ2xpZW50T3B0aW9ucyBpcyBjb25zdW1lZCBhbmQgdXBkYXRlZCBieSB7QGxpbmtjb2RlIENsaWVudEhlbHBlcnN9LiAqL1xuZXhwb3J0IGNsYXNzIENsaWVudE9wdGlvbnMge1xuICAvKiogYXBpS2V5IGlmIGRlZmluZWQgYXBpS2V5IGlzIHVzZWQgdG8gY2FsY3VsYXRlIGF1dGggaGVhZGVycy4gKi9cbiAgcHVibGljIGFwaUtleTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAvKiogYXBpU2VjcmV0S2V5IGlmIGRlZmluZWQgYXBpU2VjcmV0S2V5IGlzIHVzZWQgdG8gY2FsY3VsYXRlIGF1dGggaGVhZGVycy4gICovXG4gIHB1YmxpYyBhcGlTZWNyZXRLZXk6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIGJhc2VVcmwgaXMgdGhlIGJhc2UgcmVxdWVzdCB1cmwuIFRoZSBkZWZhdWx0IGlzIHRoZSBkZXZlbG9wbWVudCByZW50ZHluYW1pY3MgYXBpLiBBIGN1c3RvbVxuICAgKiBzdHJpbmcgbWF5IGJlIHByb3ZpZGVkIGJleW9uZCB0aGUge0BsaW5rY29kZSBCQVNFX1VSTH0gb3B0aW9ucy5cbiAgICovXG4gIHB1YmxpYyBiYXNlVXJsOiBCQVNFX1VSTCB8IHN0cmluZyA9IEJBU0VfVVJMLkRFVl9SRDtcblxuICAvKipcbiAgICogZ2V0RW5jb2RlciBpcyB1c2VkIHRvIGVuY29kZSB0ZXh0LiBUaGUgZW5jb2RlciBjYW4gYmUgb3ZlcnJpZGRlbiBhcyBuZWVkZWQuIEZvciBleGFtcGxlIGluIGFcbiAgICogbm9kZSBlbnZpcm9ubWVudC5cbiAgICogQGV4YW1wbGVcbiAgICogY29uc3Qgb3B0aW9ucyA9IG5ldyBDbGllbnRPcHRpb25zKCk7XG4gICAqIG9wdGlvbnMuZ2V0RW5jb2RlciA9IGFzeW5jICgpID0+IG5ldyAoYXdhaXQgaW1wb3J0KCd1dGlsJykpLlRleHRFbmNvZGVyKCk7XG4gICAqL1xuICBwdWJsaWMgZ2V0RW5jb2RlciA9IGFzeW5jICgpOiBQcm9taXNlPFJkRW5jb2Rlcj4gPT4gbmV3IFRleHRFbmNvZGVyKCk7XG5cbiAgLyoqXG4gICAqIGdldENyeXB0b2dyYXBoZXIgaXMgdXNlZCBmb3IgY3J5cHRvZ3JhcGh5LiBUaGUgY3J5cHRvZ3JhcGhlciBjYW4gYmUgb3ZlcnJpZGRlbiBhcyBuZWVkZWQuIEZvclxuICAgKiBleGFtcGxlIGluIGEgbm9kZSBlbnZpcm9ubWVudC5cbiAgICogQGV4YW1wbGVcbiAgICogY29uc3Qgb3B0aW9ucyA9IG5ldyBDbGllbnRPcHRpb25zKCk7XG4gICAqIG9wdGlvbnMuZ2V0Q3J5cHRvZ3JhcGhlciA9IGFzeW5jICgpID0+IChhd2FpdCBpbXBvcnQoJ2NyeXB0bycpKS5zdWJ0bGU7XG4gICAqL1xuICBwdWJsaWMgZ2V0Q3J5cHRvZ3JhcGhlciA9IGFzeW5jICgpOiBQcm9taXNlPFJkQ3J5cHRvZ3JhcGhlcj4gPT4gY3J5cHRvLnN1YnRsZTtcbn1cblxuLyoqXG4gKiBDbGllbnRIZWxwZXJzIGlzIGEgY29sbGVjdGlvbiBvZiB1dGlsaXRpZXMgY29uc3VtZWQgYnkge0BsaW5rY29kZSBDbGllbnR9LiBDbGllbnRIZWxwZXJzIGNhbiBiZVxuICogdXNlZCB0byBjYWxjdWxhdGUgaGVhZGVycyBpbiBjYXNlIGEgY29uc3VtZXIgd2FudHMgdG8gYnVpbGQgdGhlaXIgb3duIEFQSSBjbGllbnQuXG4gKi9cbmV4cG9ydCBjbGFzcyBDbGllbnRIZWxwZXJzIHtcbiAgcHJpdmF0ZSBvcHRpb25zOiBDbGllbnRPcHRpb25zO1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IENsaWVudE9wdGlvbnMpIHtcbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICB9XG5cbiAgLyoqXG4gICAqIGJhc2VVcmwgaXMgdGhlIGJhc2UgdXJsIHVzZWQgdGhyb3VnaG91dCB0aGUge0BsaW5rY29kZSBDbGllbnRIZWxwZXJzfSBpbnN0YW5jZS4gSXQgaXMgaW5pdGlhbGx5XG4gICAqIGNvbmZpZ3VyZWQgdGhyb3VnaCB7QGxpbmtjb2RlIENsaWVudE9wdGlvbnN9LlxuICAgKi9cbiAgZ2V0IGJhc2VVcmwoKSB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5iYXNlVXJsO1xuICB9XG5cbiAgLyoqXG4gICAqIGdldFRpbWVzdGFtcCBpcyB1c2VkIHRvIGNhbGN1bGF0ZSB0aGUgdGltZXN0YW1wIGhlYWRlci4gVGhpcyBtZXRob2QgaXMgbm90IGxpa2VseSB0byBiZSBjYWxsZWRcbiAgICogb24gaXQncyBvd24uIEluc3RlYWQsIGl0IGlzIHR5cGljYWxseSB1c2VkIHRvIG1vY2sgdGhlIGN1cnJlbnQgdGltZS5cbiAgICovXG4gIHB1YmxpYyBnZXRUaW1lc3RhbXAoKSB7XG4gICAgcmV0dXJuIERhdGUubm93KCk7XG4gIH1cblxuICAvKipcbiAgICogZ2V0SGVhZGVycyBjcmVhdGVzIGhlYWRlcnMgZm9yIHRoZSBnaXZlbiBwYXJhbXMuIElmIGFuIGF1dGggdG9rZW4gaXMgaW5jbHVkZWQsIHRoaXMgbWV0aG9kIHdpbGxcbiAgICogZ2VuZXJhdGUgYW4gYEF1dGhvcml6YXRpb25gIGhlYWRlci5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBnZXRIZWFkZXJzKFxuICAgIGVuZHBvaW50OiBzdHJpbmcsXG4gICAgcGF5bG9hZD86IFBheWxvYWQgfCB1bmRlZmluZWQsXG4gICAgYXV0aFRva2VuPzogc3RyaW5nIHwgdW5kZWZpbmVkXG4gICkge1xuICAgIGNvbnN0IGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICBpZiAodGhpcy5vcHRpb25zLmFwaUtleSAmJiB0aGlzLm9wdGlvbnMuYXBpU2VjcmV0S2V5KSB7XG4gICAgICBpZiAoIXBheWxvYWQgfHwgIU9iamVjdC5rZXlzKHBheWxvYWQpLmxlbmd0aCkge1xuICAgICAgICBwYXlsb2FkID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiBwYXlsb2FkICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBwYXlsb2FkID0gSlNPTi5zdHJpbmdpZnkodGhpcy5mb3JtYXRQYXlsb2FkKHBheWxvYWQpKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHRpbWVzdGFtcCA9IHRoaXMuZ2V0VGltZXN0YW1wKCk7XG4gICAgICBjb25zdCBub25jZSA9IGF3YWl0IHRoaXMuZ2V0Tm9uY2UodGltZXN0YW1wLCBlbmRwb2ludCwgcGF5bG9hZCk7XG4gICAgICBpZiAoYXV0aFRva2VuKSB7XG4gICAgICAgIGhlYWRlcnMuQXV0aG9yaXphdGlvbiA9ICdUT0tFTiAnICsgYXV0aFRva2VuO1xuICAgICAgfVxuICAgICAgaGVhZGVyc1sneC1yZC1hcGkta2V5J10gPSB0aGlzLm9wdGlvbnMuYXBpS2V5O1xuICAgICAgaGVhZGVyc1sneC1yZC1hcGktbm9uY2UnXSA9IG5vbmNlO1xuICAgICAgaGVhZGVyc1sneC1yZC10aW1lc3RhbXAnXSA9IHRpbWVzdGFtcC50b1N0cmluZygpO1xuICAgICAgcmV0dXJuIGhlYWRlcnM7XG4gICAgfVxuICAgIHJldHVybiBoZWFkZXJzO1xuICB9XG5cbiAgLyoqIGZvcm1hdFBheWxvYWQgZm9ybWF0cyB0aGUgcGF5bG9hZCBmb3Igbm9uY2UgY2FsY3VsYXRpb24uICovXG4gIHB1YmxpYyBmb3JtYXRQYXlsb2FkKHBheWxvYWQ6IFBheWxvYWQpOiBQYXlsb2FkIHtcbiAgICBsZXQgZm9ybWF0dGVkUGF5bG9hZDogUGF5bG9hZCA9IHt9O1xuICAgIGlmIChwYXlsb2FkID09PSB1bmRlZmluZWQgfHwgcGF5bG9hZCA9PT0gbnVsbCkge1xuICAgICAgZm9ybWF0dGVkUGF5bG9hZCA9IG51bGw7XG4gICAgfSBlbHNlIGlmIChwYXlsb2FkICE9PSBPYmplY3QocGF5bG9hZCkpIHtcbiAgICAgIGZvcm1hdHRlZFBheWxvYWQgPSBwYXlsb2FkO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShwYXlsb2FkKSkge1xuICAgICAgZm9ybWF0dGVkUGF5bG9hZCA9IFtdO1xuICAgICAgcGF5bG9hZC5mb3JFYWNoKChfLCBpbmRleCkgPT4ge1xuICAgICAgICBmb3JtYXR0ZWRQYXlsb2FkW2luZGV4XSA9IHRoaXMuZm9ybWF0UGF5bG9hZChwYXlsb2FkW2luZGV4XSk7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgT2JqZWN0LmtleXMocGF5bG9hZClcbiAgICAgICAgLnNvcnQoKVxuICAgICAgICAuZm9yRWFjaChrID0+IHtcbiAgICAgICAgICBpZiAodHlwZW9mIHBheWxvYWRba10gPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBmb3JtYXR0ZWRQYXlsb2FkW2tdID0gdGhpcy5mb3JtYXRQYXlsb2FkKHBheWxvYWRba10pO1xuICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHBheWxvYWRba10gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBmb3JtYXR0ZWRQYXlsb2FkW2tdID0gcGF5bG9hZFtrXS5yZXBsYWNlKC8gL2csICcnKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZm9ybWF0dGVkUGF5bG9hZFtrXSA9IHBheWxvYWRba107XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGZvcm1hdHRlZFBheWxvYWQ7XG4gIH1cblxuICAvKiogZ2V0Tm9uY2UgY2FsY3VsYXRlcyB0aGUgbm9uY2UgZm9yIHRoZSBnaXZlbiBwYXJhbXMuICovXG4gIHB1YmxpYyBhc3luYyBnZXROb25jZSh0aW1lc3RhbXA6IG51bWJlciwgdXJsOiBzdHJpbmcsIHBheWxvYWRTdHI/OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGlmICghdGhpcy5vcHRpb25zLmFwaVNlY3JldEtleSkgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgnJyk7XG4gICAgY29uc3QgZW5jb2RlZFVybCA9IGVuY29kZVVSSSh1cmwpXG4gICAgICAucmVwbGFjZSgvJTdbQ2NdL2csICd8JylcbiAgICAgIC5yZXBsYWNlKC8lMjAvZywgJyAnKTtcbiAgICBjb25zdCBub25jZVN0ciA9XG4gICAgICB0eXBlb2YgcGF5bG9hZFN0ciAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAgPyB0aW1lc3RhbXAgKyBlbmNvZGVkVXJsICsgcGF5bG9hZFN0clxuICAgICAgICA6IHRpbWVzdGFtcCArIGVuY29kZWRVcmw7XG4gICAgY29uc3QgY3J5cHRvZ3JhcGhlciA9IGF3YWl0IHRoaXMub3B0aW9ucy5nZXRDcnlwdG9ncmFwaGVyKCk7XG4gICAgY29uc3QgZW5jb2RlciA9IGF3YWl0IHRoaXMub3B0aW9ucy5nZXRFbmNvZGVyKCk7XG4gICAgY29uc3Qga2V5ID0gZW5jb2Rlci5lbmNvZGUodGhpcy5vcHRpb25zLmFwaVNlY3JldEtleSk7XG4gICAgY29uc3QgZGF0YSA9IGVuY29kZXIuZW5jb2RlKG5vbmNlU3RyKTtcbiAgICBjb25zdCBhbGdvcml0aG0gPSB7IG5hbWU6ICdITUFDJywgaGFzaDogJ1NIQS0xJyB9O1xuICAgIGNvbnN0IGhtYWMgPSBhd2FpdCBjcnlwdG9ncmFwaGVyLmltcG9ydEtleSgncmF3Jywga2V5LCBhbGdvcml0aG0sIGZhbHNlLCBbJ3NpZ24nXSk7XG4gICAgY29uc3Qgc2lnbmVkID0gYXdhaXQgY3J5cHRvZ3JhcGhlci5zaWduKGFsZ29yaXRobS5uYW1lLCBobWFjLCBkYXRhKTtcbiAgICByZXR1cm4gX2hleERpZ2VzdChzaWduZWQpO1xuICB9XG5cbiAgLyoqIGVuY3J5cHRQYXNzd29yZCBlbmNyeXB0cyB0aGUgcGFzc3dvcmQgZm9yIGxvZ2luLiAqL1xuICBwdWJsaWMgYXN5bmMgZW5jcnlwdFBhc3N3b3JkKHBhc3N3b3JkOiBzdHJpbmcpIHtcbiAgICBjb25zdCBjcnlwdG9ncmFwaGVyID0gYXdhaXQgdGhpcy5vcHRpb25zLmdldENyeXB0b2dyYXBoZXIoKTtcbiAgICBjb25zdCBlbmNvZGVyID0gYXdhaXQgdGhpcy5vcHRpb25zLmdldEVuY29kZXIoKTtcbiAgICBjb25zdCBlbmNvZGVkUGFzc3dvcmQgPSBlbmNvZGVyLmVuY29kZShwYXNzd29yZCk7XG4gICAgY29uc3QgZGlnZXN0ZWRQYXNzd29yZCA9IGF3YWl0IGNyeXB0b2dyYXBoZXIuZGlnZXN0KCdTSEEtMScsIGVuY29kZWRQYXNzd29yZCk7XG4gICAgcmV0dXJuIF9oZXhEaWdlc3QoZGlnZXN0ZWRQYXNzd29yZCk7XG4gIH1cbn1cblxuY29uc3QgX2hleERpZ2VzdCA9IChidWY6IEFycmF5QnVmZmVyKTogc3RyaW5nID0+XG4gIEFycmF5LmZyb20obmV3IFVpbnQ4QXJyYXkoYnVmKSlcbiAgICAubWFwKGIgPT4gYi50b1N0cmluZygxNikucGFkU3RhcnQoMiwgJzAnKSlcbiAgICAuam9pbignJyk7XG4iXX0=