270 lines
36 KiB
JavaScript
270 lines
36 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.toTypescript = void 0;
|
|
const type_1 = require("./type");
|
|
const type_of_1 = require("./checks/type-of");
|
|
const instance_of_1 = require("./checks/instance-of");
|
|
const value_1 = require("./checks/value");
|
|
const array_1 = require("./checks/array");
|
|
const struct_1 = require("./checks/struct");
|
|
const map_1 = require("./checks/map");
|
|
const set_1 = require("./checks/set");
|
|
const any_1 = require("./checks/any");
|
|
const is_1 = require("./checks/is");
|
|
function toTypescript(...args) {
|
|
if (args.length === 2) {
|
|
const [type, userOpts] = args;
|
|
const opts = Object.assign({ indent: " ", indentLevel: 0 }, userOpts);
|
|
// assignToType is only valid at the top level, so delete it if it exists
|
|
delete opts.assignToType;
|
|
const ts = toTS(type, opts);
|
|
if (userOpts.assignToType)
|
|
return `type ${userOpts.assignToType} = ${ts};`;
|
|
return ts;
|
|
}
|
|
const arg = args[0];
|
|
if (arg instanceof type_1.Type)
|
|
return toTypescript(arg, {});
|
|
const keys = Object.keys(arg);
|
|
if (keys.length === 0)
|
|
return "";
|
|
const output = [];
|
|
for (const key of keys) {
|
|
const refs = Object.assign({}, arg);
|
|
delete refs[key];
|
|
output.push(toTypescript(arg[key], {
|
|
useReference: refs,
|
|
assignToType: key,
|
|
}));
|
|
}
|
|
return output.join("\n\n");
|
|
}
|
|
exports.toTypescript = toTypescript;
|
|
function toTS(type, opts) {
|
|
if (opts.useReference) {
|
|
for (const key in opts.useReference) {
|
|
const val = opts.useReference[key];
|
|
if (val === type)
|
|
return key;
|
|
}
|
|
}
|
|
if (type instanceof type_1.Comment)
|
|
return fromComment(type, opts);
|
|
if (type instanceof type_1.Either)
|
|
return fromEither(type, opts);
|
|
if (type instanceof type_1.DefaultIntersect)
|
|
return fromIntersect(type, opts);
|
|
if (type instanceof struct_1.MergeIntersect)
|
|
return fromIntersect(type, opts);
|
|
if (type instanceof type_1.Validation)
|
|
return fromValidation();
|
|
if (type instanceof type_of_1.TypeOf)
|
|
return fromTypeof(type);
|
|
if (type instanceof instance_of_1.InstanceOf)
|
|
return fromInstanceOf(type);
|
|
if (type instanceof value_1.Value)
|
|
return fromValue(type);
|
|
if (type instanceof array_1.Arr)
|
|
return fromArr(type, opts);
|
|
if (type instanceof struct_1.Struct)
|
|
return fromStruct(type, opts);
|
|
if (type instanceof struct_1.Dict)
|
|
return fromDict(type, opts);
|
|
if (type instanceof map_1.MapType)
|
|
return fromMap(type, opts);
|
|
if (type instanceof set_1.SetType)
|
|
return fromSet(type, opts);
|
|
if (type instanceof any_1.Any)
|
|
return fromAny();
|
|
if (type instanceof is_1.Is)
|
|
return fromIs(type);
|
|
if (type instanceof struct_1.PartialStruct)
|
|
return fromPartial(type, opts);
|
|
return fromNever(type);
|
|
}
|
|
function fromPartial(p, opts) {
|
|
return `Partial<${toTS(p.struct, opts)}>`;
|
|
}
|
|
function fromComment(c, opts) {
|
|
const i = indent(opts);
|
|
const commentLines = formatCommentString(c.commentStr, opts);
|
|
return `${commentLines}\n${i}${toTS(c.wrapped, opts)}`;
|
|
}
|
|
function formatCommentString(commentStr, opts) {
|
|
const i = indent(opts);
|
|
const commentLines = commentStr.split("\n").map(line => {
|
|
return line.trim();
|
|
}).filter(line => line !== "");
|
|
if (commentLines.length === 0)
|
|
return "";
|
|
if (commentLines.length === 1) {
|
|
return `// ${commentLines[0]}`;
|
|
}
|
|
const lines = ['/*'];
|
|
for (const line of commentLines) {
|
|
lines.push(`${i} * ${line.trim()}`);
|
|
}
|
|
lines.push(`${i} */`);
|
|
return lines.join("\n");
|
|
}
|
|
// TODO: Should either strip immediate-child comments?
|
|
function fromEither(e, opts) {
|
|
const i = indent(opts);
|
|
return [
|
|
toTS(e.l, opts),
|
|
`${i}${opts.indent}| ${toTS(e.r, Object.assign(Object.assign({}, opts), { indentLevel: opts.indentLevel + 1 }))}`,
|
|
].join("\n");
|
|
}
|
|
// TODO: Should intersect strip immediate-child comments?
|
|
function fromIntersect(i, opts) {
|
|
// Handle validations chained with actual TS types, converting them to comments
|
|
if (i.l instanceof type_1.Validation)
|
|
return toTS(new type_1.Comment(i.l.desc, i.r), opts);
|
|
if (i.r instanceof type_1.Validation)
|
|
return toTS(new type_1.Comment(i.r.desc, i.l), opts);
|
|
const indentation = indent(opts);
|
|
return [
|
|
toTS(i.l, opts),
|
|
`${indentation}${opts.indent}& ${toTS(i.r, Object.assign(Object.assign({}, opts), { indentLevel: opts.indentLevel + 1 }))}`,
|
|
].join("\n");
|
|
}
|
|
function fromValidation() {
|
|
throw new Error("Can't convert arbitrary validation functions to TypeScript types; make sure to .and() it " +
|
|
"with a valid type, and it will be converted into a comment above the type");
|
|
}
|
|
function fromTypeof(t) {
|
|
switch (t.typestring) {
|
|
case "undefined": return t.typestring;
|
|
case "object": return "Object";
|
|
case "boolean": return t.typestring;
|
|
case "number": return t.typestring;
|
|
case "string": return t.typestring;
|
|
case "symbol": return "Symbol";
|
|
case "function": return "Function";
|
|
case "bigint": return "bigint";
|
|
}
|
|
}
|
|
function fromInstanceOf(i) {
|
|
if (!i.klass.name)
|
|
throw new Error("Can't convert anonymous classes to TypeScript");
|
|
return `${i.klass.name}`;
|
|
}
|
|
function fromValue(v) {
|
|
const vType = typeof v.val;
|
|
if (vType !== "string" && vType !== "number" && vType !== "boolean" && v.val !== null && v.val !== undefined) {
|
|
throw new Error("Only string, numeric, undefined, boolean, and null value types can be auto-converted to TypeScript");
|
|
}
|
|
if (vType === "string")
|
|
return JSON.stringify(v.val);
|
|
return `${v.val}`;
|
|
}
|
|
function fromArr(a, opts) {
|
|
return `Array<${toTS(a.elementType, opts)}>`;
|
|
}
|
|
function fromStruct(s, opts) {
|
|
const lines = ["{"];
|
|
const keyOpts = Object.assign(Object.assign({}, opts), { indentLevel: opts.indentLevel + 1 });
|
|
const keyIndent = indent(keyOpts);
|
|
const keys = Object.keys(s.definition);
|
|
for (let i = 0; i < keys.length; i++) {
|
|
const key = keys[i];
|
|
const keyType = [key];
|
|
const val = s.definition[key];
|
|
if (val instanceof struct_1.MissingKey) {
|
|
throw new Error("missing(...) fields can't be represented in TypeScript; consider using optional(...)");
|
|
}
|
|
if (val instanceof struct_1.OptionalKey)
|
|
keyType.push("?");
|
|
keyType.push(": ");
|
|
const stripped = stripOuterComments(val);
|
|
if (stripped.comments.length > 0) {
|
|
// Visually separate the start of a commented field unless it's the first field
|
|
if (i !== 0) {
|
|
// But don't double-newline if you already separated the last line
|
|
if (lines[lines.length - 1] !== "")
|
|
lines.push("");
|
|
}
|
|
// Put the comment on the line above the key
|
|
lines.push(keyIndent + formatCommentString(stripped.comments.join("\n"), keyOpts));
|
|
}
|
|
keyType.push(toTS(stripped.inner, keyOpts));
|
|
keyType.push(",");
|
|
lines.push(keyIndent + keyType.join(""));
|
|
// Visually separate the end of a commented field, unless it's the last field
|
|
if (stripped.comments.length > 0 && i !== keys.length - 1)
|
|
lines.push("");
|
|
}
|
|
lines.push(indent(opts) + "}");
|
|
return lines.join("\n");
|
|
}
|
|
function stripOuterComments(t) {
|
|
if (t instanceof struct_1.OptionalKey)
|
|
return stripOuterComments(t.type);
|
|
if (t instanceof type_1.Comment) {
|
|
const inner = stripOuterComments(t.wrapped);
|
|
return {
|
|
comments: [t.commentStr, ...inner.comments],
|
|
inner: inner.inner,
|
|
};
|
|
}
|
|
const algebra = [type_1.DefaultIntersect, struct_1.MergeIntersect, type_1.Either];
|
|
for (const al of algebra) {
|
|
if (t instanceof al) {
|
|
if (t.l instanceof type_1.Validation) {
|
|
return stripOuterComments(new type_1.Comment(t.l.desc, t.r));
|
|
}
|
|
if (t.r instanceof type_1.Validation) {
|
|
return stripOuterComments(new type_1.Comment(t.r.desc, t.l));
|
|
}
|
|
if (t.l instanceof type_1.Comment) {
|
|
return stripOuterComments(handleStripAlgebra(t.l.commentStr, t.l.wrapped, t.r, al));
|
|
}
|
|
if (t.r instanceof type_1.Comment) {
|
|
return stripOuterComments(handleStripAlgebra(t.r.commentStr, t.l, t.r.wrapped, al));
|
|
}
|
|
}
|
|
}
|
|
return {
|
|
comments: [],
|
|
inner: t,
|
|
};
|
|
}
|
|
function handleStripAlgebra(desc, r, l, constr) {
|
|
return new type_1.Comment(desc, new constr(r, l));
|
|
}
|
|
function fromDict(d, opts) {
|
|
const i = indent(opts);
|
|
const valString = toTS(d.valueType, Object.assign(Object.assign({}, opts), { indentLevel: opts.indentLevel + 1 }));
|
|
// For single-line values, return a single-line dict
|
|
if (valString.indexOf("\n") < 0)
|
|
return `{[${d.namedKey}: string]: ${valString}}`;
|
|
// For multiline values, return a multiline dict
|
|
return [
|
|
"{",
|
|
`${i}${opts.indent}[${d.namedKey}: string]: ${valString}`,
|
|
`${i}}`,
|
|
].join("\n");
|
|
}
|
|
function fromMap(m, opts) {
|
|
const keyString = toTS(m.keyType, opts);
|
|
const valString = toTS(m.valueType, opts);
|
|
return `Map<${keyString}, ${valString}>`;
|
|
}
|
|
function fromSet(s, opts) {
|
|
const valString = toTS(s.valueType, opts);
|
|
return `Set<${valString}>`;
|
|
}
|
|
function fromAny() {
|
|
return "any";
|
|
}
|
|
function fromIs(i) {
|
|
return i.name;
|
|
}
|
|
// Despite not using the type, we take it to help ensure exhaustiveness checking in the toTS fn
|
|
function fromNever(_) {
|
|
return "never";
|
|
}
|
|
function indent(opts) {
|
|
return opts.indent.repeat(opts.indentLevel);
|
|
}
|
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG8tdHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9saWIvdG8tdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsaUNBQTZFO0FBQzdFLDhDQUEwQztBQUMxQyxzREFBa0Q7QUFDbEQsMENBQXVDO0FBQ3ZDLDBDQUFxQztBQUNyQyw0Q0FBdUc7QUFDdkcsc0NBQXVDO0FBQ3ZDLHNDQUF1QztBQUN2QyxzQ0FBbUM7QUFDbkMsb0NBQWlDO0FBcUJqQyxTQUFnQixZQUFZLENBQUMsR0FBRyxJQUFzRTtJQUNwRyxJQUFHLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDckIsTUFBTSxDQUFFLElBQUksRUFBRSxRQUFRLENBQUUsR0FBRyxJQUFJLENBQUM7UUFDaEMsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLENBQUMsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ3ZFLHlFQUF5RTtRQUN6RSxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7UUFFekIsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztRQUU1QixJQUFHLFFBQVEsQ0FBQyxZQUFZO1lBQUUsT0FBTyxRQUFRLFFBQVEsQ0FBQyxZQUFZLE1BQU0sRUFBRSxHQUFHLENBQUM7UUFDMUUsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQ25CLElBQUcsR0FBRyxZQUFZLFdBQUk7UUFBRSxPQUFPLFlBQVksQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFckQsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM5QixJQUFHLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQztRQUFFLE9BQU8sRUFB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LElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUM5QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVHlwZSwgQ29tbWVudCwgRWl0aGVyLCBEZWZhdWx0SW50ZXJzZWN0LCBWYWxpZGF0aW9uIH0gZnJvbSBcIi4vdHlwZVwiO1xuaW1wb3J0IHsgVHlwZU9mIH0gZnJvbSBcIi4vY2hlY2tzL3R5cGUtb2ZcIjtcbmltcG9ydCB7IEluc3RhbmNlT2YgfSBmcm9tIFwiLi9jaGVja3MvaW5zdGFuY2Utb2ZcIjtcbmltcG9ydCB7IFZhbHVlIH0gZnJvbSBcIi4vY2hlY2tzL3ZhbHVlXCI7XG5pbXBvcnQgeyBBcnIgfSBmcm9tIFwiLi9jaGVja3MvYXJyYXlcIjtcbmltcG9ydCB7IFBhcnRpYWxTdHJ1Y3QsIFN0cnVjdCwgTWlzc2luZ0tleSwgT3B0aW9uYWxLZXksIERpY3QsIE1lcmdlSW50ZXJzZWN0IH0gZnJvbSBcIi4vY2hlY2tzL3N0cnVjdFwiO1xuaW1wb3J0IHsgTWFwVHlwZSB9IGZyb20gXCIuL2NoZWNrcy9tYXBcIjtcbmltcG9ydCB7IFNldFR5cGUgfSBmcm9tIFwiLi9jaGVja3Mvc2V0XCI7XG5pbXBvcnQgeyBBbnkgfSBmcm9tIFwiLi9jaGVja3MvYW55XCI7XG5pbXBvcnQgeyBJcyB9IGZyb20gXCIuL2NoZWNrcy9pc1wiO1xuaW1wb3J0IHsgTmV2ZXIgfSBmcm9tIFwiLi9jaGVja3MvbmV2ZXJcIjtcbmltcG9ydCB7IEtpbmQgfSBmcm9tIFwiLi9raW5kXCI7XG5cbnR5cGUgVG9UeXBlc2NyaXB0T3B0cyA9IHtcbiAgdXNlUmVmZXJlbmNlPzoge1xuICAgIFtyZWY6IHN0cmluZ106IFR5cGU8YW55PixcbiAgfSxcblxuICBpbmRlbnQ6IHN0cmluZyxcbiAgaW5kZW50TGV2ZWw6IG51bWJlcixcbn07XG5cbmV4cG9ydCB0eXBlIFR5cGVzY3JpcHRVc2VyT3B0cyA9IFBhcnRpYWw8VG9UeXBlc2NyaXB0T3B0cz4gJiB7XG4gIGFzc2lnblRvVHlwZT86IHN0cmluZyxcbn07XG5cbnR5cGUgU2luZ2xlQ29udmVyc2lvbldpdGhPcHRzID0gWyB0eXBlOiBLaW5kLCB1c2VyT3B0czogVHlwZXNjcmlwdFVzZXJPcHRzIF07XG50eXBlIFNpbmdsZUNvbnZlcnNpb24gPSBbIHR5cGU6IEtpbmQgXTtcbnR5cGUgTXVsdGlwbGVDb252ZXJzaW9uID0gWyB0eXBlczogeyBbbmFtZTogc3RyaW5nXTogS2luZCB9IF07XG5cbmV4cG9ydCBmdW5jdGlvbiB0b1R5cGVzY3JpcHQoLi4uYXJnczogU2luZ2xlQ29udmVyc2lvbiB8IFNpbmdsZUNvbnZlcnNpb25XaXRoT3B0cyB8IE11bHRpcGxlQ29udmVyc2lvbik6IHN0cmluZyB7XG4gIGlmKGFyZ3MubGVuZ3RoID09PSAyKSB7XG4gICAgY29uc3QgWyB0eXBlLCB1c2VyT3B0cyBdID0gYXJncztcbiAgICBjb25zdCBvcHRzID0gT2JqZWN0LmFzc2lnbih7IGluZGVudDogXCIgIFwiLCBpbmRlbnRMZXZlbDogMCB9LCB1c2VyT3B0cyk7XG4gICAgLy8gYXNzaWduVG9UeXBlIGlzIG9ubHkgdmFsaWQgYXQgdGhlIHRvcCBsZXZlbCwgc28gZGVsZXRlIGl0IGlmIGl0IGV4aXN0c1xuICAgIGRlbGV0ZSBvcHRzLmFzc2lnblRvVHlwZTtcblxuICAgIGNvbnN0IHRzID0gdG9UUyh0eXBlLCBvcHRzKTtcblxuICAgIGlmKHVzZXJPcHRzLmFzc2lnblRvVHlwZSkgcmV0dXJuIGB0eXBlICR7dXNlck9wdHMuYXNzaWduVG9UeXBlfSA9ICR7dHN9O2A7XG4gICAgcmV0dXJuIHRzO1xuICB9XG5cbiAgY29uc3QgYXJnID0gYXJnc1swXVxuICBpZihhcmcgaW5zdGFuY2VvZiBUeXBlKSByZXR1cm4gdG9UeXBlc2NyaXB0KGFyZywge30pO1xuXG4gIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhhcmcpO1xuICBpZihrZXlzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIFwiXCI7XG4gIGNvbnN0IG91dHB1dDogc3RyaW5nW10gPSBbXTtcbiAgZm9yKGNvbnN0IGtleSBvZiBrZXlzKSB7XG4gICAgY29uc3QgcmVmcyA9IE9iamVjdC5hc3NpZ24oe30sIGFyZyk7XG4gICAgZGVsZXRlIHJlZnNba2V5XTtcbiAgICBvdXRwdXQucHVzaCh0b1R5cGVzY3JpcHQoYXJnW2tleV0sIHtcbiAgICAgIHVzZVJlZmVyZW5jZTogcmVmcyxcbiAgICAgIGFzc2lnblRvVHlwZToga2V5LFxuICAgIH0pKTtcbiAgfVxuICByZXR1cm4gb3V0cHV0LmpvaW4oXCJcXG5cXG5cIik7XG59XG5cbmZ1bmN0aW9uIHRvVFModHlwZTogS2luZCwgb3B0czogVG9UeXBlc2NyaXB0T3B0cyk6IHN0cmluZyB7XG4gIGlmKG9wdHMudXNlUmVmZXJlbmNlKSB7XG4gICAgZm9yKGNvbnN0IGtleSBpbiBvcHRzLnVzZVJlZmVyZW5jZSkge1xuICAgICAgY29uc3QgdmFsID0gb3B0cy51c2VSZWZlcmVuY2Vba2V5XTtcbiAgICAgIGlmKHZhbCA9PT0gdHlwZSkgcmV0dXJuIGtleTtcbiAgICB9XG4gIH1cblxuICBpZih0eXBlIGluc3RhbmNlb2YgQ29tbWVudCkgcmV0dXJuIGZyb21Db21tZW50KHR5cGUsIG9wdHMpO1xuICBpZih0eXBlIGluc3RhbmNlb2YgRWl0aGVyKSByZXR1cm4gZnJvbUVpdGhlcih0eXBlLCBvcHRzKTtcbiAgaWYodHlwZSBpbnN0YW5jZW9mIERlZmF1bHRJbnRlcnNlY3QpIHJldHVybiBmcm9tSW50ZXJzZWN0KHR5cGUsIG9wdHMpO1xuICBpZih0eXBlIGluc3RhbmNlb2YgTWVyZ2VJbnRlcnNlY3QpIHJldHVybiBmcm9tSW50ZXJzZWN0KHR5cGUsIG9wdHMpO1xuICBpZih0eXBlIGluc3RhbmNlb2YgVmFsaWRhdGlvbikgcmV0dXJuIGZyb21WYWxpZGF0aW9uKCk7XG4gIGlmKHR5cGUgaW5zdGFuY2VvZiBUeXBlT2YpIHJldHVybiBmcm9tVHlwZW9mKHR5cGUpO1xuICBpZih0eXBlIGluc3RhbmNlb2YgSW5zdGFuY2VPZikgcmV0dXJuIGZyb21JbnN0YW5jZU9mKHR5cGUpO1xuICBpZih0eXBlIGluc3RhbmNlb2YgVmFsdWUpIHJldHVybiBmcm9tVmFsdWUodHlwZSk7XG4gIGlmKHR5cGUgaW5zdGFuY2VvZiBBcnIpIHJldHVybiBmcm9tQXJyKHR5cGUsIG9wdHMpO1xuICBpZih0eXBlIGluc3RhbmNlb2YgU3RydWN0KSByZXR1cm4gZnJvbVN0cnVjdCh0eXBlLCBvcHRzKTtcbiAgaWYodHlwZSBpbnN0YW5jZW9mIERpY3QpIHJldHVybiBmcm9tRGljdCh0eXBlLCBvcHRzKTtcbiAgaWYodHlwZSBpbnN0YW5jZW9mIE1hcFR5cGUpIHJldHVybiBmcm9tTWFwKHR5cGUsIG9wdHMpO1xuICBpZih0eXBlIGluc3RhbmNlb2YgU2V0VHlwZSkgcmV0dXJuIGZyb21TZXQodHlwZSwgb3B0cyk7XG4gIGlmKHR5cGUgaW5zdGFuY2VvZiBBbnkpIHJldHVybiBmcm9tQW55KCk7XG4gIGlmKHR5cGUgaW5zdGFuY2VvZiBJcykgcmV0dXJuIGZyb21Jcyh0eXBlKTtcbiAgaWYodHlwZSBpbnN0YW5jZW9mIFBhcnRpYWxTdHJ1Y3QpIHJldHVybiBmcm9tUGFydGlhbCh0eXBlLCBvcHRzKTtcbiAgcmV0dXJuIGZyb21OZXZlcih0eXBlKTtcbn1cblxuZnVuY3Rpb24gZnJvbVBhcnRpYWwocDogUGFydGlhbFN0cnVjdDxhbnk+LCBvcHRzOiBUb1R5cGVzY3JpcHRPcHRzKSB7XG4gIHJldHVybiBgUGFydGlhbDwke3RvVFMocC5zdHJ1Y3QsIG9wdHMpfT5gO1xufVxuXG5mdW5jdGlvbiBmcm9tQ29tbWVudChjOiBDb21tZW50PGFueT4sIG9wdHM6IFRvVHlwZXNjcmlwdE9wdHMpIHtcbiAgY29uc3QgaSA9IGluZGVudChvcHRzKTtcbiAgY29uc3QgY29tbWVudExpbmVzID0gZm9ybWF0Q29tbWVudFN0cmluZyhjLmNvbW1lbnRTdHIsIG9wdHMpO1xuICByZXR1cm4gYCR7Y29tbWVudExpbmVzfVxcbiR7aX0ke3RvVFMoYy53cmFwcGVkLCBvcHRzKX1gO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRDb21tZW50U3RyaW5nKGNvbW1lbnRTdHI6IHN0cmluZywgb3B0czogVG9UeXBlc2NyaXB0T3B0cykge1xuICBjb25zdCBpID0gaW5kZW50KG9wdHMpO1xuXG4gIGNvbnN0IGNvbW1lbnRMaW5lcyA9IGNvbW1lbnRTdHIuc3BsaXQoXCJcXG5cIikubWFwKGxpbmUgPT4ge1xuICAgIHJldHVybiBsaW5lLnRyaW0oKTtcbiAgfSkuZmlsdGVyKGxpbmUgPT4gbGluZSAhPT0gXCJcIik7XG5cbiAgaWYoY29tbWVudExpbmVzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIFwiXCI7XG4gIGlmKGNvbW1lbnRMaW5lcy5sZW5ndGggPT09IDEpIHtcbiAgICByZXR1cm4gYC8vICR7Y29tbWVudExpbmVzWzBdfWA7XG4gIH1cblxuICBjb25zdCBsaW5lcyA9IFsgJy8qJyBdXG4gIGZvcihjb25zdCBsaW5lIG9mIGNvbW1lbnRMaW5lcykge1xuICAgIGxpbmVzLnB1c2goYCR7aX0gKiAke2xpbmUudHJpbSgpfWApO1xuICB9XG4gIGxpbmVzLnB1c2goYCR7aX0gKi9gKTtcbiAgcmV0dXJuIGxpbmVzLmpvaW4oXCJcXG5cIik7XG59XG5cbi8vIFRPRE86IFNob3VsZCBlaXRoZXIgc3RyaXAgaW1tZWRpYXRlLWNoaWxkIGNvbW1lbnRzP1xuZnVuY3Rpb24gZnJvbUVpdGhlcihlOiBFaXRoZXI8YW55LCBhbnk+LCBvcHRzOiBUb1R5cGVzY3JpcHRPcHRzKSB7XG4gIGNvbnN0IGkgPSBpbmRlbnQob3B0cyk7XG4gIHJldHVybiBbXG4gICAgdG9UUyhlLmwsIG9wdHMpLFxuICAgIGAke2l9JHtvcHRzLmluZGVudH18ICR7dG9UUyhlLnIsIHsuLi5vcHRzLCBpbmRlbnRMZXZlbDogb3B0cy5pbmRlbnRMZXZlbCArIDF9KX1gLFxuICBdLmpvaW4oXCJcXG5cIik7XG59XG5cbi8vIFRPRE86IFNob3VsZCBpbnRlcnNlY3Qgc3RyaXAgaW1tZWRpYXRlLWNoaWxkIGNvbW1lbnRzP1xuZnVuY3Rpb24gZnJvbUludGVyc2VjdChcbiAgaTogRGVmYXVsdEludGVyc2VjdDxhbnksIGFueT4gfCBNZXJnZUludGVyc2VjdDxhbnksIGFueSwgYW55LCBhbnk+LFxuICBvcHRzOiBUb1R5cGVzY3JpcHRPcHRzLFxuKSB7XG4gIC8vIEhhbmRsZSB2YWxpZGF0aW9ucyBjaGFpbmVkIHdpdGggYWN0dWFsIFRTIHR5cGVzLCBjb252ZXJ0aW5nIHRoZW0gdG8gY29tbWVudHNcbiAgaWYoaS5sIGluc3RhbmNlb2YgVmFsaWRhdGlvbikgcmV0dXJuIHRvVFMobmV3IENvbW1lbnQoaS5sLmRlc2MsIGkuciksIG9wdHMpO1xuICBpZihpLnIgaW5zdGFuY2VvZiBWYWxpZGF0aW9uKSByZXR1cm4gdG9UUyhuZXcgQ29tbWVudChpLnIuZGVzYywgaS5sKSwgb3B0cyk7XG5cbiAgY29uc3QgaW5kZW50YXRpb24gPSBpbmRlbnQob3B0cyk7XG4gIHJldHVybiBbXG4gICAgdG9UUyhpLmwsIG9wdHMpLFxuICAgIGAke2luZGVudGF0aW9ufSR7b3B0cy5pbmRlbnR9JiAke3RvVFMoaS5yLCB7Li4ub3B0cywgaW5kZW50TGV2ZWw6IG9wdHMuaW5kZW50TGV2ZWwgKyAxfSl9YCxcbiAgXS5qb2luKFwiXFxuXCIpO1xufVxuXG5mdW5jdGlvbiBmcm9tVmFsaWRhdGlvbigpOiBzdHJpbmcge1xuICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgXCJDYW4ndCBjb252ZXJ0IGFyYml0cmFyeSB2YWxpZGF0aW9uIGZ1bmN0aW9ucyB0byBUeXBlU2NyaXB0IHR5cGVzOyBtYWtlIHN1cmUgdG8gLmFuZCgpIGl0IFwiICtcbiAgICAgIFwid2l0aCBhIHZhbGlkIHR5cGUsIGFuZCBpdCB3aWxsIGJlIGNvbnZlcnRlZCBpbnRvIGEgY29tbWVudCBhYm92ZSB0aGUgdHlwZVwiXG4gICk7XG59XG5cbmZ1bmN0aW9uIGZyb21UeXBlb2YodDogVHlwZU9mPGFueT4pOiBzdHJpbmcge1xuICBzd2l0Y2godC50eXBlc3RyaW5nKSB7XG4gICAgY2FzZSBcInVuZGVmaW5lZFwiOiByZXR1cm4gdC50eXBlc3RyaW5nO1xuICAgIGNhc2UgXCJvYmplY3RcIjogcmV0dXJuIFwiT2JqZWN0XCI7XG4gICAgY2FzZSBcImJvb2xlYW5cIjogcmV0dXJuIHQudHlwZXN0cmluZztcbiAgICBjYXNlIFwibnVtYmVyXCI6IHJldHVybiB0LnR5cGVzdHJpbmc7XG4gICAgY2FzZSBcInN0cmluZ1wiOiByZXR1cm4gdC50eXBlc3RyaW5nO1xuICAgIGNhc2UgXCJzeW1ib2xcIjogcmV0dXJuIFwiU3ltYm9sXCI7XG4gICAgY2FzZSBcImZ1bmN0aW9uXCI6IHJldHVybiBcIkZ1bmN0aW9uXCI7XG4gICAgY2FzZSBcImJpZ2ludFwiOiByZXR1cm4gXCJiaWdpbnRcIjtcbiAgfVxufVxuXG5mdW5jdGlvbiBmcm9tSW5zdGFuY2VPZihpOiBJbnN0YW5jZU9mPGFueT4pIHtcbiAgaWYoIWkua2xhc3MubmFtZSkgdGhyb3cgbmV3IEVycm9yKFwiQ2FuJ3QgY29udmVydCBhbm9ueW1vdXMgY2xhc3NlcyB0byBUeXBlU2NyaXB0XCIpO1xuICByZXR1cm4gYCR7aS5rbGFzcy5uYW1lfWA7XG59XG5cbmZ1bmN0aW9uIGZyb21WYWx1ZSh2OiBWYWx1ZTxhbnk+KSB7XG4gIGNvbnN0IHZUeXBlID0gdHlwZW9mIHYudmFsO1xuICBpZih2VHlwZSAhPT0gXCJzdHJpbmdcIiAmJiB2VHlwZSAhPT0gXCJudW1iZXJcIiAmJiB2VHlwZSAhPT0gXCJib29sZWFuXCIgJiYgdi52YWwgIT09IG51bGwgJiYgdi52YWwgIT09IHVuZGVmaW5lZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIFwiT25seSBzdHJpbmcsIG51bWVyaWMsIHVuZGVmaW5lZCwgYm9vbGVhbiwgYW5kIG51bGwgdmFsdWUgdHlwZXMgY2FuIGJlIGF1dG8tY29udmVydGVkIHRvIFR5cGVTY3JpcHRcIlxuICAgICk7XG4gIH1cbiAgaWYodlR5cGUgPT09IFwic3RyaW5nXCIpIHJldHVybiBKU09OLnN0cmluZ2lmeSh2LnZhbCk7XG5cbiAgcmV0dXJuIGAke3YudmFsfWA7XG59XG5cbmZ1bmN0aW9uIGZyb21BcnIoYTogQXJyPGFueT4sIG9wdHM6IFRvVHlwZXNjcmlwdE9wdHMpIHtcbiAgcmV0dXJuIGBBcnJheTwke3RvVFMoYS5lbGVtZW50VHlwZSwgb3B0cyl9PmA7XG59XG5cbmZ1bmN0aW9uIGZyb21TdHJ1Y3QoczogU3RydWN0PGFueT4sIG9wdHM6IFRvVHlwZXNjcmlwdE9wdHMpIHtcbiAgY29uc3QgbGluZXMgPSBbIFwie1wiIF07XG4gIGNvbnN0IGtleU9wdHMgPSB7XG4gICAgLi4ub3B0cyxcbiAgICBpbmRlbnRMZXZlbDogb3B0cy5pbmRlbnRMZXZlbCArIDEsXG4gIH07XG4gIGNvbnN0IGtleUluZGVudCA9IGluZGVudChrZXlPcHRzKTtcbiAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKHMuZGVmaW5pdGlvbik7XG5cbiAgZm9yKGxldCBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBrZXkgPSBrZXlzW2ldO1xuICAgIGNvbnN0IGtleVR5cGUgPSBbIGtleSBdO1xuICAgIGNvbnN0IHZhbCA9IHMuZGVmaW5pdGlvbltrZXldO1xuICAgIGlmKHZhbCBpbnN0YW5jZW9mIE1pc3NpbmdLZXkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJtaXNzaW5nKC4uLikgZmllbGRzIGNhbid0IGJlIHJlcHJlc2VudGVkIGluIFR5cGVTY3JpcHQ7IGNvbnNpZGVyIHVzaW5nIG9wdGlvbmFsKC4uLilcIlxuICAgICAgKTtcbiAgICB9XG4gICAgaWYodmFsIGluc3RhbmNlb2YgT3B0aW9uYWxLZXkpIGtleVR5cGUucHVzaChcIj9cIik7XG4gICAga2V5VHlwZS5wdXNoKFwiOiBcIik7XG4gICAgY29uc3Qgc3RyaXBwZWQgPSBzdHJpcE91dGVyQ29tbWVudHModmFsKTtcbiAgICBpZihzdHJpcHBlZC5jb21tZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICAvLyBWaXN1YWxseSBzZXBhcmF0ZSB0aGUgc3RhcnQgb2YgYSBjb21tZW50ZWQgZmllbGQgdW5sZXNzIGl0J3MgdGhlIGZpcnN0IGZpZWxkXG4gICAgICBpZihpICE9PSAwKSB7XG4gICAgICAgIC8vIEJ1dCBkb24ndCBkb3VibGUtbmV3bGluZSBpZiB5b3UgYWxyZWFkeSBzZXBhcmF0ZWQgdGhlIGxhc3QgbGluZVxuICAgICAgICBpZihsaW5lc1tsaW5lcy5sZW5ndGggLSAxXSAhPT0gXCJcIikgbGluZXMucHVzaChcIlwiKTtcbiAgICAgIH1cbiAgICAgIC8vIFB1dCB0aGUgY29tbWVudCBvbiB0aGUgbGluZSBhYm92ZSB0aGUga2V5XG4gICAgICBsaW5lcy5wdXNoKGtleUluZGVudCArIGZvcm1hdENvbW1lbnRTdHJpbmcoc3RyaXBwZWQuY29tbWVudHMuam9pbihcIlxcblwiKSwga2V5T3B0cykpO1xuICAgIH1cbiAgICBrZXlUeXBlLnB1c2godG9UUyhzdHJpcHBlZC5pbm5lciwga2V5T3B0cykpO1xuICAgIGtleVR5cGUucHVzaChcIixcIik7XG4gICAgbGluZXMucHVzaChrZXlJbmRlbnQgKyBrZXlUeXBlLmpvaW4oXCJcIikpO1xuXG4gICAgLy8gVmlzdWFsbHkgc2VwYXJhdGUgdGhlIGVuZCBvZiBhIGNvbW1lbnRlZCBmaWVsZCwgdW5sZXNzIGl0J3MgdGhlIGxhc3QgZmllbGRcbiAgICBpZihzdHJpcHBlZC5jb21tZW50cy5sZW5ndGggPiAwICYmIGkgIT09IGtleXMubGVuZ3RoIC0gMSkgbGluZXMucHVzaChcIlwiKTtcbiAgfVxuICBsaW5lcy5wdXNoKGluZGVudChvcHRzKSArIFwifVwiKTtcblxuICByZXR1cm4gbGluZXMuam9pbihcIlxcblwiKTtcbn1cblxudHlwZSBTdHJpcHBlZENvbW1lbnRzID0ge1xuICBjb21tZW50czogc3RyaW5nW10sXG4gIGlubmVyOiBLaW5kLFxufTtcblxuZnVuY3Rpb24gc3RyaXBPdXRlckNvbW1lbnRzKHQ6IEtpbmQgfCBPcHRpb25hbEtleTxhbnk+KTogU3RyaXBwZWRDb21tZW50cyB7XG4gIGlmKHQgaW5zdGFuY2VvZiBPcHRpb25hbEtleSkgcmV0dXJuIHN0cmlwT3V0ZXJDb21tZW50cyh0LnR5cGUpO1xuICBpZih0IGluc3RhbmNlb2YgQ29tbWVudCkge1xuICAgIGNvbnN0IGlubmVyID0gc3RyaXBPdXRlckNvbW1lbnRzKHQud3JhcHBlZCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbW1lbnRzOiBbIHQuY29tbWVudFN0ciwgLi4uaW5uZXIuY29tbWVudHMgXSxcbiAgICAgIGlubmVyOiBpbm5lci5pbm5lcixcbiAgICB9XG4gIH1cblxuICBjb25zdCBhbGdlYnJhID0gWyBEZWZhdWx0SW50ZXJzZWN0LCBNZXJnZUludGVyc2VjdCwgRWl0aGVyIF0gYXMgY29uc3Q7XG5cbiAgZm9yKGNvbnN0IGFsIG9mIGFsZ2VicmEpIHtcbiAgICBpZih0IGluc3RhbmNlb2YgYWwpIHtcbiAgICAgIGlmKHQubCBpbnN0YW5jZW9mIFZhbGlkYXRpb24pIHtcbiAgICAgICAgcmV0dXJuIHN0cmlwT3V0ZXJDb21tZW50cyhuZXcgQ29tbWVudCh0LmwuZGVzYywgdC5yKSk7XG4gICAgICB9XG4gICAgICBpZih0LnIgaW5zdGFuY2VvZiBWYWxpZGF0aW9uKSB7XG4gICAgICAgIHJldHVybiBzdHJpcE91dGVyQ29tbWVudHMobmV3IENvbW1lbnQodC5yLmRlc2MsIHQubCkpO1xuICAgICAgfVxuICAgICAgaWYodC5sIGluc3RhbmNlb2YgQ29tbWVudCkge1xuICAgICAgICByZXR1cm4gc3RyaXBPdXRlckNvbW1lbnRzKGhhbmRsZVN0cmlwQWxnZWJyYSh0LmwuY29tbWVudFN0ciwgdC5sLndyYXBwZWQsIHQuciwgYWwpKTtcbiAgICAgIH1cbiAgICAgIGlmKHQuciBpbnN0YW5jZW9mIENvbW1lbnQpIHtcbiAgICAgICAgcmV0dXJuIHN0cmlwT3V0ZXJDb21tZW50cyhoYW5kbGVTdHJpcEFsZ2VicmEodC5yLmNvbW1lbnRTdHIsIHQubCwgdC5yLndyYXBwZWQsIGFsKSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBjb21tZW50czogW10sXG4gICAgaW5uZXI6IHQsXG4gIH07XG59XG5cbmZ1bmN0aW9uIGhhbmRsZVN0cmlwQWxnZWJyYShcbiAgZGVzYzogc3RyaW5nLFxuICByOiBUeXBlPGFueT4sXG4gIGw6IFR5cGU8YW55PixcbiAgY29uc3RyOiB7IG5ldyhyOiBhbnksIGw6IGFueSk6IFR5cGU8YW55PiB9XG4pOiBUeXBlPGFueT4ge1xuICByZXR1cm4gbmV3IENvbW1lbnQoZGVzYywgbmV3IGNvbnN0cihyLCBsKSk7XG59XG5cbmZ1bmN0aW9uIGZyb21EaWN0KGQ6IERpY3Q8YW55Piwgb3B0czogVG9UeXBlc2NyaXB0T3B0cykge1xuICBjb25zdCBpID0gaW5kZW50KG9wdHMpO1xuICBjb25zdCB2YWxTdHJpbmcgPSB0b1RTKGQudmFsdWVUeXBlLCB7Li4ub3B0cywgaW5kZW50TGV2ZWw6IG9wdHMuaW5kZW50TGV2ZWwgKyAxfSk7XG5cbiAgLy8gRm9yIHNpbmdsZS1saW5lIHZhbHVlcywgcmV0dXJuIGEgc2luZ2xlLWxpbmUgZGljdFxuICBpZih2YWxTdHJpbmcuaW5kZXhPZihcIlxcblwiKSA8IDApIHJldHVybiBge1ske2QubmFtZWRLZXl9OiBzdHJpbmddOiAke3ZhbFN0cmluZ319YDtcblxuICAvLyBGb3IgbXVsdGlsaW5lIHZhbHVlcywgcmV0dXJuIGEgbXVsdGlsaW5lIGRpY3RcbiAgcmV0dXJuIFtcbiAgICBcIntcIixcbiAgICBgJHtpfSR7b3B0cy5pbmRlbnR9WyR7ZC5uYW1lZEtleX06IHN0cmluZ106ICR7dmFsU3RyaW5nfWAsXG4gICAgYCR7aX19YCxcbiAgXS5qb2luKFwiXFxuXCIpO1xufVxuXG5mdW5jdGlvbiBmcm9tTWFwKG06IE1hcFR5cGU8YW55LCBhbnk+LCBvcHRzOiBUb1R5cGVzY3JpcHRPcHRzKSB7XG4gIGNvbnN0IGtleVN0cmluZyA9IHRvVFMobS5rZXlUeXBlLCBvcHRzKTtcbiAgY29uc3QgdmFsU3RyaW5nID0gdG9UUyhtLnZhbHVlVHlwZSwgb3B0cyk7XG4gIHJldHVybiBgTWFwPCR7a2V5U3RyaW5nfSwgJHt2YWxTdHJpbmd9PmA7XG59XG5cbmZ1bmN0aW9uIGZyb21TZXQoczogU2V0VHlwZTxhbnk+LCBvcHRzOiBUb1R5cGVzY3JpcHRPcHRzKSB7XG4gIGNvbnN0IHZhbFN0cmluZyA9IHRvVFMocy52YWx1ZVR5cGUsIG9wdHMpO1xuICByZXR1cm4gYFNldDwke3ZhbFN0cmluZ30+YDtcbn1cblxuZnVuY3Rpb24gZnJvbUFueSgpIHtcbiAgcmV0dXJuIFwiYW55XCI7XG59XG5cbmZ1bmN0aW9uIGZyb21JcyhpOiBJczxhbnk+KSB7XG4gIHJldHVybiBpLm5hbWU7XG59XG5cbi8vIERlc3BpdGUgbm90IHVzaW5nIHRoZSB0eXBlLCB3ZSB0YWtlIGl0IHRvIGhlbHAgZW5zdXJlIGV4aGF1c3RpdmVuZXNzIGNoZWNraW5nIGluIHRoZSB0b1RTIGZuXG5mdW5jdGlvbiBmcm9tTmV2ZXIoXzogTmV2ZXIpIHtcbiAgcmV0dXJuIFwibmV2ZXJcIjtcbn1cblxuZnVuY3Rpb24gaW5kZW50KG9wdHM6IFRvVHlwZXNjcmlwdE9wdHMpIHtcbiAgcmV0dXJuIG9wdHMuaW5kZW50LnJlcGVhdChvcHRzLmluZGVudExldmVsKTtcbn1cbiJdfQ==
|