@dpkit/table
Version:
Data Package implementation in TypeScript.
185 lines • 26.8 kB
JavaScript
import { col } from "nodejs-polars";
import { getPolarsSchema } from "../schema/index.js";
export async function inferSchemaFromTable(table, options) {
const { sampleRows = 100 } = options ?? {};
const sample = await table.head(sampleRows).collect();
return inferSchemaFromSample(sample, options);
}
export function inferSchemaFromSample(sample, options) {
const { confidence = 0.9, fieldTypes, keepStrings } = options ?? {};
const typeMapping = createTypeMapping();
const regexMapping = createRegexMapping(options);
const polarsSchema = getPolarsSchema(sample.schema);
const fieldNames = options?.fieldNames ?? polarsSchema.fields.map(f => f.name);
const failureThreshold = sample.height - Math.floor(sample.height * confidence) || 1;
const schema = {
fields: [],
};
for (const name of fieldNames) {
const polarsField = polarsSchema.fields.find(f => f.name === name);
if (!polarsField) {
throw new Error(`Field "${name}" not found in the table`);
}
// TODO: Remove this workaround once the issue is fixed
// https://github.com/pola-rs/nodejs-polars/issues/372
let variant = polarsField.type.variant;
if (!typeMapping[variant]) {
variant = variant.slice(0, -1);
}
let type = fieldTypes?.[name] ?? typeMapping[variant] ?? "any";
if (type === "array" && options?.arrayType === "list") {
type = "list";
}
let field = { name, type };
if (!keepStrings && type === "string" && !fieldTypes?.[name]) {
for (const [regex, patch] of Object.entries(regexMapping)) {
const failures = sample
.filter(col(name).str.contains(regex).not())
.head(failureThreshold).height;
if (failures < failureThreshold) {
field = { ...field, ...patch };
break;
}
}
}
enhanceField(field, options);
schema.fields.push(field);
}
enhanceSchema(schema, options);
return schema;
}
function createTypeMapping() {
const mapping = {
Array: "array",
Bool: "boolean",
Categorical: "string",
Date: "date",
Datetime: "datetime",
Decimal: "number",
Float32: "number",
Float64: "number",
Int16: "integer",
Int32: "integer",
Int64: "integer",
Int8: "integer",
List: "array",
Null: "any",
Object: "object",
String: "string",
Struct: "object",
Time: "time",
UInt16: "integer",
UInt32: "integer",
UInt64: "integer",
UInt8: "integer",
Utf8: "string",
};
return mapping;
}
function createRegexMapping(options) {
const { commaDecimal, monthFirst } = options ?? {};
const mapping = {
// Numeric
"^\\d+$": { type: "integer" },
"^\\d{1,3}(,\\d{3})+$": commaDecimal
? { type: "number" }
: { type: "integer", groupChar: "," },
"^\\d+\\.\\d+$": commaDecimal
? { type: "integer", groupChar: "." }
: { type: "number" },
"^\\d{1,3}(,\\d{3})+\\.\\d+$": { type: "number", groupChar: "," },
"^\\d{1,3}(\\.\\d{3})+,\\d+$": {
type: "number",
groupChar: ".",
decimalChar: ",",
},
// Boolean
"^(true|True|TRUE|false|False|FALSE)$": { type: "boolean" },
// Date
"^\\d{4}-\\d{2}-\\d{2}$": { type: "date" },
"^\\d{4}/\\d{2}/\\d{2}$": { type: "date", format: "%Y/%m/%d" },
"^\\d{2}/\\d{2}/\\d{4}$": monthFirst
? { type: "date", format: "%m/%d/%Y" }
: { type: "date", format: "%d/%m/%Y" },
"^\\d{2}-\\d{2}-\\d{4}$": monthFirst
? { type: "date", format: "%m-%d-%Y" }
: { type: "date", format: "%d-%m-%Y" },
"^\\d{2}\\.\\d{2}\\.\\d{4}$": monthFirst
? { type: "date", format: "%m.%d.%Y" }
: { type: "date", format: "%d.%m.%Y" },
// Time
"^\\d{2}:\\d{2}:\\d{2}$": { type: "time" },
"^\\d{2}:\\d{2}$": { type: "time", format: "%H:%M" },
"^\\d{1,2}:\\d{2}:\\d{2}\\s*(am|pm|AM|PM)$": {
type: "time",
format: "%I:%M:%S %p",
},
"^\\d{1,2}:\\d{2}\\s*(am|pm|AM|PM)$": { type: "time", format: "%I:%M %p" },
"^\\d{2}:\\d{2}:\\d{2}[+-]\\d{2}:?\\d{2}$": { type: "time" },
// Datetime - ISO format
"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z?$": { type: "datetime" },
"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}[+-]\\d{2}:?\\d{2}$": {
type: "datetime",
},
"^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$": {
type: "datetime",
format: "%Y-%m-%d %H:%M:%S",
},
"^\\d{2}/\\d{2}/\\d{4} \\d{2}:\\d{2}$": monthFirst
? { type: "datetime", format: "%m/%d/%Y %H:%M" }
: { type: "datetime", format: "%d/%m/%Y %H:%M" },
"^\\d{2}/\\d{2}/\\d{4} \\d{2}:\\d{2}:\\d{2}$": monthFirst
? { type: "datetime", format: "%m/%d/%Y %H:%M:%S" }
: { type: "datetime", format: "%d/%m/%Y %H:%M:%S" },
// Object
"^\\{": { type: "object" },
// Array
"^\\[": { type: "array" },
// List
// TODO: Support commaDecimal
"^\\d+,\\d+$": { type: "list", itemType: "integer" },
"^[\\d.]+,[\\d.]+$": { type: "list", itemType: "number" },
};
return mapping;
}
function enhanceField(field, options) {
if (field.type === "string") {
field.format = options?.stringFormat ?? field.format;
}
else if (field.type === "integer") {
field.groupChar = options?.groupChar ?? field.groupChar;
field.bareNumber = options?.bareNumber ?? field.bareNumber;
}
else if (field.type === "number") {
field.decimalChar = options?.decimalChar ?? field.decimalChar;
field.groupChar = options?.groupChar ?? field.groupChar;
field.bareNumber = options?.bareNumber ?? field.bareNumber;
}
else if (field.type === "boolean") {
field.trueValues = options?.trueValues ?? field.trueValues;
field.falseValues = options?.falseValues ?? field.falseValues;
}
else if (field.type === "datetime") {
field.format = options?.datetimeFormat ?? field.format;
}
else if (field.type === "date") {
field.format = options?.dateFormat ?? field.format;
}
else if (field.type === "time") {
field.format = options?.timeFormat ?? field.format;
}
else if (field.type === "list") {
field.delimiter = options?.listDelimiter ?? field.delimiter;
field.itemType = options?.listItemType ?? field.itemType;
}
else if (field.type === "geopoint") {
field.format = options?.geopointFormat ?? field.format;
}
else if (field.type === "geojson") {
field.format = options?.geojsonFormat ?? field.format;
}
}
function enhanceSchema(schema, options) {
schema.missingValues = options?.missingValues ?? schema.missingValues;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5mZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zY2hlbWEvaW5mZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUNuQyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sb0JBQW9CLENBQUE7QUFlcEQsTUFBTSxDQUFDLEtBQUssVUFBVSxvQkFBb0IsQ0FDeEMsS0FBWSxFQUNaLE9BQTRCO0lBRTVCLE1BQU0sRUFBRSxVQUFVLEdBQUcsR0FBRyxFQUFFLEdBQUcsT0FBTyxJQUFJLEVBQUUsQ0FBQTtJQUUxQyxNQUFNLE1BQU0sR0FBRyxNQUFNLEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUE7SUFDckQsT0FBTyxxQkFBcUIsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUE7QUFDL0MsQ0FBQztBQUVELE1BQU0sVUFBVSxxQkFBcUIsQ0FDbkMsTUFBaUIsRUFDakIsT0FBbUQ7SUFFbkQsTUFBTSxFQUFFLFVBQVUsR0FBRyxHQUFHLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxHQUFHLE9BQU8sSUFBSSxFQUFFLENBQUE7SUFFbkUsTUFBTSxXQUFXLEdBQUcsaUJBQWlCLEVBQUUsQ0FBQTtJQUN2QyxNQUFNLFlBQVksR0FBRyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsQ0FBQTtJQUVoRCxNQUFNLFlBQVksR0FBRyxlQUFlLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBQ25ELE1BQU0sVUFBVSxHQUFHLE9BQU8sRUFBRSxVQUFVLElBQUksWUFBWSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUE7SUFFOUUsTUFBTSxnQkFBZ0IsR0FDcEIsTUFBTSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxN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LEVBQUUsYUFBYSxJQUFJLEtBQUssQ0FBQyxTQUFTLENBQUE7UUFDM0QsS0FBSyxDQUFDLFFBQVEsR0FBRyxPQUFPLEVBQUUsWUFBWSxJQUFJLEtBQUssQ0FBQyxRQUFRLENBQUE7SUFDMUQsQ0FBQztTQUFNLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxVQUFVLEVBQUUsQ0FBQztRQUNyQyxLQUFLLENBQUMsTUFBTSxHQUFHLE9BQU8sRUFBRSxjQUFjLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQTtJQUN4RCxDQUFDO1NBQU0sSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ3BDLEtBQUssQ0FBQyxNQUFNLEdBQUcsT0FBTyxFQUFFLGFBQWEsSUFBSSxLQUFLLENBQUMsTUFBTSxDQUFBO0lBQ3ZELENBQUM7QUFDSCxDQUFDO0FBRUQsU0FBUyxhQUFhLENBQUMsTUFBYyxFQUFFLE9BQTRCO0lBQ2pFLE1BQU0sQ0FBQyxhQUFhLEdBQUcsT0FBTyxFQUFFLGFBQWEsSUFBSSxNQUFNLENBQUMsYUFBYSxDQUFBO0FBQ3ZFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IEZpZWxkLCBTY2hlbWEgfSBmcm9tIFwiQGRwa2l0L2NvcmVcIlxuaW1wb3J0IHR5cGUgeyBEYXRhRnJhbWUgfSBmcm9tIFwibm9kZWpzLXBvbGFyc1wiXG5pbXBvcnQgeyBjb2wgfSBmcm9tIFwibm9kZWpzLXBvbGFyc1wiXG5pbXBvcnQgeyBnZXRQb2xhcnNTY2hlbWEgfSBmcm9tIFwiLi4vc2NoZW1hL2luZGV4LnRzXCJcbmltcG9ydCB0eXBlIHsgVGFibGUgfSBmcm9tIFwiLi4vdGFibGUvaW5kZXgudHNcIlxuaW1wb3J0IHR5cGUgeyBTY2hlbWFPcHRpb25zIH0gZnJvbSBcIi4vT3B0aW9ucy50c1wiXG5cbi8vIFRPRE86IEltcGxlbWVudCBhY3R1YWwgb3B0aW9ucyB1c2FnZSBmb3IgaW5mZXJyaW5nXG4vLyBUT0RPOiBSZXZpZXcgZGVmYXVsdCB2YWx1ZXMgYmVpbmcge2ZpZWxkczogW119IHZzIHVuZGVmaW5lZFxuXG5leHBvcnQgaW50ZXJmYWNlIEluZmVyU2NoZW1hT3B0aW9ucyBleHRlbmRzIFNjaGVtYU9wdGlvbnMge1xuICBzYW1wbGVSb3dzPzogbnVtYmVyXG4gIGNvbmZpZGVuY2U/OiBudW1iZXJcbiAgY29tbWFEZWNpbWFsPzogYm9vbGVhblxuICBtb250aEZpcnN0PzogYm9vbGVhblxuICBrZWVwU3RyaW5ncz86IGJvb2xlYW5cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGluZmVyU2NoZW1hRnJvbVRhYmxlKFxuICB0YWJsZTogVGFibGUsXG4gIG9wdGlvbnM/OiBJbmZlclNjaGVtYU9wdGlvbnMsXG4pIHtcbiAgY29uc3QgeyBzYW1wbGVSb3dzID0gMTAwIH0gPSBvcHRpb25zID8/IHt9XG5cbiAgY29uc3Qgc2FtcGxlID0gYXdhaXQgdGFibGUuaGVhZChzYW1wbGVSb3dzKS5jb2xsZWN0KClcbiAgcmV0dXJuIGluZmVyU2NoZW1hRnJvbVNhbXBsZShzYW1wbGUsIG9wdGlvbnMpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpbmZlclNjaGVtYUZyb21TYW1wbGUoXG4gIHNhbXBsZTogRGF0YUZyYW1lLFxuICBvcHRpb25zPzogRXhjbHVkZTxJbmZlclNjaGVtYU9wdGlvbnMsIFwic2FtcGxlUm93c1wiPixcbikge1xuICBjb25zdCB7IGNvbmZpZGVuY2UgPSAwLjksIGZpZWxkVHlwZXMsIGtlZXBTdHJpbmdzIH0gPSBvcHRpb25zID8/IHt9XG5cbiAgY29uc3QgdHlwZU1hcHBpbmcgPSBjcmVhdGVUeXBlTWFwcGluZygpXG4gIGNvbnN0IHJlZ2V4TWFwcGluZyA9IGNyZWF0ZVJlZ2V4TWFwcGluZyhvcHRpb25zKVxuXG4gIGNvbnN0IHBvbGFyc1NjaGVtYSA9IGdldFBvbGFyc1NjaGVtYShzYW1wbGUuc2NoZW1hKVxuICBjb25zdCBmaWVsZE5hbWVzID0gb3B0aW9ucz8uZmllbGROYW1lcyA/PyBwb2xhcnNTY2hlbWEuZmllbGRzLm1hcChmID0+IGYubmFtZSlcblxuICBjb25zdCBmYWlsdXJlVGhyZXNob2xkID1cbiAgICBzYW1wbGUuaGVpZ2h0IC0gTWF0aC5mbG9vcihzYW1wbGUuaGVpZ2h0ICogY29uZmlkZW5jZSkgfHwgMVxuXG4gIGNvbnN0IHNjaGVtYTogU2NoZW1hID0ge1xuICAgIGZpZWxkczogW10sXG4gIH1cblxuICBmb3IgKGNvbnN0IG5hbWUgb2YgZmllbGROYW1lcykge1xuICAgIGNvbnN0IHBvbGFyc0ZpZWxkID0gcG9sYXJzU2NoZW1hLmZpZWxkcy5maW5kKGYgPT4gZi5uYW1lID09PSBuYW1lKVxuICAgIGlmICghcG9sYXJzRmllbGQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRmllbGQgXCIke25hbWV9XCIgbm90IGZvdW5kIGluIHRoZSB0YWJsZWApXG4gICAgfVxuXG4gICAgLy8gVE9ETzogUmVtb3ZlIHRoaXMgd29ya2Fyb3VuZCBvbmNlIHRoZSBpc3N1ZSBpcyBmaXhlZFxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9wb2xhLXJzL25vZGVqcy1wb2xhcnMvaXNzdWVzLzM3MlxuICAgIGxldCB2YXJpYW50ID0gcG9sYXJzRmllbGQudHlwZS52YXJpYW50IGFzIHN0cmluZ1xuICAgIGlmICghdHlwZU1hcHBpbmdbdmFyaWFudF0pIHtcbiAgICAgIHZhcmlhbnQgPSB2YXJpYW50LnNsaWNlKDAsIC0xKVxuICAgIH1cblxuICAgIGxldCB0eXBlID0gZmllbGRUeXBlcz8uW25hbWVdID8/IHR5cGVNYXBwaW5nW3ZhcmlhbnRdID8/IFwiYW55XCJcblxuICAgIGlmICh0eXBlID09PSBcImFycmF5XCIgJiYgb3B0aW9ucz8uYXJyYXlUeXBlID09PSBcImxpc3RcIikge1xuICAgICAgdHlwZSA9IFwibGlzdFwiXG4gICAgfVxuXG4gICAgbGV0IGZpZWxkID0geyBuYW1lLCB0eXBlIH1cbiAgICBpZiAoIWtlZXBTdHJpbmdzICYmIHR5cGUgPT09IFwic3RyaW5nXCIgJiYgIWZpZWxkVHlwZXM/LltuYW1lXSkge1xuICAgICAgZm9yIChjb25zdCBbcmVnZXgsIHBhdGNoXSBvZiBPYmplY3QuZW50cmllcyhyZWdleE1hcHBpbmcpKSB7XG4gICAgICAgIGNvbnN0IGZhaWx1cmVzID0gc2FtcGxlXG4gICAgICAgICAgLmZpbHRlcihjb2wobmFtZSkuc3RyLmNvbnRhaW5zKHJlZ2V4KS5ub3QoKSlcbiAgICAgICAgICAuaGVhZChmYWlsdXJlVGhyZXNob2xkKS5oZWlnaHRcbiAgICAgICAgaWYgKGZhaWx1cmVzIDwgZmFpbHVyZVRocmVzaG9sZCkge1xuICAgICAgICAgIGZpZWxkID0geyAuLi5maWVsZCwgLi4ucGF0Y2ggfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBlbmhhbmNlRmllbGQoZmllbGQsIG9wdGlvbnMpXG4gICAgc2NoZW1hLmZpZWxkcy5wdXNoKGZpZWxkKVxuICB9XG5cbiAgZW5oYW5jZVNjaGVtYShzY2hlbWEsIG9wdGlvbnMpXG4gIHJldHVybiBzY2hlbWFcbn1cblxuZnVuY3Rpb24gY3JlYXRlVHlwZU1hcHBpbmcoKSB7XG4gIGNvbnN0IG1hcHBpbmc6IFJlY29yZDxzdHJpbmcsIEZpZWxkW1widHlwZVwiXT4gPSB7XG4gICAgQXJyYXk6IFwiYXJyYXlcIixcbiAgICBCb29sOiBcImJvb2xlYW5cIixcbiAgICBDYXRlZ29yaWNhbDogXCJzdHJpbmdcIixcbiAgICBEYXRlOiBcImRhdGVcIixcbiAgICBEYXRldGltZTogXCJkYXRldGltZVwiLFxuICAgIERlY2ltYWw6IFwibnVtYmVyXCIsXG4gICAgRmxvYXQzMjogXCJudW1iZXJcIixcbiAgICBGbG9hdDY0OiBcIm51bWJlclwiLFxuICAgIEludDE2OiBcImludGVnZXJcIixcbiAgICBJbnQzMjogXCJpbnRlZ2VyXCIsXG4gICAgSW50NjQ6IFwiaW50ZWdlclwiLFxuICAgIEludDg6IFwiaW50ZWdlclwiLFxuICAgIExpc3Q6IFwiYXJyYXlcIixcbiAgICBOdWxsOiBcImFueVwiLFxuICAgIE9iamVjdDogXCJvYmplY3RcIixcbiAgICBTdHJpbmc6IFwic3RyaW5nXCIsXG4gICAgU3RydWN0OiBcIm9iamVjdFwiLFxuICAgIFRpbWU6IFwidGltZVwiLFxuICAgIFVJbnQxNjogXCJpbnRlZ2VyXCIsXG4gICAgVUludDMyOiBcImludGVnZXJcIixcbiAgICBVSW50NjQ6IFwiaW50ZWdlclwiLFxuICAgIFVJbnQ4OiBcImludGVnZXJcIixcbiAgICBVdGY4OiBcInN0cmluZ1wiLFxuICB9XG5cbiAgcmV0dXJuIG1hcHBpbmdcbn1cblxuZnVuY3Rpb24gY3JlYXRlUmVnZXhNYXBwaW5nKG9wdGlvbnM/OiBJbmZlclNjaGVtYU9wdGlvbnMpIHtcbiAgY29uc3QgeyBjb21tYURlY2ltYWwsIG1vbnRoRmlyc3QgfSA9IG9wdGlvbnMgPz8ge31cblxuICBjb25zdCBtYXBwaW5nOiBSZWNvcmQ8c3RyaW5nLCBQYXJ0aWFsPEZpZWxkPj4gPSB7XG4gICAgLy8gTnVtZXJpY1xuICAgIFwiXlxcXFxkKyRcIjogeyB0eXBlOiBcImludGVnZXJcIiB9LFxuICAgIFwiXlxcXFxkezEsM30oLFxcXFxkezN9KSskXCI6IGNvbW1hRGVjaW1hbFxuICAgICAgPyB7IHR5cGU6IFwibnVtYmVyXCIgfVxuICAgICAgOiB7IHR5cGU6IFwiaW50ZWdlclwiLCBncm91cENoYXI6IFwiLFwiIH0sXG4gICAgXCJeXFxcXGQrXFxcXC5cXFxcZCskXCI6IGNvbW1hRGVjaW1hbFxuICAgICAgPyB7IHR5cGU6IFwiaW50ZWdlclwiLCBncm91cENoYXI6IFwiLlwiIH1cbiAgICAgIDogeyB0eXBlOiBcIm51bWJlclwiIH0sXG4gICAgXCJeXFxcXGR7MSwzfSgsXFxcXGR7M30pK1xcXFwuXFxcXGQrJFwiOiB7IHR5cGU6IFwibnVtYmVyXCIsIGdyb3VwQ2hhcjogXCIsXCIgfSxcbiAgICBcIl5cXFxcZHsxLDN9KFxcXFwuXFxcXGR7M30pKyxcXFxcZCskXCI6IHtcbiAgICAgIHR5cGU6IFwibnVtYmVyXCIsXG4gICAgICBncm91cENoYXI6IFwiLlwiLFxuICAgICAgZGVjaW1hbENoYXI6IFwiLFwiLFxuICAgIH0sXG5cbiAgICAvLyBCb29sZWFuXG4gICAgXCJeKHRydWV8VHJ1ZXxUUlVFfGZhbHNlfEZhbHNlfEZBTFNFKSRcIjogeyB0eXBlOiBcImJvb2xlYW5cIiB9LFxuXG4gICAgLy8gRGF0ZVxuICAgIFwiXlxcXFxkezR9LVxcXFxkezJ9LVxcXFxkezJ9JFwiOiB7IHR5cGU6IFwiZGF0ZVwiIH0sXG4gICAgXCJeXFxcXGR7NH0vXFxcXGR7Mn0vXFxcXGR7Mn0kXCI6IHsgdHlwZTogXCJkYXRlXCIsIGZvcm1hdDogXCIlWS8lbS8lZFwiIH0sXG4gICAgXCJeXFxcXGR7Mn0vXFxcXGR7Mn0vXFxcXGR7NH0kXCI6IG1vbnRoRmlyc3RcbiAgICAgID8geyB0eXBlOiBcImRhdGVcIiwgZm9ybWF0OiBcIiVtLyVkLyVZXCIgfVxuICAgICAgOiB7IHR5cGU6IFwiZGF0ZVwiLCBmb3JtYXQ6IFwiJWQvJW0vJVlcIiB9LFxuICAgIFwiXlxcXFxkezJ9LVxcXFxkezJ9LVxcXFxkezR9JFwiOiBtb250aEZpcnN0XG4gICAgICA/IHsgdHlwZTogXCJkYXRlXCIsIGZvcm1hdDogXCIlbS0lZC0lWVwiIH1cbiAgICAgIDogeyB0eXBlOiBcImRhdGVcIiwgZm9ybWF0OiBcIiVkLSVtLSVZXCIgfSxcbiAgICBcIl5cXFxcZHsyfVxcXFwuXFxcXGR7Mn1cXFxcLlxcXFxkezR9JFwiOiBtb250aEZpcnN0XG4gICAgICA/IHsgdHlwZTogXCJkYXRlXCIsIGZvcm1hdDogXCIlbS4lZC4lWVwiIH1cbiAgICAgIDogeyB0eXBlOiBcImRhdGVcIiwgZm9ybWF0OiBcIiVkLiVtLiVZXCIgfSxcblxuICAgIC8vIFRpbWVcbiAgICBcIl5cXFxcZHsyfTpcXFxcZHsyfTpcXFxcZHsyfSRcIjogeyB0eXBlOiBcInRpbWVcIiB9LFxuICAgIFwiXlxcXFxkezJ9OlxcXFxkezJ9JFwiOiB7IHR5cGU6IFwidGltZVwiLCBmb3JtYXQ6IFwiJUg6JU1cIiB9LFxuICAgIFwiXlxcXFxkezEsMn06XFxcXGR7Mn06XFxcXGR7Mn1cXFxccyooYW18cG18QU18UE0pJFwiOiB7XG4gICAgICB0eXBlOiBcInRpbWVcIixcbiAgICAgIGZvcm1hdDogXCIlSTolTTolUyAlcFwiLFxuICAgIH0sXG4gICAgXCJeXFxcXGR7MSwyfTpcXFxcZHsyfVxcXFxzKihhbXxwbXxBTXxQTSkkXCI6IHsgdHlwZTogXCJ0aW1lXCIsIGZvcm1hdDogXCIlSTolTSAlcFwiIH0sXG4gICAgXCJeXFxcXGR7Mn06XFxcXGR7Mn06XFxcXGR7Mn1bKy1dXFxcXGR7Mn06P1xcXFxkezJ9JFwiOiB7IHR5cGU6IFwidGltZVwiIH0sXG5cbiAgICAvLyBEYXRldGltZSAtIElTTyBmb3JtYXRcbiAgICBcIl5cXFxcZHs0fS1cXFxcZHsyfS1cXFxcZHsyfVRcXFxcZHsyfTpcXFxcZHsyfTpcXFxcZHsyfVo/JFwiOiB7IHR5cGU6IFwiZGF0ZXRpbWVcIiB9LFxuICAgIFwiXlxcXFxkezR9LVxcXFxkezJ9LVxcXFxkezJ9VFxcXFxkezJ9OlxcXFxkezJ9OlxcXFxkezJ9WystXVxcXFxkezJ9Oj9cXFxcZHsyfSRcIjoge1xuICAgICAgdHlwZTogXCJkYXRldGltZVwiLFxuICAgIH0sXG4gICAgXCJeXFxcXGR7NH0tXFxcXGR7Mn0tXFxcXGR7Mn0gXFxcXGR7Mn06XFxcXGR7Mn06XFxcXGR7Mn0kXCI6IHtcbiAgICAgIHR5cGU6IFwiZGF0ZXRpbWVcIixcbiAgICAgIGZvcm1hdDogXCIlWS0lbS0lZCAlSDolTTolU1wiLFxuICAgIH0sXG4gICAgXCJeXFxcXGR7Mn0vXFxcXGR7Mn0vXFxcXGR7NH0gXFxcXGR7Mn06XFxcXGR7Mn0kXCI6IG1vbnRoRmlyc3RcbiAgICAgID8geyB0eXBlOiBcImRhdGV0aW1lXCIsIGZvcm1hdDogXCIlbS8lZC8lWSAlSDolTVwiIH1cbiAgICAgIDogeyB0eXBlOiBcImRhdGV0aW1lXCIsIGZvcm1hdDogXCIlZC8lbS8lWSAlSDolTVwiIH0sXG4gICAgXCJeXFxcXGR7Mn0vXFxcXGR7Mn0vXFxcXGR7NH0gXFxcXGR7Mn06XFxcXGR7Mn06XFxcXGR7Mn0kXCI6IG1vbnRoRmlyc3RcbiAgICAgID8geyB0eXBlOiBcImRhdGV0aW1lXCIsIGZvcm1hdDogXCIlbS8lZC8lWSAlSDolTTolU1wiIH1cbiAgICAgIDogeyB0eXBlOiBcImRhdGV0aW1lXCIsIGZvcm1hdDogXCIlZC8lbS8lWSAlSDolTTolU1wiIH0sXG5cbiAgICAvLyBPYmplY3RcbiAgICBcIl5cXFxce1wiOiB7IHR5cGU6IFwib2JqZWN0XCIgfSxcblxuICAgIC8vIEFycmF5XG4gICAgXCJeXFxcXFtcIjogeyB0eXBlOiBcImFycmF5XCIgfSxcblxuICAgIC8vIExpc3RcbiAgICAvLyBUT0RPOiBTdXBwb3J0IGNvbW1hRGVjaW1hbFxuICAgIFwiXlxcXFxkKyxcXFxcZCskXCI6IHsgdHlwZTogXCJsaXN0XCIsIGl0ZW1UeXBlOiBcImludGVnZXJcIiB9LFxuICAgIFwiXltcXFxcZC5dKyxbXFxcXGQuXSskXCI6IHsgdHlwZTogXCJsaXN0XCIsIGl0ZW1UeXBlOiBcIm51bWJlclwiIH0sXG4gIH1cblxuICByZXR1cm4gbWFwcGluZ1xufVxuXG5mdW5jdGlvbiBlbmhhbmNlRmllbGQoZmllbGQ6IEZpZWxkLCBvcHRpb25zPzogSW5mZXJTY2hlbWFPcHRpb25zKSB7XG4gIGlmIChmaWVsZC50eXBlID09PSBcInN0cmluZ1wiKSB7XG4gICAgZmllbGQuZm9ybWF0ID0gb3B0aW9ucz8uc3RyaW5nRm9ybWF0ID8/IGZpZWxkLmZvcm1hdFxuICB9IGVsc2UgaWYgKGZpZWxkLnR5cGUgPT09IFwiaW50ZWdlclwiKSB7XG4gICAgZmllbGQuZ3JvdXBDaGFyID0gb3B0aW9ucz8uZ3JvdXBDaGFyID8/IGZpZWxkLmdyb3VwQ2hhclxuICAgIGZpZWxkLmJhcmVOdW1iZXIgPSBvcHRpb25zPy5iYXJlTnVtYmVyID8/IGZpZWxkLmJhcmVOdW1iZXJcbiAgfSBlbHNlIGlmIChmaWVsZC50eXBlID09PSBcIm51bWJlclwiKSB7XG4gICAgZmllbGQuZGVjaW1hbENoYXIgPSBvcHRpb25zPy5kZWNpbWFsQ2hhciA/PyBmaWVsZC5kZWNpbWFsQ2hhclxuICAgIGZpZWxkLmdyb3VwQ2hhciA9IG9wdGlvbnM/Lmdyb3VwQ2hhciA/PyBmaWVsZC5ncm91cENoYXJcbiAgICBmaWVsZC5iYXJlTnVtYmVyID0gb3B0aW9ucz8uYmFyZU51bWJlciA/PyBmaWVsZC5iYXJlTnVtYmVyXG4gIH0gZWxzZSBpZiAoZmllbGQudHlwZSA9PT0gXCJib29sZWFuXCIpIHtcbiAgICBmaWVsZC50cnVlVmFsdWVzID0gb3B0aW9ucz8udHJ1ZVZhbHVlcyA/PyBmaWVsZC50cnVlVmFsdWVzXG4gICAgZmllbGQuZmFsc2VWYWx1ZXMgPSBvcHRpb25zPy5mYWxzZVZhbHVlcyA/PyBmaWVsZC5mYWxzZVZhbHVlc1xuICB9IGVsc2UgaWYgKGZpZWxkLnR5cGUgPT09IFwiZGF0ZXRpbWVcIikge1xuICAgIGZpZWxkLmZvcm1hdCA9IG9wdGlvbnM/LmRhdGV0aW1lRm9ybWF0ID8/IGZpZWxkLmZvcm1hdFxuICB9IGVsc2UgaWYgKGZpZWxkLnR5cGUgPT09IFwiZGF0ZVwiKSB7XG4gICAgZmllbGQuZm9ybWF0ID0gb3B0aW9ucz8uZGF0ZUZvcm1hdCA/PyBmaWVsZC5mb3JtYXRcbiAgfSBlbHNlIGlmIChmaWVsZC50eXBlID09PSBcInRpbWVcIikge1xuICAgIGZpZWxkLmZvcm1hdCA9IG9wdGlvbnM/LnRpbWVGb3JtYXQgPz8gZmllbGQuZm9ybWF0XG4gIH0gZWxzZSBpZiAoZmllbGQudHlwZSA9PT0gXCJsaXN0XCIpIHtcbiAgICBmaWVsZC5kZWxpbWl0ZXIgPSBvcHRpb25zPy5saXN0RGVsaW1pdGVyID8/IGZpZWxkLmRlbGltaXRlclxuICAgIGZpZWxkLml0ZW1UeXBlID0gb3B0aW9ucz8ubGlzdEl0ZW1UeXBlID8/IGZpZWxkLml0ZW1UeXBlXG4gIH0gZWxzZSBpZiAoZmllbGQudHlwZSA9PT0gXCJnZW9wb2ludFwiKSB7XG4gICAgZmllbGQuZm9ybWF0ID0gb3B0aW9ucz8uZ2VvcG9pbnRGb3JtYXQgPz8gZmllbGQuZm9ybWF0XG4gIH0gZWxzZSBpZiAoZmllbGQudHlwZSA9PT0gXCJnZW9qc29uXCIpIHtcbiAgICBmaWVsZC5mb3JtYXQgPSBvcHRpb25zPy5nZW9qc29uRm9ybWF0ID8/IGZpZWxkLmZvcm1hdFxuICB9XG59XG5cbmZ1bmN0aW9uIGVuaGFuY2VTY2hlbWEoc2NoZW1hOiBTY2hlbWEsIG9wdGlvbnM/OiBJbmZlclNjaGVtYU9wdGlvbnMpIHtcbiAgc2NoZW1hLm1pc3NpbmdWYWx1ZXMgPSBvcHRpb25zPy5taXNzaW5nVmFsdWVzID8/IHNjaGVtYS5taXNzaW5nVmFsdWVzXG59XG4iXX0=