This repository has been archived on 2026-03-28. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files

207 lines
28 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.toJSONSchema = exports.JSON_SCHEMA_VERSION = 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");
const never_1 = require("./checks/never");
exports.JSON_SCHEMA_VERSION = "https://json-schema.org/draft/2020-12/schema";
const defaultOpts = {
errorOnValidations: true,
errorOnIs: true,
errorOnNever: true,
};
function toJSONSchema(title, type, opts) {
const options = Object.assign(Object.assign({}, defaultOpts), opts);
return addMetadata(title, typeToSchema(type, options));
}
exports.toJSONSchema = toJSONSchema;
function typeToSchema(type, options) {
if (type instanceof type_1.Comment) {
return Object.assign({ description: formatCommentString(type.commentStr) }, typeToSchema(type.wrapped, options));
}
if (type instanceof type_1.Either)
return fromEither(type, options);
if (type instanceof type_1.DefaultIntersect)
return fromIntersect(type, options);
if (type instanceof struct_1.MergeIntersect)
return fromIntersect(type, options);
if (type instanceof type_1.Validation)
return fromValidation(type, options);
if (type instanceof type_of_1.TypeOf)
return fromTypeof(type);
if (type instanceof instance_of_1.InstanceOf) {
throw `Structural instanceOf types can't be converted to JSON Schema`;
}
if (type instanceof value_1.Value)
return fromValue(type);
if (type instanceof array_1.Arr)
return fromArray(type, options);
if (type instanceof struct_1.Struct)
return fromStruct(type, options);
if (type instanceof struct_1.Dict)
return fromDict(type, options);
if (type instanceof map_1.MapType) {
throw `Structural Map types can't be converted to JSON Schema; consider using a dict`;
}
if (type instanceof set_1.SetType) {
throw `Structural Set types can't be converted to JSON Schema; consider using an array`;
}
if (type instanceof any_1.Any) {
return {};
}
if (type instanceof is_1.Is)
return fromIs(type, options);
if (type instanceof never_1.Never)
return fromNever(type, options);
return fromPartial(type, options);
}
function areSerializableValues(types) {
for (const type of types) {
if (!(type instanceof value_1.Value))
return false;
if (!isSerializable(type.val))
return false;
}
return true;
}
function isSerializable(value) {
try {
JSON.parse(JSON.stringify(value));
}
catch (_a) {
return false;
}
return true;
}
function fromEither(type, options) {
// While the Either type could theoretically just map to recursive anyOf schemas, in practice it's
// much more readable to have it attempt to generate an enum list of all values (if it's a bunch
// of values unioned together, AND the values are all serializable to JSON), or a flat anyOf list
// otherwise. So, we walk the tree and collect all the types, and do that.
const allTypes = flatTypes(type_1.Either, type);
if (areSerializableValues(allTypes)) {
return {
enum: allTypes.map(t => t.val),
};
}
return {
anyOf: allTypes.map(type => typeToSchema(type, options)),
};
}
function fromIntersect(type, options) {
if (type.r instanceof type_1.Validation) {
if (options.errorOnValidations) {
throw `Structural type contains a validation, but errorOnValidations was set to true`;
}
return Object.assign({ description: type.r.desc }, typeToSchema(type.l, options));
}
return {
allOf: flatTypes(type instanceof type_1.DefaultIntersect ? type_1.DefaultIntersect : struct_1.MergeIntersect, type).map(t => typeToSchema(t, options)),
};
}
function fromValidation(type, options) {
if (options.errorOnValidations) {
throw `Structural type contains a validation, but errorOnValidations was set to true`;
}
return {
description: type.desc
};
}
function fromTypeof(type) {
switch (type.typestring) {
case "string": return { type: "string" };
case "number": return { type: "number" };
case "boolean": return { type: "boolean" };
case "object": return { type: "object", properties: {} };
}
throw `Can't convert Structural TypeOf<${type.typestring}> checks into JSON Schema`;
}
function fromValue(type) {
if (!isSerializable(type.val)) {
throw `Value type expects ${type.val}, but it isn't serializable to JSON`;
}
if (type.val === null)
return { type: "null" };
return {
const: type.val,
};
}
function fromArray(type, options) {
return {
type: 'array',
items: typeToSchema(type.elementType, options),
};
}
function fromStruct(type, options) {
const properties = {};
const required = [];
const keys = Object.keys(type.definition);
for (const key of keys) {
const val = type.definition[key];
if (val instanceof struct_1.MissingKey || val instanceof struct_1.OptionalKey) {
properties[key] = typeToSchema(val.type, options);
}
else {
required.push(key);
properties[key] = typeToSchema(val, options);
}
}
return {
type: 'object',
required, properties,
};
}
function fromDict(type, options) {
return {
type: 'object',
properties: {},
additionalProperties: typeToSchema(type.valueType, options),
};
}
function fromIs(type, options) {
if (options.errorOnIs) {
throw `Structural type contains an Is check, but errorOnIs was set to true`;
}
return {
description: type.name,
};
}
function fromNever(_, options) {
if (options.errorOnNever) {
throw `Structural type contains a Never check, but errorOnNever was set to true`;
}
return {
allOf: [{ type: "string" }, { type: "number" }],
};
}
function fromPartial(type, options) {
// Since Partial<T> only makes top-level keys optional, we just modify the required array
const schema = fromStruct(type.struct, options);
if ('required' in schema)
schema.required = [];
return schema;
}
function flatTypes(klass, node) {
if (node instanceof klass) {
return flatTypes(klass, node.l).concat(flatTypes(klass, node.r));
}
return [node];
}
function formatCommentString(commentStr) {
const commentLines = commentStr.split("\n").map(line => {
return line.trim();
}).filter(line => line !== "");
return commentLines.join("\n");
}
function addMetadata(title, schema) {
return Object.assign({ $schema: exports.JSON_SCHEMA_VERSION, title }, schema);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG8tanNvbnNjaGVtYS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi90by1qc29uc2NoZW1hLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLGlDQUE2RTtBQUM3RSw4Q0FBMEM7QUFDMUMsc0RBQWtEO0FBQ2xELDBDQUF1QztBQUN2QywwQ0FBcUM7QUFDckMsNENBQXVHO0FBQ3ZHLHNDQUF1QztBQUN2QyxzQ0FBdUM7QUFDdkMsc0NBQW1DO0FBQ25DLG9DQUFpQztBQUNqQywwQ0FBdUM7QUFHMUIsUUFBQSxtQkFBbUIsR0FBRyw4Q0FBdUQsQ0FBQztBQW1FM0YsTUFBTSxXQUFXLEdBQXNCO0lBQ3JDLGtCQUFrQixFQUFFLElBQUk7SUFDeEIsU0FBUyxFQUFFLElBQUk7SUFDZixZQUFZLEVBQUUsSUFBSTtDQUNuQixDQUFDO0FBRUYsU0FBZ0IsWUFBWSxDQUFDLEtBQWEsRUFBRSxJQUFVLEVBQUUsSUFBYztJQUNwRSxNQUFNLE9BQU8sbUNBQ1IsV0FBVyxHQUNYLElBQUksQ0FDUixDQUFDO0lBRUYsT0FBTyxXQUFXLENBQUMsS0FBSyxFQUFFLFlBQVksQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztBQUN6RCxDQUFDO0FBUEQsb0NBT0M7QUFFRCxTQUFTLFlBQVksQ0FBQyxJQUFVLEVBQUUsT0FBMEI7SUFDMUQsSUFBRyxJQUFJLFlBQVksY0FBTyxFQUFFLENBQUM7UUFDM0IsdUJBQ0UsV0FBVyxFQUFFLG1CQUFtQixDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFDOUMsWUFBWSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLEVBQ3RDO0lBQ0osQ0FBQztJQUNELElBQUcsSUFBSSxZQUFZLGFBQU07UUFBRSxPQUFPLFVBQVUsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDNUQsSUFBRyxJQUFJLFlBQVksdUJBQWdCO1FBQUUsT0FBTyxhQUFhLENBQUMsSUFBSSxFQUFFLE9B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Q0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ2hELElBQUcsVUFBVSxJQUFJLE1BQU07UUFBRSxNQUFNLENBQUMsUUFBUSxHQUFHLEVBQUUsQ0FBQztJQUM5QyxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQ2hCLEtBSUMsRUFDRCxJQUFlO0lBRWYsSUFBRyxJQUFJLFlBQVksS0FBSyxFQUFFLENBQUM7UUFDekIsT0FBTyxTQUFTLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNuRSxDQUFDO0lBQ0QsT0FBTyxDQUFFLElBQUksQ0FBRSxDQUFDO0FBQ2xCLENBQUM7QUFFRCxTQUFTLG1CQUFtQixDQUFDLFVBQWtCO0lBQzdDLE1BQU0sWUFBWSxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFO1FBQ3JELE9BQU8sSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ3JCLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksS0FBSyxFQUFFLENBQUMsQ0FBQztJQUMvQixPQUFPLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDakMsQ0FBQztBQUVELFNBQVMsV0FBVyxDQUFDLEtBQWEsRUFBRSxNQUFrQjtJQUNwRCx1QkFDRSxPQUFPLEVBQUUsMkJBQW1CLEVBQzVCLEtBQUssSUFDRixNQUFNLEVBQ1Q7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVHlwZSwgQ29tbWVudCwgRWl0aGVyLCBEZWZhdWx0SW50ZXJzZWN0LCBWYWxpZGF0aW9uIH0gZnJvbSBcIi4vdHlwZVwiO1xuaW1wb3J0IHsgVHlwZU9mIH0gZnJvbSBcIi4vY2hlY2tzL3R5cGUtb2ZcIjtcbmltcG9ydCB7IEluc3RhbmNlT2YgfSBmcm9tIFwiLi9jaGVja3MvaW5zdGFuY2Utb2ZcIjtcbmltcG9ydCB7IFZhbHVlIH0gZnJvbSBcIi4vY2hlY2tzL3ZhbHVlXCI7XG5pbXBvcnQgeyBBcnIgfSBmcm9tIFwiLi9jaGVja3MvYXJyYXlcIjtcbmltcG9ydCB7IFBhcnRpYWxTdHJ1Y3QsIFN0cnVjdCwgTWlzc2luZ0tleSwgT3B0aW9uYWxLZXksIERpY3QsIE1lcmdlSW50ZXJzZWN0IH0gZnJvbSBcIi4vY2hlY2tzL3N0cnVjdFwiO1xuaW1wb3J0IHsgTWFwVHlwZSB9IGZyb20gXCIuL2NoZWNrcy9tYXBcIjtcbmltcG9ydCB7IFNldFR5cGUgfSBmcm9tIFwiLi9jaGVja3Mvc2V0XCI7XG5pbXBvcnQgeyBBbnkgfSBmcm9tIFwiLi9jaGVja3MvYW55XCI7XG5pbXBvcnQgeyBJcyB9IGZyb20gXCIuL2NoZWNrcy9pc1wiO1xuaW1wb3J0IHsgTmV2ZXIgfSBmcm9tIFwiLi9jaGVja3MvbmV2ZXJcIjtcbmltcG9ydCB7IEtpbmQgfSBmcm9tIFwiLi9raW5kXCI7XG5cbmV4cG9ydCBjb25zdCBKU09OX1NDSEVNQV9WRVJTSU9OID0gXCJodHRwczovL2pzb24tc2NoZW1hLm9yZy9kcmFmdC8yMDIwLTEyL3NjaGVtYVwiIGFzIGNvbnN0O1xudHlwZSBUb3BMZXZlbDxUPiA9IFQgJiB7XG4gICRzY2hlbWE6IHR5cGVvZiBKU09OX1NDSEVNQV9WRVJTSU9OLFxuICB0aXRsZTogc3RyaW5nLFxufTtcblxuLy8gVE9ETzogYSB0aXRsZSBhbm5vdGF0aW9uIGJ1aWx0IGludG8gc3RydWN0dXJhbC4gZGVzY3JpcHRpb24gY2FuIGJlIHRyYW5zZm9ybWVkIGZyb20gY29tbWVudHMuXG4vLyB5b3Ugc2hvdWxkIGFsc28gaGF2ZSBhIHZhcmlhbnQgb2YgdG9KU09OU2NoZW1hIHRoYXQgbWFuZGF0ZXMgdG9wLWxldmVsIHRpdGxlcyBieSBpbnNpc3RpbmcgdGhhdFxuLy8gdGhlIHR5cGUgcGFzc2VkIGluIGlzIGEgVGl0bGUgdHlwZSBpbnN0ZWFkIG9mIGEgS2luZCB0eXBlLlxudHlwZSBBbm5vdGF0ZWQ8VD4gPSBUICYge1xuICBkZXNjcmlwdGlvbj86IHN0cmluZyxcbn07XG5cbmV4cG9ydCB0eXBlIEpTT05WYWx1ZSA9IG51bGxcbiAgICAgICAgICAgICAgICAgICAgICB8IHN0cmluZ1xuICAgICAgICAgICAgICAgICAgICAgIHwgbnVtYmVyXG4gICAgICAgICAgICAgICAgICAgICAgfCBib29sZWFuXG4gICAgICAgICAgICAgICAgICAgICAgfCBBcnJheTxKU09OVmFsdWU+XG4gICAgICAgICAgICAgICAgICAgICAgfCB7IFtrZXk6IHN0cmluZ106IEpTT05WYWx1ZSB9XG4gICAgICAgICAgICAgICAgICAgICAgO1xuXG5leHBvcnQgdHlwZSBKU09OU2NoZW1hID0gQW5ub3RhdGVkPHsgdHlwZTogXCJzdHJpbmdcIiB9PlxuICAgICAgICAgICAgICAgICAgICAgICB8IEFubm90YXRlZDx7IHR5cGU6IFwibnVtYmVyXCIgfT5cbiAgICAgICAgICAgICAgICAgICAgICAgfCBBbm5vdGF0ZWQ8eyB0eXBlOiBcImJvb2xlYW5cIiB9PlxuICAgICAgICAgICAgICAgICAgICAgICB8IEFubm90YXRlZDx7IHR5cGU6IFwibnVsbFwiIH0+XG4gICAgICAgICAgICAgICAgICAgICAgIHwgQW5ub3RhdGVkPHt9PiAvLyB7fSBpcyBKU09OIHNjaGVtYSdzIGFueSB0eXBlXG4gICAgICAgICAgICAgICAgICAgICAgIHwgQW5ub3RhdGVkPHtcbiAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcIm9iamVjdFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkOiBzdHJpbmdbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICBba2V5OiBzdHJpbmddOiBKU09OU2NoZW1hLFxuICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgIH0+XG4gICAgICAgICAgICAgICAgICAgICAgIHwgQW5ub3RhdGVkPHtcbiAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcIm9iamVjdFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERpY3Q8VD4gdHlwZSBpcyB7IHByb3BlcnRpZXM6IHt9LCBhZGRpdGlvbmFsUHJvcGVydGllczogVCB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydGllczoge30sXG4gICAgICAgICAgICAgICAgICAgICAgICAgYWRkaXRpb25hbFByb3BlcnRpZXM/OiBKU09OU2NoZW1hLFxuICAgICAgICAgICAgICAgICAgICAgICB9PlxuICAgICAgICAgICAgICAgICAgICAgICB8IEFubm90YXRlZDx7XG4gICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJhcnJheVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1zPzogSlNPTlNjaGVtYSxcbiAgICAgICAgICAgICAgICAgICAgICAgfT5cbiAgICAgICAgICAgICAgICAgICAgICAgfCBBbm5vdGF0ZWQ8e1xuICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGludGVyc2VjdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgIGFsbE9mOiBKU09OU2NoZW1hW10sXG4gICAgICAgICAgICAgICAgICAgICAgIH0+XG4gICAgICAgICAgICAgICAgICAgICAgIHwgQW5ub3RhdGVkPHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAvLyB1bmlvblxuICAgICAgICAgICAgICAgICAgICAgICAgIGFueU9mOiBKU09OU2NoZW1hW10sXG4gICAgICAgICAgICAgICAgICAgICAgIH0+XG4gICAgICAgICAgICAgICAgICAgICAgIHwgQW5ub3RhdGVkPHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0ZWNobmljYWxseSB0aGlzIGNhbiBiZSByZXByZXNlbnRlZCBhcyBhbnlPZihbIC4uLmNvbnN0cyBdKSwgYnV0IGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJlYWRhYmlsaXR5IGlmIGFsbCBvZiBhIHVuaW9uIGlzIGNvbnN0IHZhbHVlcyBpbW8geW91IHNob3VsZCBvdXRwdXQgYW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAvLyBlbnVtIHJhdGhlciB0aGFuIHRoZSBtb3JlIGNvbXBsZXggdHlwZVxuICAgICAgICAgICAgICAgICAgICAgICAgIGVudW06IEFycmF5PEpTT05WYWx1ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgfT5cbiAgICAgICAgICAgICAgICAgICAgICAgfCBBbm5vdGF0ZWQ8e1xuICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0OiBKU09OVmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgIH0+XG4gICAgICAgICAgICAgICAgICAgICAgIDtcblxudHlwZSBPcHRpb25zID0ge1xuICBlcnJvck9uVmFsaWRhdGlvbnM/OiBib29sZWFuLFxuICBlcnJvck9uSXM/OiBib29sZWFuLFxuICBlcnJvck9uTmV2ZXI/OiBib29sZWFuLFxufTtcbmNvbnN0IGRlZmF1bHRPcHRzOiBSZXF1aXJlZDxPcHRpb25zPiA9IHtcbiAgZXJyb3JPblZhbGlkYXRpb25zOiB0cnVlLFxuICBlcnJvck9uSXM6IHRydWUsXG4gIGVycm9yT25OZXZlcjogdHJ1ZSxcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiB0b0pTT05TY2hlbWEodGl0bGU6IHN0cmluZywgdHlwZTogS2luZCwgb3B0cz86IE9wdGlvbnMpOiBUb3BMZXZlbDxKU09OU2NoZW1hPiB7XG4gIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgLi4uZGVmYXVsdE9wdHMsXG4gICAgLi4ub3B0cyxcbiAgfTtcblxuICByZXR1cm4gYWRkTWV0YWRhdGEodGl0bGUsIHR5cGVUb1NjaGVtYSh0eXBlLCBvcHRpb25zKSk7XG59XG5cbmZ1bmN0aW9uIHR5cGVUb1NjaGVtYSh0eXBlOiBLaW5kLCBvcHRpb25zOiBSZXF1aXJlZDxPcHRpb25zPik6IEpTT05TY2hlbWEge1xuICBpZih0eXBlIGluc3RhbmNlb2YgQ29tbWVudCkge1xuICAgIHJldHVybiB7XG4gICAgICBkZXNjcmlwdGlvbjogZm9ybWF0Q29tbWVudFN0cmluZyh0eXBlLmNvbW1lbnRTdHIpLFxuICAgICAgLi4udHlwZVRvU2NoZW1hKHR5cGUud3JhcHBlZCwgb3B0aW9ucylcbiAgICB9O1xuICB9XG4gIGlmKHR5cGUgaW5zdGFuY2VvZiBFaXRoZXIpIHJldHVybiBmcm9tRWl0aGVyKHR5cGUsIG9wdGlvbnMpO1xuICBpZih0eXBlIGluc3RhbmNlb2YgRGVmYXVsdEludGVyc2VjdCkgcmV0dXJuIGZyb21JbnRlcnNlY3QodHlwZSwgb3B0aW9ucyk7XG4gIGlmKHR5cGUgaW5zdGFuY2VvZiBNZXJnZUludGVyc2VjdCkgcmV0dXJuIGZyb21JbnRlcnNlY3QodHlwZSwgb3B0aW9ucyk7XG4gIGlmKHR5cGUgaW5zdGFuY2VvZiBWYWxpZGF0aW9uKSByZXR1cm4gZnJvbVZhbGlkYXRpb24odHlwZSwgb3B0aW9ucyk7XG4gIGlmKHR5cGUgaW5zdGFuY2VvZiBUeXBlT2YpIHJldHVybiBmcm9tVHlwZW9mKHR5cGUpO1xuICBpZih0eXBlIGluc3RhbmNlb2YgSW5zdGFuY2VPZikge1xuICAgIHRocm93IGBTdHJ1Y3R1cmFsIGluc3RhbmNlT2YgdHlwZXMgY2FuJ3QgYmUgY29udmVydGVkIHRvIEpTT04gU2NoZW1hYDtcbiAgfVxuICBpZih0eXBlIGluc3RhbmNlb2YgVmFsdWUpIHJldHVybiBmcm9tVmFsdWUodHlwZSk7XG4gIGlmKHR5cGUgaW5zdGFuY2VvZiBBcnIpIHJldHVybiBmcm9tQXJyYXkodHlwZSwgb3B0aW9ucyk7XG4gIGlmKHR5cGUgaW5zdGFuY2VvZiBTdHJ1Y3QpIHJldHVybiBmcm9tU3RydWN0KHR5cGUsIG9wdGlvbnMpO1xuICBpZih0eXBlIGluc3RhbmNlb2YgRGljdCkgcmV0dXJuIGZyb21EaWN0KHR5cGUsIG9wdGlvbnMpO1xuICBpZih0eXBlIGluc3RhbmNlb2YgTWFwVHlwZSkge1xuICAgIHRocm93IGBTdHJ1Y3R1cmFsIE1hcCB0eXBlcyBjYW4ndCBiZSBjb252ZXJ0ZWQgdG8gSlNPTiBTY2hlbWE7IGNvbnNpZGVyIHVzaW5nIGEgZGljdGA7XG4gIH1cbiAgaWYodHlwZSBpbnN0YW5jZW9mIFNldFR5cGUpIHtcbiAgICB0aHJvdyBgU3RydWN0dXJhbCBTZXQgdHlwZXMgY2FuJ3QgYmUgY29udmVydGVkIHRvIEpTT04gU2NoZW1hOyBjb25zaWRlciB1c2luZyBhbiBhcnJheWA7XG4gIH1cbiAgaWYodHlwZSBpbnN0YW5jZW9mIEFueSkge1xuICAgIHJldHVybiB7fTtcbiAgfVxuICBpZih0eXBlIGluc3RhbmNlb2YgSXMpIHJldHVybiBmcm9tSXModHlwZSwgb3B0aW9ucyk7XG4gIGlmKHR5cGUgaW5zdGFuY2VvZiBOZXZlcikgcmV0dXJuIGZyb21OZXZlcih0eXBlLCBvcHRpb25zKTtcblxuICByZXR1cm4gZnJvbVBhcnRpYWwodHlwZSwgb3B0aW9ucyk7XG59XG5cbmZ1bmN0aW9uIGFyZVNlcmlhbGl6YWJsZVZhbHVlcyh0eXBlczogQXJyYXk8VHlwZTxhbnk+Pik6IHR5cGVzIGlzIEFycmF5PFZhbHVlPEpTT05WYWx1ZT4+IHtcbiAgZm9yKGNvbnN0IHR5cGUgb2YgdHlwZXMpIHtcbiAgICBpZighKHR5cGUgaW5zdGFuY2VvZiBWYWx1ZSkpIHJldHVybiBmYWxzZTtcbiAgICBpZighaXNTZXJpYWxpemFibGUodHlwZS52YWwpKSByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGlzU2VyaWFsaXphYmxlKHZhbHVlOiBhbnkpOiB2YWx1ZSBpcyBKU09OVmFsdWUge1xuICB0cnkge1xuICAgIEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodmFsdWUpKTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBmcm9tRWl0aGVyKHR5cGU6IEVpdGhlcjxhbnksIGFueT4sIG9wdGlvbnM6IFJlcXVpcmVkPE9wdGlvbnM+KTogSlNPTlNjaGVtYSB7XG4gIC8vIFdoaWxlIHRoZSBFaXRoZXIgdHlwZSBjb3VsZCB0aGVvcmV0aWNhbGx5IGp1c3QgbWFwIHRvIHJlY3Vyc2l2ZSBhbnlPZiBzY2hlbWFzLCBpbiBwcmFjdGljZSBpdCdzXG4gIC8vIG11Y2ggbW9yZSByZWFkYWJsZSB0byBoYXZlIGl0IGF0dGVtcHQgdG8gZ2VuZXJhdGUgYW4gZW51bSBsaXN0IG9mIGFsbCB2YWx1ZXMgKGlmIGl0J3MgYSBidW5jaFxuICAvLyBvZiB2YWx1ZXMgdW5pb25lZCB0b2dldGhlciwgQU5EIHRoZSB2YWx1ZXMgYXJlIGFsbCBzZXJpYWxpemFibGUgdG8gSlNPTiksIG9yIGEgZmxhdCBhbnlPZiBsaXN0XG4gIC8vIG90aGVyd2lzZS4gU28sIHdlIHdhbGsgdGhlIHRyZWUgYW5kIGNvbGxlY3QgYWxsIHRoZSB0eXBlcywgYW5kIGRvIHRoYXQuXG4gIGNvbnN0IGFsbFR5cGVzID0gZmxhdFR5cGVzKEVpdGhlciwgdHlwZSk7XG5cbiAgaWYoYXJlU2VyaWFsaXphYmxlVmFsdWVzKGFsbFR5cGVzKSkge1xuICAgIHJldHVybiB7XG4gICAgICBlbnVtOiBhbGxUeXBlcy5tYXAodCA9PiB0LnZhbCksXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgYW55T2Y6IGFsbFR5cGVzLm1hcCh0eXBlID0+IHR5cGVUb1NjaGVtYSh0eXBlLCBvcHRpb25zKSksXG4gIH07XG59XG5cbmZ1bmN0aW9uIGZyb21JbnRlcnNlY3QoXG4gIHR5cGU6IERlZmF1bHRJbnRlcnNlY3Q8YW55LCBhbnk+IHwgTWVyZ2VJbnRlcnNlY3Q8YW55LCBhbnksIGFueSwgYW55PixcbiAgb3B0aW9uczogUmVxdWlyZWQ8T3B0aW9ucz4sXG4pOiBKU09OU2NoZW1hIHtcbiAgaWYodHlwZS5yIGluc3RhbmNlb2YgVmFsaWRhdGlvbikge1xuICAgIGlmKG9wdGlvbnMuZXJyb3JPblZhbGlkYXRpb25zKSB7XG4gICAgICB0aHJvdyBgU3RydWN0dXJhbCB0eXBlIGNvbnRhaW5zIGEgdmFsaWRhdGlvbiwgYnV0IGVycm9yT25WYWxpZGF0aW9ucyB3YXMgc2V0IHRvIHRydWVgO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgZGVzY3JpcHRpb246IHR5cGUuci5kZXNjLFxuICAgICAgLi4udHlwZVRvU2NoZW1hKHR5cGUubCwgb3B0aW9ucyksXG4gICAgfTtcbiAgfVxuICByZXR1cm4ge1xuICAgIGFsbE9mOiBmbGF0VHlwZXMoXG4gICAgICB0eXBlIGluc3RhbmNlb2YgRGVmYXVsdEludGVyc2VjdCA/IERlZmF1bHRJbnRlcnNlY3QgOiBNZXJnZUludGVyc2VjdCxcbiAgICAgIHR5cGUsXG4gICAgKS5tYXAodCA9PiB0eXBlVG9TY2hlbWEodCwgb3B0aW9ucykpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBmcm9tVmFsaWRhdGlvbih0eXBlOiBWYWxpZGF0aW9uPGFueT4sIG9wdGlvbnM6IFJlcXVpcmVkPE9wdGlvbnM+KTogSlNPTlNjaGVtYSB7XG4gIGlmKG9wdGlvbnMuZXJyb3JPblZhbGlkYXRpb25zKSB7XG4gICAgdGhyb3cgYFN0cnVjdHVyYWwgdHlwZSBjb250YWlucyBhIHZhbGlkYXRpb24sIGJ1dCBlcnJvck9uVmFsaWRhdGlvbnMgd2FzIHNldCB0byB0cnVlYDtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgZGVzY3JpcHRpb246IHR5cGUuZGVzY1xuICB9O1xufVxuXG5mdW5jdGlvbiBmcm9tVHlwZW9mKHR5cGU6IFR5cGVPZjxhbnk+KTogSlNPTlNjaGVtYSB7XG4gIHN3aXRjaCh0eXBlLnR5cGVzdHJpbmcpIHtcbiAgICBjYXNlIFwic3RyaW5nXCI6IHJldHVybiB7IHR5cGU6IFwic3RyaW5nXCIgfTtcbiAgICBjYXNlIFwibnVtYmVyXCI6IHJldHVybiB7IHR5cGU6IFwibnVtYmVyXCIgfTtcbiAgICBjYXNlIFwiYm9vbGVhblwiOiByZXR1cm4geyB0eXBlOiBcImJvb2xlYW5cIiB9O1xuICAgIGNhc2UgXCJvYmplY3RcIjogcmV0dXJuIHsgdHlwZTogXCJvYmplY3RcIiwgcHJvcGVydGllczoge30gfTtcbiAgfVxuICB0aHJvdyBgQ2FuJ3QgY29udmVydCBTdHJ1Y3R1cmFsIFR5cGVPZjwke3R5cGUudHlwZXN0cmluZ30+IGNoZWNrcyBpbnRvIEpTT04gU2NoZW1hYFxufVxuXG5mdW5jdGlvbiBmcm9tVmFsdWUodHlwZTogVmFsdWU8YW55Pik6IEpTT05TY2hlbWEge1xuICBpZighaXNTZXJpYWxpemFibGUodHlwZS52YWwpKSB7XG4gICAgdGhyb3cgYFZhbHVlIHR5cGUgZXhwZWN0cyAke3R5cGUudmFsfSwgYnV0IGl0IGlzbid0IHNlcmlhbGl6YWJsZSB0byBKU09OYDtcbiAgfVxuXG4gIGlmKHR5cGUudmFsID09PSBudWxsKSByZXR1cm4geyB0eXBlOiBcIm51bGxcIiB9O1xuXG4gIHJldHVybiB7XG4gICAgY29uc3Q6IHR5cGUudmFsLFxuICB9O1xufVxuXG5mdW5jdGlvbiBmcm9tQXJyYXkodHlwZTogQXJyPGFueT4sIG9wdGlvbnM6IFJlcXVpcmVkPE9wdGlvbnM+KTogSlNPTlNjaGVtYSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogJ2FycmF5JyxcbiAgICBpdGVtczogdHlwZVRvU2NoZW1hKHR5cGUuZWxlbWVudFR5cGUsIG9wdGlvbnMpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBmcm9tU3RydWN0KHR5cGU6IFN0cnVjdDxhbnk+LCBvcHRpb25zOiBSZXF1aXJlZDxPcHRpb25zPik6IEpTT05TY2hlbWEge1xuICBjb25zdCBwcm9wZXJ0aWVzOiB7IFtrZXk6IHN0cmluZ106IEpTT05TY2hlbWEgfSA9IHt9O1xuICBjb25zdCByZXF1aXJlZDogc3RyaW5nW10gPSBbXTtcbiAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKHR5cGUuZGVmaW5pdGlvbik7XG4gIGZvcihjb25zdCBrZXkgb2Yga2V5cykge1xuICAgIGNvbnN0IHZhbCA9IHR5cGUuZGVmaW5pdGlvbltrZXldO1xuICAgIGlmKHZhbCBpbnN0YW5jZW9mIE1pc3NpbmdLZXkgfHwgdmFsIGluc3RhbmNlb2YgT3B0aW9uYWxLZXkpIHtcbiAgICAgIHByb3BlcnRpZXNba2V5XSA9IHR5cGVUb1NjaGVtYSh2YWwudHlwZSwgb3B0aW9ucyk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgcmVxdWlyZWQucHVzaChrZXkpO1xuICAgICAgcHJvcGVydGllc1trZXldID0gdHlwZVRvU2NoZW1hKHZhbCwgb3B0aW9ucyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICByZXF1aXJlZCwgcHJvcGVydGllcyxcbiAgfTtcbn1cblxuZnVuY3Rpb24gZnJvbURpY3QodHlwZTogRGljdDxhbnk+LCBvcHRpb25zOiBSZXF1aXJlZDxPcHRpb25zPik6IEpTT05TY2hlbWEge1xuICByZXR1cm4ge1xuICAgIHR5cGU6ICdvYmplY3QnLFxuICAgIHByb3BlcnRpZXM6IHt9LFxuICAgIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB0eXBlVG9TY2hlbWEodHlwZS52YWx1ZVR5cGUsIG9wdGlvbnMpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBmcm9tSXModHlwZTogSXM8YW55Piwgb3B0aW9uczogUmVxdWlyZWQ8T3B0aW9ucz4pIHtcbiAgaWYob3B0aW9ucy5lcnJvck9uSXMpIHtcbiAgICB0aHJvdyBgU3RydWN0dXJhbCB0eXBlIGNvbnRhaW5zIGFuIElzIGNoZWNrLCBidXQgZXJyb3JPbklzIHdhcyBzZXQgdG8gdHJ1ZWA7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGRlc2NyaXB0aW9uOiB0eXBlLm5hbWUsXG4gIH07XG59XG5cbmZ1bmN0aW9uIGZyb21OZXZlcihfOiBOZXZlciwgb3B0aW9uczogUmVxdWlyZWQ8T3B0aW9ucz4pOiBKU09OU2NoZW1hIHtcbiAgaWYob3B0aW9ucy5lcnJvck9uTmV2ZXIpIHtcbiAgICB0aHJvdyBgU3RydWN0dXJhbCB0eXBlIGNvbnRhaW5zIGEgTmV2ZXIgY2hlY2ssIGJ1dCBlcnJvck9uTmV2ZXIgd2FzIHNldCB0byB0cnVlYDtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgYWxsT2Y6IFsgeyB0eXBlOiBcInN0cmluZ1wiIH0sIHsgdHlwZTogXCJudW1iZXJcIiB9IF0sXG4gIH07XG59XG5cbmZ1bmN0aW9uIGZyb21QYXJ0aWFsKHR5cGU6IFBhcnRpYWxTdHJ1Y3Q8YW55Piwgb3B0aW9uczogUmVxdWlyZWQ8T3B0aW9ucz4pOiBKU09OU2NoZW1hIHtcbiAgLy8gU2luY2UgUGFydGlhbDxUPiBvbmx5IG1ha2VzIHRvcC1sZXZlbCBrZXlzIG9wdGlvbmFsLCB3ZSBqdXN0IG1vZGlmeSB0aGUgcmVxdWlyZWQgYXJyYXlcbiAgY29uc3Qgc2NoZW1hID0gZnJvbVN0cnVjdCh0eXBlLnN0cnVjdCwgb3B0aW9ucyk7XG4gIGlmKCdyZXF1aXJlZCcgaW4gc2NoZW1hKSBzY2hlbWEucmVxdWlyZWQgPSBbXTtcbiAgcmV0dXJuIHNjaGVtYTtcbn1cblxuZnVuY3Rpb24gZmxhdFR5cGVzKFxuICBrbGFzczoge1xuICAgIG5ldyguLi5hcmdzOiBhbnkpOiBFaXRoZXI8YW55LCBhbnk+XG4gICAgICAgICAgICAgICAgICAgICB8IERlZmF1bHRJbnRlcnNlY3Q8YW55LCBhbnk+XG4gICAgICAgICAgICAgICAgICAgICB8IE1lcmdlSW50ZXJzZWN0PGFueSwgYW55LCBhbnksIGFueT5cbiAgfSxcbiAgbm9kZTogVHlwZTxhbnk+XG4pOiBBcnJheTxUeXBlPGFueT4+IHtcbiAgaWYobm9kZSBpbnN0YW5jZW9mIGtsYXNzKSB7XG4gICAgcmV0dXJuIGZsYXRUeXBlcyhrbGFzcywgbm9kZS5sKS5jb25jYXQoZmxhdFR5cGVzKGtsYXNzLCBub2RlLnIpKTtcbiAgfVxuICByZXR1cm4gWyBub2RlIF07XG59XG5cbmZ1bmN0aW9uIGZvcm1hdENvbW1lbnRTdHJpbmcoY29tbWVudFN0cjogc3RyaW5nKSB7XG4gIGNvbnN0IGNvbW1lbnRMaW5lcyA9IGNvbW1lbnRTdHIuc3BsaXQoXCJcXG5cIikubWFwKGxpbmUgPT4ge1xuICAgIHJldHVybiBsaW5lLnRyaW0oKTtcbiAgfSkuZmlsdGVyKGxpbmUgPT4gbGluZSAhPT0gXCJcIik7XG4gIHJldHVybiBjb21tZW50TGluZXMuam9pbihcIlxcblwiKTtcbn1cblxuZnVuY3Rpb24gYWRkTWV0YWRhdGEodGl0bGU6IHN0cmluZywgc2NoZW1hOiBKU09OU2NoZW1hKTogVG9wTGV2ZWw8SlNPTlNjaGVtYT4ge1xuICByZXR1cm4ge1xuICAgICRzY2hlbWE6IEpTT05fU0NIRU1BX1ZFUlNJT04sXG4gICAgdGl0bGUsXG4gICAgLi4uc2NoZW1hLFxuICB9O1xufVxuIl19