UNPKG

@dpkit/table

Version:

Data Package implementation in TypeScript.

185 lines 26.8 kB
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=