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