UNPKG

tedious

Version:

A TDS driver, for connecting to MS SQLServer databases.

175 lines (166 loc) • 23.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _errors = require("../errors"); var _writableTrackingBuffer = _interopRequireDefault(require("../tracking-buffer/writable-tracking-buffer")); var _plpStream = require("./plp-stream"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const TVP_TYPE_ID = 0xF3; const TVP_ROW_TOKEN = Buffer.from([0x01]); const TVP_END_TOKEN = Buffer.from([0x00]); // A NULL table: no columns, and the end tokens of the column metadata and // of the rows. const NULL_TABLE = Buffer.from([0xFF, 0xFF, 0x00, 0x00]); function validateTable(value) { if (value == null) { return null; } if (typeof value !== 'object' || !Array.isArray(value.columns)) { throw new TypeError('Invalid table.'); } const rows = value.rows; if (!Array.isArray(rows) && !(0, _plpStream.isAsyncIterable)(rows)) { throw new TypeError('Invalid table.'); } return value; } // One cell per column, reused for every row: a type writes a cell's bytes // as soon as it is handed the cell and keeps no reference to it. function cellsFor(columns) { return columns.map(column => ({ value: undefined, length: column.length, scale: column.scale, precision: column.precision })); } function writeTvpTypeInfo(buffer, value) { buffer.writeUInt8(TVP_TYPE_ID); // DbName buffer.writeBVarchar('', 'ucs2'); // OwningSchema buffer.writeBVarchar(value?.schema ?? '', 'ucs2'); // TypeName buffer.writeBVarchar(value?.name ?? '', 'ucs2'); } // The column metadata after the column count: one entry per column, then // the end token. function writeColumns(buffer, columns, options) { for (let i = 0, len = columns.length; i < len; i++) { const column = columns[i]; // UserType buffer.writeUInt32LE(0x00000000); // Flags buffer.writeUInt16LE(0x0000); // TYPE_INFO column.type.writeTypeInfo(buffer, { value: undefined, length: column.length, precision: column.precision, scale: column.scale }, options); // ColName buffer.writeUInt8(0x00); } buffer.writeBuffer(TVP_END_TOKEN); } function writeColumnMetadata(buffer, value, options) { buffer.writeUInt16LE(value.columns.length); writeColumns(buffer, value.columns, options); } // Validates and writes a row cell by cell. A cell that fails validation // leaves the row half written, which does not matter: the request is // abandoned with the error and the buffer never reaches the wire. function writeRow(buffer, columns, cells, row, rowIndex, collation, options) { if (!Array.isArray(row)) { throw new _errors.InputError(`TVP row at index ${rowIndex} is not an array`); } // Every declared column must have a value: the row metadata covers all // columns, so a shorter or longer row would desync the server's parse. if (row.length !== columns.length) { throw new _errors.InputError(`TVP row at index ${rowIndex} has ${row.length} value(s), but ${columns.length} column(s) are declared`); } buffer.writeBuffer(TVP_ROW_TOKEN); for (let k = 0, len = row.length; k < len; k++) { const column = columns[k]; const cell = cells[k]; try { cell.value = column.type.validate(row[k], collation); } catch (error) { throw new _errors.InputError(`TVP column '${column.name}' has invalid data at row index ${rowIndex}`, { cause: error }); } // TvpColumnData column.type.writeValue(buffer, cell, options); } } // Rows given as an array are written in a synchronous loop, so the only // asynchrony is the yield for every chunk's worth of rows. async function* writeRows(buffer, value, rows, collation, options) { writeColumnMetadata(buffer, value, options); const cells = cellsFor(value.columns); for (let i = 0, len = rows.length; i < len; i++) { writeRow(buffer, value.columns, cells, rows[i], i, collation, options); if (buffer.length >= _writableTrackingBuffer.default.CHUNK_SIZE) { yield; } } buffer.writeBuffer(TVP_END_TOKEN); } async function* writeRowsFrom(buffer, value, rows, collation, options) { writeColumnMetadata(buffer, value, options); const cells = cellsFor(value.columns); let rowIndex = 0; for await (const row of rows) { writeRow(buffer, value.columns, cells, row, rowIndex++, collation, options); if (buffer.length >= _writableTrackingBuffer.default.CHUNK_SIZE) { yield; } } buffer.writeBuffer(TVP_END_TOKEN); } const TVP = { id: TVP_TYPE_ID, type: 'TVPTYPE', name: 'TVP', declaration: function (parameter) { const value = parameter.value; // Temporary solution. Remove 'any' later. const schema = value.schema ? value.schema + '.' : ''; return schema + value.name + ' readonly'; }, validate(value) { return validateTable(value); }, resolve(parameter, collation) { // A TVP's `writeValue` always returns the rest of the write, whether // its rows are an array or an async iterable. const data = { value: validateTable(parameter.value) }; if (collation) { data.collation = collation; } return data; }, writeTypeInfo(buffer, parameter) { writeTvpTypeInfo(buffer, parameter.value); }, async *writeValue(buffer, parameter, options) { const value = parameter.value; if (value == null) { buffer.writeBuffer(NULL_TABLE); return; } if (Array.isArray(value.rows)) { yield* writeRows(buffer, value, value.rows, parameter.collation, options); return; } yield* writeRowsFrom(buffer, value, value.rows, parameter.collation, options); } }; var _default = exports.default = TVP; module.exports = TVP; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfZXJyb3JzIiwicmVxdWlyZSIsIl93cml0YWJsZVRyYWNraW5nQnVmZmVyIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsIl9wbHBTdHJlYW0iLCJlIiwiX19lc01vZHVsZSIsImRlZmF1bHQiLCJUVlBfVFlQRV9JRCIsIlRWUF9ST1dfVE9LRU4iLCJCdWZmZXIiLCJmcm9tIiwiVFZQX0VORF9UT0tFTiIsIk5VTExfVEFCTEUiLCJ2YWxpZGF0ZVRhYmxlIiwidmFsdWUiLCJBcnJheSIsImlzQXJyYXkiLCJjb2x1bW5zIiwiVHlwZUVycm9yIiwicm93cyIsImlzQXN5bmNJdGVyYWJsZSIsImNlbGxzRm9yIiwibWFwIiwiY29sdW1uIiwidW5kZWZpbmVkIiwibGVuZ3RoIiwic2NhbGUiLCJwcmVjaXNpb24iLCJ3cml0ZVR2cFR5cGVJbmZvIiwiYnVmZmVyIiwid3JpdGVVSW50OCIsIndyaXRlQlZhcmNoYXIiLCJzY2hlbWEiLCJuYW1lIiwid3JpdGVDb2x1bW5zIiwib3B0aW9ucyIsImkiLCJsZW4iLCJ3cml0ZVVJbnQzMkxFIiwid3JpdGVVSW50MTZMRSIsInR5cGUiLCJ3cml0ZVR5cGVJbmZvIiwid3JpdGVCdWZmZXIiLCJ3cml0ZUNvbHVtbk1ldGFkYXRhIiwid3JpdGVSb3ciLCJjZWxscyIsInJvdyIsInJvd0luZGV4IiwiY29sbGF0aW9uIiwiSW5wdXRFcnJvciIsImsiLCJjZWxsIiwidmFsaWRhdGUiLCJlcnJvciIsImNhdXNlIiwid3JpdGVWYWx1ZSIsIndyaXRlUm93cyIsIldyaXRhYmxlVHJhY2tpbmdCdWZmZXIiLCJDSFVOS19TSVpFIiwid3JpdGVSb3dzRnJvbSIsIlRWUCIsImlkIiwiZGVjbGFyYXRpb24iLCJwYXJhbWV0ZXIiLCJyZXNvbHZlIiwiZGF0YSIsIl9kZWZhdWx0IiwiZXhwb3J0cyIsIm1vZHVsZSJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXRhLXR5cGVzL3R2cC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyB0eXBlIERhdGFUeXBlLCB0eXBlIFBhcmFtZXRlckRhdGEgfSBmcm9tICcuLi9kYXRhLXR5cGUnO1xuaW1wb3J0IHsgdHlwZSBJbnRlcm5hbENvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSAnLi4vY29ubmVjdGlvbic7XG5pbXBvcnQgeyB0eXBlIENvbGxhdGlvbiB9IGZyb20gJy4uL2NvbGxhdGlvbic7XG5pbXBvcnQgeyBJbnB1dEVycm9yIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCBXcml0YWJsZVRyYWNraW5nQnVmZmVyIGZyb20gJy4uL3RyYWNraW5nLWJ1ZmZlci93cml0YWJsZS10cmFja2luZy1idWZmZXInO1xuaW1wb3J0IHsgaXNBc3luY0l0ZXJhYmxlIH0gZnJvbSAnLi9wbHAtc3RyZWFtJztcblxuY29uc3QgVFZQX1RZUEVfSUQgPSAweEYzO1xuXG5jb25zdCBUVlBfUk9XX1RPS0VOID0gQnVmZmVyLmZyb20oWzB4MDFdKTtcbmNvbnN0IFRWUF9FTkRfVE9LRU4gPSBCdWZmZXIuZnJvbShbMHgwMF0pO1xuXG4vLyBBIE5VTEwgdGFibGU6IG5vIGNvbHVtbnMsIGFuZCB0aGUgZW5kIHRva2VucyBvZiB0aGUgY29sdW1uIG1ldGFkYXRhIGFuZFxuLy8gb2YgdGhlIHJvd3MuXG5jb25zdCBOVUxMX1RBQkxFID0gQnVmZmVyLmZyb20oWzB4RkYsIDB4RkYsIDB4MDAsIDB4MDBdKTtcblxuaW50ZXJmYWNlIFR2cENvbHVtbiB7XG4gIG5hbWU6IHN0cmluZztcbiAgdHlwZTogRGF0YVR5cGU7XG4gIGxlbmd0aD86IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgcHJlY2lzaW9uPzogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICBzY2FsZT86IG51bWJlciB8IHVuZGVmaW5lZDtcbn1cblxudHlwZSBUdnBSb3cgPSB1bmtub3duW107XG5cbmludGVyZmFjZSBUdnBWYWx1ZSB7XG4gIG5hbWU/OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIHNjaGVtYT86IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgY29sdW1uczogVHZwQ29sdW1uW107XG4gIC8vIFJvd3MgYXJlIHZhbGlkYXRlZCBhcyB0aGV5IGFyZSB3cml0dGVuLCB3aGV0aGVyIHRoZXkgYXJlIGdpdmVuIGFzIGFuXG4gIC8vIGFycmF5IG9yIGFzIGFuIGFzeW5jIGl0ZXJhYmxlIHRoYXQgaXMgcmVhZCB3aGlsZSB0aGUgcmVxdWVzdCBpcyB3cml0dGVuLlxuICByb3dzOiBUdnBSb3dbXSB8IEFzeW5jSXRlcmFibGU8VHZwUm93Pjtcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVUYWJsZSh2YWx1ZTogdW5rbm93bik6IFR2cFZhbHVlIHwgbnVsbCB7XG4gIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBpZiAodHlwZW9mIHZhbHVlICE9PSAnb2JqZWN0JyB8fCAhQXJyYXkuaXNBcnJheSgodmFsdWUgYXMgVHZwVmFsdWUpLmNvbHVtbnMpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignSW52YWxpZCB0YWJsZS4nKTtcbiAgfVxuXG4gIGNvbnN0IHJvd3MgPSAodmFsdWUgYXMgVHZwVmFsdWUpLnJvd3M7XG4gIGlmICghQXJyYXkuaXNBcnJheShyb3dzKSAmJiAhaXNBc3luY0l0ZXJhYmxlKHJvd3MpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignSW52YWxpZCB0YWJsZS4nKTtcbiAgfVxuXG4gIHJldHVybiB2YWx1ZSBhcyBUdnBWYWx1ZTtcbn1cblxuLy8gT25lIGNlbGwgcGVyIGNvbHVtbiwgcmV1c2VkIGZvciBldmVyeSByb3c6IGEgdHlwZSB3cml0ZXMgYSBjZWxsJ3MgYnl0ZXNcbi8vIGFzIHNvb24gYXMgaXQgaXMgaGFuZGVkIHRoZSBjZWxsIGFuZCBrZWVwcyBubyByZWZlcmVuY2UgdG8gaXQuXG5mdW5jdGlvbiBjZWxsc0Zvcihjb2x1bW5zOiBUdnBDb2x1bW5bXSk6IFBhcmFtZXRlckRhdGFbXSB7XG4gIHJldHVybiBjb2x1bW5zLm1hcCgoY29sdW1uKSA9PiAoeyB2YWx1ZTogdW5kZWZpbmVkLCBsZW5ndGg6IGNvbHVtbi5sZW5ndGgsIHNjYWxlOiBjb2x1bW4uc2NhbGUsIHByZWNpc2lvbjogY29sdW1uLnByZWNpc2lvbiB9KSk7XG59XG5cbmZ1bmN0aW9uIHdyaXRlVHZwVHlwZUluZm8oYnVmZmVyOiBXcml0YWJsZVRyYWNraW5nQnVmZmVyLCB2YWx1ZTogVHZwVmFsdWUgfCBudWxsKSB7XG4gIGJ1ZmZlci53cml0ZVVJbnQ4KFRWUF9UWVBFX0lEKTtcbiAgLy8gRGJOYW1lXG4gIGJ1ZmZlci53cml0ZUJWYXJjaGFyKCcnLCAndWNzMicpO1xuICAvLyBPd25pbmdTY2hlbWFcbiAgYnVmZmVyLndyaXRlQlZhcmNoYXIodmFsdWU/LnNjaGVtYSA/PyAnJywgJ3VjczInKTtcbiAgLy8gVHlwZU5hbWVcbiAgYnVmZmVyLndyaXRlQlZhcmNoYXIodmFsdWU/Lm5hbWUgPz8gJycsICd1Y3MyJyk7XG59XG5cbi8vIFRoZSBjb2x1bW4gbWV0YWRhdGEgYWZ0ZXIgdGhlIGNvbHVtbiBjb3VudDogb25lIGVudHJ5IHBlciBjb2x1bW4sIHRoZW5cbi8vIHRoZSBlbmQgdG9rZW4uXG5mdW5jdGlvbiB3cml0ZUNvbHVtbnMoYnVmZmVyOiBXcml0YWJsZVRyYWNraW5nQnVmZmVyLCBjb2x1bW5zOiBUdnBDb2x1bW5bXSwgb3B0aW9uczogSW50ZXJuYWxDb25uZWN0aW9uT3B0aW9ucykge1xuICBmb3IgKGxldCBpID0gMCwgbGVuID0gY29sdW1ucy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgIGNvbnN0IGNvbHVtbiA9IGNvbHVtbnNbaV07XG5cbiAgICAvLyBVc2VyVHlwZVxuICAgIGJ1ZmZlci53cml0ZVVJbnQzMkxFKDB4MDAwMDAwMDApO1xuICAgIC8vIEZsYWdzXG4gICAgYnVmZmVyLndyaXRlVUludDE2TEUoMHgwMDAwKTtcbiAgICAvLyBUWVBFX0lORk9cbiAgICBjb2x1bW4udHlwZS53cml0ZVR5cGVJbmZvKGJ1ZmZlciwgeyB2YWx1ZTogdW5kZWZpbmVkLCBsZW5ndGg6IGNvbHVtbi5sZW5ndGgsIHByZWNpc2lvbjogY29sdW1uLnByZWNpc2lvbiwgc2NhbGU6IGNvbHVtbi5zY2FsZSB9LCBvcHRpb25zKTtcbiAgICAvLyBDb2xOYW1lXG4gICAgYnVmZmVyLndyaXRlVUludDgoMHgwMCk7XG4gIH1cblxuICBidWZmZXIud3JpdGVCdWZmZXIoVFZQX0VORF9UT0tFTik7XG59XG5cbmZ1bmN0aW9uIHdyaXRlQ29sdW1uTWV0YWRhdGEoYnVmZmVyOiBXcml0YWJsZVRyYWNraW5nQnVmZmVyLCB2YWx1ZTogVHZwVmFsdWUsIG9wdGlvbnM6IEludGVybmFsQ29ubmVjdGlvbk9wdGlvbnMpIHtcbiAgYnVmZmVyLndyaXRlVUludDE2TEUodmFsdWUuY29sdW1ucy5sZW5ndGgpO1xuICB3cml0ZUNvbHVtbnMoYnVmZmVyLCB2YWx1ZS5jb2x1bW5zLCBvcHRpb25zKTtcbn1cblxuLy8gVmFsaWRhdGVzIGFuZCB3cml0ZXMgYSByb3cgY2VsbCBieSBjZWxsLiBBIGNlbGwgdGhhdCBmYWlscyB2YWxpZGF0aW9uXG4vLyBsZWF2ZXMgdGhlIHJvdyBoYWxmIHdyaXR0ZW4sIHdoaWNoIGRvZXMgbm90IG1hdHRlcjogdGhlIHJlcXVlc3QgaXNcbi8vIGFiYW5kb25lZCB3aXRoIHRoZSBlcnJvciBhbmQgdGhlIGJ1ZmZlciBuZXZlciByZWFjaGVzIHRoZSB3aXJlLlxuZnVuY3Rpb24gd3JpdGVSb3coYnVmZmVyOiBXcml0YWJsZVRyYWNraW5nQnVmZmVyLCBjb2x1bW5zOiBUdnBDb2x1bW5bXSwgY2VsbHM6IFBhcmFtZXRlckRhdGFbXSwgcm93OiBUdnBSb3csIHJvd0luZGV4OiBudW1iZXIsIGNvbGxhdGlvbjogQ29sbGF0aW9uIHwgdW5kZWZpbmVkLCBvcHRpb25zOiBJbnRlcm5hbENvbm5lY3Rpb25PcHRpb25zKSB7XG4gIGlmICghQXJyYXkuaXNBcnJheShyb3cpKSB7XG4gICAgdGhyb3cgbmV3IElucHV0RXJyb3IoYFRWUCByb3cgYXQgaW5kZXggJHtyb3dJbmRleH0gaXMgbm90IGFuIGFycmF5YCk7XG4gIH1cblxuICAvLyBFdmVyeSBkZWNsYXJlZCBjb2x1bW4gbXVzdCBoYXZlIGEgdmFsdWU6IHRoZSByb3cgbWV0YWRhdGEgY292ZXJzIGFsbFxuICAvLyBjb2x1bW5zLCBzbyBhIHNob3J0ZXIgb3IgbG9uZ2VyIHJvdyB3b3VsZCBkZXN5bmMgdGhlIHNlcnZlcidzIHBhcnNlLlxuICBpZiAocm93Lmxlbmd0aCAhPT0gY29sdW1ucy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgSW5wdXRFcnJvcihgVFZQIHJvdyBhdCBpbmRleCAke3Jvd0luZGV4fSBoYXMgJHtyb3cubGVuZ3RofSB2YWx1ZShzKSwgYnV0ICR7Y29sdW1ucy5sZW5ndGh9IGNvbHVtbihzKSBhcmUgZGVjbGFyZWRgKTtcbiAgfVxuXG4gIGJ1ZmZlci53cml0ZUJ1ZmZlcihUVlBfUk9XX1RPS0VOKTtcblxuICBmb3IgKGxldCBrID0gMCwgbGVuID0gcm93Lmxlbmd0aDsgayA8IGxlbjsgaysrKSB7XG4gICAgY29uc3QgY29sdW1uID0gY29sdW1uc1trXTtcbiAgICBjb25zdCBjZWxsID0gY2VsbHNba107XG5cbiAgICB0cnkge1xuICAgICAgY2VsbC52YWx1ZSA9IGNvbHVtbi50eXBlLnZhbGlkYXRlKHJvd1trXSwgY29sbGF0aW9uKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhyb3cgbmV3IElucHV0RXJyb3IoYFRWUCBjb2x1bW4gJyR7Y29sdW1uLm5hbWV9JyBoYXMgaW52YWxpZCBkYXRhIGF0IHJvdyBpbmRleCAke3Jvd0luZGV4fWAsIHsgY2F1c2U6IGVycm9yIH0pO1xuICAgIH1cblxuICAgIC8vIFR2cENvbHVtbkRhdGFcbiAgICBjb2x1bW4udHlwZS53cml0ZVZhbHVlKGJ1ZmZlciwgY2VsbCwgb3B0aW9ucyk7XG4gIH1cbn1cblxuLy8gUm93cyBnaXZlbiBhcyBhbiBhcnJheSBhcmUgd3JpdHRlbiBpbiBhIHN5bmNocm9ub3VzIGxvb3AsIHNvIHRoZSBvbmx5XG4vLyBhc3luY2hyb255IGlzIHRoZSB5aWVsZCBmb3IgZXZlcnkgY2h1bmsncyB3b3J0aCBvZiByb3dzLlxuYXN5bmMgZnVuY3Rpb24gKiB3cml0ZVJvd3MoYnVmZmVyOiBXcml0YWJsZVRyYWNraW5nQnVmZmVyLCB2YWx1ZTogVHZwVmFsdWUsIHJvd3M6IFR2cFJvd1tdLCBjb2xsYXRpb246IENvbGxhdGlvbiB8IHVuZGVmaW5lZCwgb3B0aW9uczogSW50ZXJuYWxDb25uZWN0aW9uT3B0aW9ucyk6IEFzeW5jR2VuZXJhdG9yPHZvaWQsIHZvaWQ+IHtcbiAgd3JpdGVDb2x1bW5NZXRhZGF0YShidWZmZXIsIHZhbHVlLCBvcHRpb25zKTtcbiAgY29uc3QgY2VsbHMgPSBjZWxsc0Zvcih2YWx1ZS5jb2x1bW5zKTtcblxuICBmb3IgKGxldCBpID0gMCwgbGVuID0gcm93cy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgIHdyaXRlUm93KGJ1ZmZlciwgdmFsdWUuY29sdW1ucywgY2VsbHMsIHJvd3NbaV0sIGksIGNvbGxhdGlvbiwgb3B0aW9ucyk7XG5cbiAgICBpZiAoYnVmZmVyLmxlbmd0aCA+PSBXcml0YWJsZVRyYWNraW5nQnVmZmVyLkNIVU5LX1NJWkUpIHtcbiAgICAgIHlpZWxkO1xuICAgIH1cbiAgfVxuXG4gIGJ1ZmZlci53cml0ZUJ1ZmZlcihUVlBfRU5EX1RPS0VOKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gKiB3cml0ZVJvd3NGcm9tKGJ1ZmZlcjogV3JpdGFibGVUcmFja2luZ0J1ZmZlciwgdmFsdWU6IFR2cFZhbHVlLCByb3dzOiBBc3luY0l0ZXJhYmxlPFR2cFJvdz4sIGNvbGxhdGlvbjogQ29sbGF0aW9uIHwgdW5kZWZpbmVkLCBvcHRpb25zOiBJbnRlcm5hbENvbm5lY3Rpb25PcHRpb25zKTogQXN5bmNHZW5lcmF0b3I8dm9pZCwgdm9pZD4ge1xuICB3cml0ZUNvbHVtbk1ldGFkYXRhKGJ1ZmZlciwgdmFsdWUsIG9wdGlvbnMpO1xuICBjb25zdCBjZWxscyA9IGNlbGxzRm9yKHZhbHVlLmNvbHVtbnMpO1xuXG4gIGxldCByb3dJbmRleCA9IDA7XG4gIGZvciBhd2FpdCAoY29uc3Qgcm93IG9mIHJvd3MpIHtcbiAgICB3cml0ZVJvdyhidWZmZXIsIHZhbHVlLmNvbHVtbnMsIGNlbGxzLCByb3csIHJvd0luZGV4KyssIGNvbGxhdGlvbiwgb3B0aW9ucyk7XG5cbiAgICBpZiAoYnVmZmVyLmxlbmd0aCA+PSBXcml0YWJsZVRyYWNraW5nQnVmZmVyLkNIVU5LX1NJWkUpIHtcbiAgICAgIHlpZWxkO1xuICAgIH1cbiAgfVxuXG4gIGJ1ZmZlci53cml0ZUJ1ZmZlcihUVlBfRU5EX1RPS0VOKTtcbn1cblxuY29uc3QgVFZQOiBEYXRhVHlwZSA9IHtcbiAgaWQ6IFRWUF9UWVBFX0lELFxuICB0eXBlOiAnVFZQVFlQRScsXG4gIG5hbWU6ICdUVlAnLFxuXG4gIGRlY2xhcmF0aW9uOiBmdW5jdGlvbihwYXJhbWV0ZXIpIHtcbiAgICBjb25zdCB2YWx1ZSA9IHBhcmFtZXRlci52YWx1ZSBhcyBhbnk7IC8vIFRlbXBvcmFyeSBzb2x1dGlvbi4gUmVtb3ZlICdhbnknIGxhdGVyLlxuICAgIGNvbnN0IHNjaGVtYSA9IHZhbHVlLnNjaGVtYSA/IHZhbHVlLnNjaGVtYSArICcuJyA6ICcnO1xuICAgIHJldHVybiBzY2hlbWEgKyB2YWx1ZS5uYW1lICsgJyByZWFkb25seSc7XG4gIH0sXG5cbiAgdmFsaWRhdGUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsaWRhdGVUYWJsZSh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVzb2x2ZShwYXJhbWV0ZXIsIGNvbGxhdGlvbikge1xuICAgIC8vIEEgVFZQJ3MgYHdyaXRlVmFsdWVgIGFsd2F5cyByZXR1cm5zIHRoZSByZXN0IG9mIHRoZSB3cml0ZSwgd2hldGhlclxuICAgIC8vIGl0cyByb3dzIGFyZSBhbiBhcnJheSBvciBhbiBhc3luYyBpdGVyYWJsZS5cbiAgICBjb25zdCBkYXRhOiBQYXJhbWV0ZXJEYXRhPFR2cFZhbHVlIHwgbnVsbD4gPSB7IHZhbHVlOiB2YWxpZGF0ZVRhYmxlKHBhcmFtZXRlci52YWx1ZSkgfTtcbiAgICBpZiAoY29sbGF0aW9uKSB7XG4gICAgICBkYXRhLmNvbGxhdGlvbiA9IGNvbGxhdGlvbjtcbiAgICB9XG5cbiAgICByZXR1cm4gZGF0YTtcbiAgfSxcblxuICB3cml0ZVR5cGVJbmZvKGJ1ZmZlciwgcGFyYW1ldGVyKSB7XG4gICAgd3JpdGVUdnBUeXBlSW5mbyhidWZmZXIsIHBhcmFtZXRlci52YWx1ZSBhcyBUdnBWYWx1ZSB8IG51bGwpO1xuICB9LFxuXG4gIGFzeW5jICogd3JpdGVWYWx1ZShidWZmZXIsIHBhcmFtZXRlciwgb3B0aW9ucykge1xuICAgIGNvbnN0IHZhbHVlID0gcGFyYW1ldGVyLnZhbHVlIGFzIFR2cFZhbHVlIHwgbnVsbDtcblxuICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgICBidWZmZXIud3JpdGVCdWZmZXIoTlVMTF9UQUJMRSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUucm93cykpIHtcbiAgICAgIHlpZWxkICogd3JpdGVSb3dzKGJ1ZmZlciwgdmFsdWUsIHZhbHVlLnJvd3MsIHBhcmFtZXRlci5jb2xsYXRpb24sIG9wdGlvbnMpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHlpZWxkICogd3JpdGVSb3dzRnJvbShidWZmZXIsIHZhbHVlLCB2YWx1ZS5yb3dzLCBwYXJhbWV0ZXIuY29sbGF0aW9uLCBvcHRpb25zKTtcbiAgfVxufTtcblxuZXhwb3J0IGRlZmF1bHQgVFZQO1xubW9kdWxlLmV4cG9ydHMgPSBUVlA7XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQUdBLElBQUFBLE9BQUEsR0FBQUMsT0FBQTtBQUNBLElBQUFDLHVCQUFBLEdBQUFDLHNCQUFBLENBQUFGLE9BQUE7QUFDQSxJQUFBRyxVQUFBLEdBQUFILE9BQUE7QUFBK0MsU0FBQUUsdUJBQUFFLENBQUEsV0FBQUEsQ0FBQSxJQUFBQSxDQUFBLENBQUFDLFVBQUEsR0FBQUQsQ0FBQSxLQUFBRSxPQUFBLEVBQUFGLENBQUE7QUFFL0MsTUFB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