UNPKG

tedious

Version:

A TDS driver, for connecting to MS SQLServer databases.

192 lines (185 loc) • 24.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BulkLoadPayload = void 0; var _writableTrackingBuffer = _interopRequireDefault(require("./tracking-buffer/writable-tracking-buffer")); var _token = require("./token/token"); var _errors = require("./errors"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const rowTokenBuffer = Buffer.from([_token.TYPE.ROW]); const textPointerAndTimestampBuffer = Buffer.from([ // TextPointer length 0x10, // TextPointer 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); const textPointerNullBuffer = Buffer.from([0x00]); function isPromiseLike(value) { return value != null && typeof value.then === 'function'; } function ignoreError() {} /** * The TDS byte stream of a bulk load: COLMETADATA, a ROW token per row, * and a DONE token at the end, serialized from the bulk load's row source. * * The payload owns the row source's iterator the way a `for await` loop * would: it requests the first row as soon as it is created, so that a * stream source is observed from the moment it is handed over, and it * closes the source through the iterator's `return()` whenever the bulk * load does not run to completion, whether the rows were being read * ([[Symbol.asyncIterator]]) or never got to be ([[close]]). * * Rows are written into one buffer that lives for the whole bulk load. * Its contents are yielded once it holds a chunk's worth * (`WritableTrackingBuffer.CHUNK_SIZE`), checked after every cell, and at * the end. Rows from a synchronous source are serialized without an * event-loop turn in between; rows from an asynchronous source are awaited * one at a time. * * @private */ class BulkLoadPayload { constructor(bulkLoad, rows) { this.bulkLoad = bulkLoad; this.iterator = typeof rows[Symbol.asyncIterator] === 'function' ? rows[Symbol.asyncIterator]() : rows[Symbol.iterator](); // The first row is requested now, before the `INSERT BULK` statement // has gone out. For a stream source this is what attaches its // iterator's listeners: an error it emits while the statement is in // flight is kept and reported on the next read, instead of being an // unhandled `'error'` event. The read is awaited when the rows are // serialized; its rejection is not unhandled until then, and neither // is a synchronous source's throw, which reaches the bulk load's // callback the same way. let first; try { first = this.iterator.next(); } catch (err) { first = Promise.reject(err); } if (isPromiseLike(first)) { const read = Promise.resolve(first); read.then(undefined, ignoreError); this.pending = read; } else { this.pending = first; } } /** * Closes the row source of a bulk load whose rows will not be read: * the `INSERT BULK` statement was rejected, the bulk load was canceled, * or the connection is no longer logged in. Best effort: a read still * pending in the source cannot be interrupted, and a close that fails * has nothing left to report to. */ close() { const iterator = this.iterator; if (typeof iterator.return !== 'function') { return; } try { const closing = iterator.return(); if (isPromiseLike(closing)) { Promise.resolve(closing).then(undefined, ignoreError); } } catch { // Nothing left to report to. } } async *[Symbol.asyncIterator]() { const bulkLoad = this.bulkLoad; const options = bulkLoad.options; const columns = bulkLoad.columns; const iterator = this.iterator; // Per column, not per cell: a text type's value is written behind a // text pointer and timestamp, or as a null pointer. const isTextType = columns.map(c => c.type.name === 'Text' || c.type.name === 'Image' || c.type.name === 'NText'); const buffer = new _writableTrackingBuffer.default(); let done = false; let closed = false; try { buffer.writeBuffer(bulkLoad.getColMetaData()); while (true) { let result = this.pending ?? iterator.next(); this.pending = undefined; if (isPromiseLike(result)) { result = await result; } if (result.done) { done = true; break; } // A row given as a promise is settled first, as `Readable.from` // settled it before handing it on. let row = result.value; if (isPromiseLike(row)) { row = await row; } buffer.writeBuffer(rowTokenBuffer); const isArray = Array.isArray(row); for (let i = 0; i < columns.length; i++) { const c = columns[i]; const value = c.type.validate(isArray ? row[i] : row[c.objName], c.collation); const parameter = { length: c.length, scale: c.scale, precision: c.precision, value: value }; if (isTextType[i] && value == null) { buffer.writeBuffer(textPointerNullBuffer); } else { if (isTextType[i]) { buffer.writeBuffer(textPointerAndTimestampBuffer); } try { c.type.writeValue(buffer, parameter, options); } catch (error) { throw new _errors.InputError(`Column '${c.name}' could not be serialized`, { cause: error }); } } // Checked after every cell, not only after every row, so that a // wide row of large cells goes downstream as it is serialized. if (buffer.length >= _writableTrackingBuffer.default.CHUNK_SIZE) { for (const chunk of buffer.getBuffers()) { yield chunk; } buffer.consume(buffer.length); } } } } catch (err) { // A failed row closes the source as a `for await` would. A close // that fails must not replace the row error the bulk load is // failing with. closed = true; if (typeof iterator.return === 'function') { try { await iterator.return(); } catch { // The row error is what surfaces. } } throw err; } finally { // The consumer stopped pulling (e.g. because the bulk load was // canceled): close the source as a `for await` would. if (!done && !closed && typeof iterator.return === 'function') { await iterator.return(); } } buffer.writeBuffer(bulkLoad.createDoneToken()); for (const chunk of buffer.getBuffers()) { yield chunk; } buffer.consume(buffer.length); } toString(indent = '') { return indent + 'BulkLoad'; } } exports.BulkLoadPayload = BulkLoadPayload; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfd3JpdGFibGVUcmFja2luZ0J1ZmZlciIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJyZXF1aXJlIiwiX3Rva2VuIiwiX2Vycm9ycyIsImUiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsInJvd1Rva2VuQnVmZmVyIiwiQnVmZmVyIiwiZnJvbSIsIlRPS0VOX1RZUEUiLCJST1ciLCJ0ZXh0UG9pbnRlckFuZFRpbWVzdGFtcEJ1ZmZlciIsInRleHRQb2ludGVyTnVsbEJ1ZmZlciIsImlzUHJvbWlzZUxpa2UiLCJ2YWx1ZSIsInRoZW4iLCJpZ25vcmVFcnJvciIsIkJ1bGtMb2FkUGF5bG9hZCIsImNvbnN0cnVjdG9yIiwiYnVsa0xvYWQiLCJyb3dzIiwiaXRlcmF0b3IiLCJTeW1ib2wiLCJhc3luY0l0ZXJhdG9yIiwiZmlyc3QiLCJuZXh0IiwiZXJyIiwiUHJvbWlzZSIsInJlamVjdCIsInJlYWQiLCJyZXNvbHZlIiwidW5kZWZpbmVkIiwicGVuZGluZyIsImNsb3NlIiwicmV0dXJuIiwiY2xvc2luZyIsIm9wdGlvbnMiLCJjb2x1bW5zIiwiaXNUZXh0VHlwZSIsIm1hcCIsImMiLCJ0eXBlIiwibmFtZSIsImJ1ZmZlciIsIldyaXRhYmxlVHJhY2tpbmdCdWZmZXIiLCJkb25lIiwiY2xvc2VkIiwid3JpdGVCdWZmZXIiLCJnZXRDb2xNZXRhRGF0YSIsInJlc3VsdCIsInJvdyIsImlzQXJyYXkiLCJBcnJheSIsImkiLCJsZW5ndGgiLCJ2YWxpZGF0ZSIsIm9iak5hbWUiLCJjb2xsYXRpb24iLCJwYXJhbWV0ZXIiLCJzY2FsZSIsInByZWNpc2lvbiIsIndyaXRlVmFsdWUiLCJlcnJvciIsIklucHV0RXJyb3IiLCJjYXVzZSIsIkNIVU5LX1NJWkUiLCJjaHVuayIsImdldEJ1ZmZlcnMiLCJjb25zdW1lIiwiY3JlYXRlRG9uZVRva2VuIiwidG9TdHJpbmciLCJpbmRlbnQiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vc3JjL2J1bGstbG9hZC1wYXlsb2FkLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBCdWxrTG9hZCBmcm9tICcuL2J1bGstbG9hZCc7XG5pbXBvcnQgV3JpdGFibGVUcmFja2luZ0J1ZmZlciBmcm9tICcuL3RyYWNraW5nLWJ1ZmZlci93cml0YWJsZS10cmFja2luZy1idWZmZXInO1xuaW1wb3J0IHsgVFlQRSBhcyBUT0tFTl9UWVBFIH0gZnJvbSAnLi90b2tlbi90b2tlbic7XG5pbXBvcnQgeyBJbnB1dEVycm9yIH0gZnJvbSAnLi9lcnJvcnMnO1xuXG5leHBvcnQgdHlwZSBSb3cgPSB1bmtub3duW10gfCB7IFtjb2xOYW1lOiBzdHJpbmddOiB1bmtub3duIH07XG5cbmNvbnN0IHJvd1Rva2VuQnVmZmVyID0gQnVmZmVyLmZyb20oWyBUT0tFTl9UWVBFLlJPVyBdKTtcbmNvbnN0IHRleHRQb2ludGVyQW5kVGltZXN0YW1wQnVmZmVyID0gQnVmZmVyLmZyb20oW1xuICAvLyBUZXh0UG9pbnRlciBsZW5ndGhcbiAgMHgxMCxcblxuICAvLyBUZXh0UG9pbnRlclxuICAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLFxuXG4gIC8vIFRpbWVzdGFtcFxuICAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwXG5dKTtcbmNvbnN0IHRleHRQb2ludGVyTnVsbEJ1ZmZlciA9IEJ1ZmZlci5mcm9tKFsweDAwXSk7XG5cbmZ1bmN0aW9uIGlzUHJvbWlzZUxpa2U8VD4odmFsdWU6IFQgfCBQcm9taXNlTGlrZTxUPik6IHZhbHVlIGlzIFByb21pc2VMaWtlPFQ+IHtcbiAgcmV0dXJuIHZhbHVlICE9IG51bGwgJiYgdHlwZW9mICh2YWx1ZSBhcyBQcm9taXNlTGlrZTxUPikudGhlbiA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuZnVuY3Rpb24gaWdub3JlRXJyb3IoKSB7fVxuXG4vKipcbiAqIFRoZSBURFMgYnl0ZSBzdHJlYW0gb2YgYSBidWxrIGxvYWQ6IENPTE1FVEFEQVRBLCBhIFJPVyB0b2tlbiBwZXIgcm93LFxuICogYW5kIGEgRE9ORSB0b2tlbiBhdCB0aGUgZW5kLCBzZXJpYWxpemVkIGZyb20gdGhlIGJ1bGsgbG9hZCdzIHJvdyBzb3VyY2UuXG4gKlxuICogVGhlIHBheWxvYWQgb3ducyB0aGUgcm93IHNvdXJjZSdzIGl0ZXJhdG9yIHRoZSB3YXkgYSBgZm9yIGF3YWl0YCBsb29wXG4gKiB3b3VsZDogaXQgcmVxdWVzdHMgdGhlIGZpcnN0IHJvdyBhcyBzb29uIGFzIGl0IGlzIGNyZWF0ZWQsIHNvIHRoYXQgYVxuICogc3RyZWFtIHNvdXJjZSBpcyBvYnNlcnZlZCBmcm9tIHRoZSBtb21lbnQgaXQgaXMgaGFuZGVkIG92ZXIsIGFuZCBpdFxuICogY2xvc2VzIHRoZSBzb3VyY2UgdGhyb3VnaCB0aGUgaXRlcmF0b3IncyBgcmV0dXJuKClgIHdoZW5ldmVyIHRoZSBidWxrXG4gKiBsb2FkIGRvZXMgbm90IHJ1biB0byBjb21wbGV0aW9uLCB3aGV0aGVyIHRoZSByb3dzIHdlcmUgYmVpbmcgcmVhZFxuICogKFtbU3ltYm9sLmFzeW5jSXRlcmF0b3JdXSkgb3IgbmV2ZXIgZ290IHRvIGJlIChbW2Nsb3NlXV0pLlxuICpcbiAqIFJvd3MgYXJlIHdyaXR0ZW4gaW50byBvbmUgYnVmZmVyIHRoYXQgbGl2ZXMgZm9yIHRoZSB3aG9sZSBidWxrIGxvYWQuXG4gKiBJdHMgY29udGVudHMgYXJlIHlpZWxkZWQgb25jZSBpdCBob2xkcyBhIGNodW5rJ3Mgd29ydGhcbiAqIChgV3JpdGFibGVUcmFja2luZ0J1ZmZlci5DSFVOS19TSVpFYCksIGNoZWNrZWQgYWZ0ZXIgZXZlcnkgY2VsbCwgYW5kIGF0XG4gKiB0aGUgZW5kLiBSb3dzIGZyb20gYSBzeW5jaHJvbm91cyBzb3VyY2UgYXJlIHNlcmlhbGl6ZWQgd2l0aG91dCBhblxuICogZXZlbnQtbG9vcCB0dXJuIGluIGJldHdlZW47IHJvd3MgZnJvbSBhbiBhc3luY2hyb25vdXMgc291cmNlIGFyZSBhd2FpdGVkXG4gKiBvbmUgYXQgYSB0aW1lLlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmV4cG9ydCBjbGFzcyBCdWxrTG9hZFBheWxvYWQgaW1wbGVtZW50cyBBc3luY0l0ZXJhYmxlPEJ1ZmZlcj4ge1xuICBkZWNsYXJlIGJ1bGtMb2FkOiBCdWxrTG9hZDtcbiAgZGVjbGFyZSBpdGVyYXRvcjogSXRlcmF0b3I8Um93PiB8IEFzeW5jSXRlcmF0b3I8Um93PjtcbiAgZGVjbGFyZSBwZW5kaW5nOiBJdGVyYXRvclJlc3VsdDxSb3c+IHwgUHJvbWlzZTxJdGVyYXRvclJlc3VsdDxSb3c+PiB8IHVuZGVmaW5lZDtcblxuICBjb25zdHJ1Y3RvcihidWxrTG9hZDogQnVsa0xvYWQsIHJvd3M6IEl0ZXJhYmxlPFJvdz4gfCBBc3luY0l0ZXJhYmxlPFJvdz4pIHtcbiAgICB0aGlzLmJ1bGtMb2FkID0gYnVsa0xvYWQ7XG5cbiAgICB0aGlzLml0ZXJhdG9yID0gdHlwZW9mIChyb3dzIGFzIFBhcnRpYWw8QXN5bmNJdGVyYWJsZTxSb3c+PilbU3ltYm9sLmFzeW5jSXRlcmF0b3JdID09PSAnZnVuY3Rpb24nID9cbiAgICAgIChyb3dzIGFzIEFzeW5jSXRlcmFibGU8Um93PilbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCkgOlxuICAgICAgKHJvd3MgYXMgSXRlcmFibGU8Um93PilbU3ltYm9sLml0ZXJhdG9yXSgpO1xuXG4gICAgLy8gVGhlIGZpcnN0IHJvdyBpcyByZXF1ZXN0ZWQgbm93LCBiZWZvcmUgdGhlIGBJTlNFUlQgQlVMS2Agc3RhdGVtZW50XG4gICAgLy8gaGFzIGdvbmUgb3V0LiBGb3IgYSBzdHJlYW0gc291cmNlIHRoaXMgaXMgd2hhdCBhdHRhY2hlcyBpdHNcbiAgICAvLyBpdGVyYXRvcidzIGxpc3RlbmVyczogYW4gZXJyb3IgaXQgZW1pdHMgd2hpbGUgdGhlIHN0YXRlbWVudCBpcyBpblxuICAgIC8vIGZsaWdodCBpcyBrZXB0IGFuZCByZXBvcnRlZCBvbiB0aGUgbmV4dCByZWFkLCBpbnN0ZWFkIG9mIGJlaW5nIGFuXG4gICAgLy8gdW5oYW5kbGVkIGAnZXJyb3InYCBldmVudC4gVGhlIHJlYWQgaXMgYXdhaXRlZCB3aGVuIHRoZSByb3dzIGFyZVxuICAgIC8vIHNlcmlhbGl6ZWQ7IGl0cyByZWplY3Rpb24gaXMgbm90IHVuaGFuZGxlZCB1bnRpbCB0aGVuLCBhbmQgbmVpdGhlclxuICAgIC8vIGlzIGEgc3luY2hyb25vdXMgc291cmNlJ3MgdGhyb3csIHdoaWNoIHJlYWNoZXMgdGhlIGJ1bGsgbG9hZCdzXG4gICAgLy8gY2FsbGJhY2sgdGhlIHNhbWUgd2F5LlxuICAgIGxldCBmaXJzdDogSXRlcmF0b3JSZXN1bHQ8Um93PiB8IFByb21pc2U8SXRlcmF0b3JSZXN1bHQ8Um93Pj47XG4gICAgdHJ5IHtcbiAgICAgIGZpcnN0ID0gdGhpcy5pdGVyYXRvci5uZXh0KCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBmaXJzdCA9IFByb21pc2UucmVqZWN0KGVycik7XG4gICAgfVxuXG4gICAgaWYgKGlzUHJvbWlzZUxpa2UoZmlyc3QpKSB7XG4gICAgICBjb25zdCByZWFkID0gUHJvbWlzZS5yZXNvbHZlKGZpcnN0KTtcbiAgICAgIHJlYWQudGhlbih1bmRlZmluZWQsIGlnbm9yZUVycm9yKTtcbiAgICAgIHRoaXMucGVuZGluZyA9IHJlYWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucGVuZGluZyA9IGZpcnN0O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgdGhlIHJvdyBzb3VyY2Ugb2YgYSBidWxrIGxvYWQgd2hvc2Ugcm93cyB3aWxsIG5vdCBiZSByZWFkOlxuICAgKiB0aGUgYElOU0VSVCBCVUxLYCBzdGF0ZW1lbnQgd2FzIHJlamVjdGVkLCB0aGUgYnVsayBsb2FkIHdhcyBjYW5jZWxlZCxcbiAgICogb3IgdGhlIGNvbm5lY3Rpb24gaXMgbm8gbG9uZ2VyIGxvZ2dlZCBpbi4gQmVzdCBlZmZvcnQ6IGEgcmVhZCBzdGlsbFxuICAgKiBwZW5kaW5nIGluIHRoZSBzb3VyY2UgY2Fubm90IGJlIGludGVycnVwdGVkLCBhbmQgYSBjbG9zZSB0aGF0IGZhaWxzXG4gICAqIGhhcyBub3RoaW5nIGxlZnQgdG8gcmVwb3J0IHRvLlxuICAgKi9cbiAgY2xvc2UoKSB7XG4gICAgY29uc3QgaXRlcmF0b3IgPSB0aGlzLml0ZXJhdG9yO1xuICAgIGlmICh0eXBlb2YgaXRlcmF0b3IucmV0dXJuICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGNsb3NpbmcgPSBpdGVyYXRvci5yZXR1cm4oKTtcbiAgICAgIGlmIChpc1Byb21pc2VMaWtlKGNsb3NpbmcpKSB7XG4gICAgICAgIFByb21pc2UucmVzb2x2ZShjbG9zaW5nKS50aGVuKHVuZGVmaW5lZCwgaWdub3JlRXJyb3IpO1xuICAgICAgfVxuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gTm90aGluZyBsZWZ0IHRvIHJlcG9ydCB0by5cbiAgICB9XG4gIH1cblxuICBhc3luYyAqW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpIHtcbiAgICBjb25zdCBidWxrTG9hZCA9IHRoaXMuYnVsa0xvYWQ7XG4gICAgY29uc3Qgb3B0aW9ucyA9IGJ1bGtMb2FkLm9wdGlvbnM7XG4gICAgY29uc3QgY29sdW1ucyA9IGJ1bGtMb2FkLmNvbHVtbnM7XG4gICAgY29uc3QgaXRlcmF0b3IgPSB0aGlzLml0ZXJhdG9yO1xuXG4gICAgLy8gUGVyIGNvbHVtbiwgbm90IHBlciBjZWxsOiBhIHRleHQgdHlwZSdzIHZhbHVlIGlzIHdyaXR0ZW4gYmVoaW5kIGFcbiAgICAvLyB0ZXh0IHBvaW50ZXIgYW5kIHRpbWVzdGFtcCwgb3IgYXMgYSBudWxsIHBvaW50ZXIuXG4gICAgY29uc3QgaXNUZXh0VHlwZSA9IGNvbHVtbnMubWFwKChjKSA9PiBjLnR5cGUubmFtZSA9PT0gJ1RleHQnIHx8IGMudHlwZS5uYW1lID09PSAnSW1hZ2UnIHx8IGMudHlwZS5uYW1lID09PSAnTlRleHQnKTtcblxuICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBXcml0YWJsZVRyYWNraW5nQnVmZmVyKCk7XG5cbiAgICBsZXQgZG9uZSA9IGZhbHNlO1xuICAgIGxldCBjbG9zZWQgPSBmYWxzZTtcbiAgICB0cnkge1xuICAgICAgYnVmZmVyLndyaXRlQnVmZmVyKGJ1bGtMb2FkLmdldENvbE1ldGFEYXRhKCkpO1xuXG4gICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBsZXQgcmVzdWx0ID0gdGhpcy5wZW5kaW5nID8/IGl0ZXJhdG9yLm5leHQoKTtcbiAgICAgICAgdGhpcy5wZW5kaW5nID0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAoaXNQcm9taXNlTGlrZShyZXN1bHQpKSB7XG4gICAgICAgICAgcmVzdWx0ID0gYXdhaXQgcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJlc3VsdC5kb25lKSB7XG4gICAgICAgICAgZG9uZSA9IHRydWU7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBIHJvdyBnaXZlbiBhcyBhIHByb21pc2UgaXMgc2V0dGxlZCBmaXJzdCwgYXMgYFJlYWRhYmxlLmZyb21gXG4gICAgICAgIC8vIHNldHRsZWQgaXQgYmVmb3JlIGhhbmRpbmcgaXQgb24uXG4gICAgICAgIGxldCByb3cgPSByZXN1bHQudmFsdWU7XG4gICAgICAgIGlmIChpc1Byb21pc2VMaWtlKHJvdykpIHtcbiAgICAgICAgICByb3cgPSBhd2FpdCByb3c7XG4gICAgICAgIH1cblxuICAgICAgICBidWZmZXIud3JpdGVCdWZmZXIocm93VG9rZW5CdWZmZXIpO1xuXG4gICAgICAgIGNvbnN0IGlzQXJyYXkgPSBBcnJheS5pc0FycmF5KHJvdyk7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29sdW1ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGNvbnN0IGMgPSBjb2x1bW5zW2ldO1xuICAgICAgICAgIGNvbnN0IHZhbHVlID0gYy50eXBlLnZhbGlkYXRlKGlzQXJyYXkgPyAocm93IGFzIHVua25vd25bXSlbaV0gOiAocm93IGFzIHsgW2NvbE5hbWU6IHN0cmluZ106IHVua25vd24gfSlbYy5vYmpOYW1lXSwgYy5jb2xsYXRpb24pO1xuXG4gICAgICAgICAgY29uc3QgcGFyYW1ldGVyID0ge1xuICAgICAgICAgICAgbGVuZ3RoOiBjLmxlbmd0aCxcbiAgICAgICAgICAgIHNjYWxlOiBjLnNjYWxlLFxuICAgICAgICAgICAgcHJlY2lzaW9uOiBjLnByZWNpc2lvbixcbiAgICAgICAgICAgIHZhbHVlOiB2YWx1ZVxuICAgICAgICAgIH07XG5cbiAgICAgICAgICBpZiAoaXNUZXh0VHlwZVtpXSAmJiB2YWx1ZSA9PSBudWxsKSB7XG4gICAgICAgICAgICBidWZmZXIud3JpdGVCdWZmZXIodGV4dFBvaW50ZXJOdWxsQnVmZmVyKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGlzVGV4dFR5cGVbaV0pIHtcbiAgICAgICAgICAgICAgYnVmZmVyLndyaXRlQnVmZmVyKHRleHRQb2ludGVyQW5kVGltZXN0YW1wQnVmZmVyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgYy50eXBlLndyaXRlVmFsdWUoYnVmZmVyLCBwYXJhbWV0ZXIsIG9wdGlvbnMpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IElucHV0RXJyb3IoYENvbHVtbiAnJHtjLm5hbWV9JyBjb3VsZCBub3QgYmUgc2VyaWFsaXplZGAsIHsgY2F1c2U6IGVycm9yIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIENoZWNrZWQgYWZ0ZXIgZXZlcnkgY2VsbCwgbm90IG9ubHkgYWZ0ZXIgZXZlcnkgcm93LCBzbyB0aGF0IGFcbiAgICAgICAgICAvLyB3aWRlIHJvdyBvZiBsYXJnZSBjZWxscyBnb2VzIGRvd25zdHJlYW0gYXMgaXQgaXMgc2VyaWFsaXplZC5cbiAgICAgICAgICBpZiAoYnVmZmVyLmxlbmd0aCA+PSBXcml0YWJsZVRyYWNraW5nQnVmZmVyLkNIVU5LX1NJWkUpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgY2h1bmsgb2YgYnVmZmVyLmdldEJ1ZmZlcnMoKSkge1xuICAgICAgICAgICAgICB5aWVsZCBjaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJ1ZmZlci5jb25zdW1lKGJ1ZmZlci5sZW5ndGgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgLy8gQSBmYWlsZWQgcm93IGNsb3NlcyB0aGUgc291cmNlIGFzIGEgYGZvciBhd2FpdGAgd291bGQuIEEgY2xvc2VcbiAgICAgIC8vIHRoYXQgZmFpbHMgbXVzdCBub3QgcmVwbGFjZSB0aGUgcm93IGVycm9yIHRoZSBidWxrIGxvYWQgaXNcbiAgICAgIC8vIGZhaWxpbmcgd2l0aC5cbiAgICAgIGNsb3NlZCA9IHRydWU7XG4gICAgICBpZiAodHlwZW9mIGl0ZXJhdG9yLnJldHVybiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGl0ZXJhdG9yLnJldHVybigpO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAvLyBUaGUgcm93IGVycm9yIGlzIHdoYXQgc3VyZmFjZXMuXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRocm93IGVycjtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgLy8gVGhlIGNvbnN1bWVyIHN0b3BwZWQgcHVsbGluZyAoZS5nLiBiZWNhdXNlIHRoZSBidWxrIGxvYWQgd2FzXG4gICAgICAvLyBjYW5jZWxlZCk6IGNsb3NlIHRoZSBzb3VyY2UgYXMgYSBgZm9yIGF3YWl0YCB3b3VsZC5cbiAgICAgIGlmICghZG9uZSAmJiAhY2xvc2VkICYmIHR5cGVvZiBpdGVyYXRvci5yZXR1cm4gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgYXdhaXQgaXRlcmF0b3IucmV0dXJuKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgYnVmZmVyLndyaXRlQnVmZmVyKGJ1bGtMb2FkLmNyZWF0ZURvbmVUb2tlbigpKTtcbiAgICBmb3IgKGNvbnN0IGNodW5rIG9mIGJ1ZmZlci5nZXRCdWZmZXJzKCkpIHtcbiAgICAgIHlpZWxkIGNodW5rO1xuICAgIH1cbiAgICBidWZmZXIuY29uc3VtZShidWZmZXIubGVuZ3RoKTtcbiAgfVxuXG4gIHRvU3RyaW5nKGluZGVudCA9ICcnKSB7XG4gICAgcmV0dXJuIGluZGVudCArICgnQnVsa0xvYWQnKTtcbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFDQSxJQUFBQSx1QkFBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsTUFBQSxHQUFBRCxPQUFBO0FBQ0EsSUFBQUUsT0FBQSxHQUFBRixPQUFBO0FBQXNDLFNBQUFELHVCQUFBSSxDQUFBLFdBQUFBLENBQUEsSUFBQUEsQ0FBQSxDQUFBQyxVQUFBLEdBQUFELENBQUEsS0FBQUUsT0FBQSxFQUFBRixDQUFBO0FBSXRDLE1BQU1HLGNBQWMsR0FBR0MsTUFBTSxDQUFDQyxJQUFJLENBQUMsQ0FBRUMsV0FBVSxDQUFDQyxHQUFHLENBQUUsQ0FBQztBQUN0RCxNQUFNQyw2QkFBNkIsR0FBR0osTUFBTSxDQUFDQyxJQUFJLENBQUM7QUFDaEQ7QUFDQSxJQUFJO0FBRUo7QUFDQSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJO0FBRTlGO0FBQ0EsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FDL0MsQ0FBQztBQUNG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