tedious
Version:
A TDS driver, for connecting to MS SQLServer databases.
192 lines (185 loc) • 24.6 kB
JavaScript
;
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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