function _array_like_to_array(arr, len) {
    if (len == null || len > arr.length) len = arr.length;
    for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
    return arr2;
}
function _array_with_holes(arr) {
    if (Array.isArray(arr)) return arr;
}
function _array_without_holes(arr) {
    if (Array.isArray(arr)) return _array_like_to_array(arr);
}
function _assert_this_initialized(self) {
    if (self === void 0) {
        throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
    }
    return self;
}
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
    try {
        var info = gen[key](arg);
        var value = info.value;
    } catch (error) {
        reject(error);
        return;
    }
    if (info.done) {
        resolve(value);
    } else {
        Promise.resolve(value).then(_next, _throw);
    }
}
function _async_to_generator(fn) {
    return function() {
        var self = this, args = arguments;
        return new Promise(function(resolve, reject) {
            var gen = fn.apply(self, args);
            function _next(value) {
                asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
            }
            function _throw(err) {
                asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
            }
            _next(undefined);
        });
    };
}
function _class_call_check(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
        throw new TypeError("Cannot call a class as a function");
    }
}
function _construct(Parent, args, Class) {
    if (_is_native_reflect_construct()) {
        _construct = Reflect.construct;
    } else {
        _construct = function construct(Parent, args, Class) {
            var a = [
                null
            ];
            a.push.apply(a, args);
            var Constructor = Function.bind.apply(Parent, a);
            var instance = new Constructor();
            if (Class) _set_prototype_of(instance, Class.prototype);
            return instance;
        };
    }
    return _construct.apply(null, arguments);
}
function _define_property(obj, key, value) {
    if (key in obj) {
        Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
        });
    } else {
        obj[key] = value;
    }
    return obj;
}
function _get_prototype_of(o) {
    _get_prototype_of = Object.setPrototypeOf ? Object.getPrototypeOf : function getPrototypeOf(o) {
        return o.__proto__ || Object.getPrototypeOf(o);
    };
    return _get_prototype_of(o);
}
function _inherits(subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function");
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, {
        constructor: {
            value: subClass,
            writable: true,
            configurable: true
        }
    });
    if (superClass) _set_prototype_of(subClass, superClass);
}
function _is_native_function(fn) {
    return Function.toString.call(fn).indexOf("[native code]") !== -1;
}
function _iterable_to_array(iter) {
    if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
}
function _iterable_to_array_limit(arr, i) {
    var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
    if (_i == null) return;
    var _arr = [];
    var _n = true;
    var _d = false;
    var _s, _e;
    try {
        for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
            _arr.push(_s.value);
            if (i && _arr.length === i) break;
        }
    } catch (err) {
        _d = true;
        _e = err;
    } finally{
        try {
            if (!_n && _i["return"] != null) _i["return"]();
        } finally{
            if (_d) throw _e;
        }
    }
    return _arr;
}
function _non_iterable_rest() {
    throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _non_iterable_spread() {
    throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _object_spread(target) {
    for(var i = 1; i < arguments.length; i++){
        var source = arguments[i] != null ? arguments[i] : {};
        var ownKeys = Object.keys(source);
        if (typeof Object.getOwnPropertySymbols === "function") {
            ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
                return Object.getOwnPropertyDescriptor(source, sym).enumerable;
            }));
        }
        ownKeys.forEach(function(key) {
            _define_property(target, key, source[key]);
        });
    }
    return target;
}
function ownKeys(object, enumerableOnly) {
    var keys = Object.keys(object);
    if (Object.getOwnPropertySymbols) {
        var symbols = Object.getOwnPropertySymbols(object);
        if (enumerableOnly) {
            symbols = symbols.filter(function(sym) {
                return Object.getOwnPropertyDescriptor(object, sym).enumerable;
            });
        }
        keys.push.apply(keys, symbols);
    }
    return keys;
}
function _object_spread_props(target, source) {
    source = source != null ? source : {};
    if (Object.getOwnPropertyDescriptors) {
        Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
    } else {
        ownKeys(Object(source)).forEach(function(key) {
            Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
        });
    }
    return target;
}
function _possible_constructor_return(self, call) {
    if (call && (_type_of(call) === "object" || typeof call === "function")) {
        return call;
    }
    return _assert_this_initialized(self);
}
function _set_prototype_of(o, p) {
    _set_prototype_of = Object.setPrototypeOf || function setPrototypeOf(o, p) {
        o.__proto__ = p;
        return o;
    };
    return _set_prototype_of(o, p);
}
function _sliced_to_array(arr, i) {
    return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
}
function _to_consumable_array(arr) {
    return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
}
function _type_of(obj) {
    "@swc/helpers - typeof";
    return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
}
function _unsupported_iterable_to_array(o, minLen) {
    if (!o) return;
    if (typeof o === "string") return _array_like_to_array(o, minLen);
    var n = Object.prototype.toString.call(o).slice(8, -1);
    if (n === "Object" && o.constructor) n = o.constructor.name;
    if (n === "Map" || n === "Set") return Array.from(n);
    if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
}
function _wrap_native_super(Class) {
    var _cache = typeof Map === "function" ? new Map() : undefined;
    _wrap_native_super = function wrapNativeSuper(Class) {
        if (Class === null || !_is_native_function(Class)) return Class;
        if (typeof Class !== "function") {
            throw new TypeError("Super expression must either be null or a function");
        }
        if (typeof _cache !== "undefined") {
            if (_cache.has(Class)) return _cache.get(Class);
            _cache.set(Class, Wrapper);
        }
        function Wrapper() {
            return _construct(Class, arguments, _get_prototype_of(this).constructor);
        }
        Wrapper.prototype = Object.create(Class.prototype, {
            constructor: {
                value: Wrapper,
                enumerable: false,
                writable: true,
                configurable: true
            }
        });
        return _set_prototype_of(Wrapper, Class);
    };
    return _wrap_native_super(Class);
}
function _is_native_reflect_construct() {
    if (typeof Reflect === "undefined" || !Reflect.construct) return false;
    if (Reflect.construct.sham) return false;
    if (typeof Proxy === "function") return true;
    try {
        Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {}));
        return true;
    } catch (e) {
        return false;
    }
}
function _create_super(Derived) {
    var hasNativeReflectConstruct = _is_native_reflect_construct();
    return function _createSuperInternal() {
        var Super = _get_prototype_of(Derived), result;
        if (hasNativeReflectConstruct) {
            var NewTarget = _get_prototype_of(this).constructor;
            result = Reflect.construct(Super, arguments, NewTarget);
        } else {
            result = Super.apply(this, arguments);
        }
        return _possible_constructor_return(this, result);
    };
}
function _ts_generator(thisArg, body) {
    var f, y, t, g, _ = {
        label: 0,
        sent: function() {
            if (t[0] & 1) throw t[1];
            return t[1];
        },
        trys: [],
        ops: []
    };
    return g = {
        next: verb(0),
        "throw": verb(1),
        "return": verb(2)
    }, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
        return this;
    }), g;
    function verb(n) {
        return function(v) {
            return step([
                n,
                v
            ]);
        };
    }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while(_)try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [
                op[0] & 2,
                t.value
            ];
            switch(op[0]){
                case 0:
                case 1:
                    t = op;
                    break;
                case 4:
                    _.label++;
                    return {
                        value: op[1],
                        done: false
                    };
                case 5:
                    _.label++;
                    y = op[1];
                    op = [
                        0
                    ];
                    continue;
                case 7:
                    op = _.ops.pop();
                    _.trys.pop();
                    continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
                        _ = 0;
                        continue;
                    }
                    if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
                        _.label = op[1];
                        break;
                    }
                    if (op[0] === 6 && _.label < t[1]) {
                        _.label = t[1];
                        t = op;
                        break;
                    }
                    if (t && _.label < t[2]) {
                        _.label = t[2];
                        _.ops.push(op);
                        break;
                    }
                    if (t[2]) _.ops.pop();
                    _.trys.pop();
                    continue;
            }
            op = body.call(thisArg, _);
        } catch (e) {
            op = [
                6,
                e
            ];
            y = 0;
        } finally{
            f = t = 0;
        }
        if (op[0] & 5) throw op[1];
        return {
            value: op[0] ? op[1] : void 0,
            done: true
        };
    }
}
var __getOwnPropNames = Object.getOwnPropertyNames;
var __require = /* @__PURE__ */ function(x) {
    return typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
        get: function(a, b) {
            return (typeof require !== "undefined" ? require : a)[b];
        }
    }) : x;
}(function(x) {
    if (typeof require !== "undefined") return require.apply(this, arguments);
    throw Error('Dynamic require of "' + x + '" is not supported');
});
var __commonJS = function(cb, mod) {
    return function __require2() {
        return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = {
            exports: {}
        }).exports, mod), mod.exports;
    };
};
// src/index.ts
import { readFileSync } from "fs";
import { cloneDeep, endsWith, merge } from "lodash";
import { dirname as dirname2 } from "path";
// src/formatter.ts
import { format as prettify } from "prettier";
function format(code, options) {
    if (!options.format) {
        return code;
    }
    return prettify(code, _object_spread({
        parser: "typescript"
    }, options.style));
}
// src/generator.ts
import { memoize as memoize2, omit } from "lodash";
// src/types/AST.ts
function hasComment(ast) {
    return "comment" in ast && ast.comment != null && ast.comment !== "" || // Compare to true because ast.deprecated might be undefined
    "deprecated" in ast && ast.deprecated === true;
}
function hasStandaloneName(ast) {
    return "standaloneName" in ast && ast.standaloneName != null && ast.standaloneName !== "";
}
var T_ANY = {
    type: "ANY"
};
var T_ANY_ADDITIONAL_PROPERTIES = {
    keyName: "[k: string]",
    type: "ANY"
};
var T_UNKNOWN = {
    type: "UNKNOWN"
};
var T_UNKNOWN_ADDITIONAL_PROPERTIES = {
    keyName: "[k: string]",
    type: "UNKNOWN"
};
// src/utils.ts
import { deburr, isPlainObject as isPlainObject2, trim, upperFirst } from "lodash";
import { basename, dirname, extname, normalize, sep, posix } from "path";
// src/types/JSONSchema.ts
import { isPlainObject, memoize } from "lodash";
var Parent = Symbol("Parent");
var getRootSchema = memoize(function(schema) {
    var parent = schema[Parent];
    if (!parent) {
        return schema;
    }
    return getRootSchema(parent);
});
function isBoolean(schema) {
    return schema === true || schema === false;
}
function isPrimitive(schema) {
    return !isPlainObject(schema);
}
function isCompound(schema) {
    return Array.isArray(schema.type) || "anyOf" in schema || "oneOf" in schema;
}
// src/utils.ts
function Try(fn, err) {
    try {
        return fn();
    } catch (e) {
        return err(e);
    }
}
var BLACKLISTED_KEYS = /* @__PURE__ */ new Set([
    "id",
    "$defs",
    "$id",
    "$schema",
    "title",
    "description",
    "default",
    "multipleOf",
    "maximum",
    "exclusiveMaximum",
    "minimum",
    "exclusiveMinimum",
    "maxLength",
    "minLength",
    "pattern",
    "additionalItems",
    "items",
    "maxItems",
    "minItems",
    "uniqueItems",
    "maxProperties",
    "minProperties",
    "required",
    "additionalProperties",
    "definitions",
    "properties",
    "patternProperties",
    "dependencies",
    "enum",
    "type",
    "allOf",
    "anyOf",
    "oneOf",
    "not"
]);
function traverseObjectKeys(obj, callback, processed) {
    Object.keys(obj).forEach(function(k) {
        if (obj[k] && typeof obj[k] === "object" && !Array.isArray(obj[k])) {
            traverse(obj[k], callback, processed, k);
        }
    });
}
function traverseArray(arr, callback, processed) {
    arr.forEach(function(s, k) {
        return traverse(s, callback, processed, k.toString());
    });
}
function traverse(schema, callback) {
    var processed = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : /* @__PURE__ */ new Set(), key = arguments.length > 3 ? arguments[3] : void 0;
    if (processed.has(schema)) {
        return;
    }
    processed.add(schema);
    callback(schema, key !== null && key !== void 0 ? key : null);
    if (schema.anyOf) {
        traverseArray(schema.anyOf, callback, processed);
    }
    if (schema.allOf) {
        traverseArray(schema.allOf, callback, processed);
    }
    if (schema.oneOf) {
        traverseArray(schema.oneOf, callback, processed);
    }
    if (schema.properties) {
        traverseObjectKeys(schema.properties, callback, processed);
    }
    if (schema.patternProperties) {
        traverseObjectKeys(schema.patternProperties, callback, processed);
    }
    if (schema.additionalProperties && typeof schema.additionalProperties === "object") {
        traverse(schema.additionalProperties, callback, processed);
    }
    if (schema.items) {
        var items = schema.items;
        if (Array.isArray(items)) {
            traverseArray(items, callback, processed);
        } else {
            traverse(items, callback, processed);
        }
    }
    if (schema.additionalItems && typeof schema.additionalItems === "object") {
        traverse(schema.additionalItems, callback, processed);
    }
    if (schema.dependencies) {
        if (Array.isArray(schema.dependencies)) {
            traverseArray(schema.dependencies, callback, processed);
        } else {
            traverseObjectKeys(schema.dependencies, callback, processed);
        }
    }
    if (schema.definitions) {
        traverseObjectKeys(schema.definitions, callback, processed);
    }
    if (schema.$defs) {
        traverseObjectKeys(schema.$defs, callback, processed);
    }
    if (schema.not) {
        traverse(schema.not, callback, processed);
    }
    Object.keys(schema).filter(function(key2) {
        return !BLACKLISTED_KEYS.has(key2);
    }).forEach(function(key2) {
        var child = schema[key2];
        if (child && typeof child === "object") {
            traverseObjectKeys(child, callback, processed);
        }
    });
}
function justName() {
    var filename = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : "";
    return stripExtension(basename(filename));
}
function stripExtension(filename) {
    return filename.replace(extname(filename), "");
}
function toSafeString(string) {
    return upperFirst(// remove accents, umlauts, ... by their basic latin letters
    deburr(string).replace(/(^\s*[^a-zA-Z_$])|([^a-zA-Z_$\d])/g, " ").replace(/^_[a-z]/g, function(match) {
        return match.toUpperCase();
    }).replace(/_[a-z]/g, function(match) {
        return match.substr(1, match.length).toUpperCase();
    }).replace(/([\d$]+[a-zA-Z])/g, function(match) {
        return match.toUpperCase();
    }).replace(/\s+([a-zA-Z])/g, function(match) {
        return trim(match.toUpperCase());
    }).replace(/\s/g, ""));
}
function generateName(from, usedNames) {
    var name = toSafeString(from);
    if (!name) {
        name = "NoName";
    }
    if (usedNames.has(name)) {
        var counter = 1;
        var nameWithCounter = "".concat(name).concat(counter);
        while(usedNames.has(nameWithCounter)){
            nameWithCounter = "".concat(name).concat(counter);
            counter++;
        }
        name = nameWithCounter;
    }
    usedNames.add(name);
    return name;
}
function error() {
    for(var _len = arguments.length, messages = new Array(_len), _key = 0; _key < _len; _key++){
        messages[_key] = arguments[_key];
    }
    var _console;
    var _getStyledTextForLogging;
    if (!process.env.VERBOSE) {
        return console.error(messages);
    }
    (_console = console).error.apply(_console, [
        (_getStyledTextForLogging = getStyledTextForLogging("red")) === null || _getStyledTextForLogging === void 0 ? void 0 : _getStyledTextForLogging("error")
    ].concat(_to_consumable_array(messages)));
}
function log(style, title) {
    for(var _len = arguments.length, messages = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++){
        messages[_key - 2] = arguments[_key];
    }
    var _console;
    var _getStyledTextForLogging;
    if (!process.env.VERBOSE) {
        return;
    }
    var lastMessage = null;
    if (messages.length > 1 && typeof messages[messages.length - 1] !== "string") {
        lastMessage = messages.splice(messages.length - 1, 1);
    }
    (_console = console).info.apply(_console, [
        __require("cli-color").whiteBright.bgCyan("debug"),
        (_getStyledTextForLogging = getStyledTextForLogging(style)) === null || _getStyledTextForLogging === void 0 ? void 0 : _getStyledTextForLogging(title)
    ].concat(_to_consumable_array(messages)));
    if (lastMessage) {
        console.dir(lastMessage, {
            depth: 6,
            maxArrayLength: 6
        });
    }
}
function getStyledTextForLogging(style) {
    if (!process.env.VERBOSE) {
        return;
    }
    switch(style){
        case "blue":
            return __require("cli-color").whiteBright.bgBlue;
        case "cyan":
            return __require("cli-color").whiteBright.bgCyan;
        case "green":
            return __require("cli-color").whiteBright.bgGreen;
        case "magenta":
            return __require("cli-color").whiteBright.bgMagenta;
        case "red":
            return __require("cli-color").whiteBright.bgRedBright;
        case "white":
            return __require("cli-color").black.bgWhite;
        case "yellow":
            return __require("cli-color").whiteBright.bgYellow;
    }
}
function escapeBlockComment(schema) {
    var replacer = "* /";
    if (schema === null || typeof schema !== "object") {
        return;
    }
    var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
    try {
        for(var _iterator = Object.keys(schema)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
            var key = _step.value;
            if (key === "description" && typeof schema[key] === "string") {
                schema[key] = schema[key].replace(/\*\//g, replacer);
            }
        }
    } catch (err) {
        _didIteratorError = true;
        _iteratorError = err;
    } finally{
        try {
            if (!_iteratorNormalCompletion && _iterator.return != null) {
                _iterator.return();
            }
        } finally{
            if (_didIteratorError) {
                throw _iteratorError;
            }
        }
    }
}
function pathTransform(outputPath, inputPath, filePath) {
    var _posix;
    var inPathList = normalize(inputPath).split(sep);
    var filePathList = dirname(normalize(filePath)).split(sep);
    var filePathRel = filePathList.filter(function(f, i) {
        return f !== inPathList[i];
    });
    return (_posix = posix).join.apply(_posix, [
        posix.normalize(outputPath)
    ].concat(_to_consumable_array(filePathRel)));
}
function maybeStripDefault(schema) {
    if (!("default" in schema)) {
        return schema;
    }
    switch(schema.type){
        case "array":
            if (Array.isArray(schema.default)) {
                return schema;
            }
            break;
        case "boolean":
            if (typeof schema.default === "boolean") {
                return schema;
            }
            break;
        case "integer":
        case "number":
            if (typeof schema.default === "number") {
                return schema;
            }
            break;
        case "string":
            if (typeof schema.default === "string") {
                return schema;
            }
            break;
        case "null":
            if (schema.default === null) {
                return schema;
            }
            break;
        case "object":
            if (isPlainObject2(schema.default)) {
                return schema;
            }
            break;
    }
    delete schema.default;
    return schema;
}
function maybeStripNameHints(schema) {
    if ("$id" in schema) {
        delete schema.$id;
    }
    if ("description" in schema) {
        delete schema.description;
    }
    if ("name" in schema) {
        delete schema.name;
    }
    return schema;
}
function appendToDescription(existingDescription) {
    for(var _len = arguments.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++){
        values[_key - 1] = arguments[_key];
    }
    if (existingDescription) {
        return "".concat(existingDescription, "\n\n").concat(values.join("\n"));
    }
    return values.join("\n");
}
function isSchemaLike(schema) {
    if (!isPlainObject2(schema)) {
        return false;
    }
    var parent = schema[Parent];
    if (parent === null) {
        return true;
    }
    var JSON_SCHEMA_KEYWORDS = [
        "$defs",
        "allOf",
        "anyOf",
        "definitions",
        "dependencies",
        "enum",
        "not",
        "oneOf",
        "patternProperties",
        "properties",
        "required"
    ];
    if (JSON_SCHEMA_KEYWORDS.some(function(_) {
        return parent[_] === schema;
    })) {
        return false;
    }
    return true;
}
// src/generator.ts
function generate(ast) {
    var options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : DEFAULT_OPTIONS;
    return [
        options.bannerComment,
        declareNamedTypes(ast, options, ast.standaloneName),
        declareNamedInterfaces(ast, options, ast.standaloneName),
        declareEnums(ast, options)
    ].filter(Boolean).join("\n\n") + "\n";
}
function declareEnums(ast, options) {
    var processed = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : /* @__PURE__ */ new Set();
    if (processed.has(ast)) {
        return "";
    }
    processed.add(ast);
    var type = "";
    switch(ast.type){
        case "ENUM":
            return generateStandaloneEnum(ast, options) + "\n";
        case "ARRAY":
            return declareEnums(ast.params, options, processed);
        case "UNION":
        case "INTERSECTION":
            return ast.params.reduce(function(prev, ast2) {
                return prev + declareEnums(ast2, options, processed);
            }, "");
        case "TUPLE":
            type = ast.params.reduce(function(prev, ast2) {
                return prev + declareEnums(ast2, options, processed);
            }, "");
            if (ast.spreadParam) {
                type += declareEnums(ast.spreadParam, options, processed);
            }
            return type;
        case "INTERFACE":
            return getSuperTypesAndParams(ast).reduce(function(prev, ast2) {
                return prev + declareEnums(ast2, options, processed);
            }, "");
        default:
            return "";
    }
}
function declareNamedInterfaces(ast, options, rootASTName) {
    var processed = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : /* @__PURE__ */ new Set();
    if (processed.has(ast)) {
        return "";
    }
    processed.add(ast);
    var type = "";
    switch(ast.type){
        case "ARRAY":
            type = declareNamedInterfaces(ast.params, options, rootASTName, processed);
            break;
        case "INTERFACE":
            type = [
                hasStandaloneName(ast) && (ast.standaloneName === rootASTName || options.declareExternallyReferenced) && generateStandaloneInterface(ast, options),
                getSuperTypesAndParams(ast).map(function(ast2) {
                    return declareNamedInterfaces(ast2, options, rootASTName, processed);
                }).filter(Boolean).join("\n")
            ].filter(Boolean).join("\n");
            break;
        case "INTERSECTION":
        case "TUPLE":
        case "UNION":
            type = ast.params.map(function(_) {
                return declareNamedInterfaces(_, options, rootASTName, processed);
            }).filter(Boolean).join("\n");
            if (ast.type === "TUPLE" && ast.spreadParam) {
                type += declareNamedInterfaces(ast.spreadParam, options, rootASTName, processed);
            }
            break;
        default:
            type = "";
    }
    return type;
}
function declareNamedTypes(ast, options, rootASTName) {
    var processed = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : /* @__PURE__ */ new Set();
    if (processed.has(ast)) {
        return "";
    }
    processed.add(ast);
    switch(ast.type){
        case "ARRAY":
            return [
                declareNamedTypes(ast.params, options, rootASTName, processed),
                hasStandaloneName(ast) ? generateStandaloneType(ast, options) : void 0
            ].filter(Boolean).join("\n");
        case "ENUM":
            return "";
        case "INTERFACE":
            return getSuperTypesAndParams(ast).map(function(ast2) {
                return (ast2.standaloneName === rootASTName || options.declareExternallyReferenced) && declareNamedTypes(ast2, options, rootASTName, processed);
            }).filter(Boolean).join("\n");
        case "INTERSECTION":
        case "TUPLE":
        case "UNION":
            return [
                hasStandaloneName(ast) ? generateStandaloneType(ast, options) : void 0,
                ast.params.map(function(ast2) {
                    return declareNamedTypes(ast2, options, rootASTName, processed);
                }).filter(Boolean).join("\n"),
                "spreadParam" in ast && ast.spreadParam ? declareNamedTypes(ast.spreadParam, options, rootASTName, processed) : void 0
            ].filter(Boolean).join("\n");
        default:
            if (hasStandaloneName(ast)) {
                return generateStandaloneType(ast, options);
            }
            return "";
    }
}
function generateTypeUnmemoized(ast, options) {
    var type = generateRawType(ast, options);
    if (options.strictIndexSignatures && ast.keyName === "[k: string]") {
        return "".concat(type, " | undefined");
    }
    return type;
}
var generateType = memoize2(generateTypeUnmemoized);
function generateRawType(ast, options) {
    log("magenta", "generator", ast);
    if (hasStandaloneName(ast)) {
        return toSafeString(ast.standaloneName);
    }
    switch(ast.type){
        case "ANY":
            return "any";
        case "ARRAY":
            return function() {
                var type = generateType(ast.params, options);
                return type.endsWith('"') ? "(" + type + ")[]" : type + "[]";
            }();
        case "BOOLEAN":
            return "boolean";
        case "INTERFACE":
            return generateInterface(ast, options);
        case "INTERSECTION":
            return generateSetOperation(ast, options);
        case "LITERAL":
            return JSON.stringify(ast.params);
        case "NEVER":
            return "never";
        case "NUMBER":
            return "number";
        case "NULL":
            return "null";
        case "OBJECT":
            return "object";
        case "REFERENCE":
            return ast.params;
        case "STRING":
            return "string";
        case "TUPLE":
            return function() {
                var addSpreadParam = function addSpreadParam(params) {
                    if (spreadParam) {
                        var spread = "...(" + generateType(spreadParam, options) + ")[]";
                        params.push(spread);
                    }
                    return params;
                };
                var paramsToString = function paramsToString(params) {
                    return "[" + params.join(", ") + "]";
                };
                var minItems = ast.minItems;
                var maxItems = ast.maxItems || -1;
                var spreadParam = ast.spreadParam;
                var astParams = _to_consumable_array(ast.params);
                if (minItems > 0 && minItems > astParams.length && ast.spreadParam === void 0) {
                    if (maxItems < 0) {
                        spreadParam = options.unknownAny ? T_UNKNOWN : T_ANY;
                    }
                }
                if (maxItems > astParams.length && ast.spreadParam === void 0) {
                    for(var i = astParams.length; i < maxItems; i += 1){
                        astParams.push(options.unknownAny ? T_UNKNOWN : T_ANY);
                    }
                }
                var paramsList = astParams.map(function(param) {
                    return generateType(param, options);
                });
                if (paramsList.length > minItems) {
                    var cumulativeParamsList = paramsList.slice(0, minItems);
                    var typesToUnion = [];
                    if (cumulativeParamsList.length > 0) {
                        typesToUnion.push(paramsToString(cumulativeParamsList));
                    } else {
                        typesToUnion.push(paramsToString([]));
                    }
                    for(var i1 = minItems; i1 < paramsList.length; i1 += 1){
                        cumulativeParamsList.push(paramsList[i1]);
                        if (i1 === paramsList.length - 1) {
                            addSpreadParam(cumulativeParamsList);
                        }
                        typesToUnion.push(paramsToString(cumulativeParamsList));
                    }
                    return typesToUnion.join("|");
                }
                return paramsToString(addSpreadParam(paramsList));
            }();
        case "UNION":
            return generateSetOperation(ast, options);
        case "UNKNOWN":
            return "unknown";
        case "CUSTOM_TYPE":
            return ast.params;
    }
}
function generateSetOperation(ast, options) {
    var members = ast.params.map(function(_) {
        return generateType(_, options);
    });
    var separator = ast.type === "UNION" ? "|" : "&";
    return members.length === 1 ? members[0] : "(" + members.join(" " + separator + " ") + ")";
}
function generateInterface(ast, options) {
    return "{\n" + ast.params.filter(function(_) {
        return !_.isPatternProperty && !_.isUnreachableDefinition;
    }).map(function(param) {
        var isRequired = param.isRequired, keyName = param.keyName, ast2 = param.ast;
        return [
            isRequired,
            keyName,
            ast2,
            generateType(ast2, options)
        ];
    }).map(function(param) {
        var _param = _sliced_to_array(param, 4), isRequired = _param[0], keyName = _param[1], ast2 = _param[2], type = _param[3];
        return (hasComment(ast2) && !ast2.standaloneName ? generateComment(ast2.comment, ast2.deprecated) + "\n" : "") + escapeKeyName(keyName) + (isRequired ? "" : "?") + ": " + type;
    }).join("\n") + "\n}";
}
function generateComment(comment, deprecated) {
    var commentLines = [
        "/**"
    ];
    if (deprecated) {
        commentLines.push(" * @deprecated");
    }
    if (typeof comment !== "undefined") {
        var _commentLines;
        (_commentLines = commentLines).push.apply(_commentLines, _to_consumable_array(comment.split("\n").map(function(_) {
            return " * " + _;
        })));
    }
    commentLines.push(" */");
    return commentLines.join("\n");
}
function generateStandaloneEnum(ast, options) {
    return (hasComment(ast) ? generateComment(ast.comment, ast.deprecated) + "\n" : "") + "export " + (options.enableConstEnums ? "const " : "") + "enum ".concat(toSafeString(ast.standaloneName), " {\n") + ast.params.map(function(param) {
        var ast2 = param.ast, keyName = param.keyName;
        return keyName + " = " + generateType(ast2, options);
    }).join(",\n") + "\n}";
}
function generateStandaloneInterface(ast, options) {
    return (hasComment(ast) ? generateComment(ast.comment, ast.deprecated) + "\n" : "") + "export interface ".concat(toSafeString(ast.standaloneName), " ") + (ast.superTypes.length > 0 ? "extends ".concat(ast.superTypes.map(function(superType) {
        return toSafeString(superType.standaloneName);
    }).join(", "), " ") : "") + generateInterface(ast, options);
}
function generateStandaloneType(ast, options) {
    return (hasComment(ast) ? generateComment(ast.comment) + "\n" : "") + "export type ".concat(toSafeString(ast.standaloneName), " = ").concat(generateType(omit(ast, "standaloneName"), options));
}
function escapeKeyName(keyName) {
    if (keyName.length && /[A-Za-z_$]/.test(keyName.charAt(0)) && /^[\w$]+$/.test(keyName)) {
        return keyName;
    }
    if (keyName === "[k: string]") {
        return keyName;
    }
    return JSON.stringify(keyName);
}
function getSuperTypesAndParams(ast) {
    return ast.params.map(function(param) {
        return param.ast;
    }).concat(ast.superTypes);
}
// src/normalizer.ts
import { isDeepStrictEqual } from "util";
var rules = /* @__PURE__ */ new Map();
function hasType(schema, type) {
    return schema.type === type || Array.isArray(schema.type) && schema.type.includes(type);
}
function isObjectType(schema) {
    return schema.properties !== void 0 || hasType(schema, "object") || hasType(schema, "any");
}
function isArrayType(schema) {
    return schema.items !== void 0 || hasType(schema, "array") || hasType(schema, "any");
}
rules.set('Remove `type=["null"]` if `enum=[null]`', function(schema) {
    if (Array.isArray(schema.enum) && schema.enum.some(function(e) {
        return e === null;
    }) && Array.isArray(schema.type) && schema.type.includes("null")) {
        schema.type = schema.type.filter(function(type) {
            return type !== "null";
        });
    }
});
rules.set("Destructure unary types", function(schema) {
    if (schema.type && Array.isArray(schema.type) && schema.type.length === 1) {
        schema.type = schema.type[0];
    }
});
rules.set("Add empty `required` property if none is defined", function(schema) {
    if (isObjectType(schema) && !("required" in schema)) {
        schema.required = [];
    }
});
rules.set("Transform `required`=false to `required`=[]", function(schema) {
    if (schema.required === false) {
        schema.required = [];
    }
});
rules.set("Default additionalProperties", function(schema, _, options) {
    if (isObjectType(schema) && !("additionalProperties" in schema) && schema.patternProperties === void 0) {
        schema.additionalProperties = options.additionalProperties;
    }
});
rules.set("Transform id to $id", function(schema, fileName) {
    if (!isSchemaLike(schema)) {
        return;
    }
    if (schema.id && schema.$id && schema.id !== schema.$id) {
        throw ReferenceError("Schema must define either id or $id, not both. Given id=".concat(schema.id, ", $id=").concat(schema.$id, " in ").concat(fileName));
    }
    if (schema.id) {
        schema.$id = schema.id;
        delete schema.id;
    }
});
rules.set("Add an $id to anything that needs it", function(schema, fileName, _options, _key, dereferencedPaths) {
    if (!isSchemaLike(schema)) {
        return;
    }
    if (!schema.$id && !schema[Parent]) {
        schema.$id = toSafeString(justName(fileName));
        return;
    }
    if (!isArrayType(schema) && !isObjectType(schema)) {
        return;
    }
    var dereferencedName = dereferencedPaths.get(schema);
    if (!schema.$id && !schema.title && dereferencedName) {
        schema.$id = toSafeString(justName(dereferencedName));
    }
    if (dereferencedName) {
        dereferencedPaths.delete(schema);
    }
});
rules.set("Escape closing JSDoc comment", function(schema) {
    escapeBlockComment(schema);
});
rules.set("Add JSDoc comments for minItems and maxItems", function(schema) {
    if (!isArrayType(schema)) {
        return;
    }
    var commentsToAppend = [
        "minItems" in schema ? "@minItems ".concat(schema.minItems) : "",
        "maxItems" in schema ? "@maxItems ".concat(schema.maxItems) : ""
    ].filter(Boolean);
    if (commentsToAppend.length) {
        schema.description = appendToDescription.apply(void 0, [
            schema.description
        ].concat(_to_consumable_array(commentsToAppend)));
    }
});
rules.set("Optionally remove maxItems and minItems", function(schema, _fileName, options) {
    if (!isArrayType(schema)) {
        return;
    }
    if ("minItems" in schema && options.ignoreMinAndMaxItems) {
        delete schema.minItems;
    }
    if ("maxItems" in schema && (options.ignoreMinAndMaxItems || options.maxItems === -1)) {
        delete schema.maxItems;
    }
});
rules.set("Normalize schema.minItems", function(schema, _fileName, options) {
    if (options.ignoreMinAndMaxItems) {
        return;
    }
    if (!isArrayType(schema)) {
        return;
    }
    var minItems = schema.minItems;
    schema.minItems = typeof minItems === "number" ? minItems : 0;
});
rules.set("Remove maxItems if it is big enough to likely cause OOMs", function(schema, _fileName, options) {
    if (options.ignoreMinAndMaxItems || options.maxItems === -1) {
        return;
    }
    if (!isArrayType(schema)) {
        return;
    }
    var maxItems = schema.maxItems, minItems = schema.minItems;
    if (maxItems !== void 0 && maxItems - minItems > options.maxItems) {
        delete schema.maxItems;
    }
});
rules.set("Normalize schema.items", function(schema, _fileName, options) {
    if (options.ignoreMinAndMaxItems) {
        return;
    }
    var maxItems = schema.maxItems, minItems = schema.minItems;
    var hasMaxItems = typeof maxItems === "number" && maxItems >= 0;
    var hasMinItems = typeof minItems === "number" && minItems > 0;
    if (schema.items && !Array.isArray(schema.items) && (hasMaxItems || hasMinItems)) {
        var items = schema.items;
        var newItems = Array(maxItems || minItems || 0).fill(items);
        if (!hasMaxItems) {
            schema.additionalItems = items;
        }
        schema.items = newItems;
    }
    if (Array.isArray(schema.items) && hasMaxItems && maxItems < schema.items.length) {
        schema.items = schema.items.slice(0, maxItems);
    }
    return schema;
});
rules.set("Remove extends, if it is empty", function(schema) {
    if (!schema.hasOwnProperty("extends")) {
        return;
    }
    if (schema.extends == null || Array.isArray(schema.extends) && schema.extends.length === 0) {
        delete schema.extends;
    }
});
rules.set("Make extends always an array, if it is defined", function(schema) {
    if (schema.extends == null) {
        return;
    }
    if (!Array.isArray(schema.extends)) {
        schema.extends = [
            schema.extends
        ];
    }
});
rules.set("Transform definitions to $defs", function(schema, fileName) {
    if (schema.definitions && schema.$defs && !isDeepStrictEqual(schema.definitions, schema.$defs)) {
        throw ReferenceError("Schema must define either definitions or $defs, not both. Given id=".concat(schema.id, " in ").concat(fileName));
    }
    if (schema.definitions) {
        schema.$defs = schema.definitions;
        delete schema.definitions;
    }
});
rules.set("Transform const to singleton enum", function(schema) {
    if (schema.const !== void 0) {
        schema.enum = [
            schema.const
        ];
        delete schema.const;
    }
});
function normalize2(rootSchema, dereferencedPaths, filename, options) {
    rules.forEach(function(rule) {
        return traverse(rootSchema, function(schema, key) {
            return rule(schema, filename, options, key, dereferencedPaths);
        });
    });
    return rootSchema;
}
// src/optimizer.ts
import { uniqBy } from "lodash";
function optimize(ast, options) {
    var processed = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : /* @__PURE__ */ new Set();
    if (processed.has(ast)) {
        return ast;
    }
    processed.add(ast);
    switch(ast.type){
        case "INTERFACE":
            return Object.assign(ast, {
                params: ast.params.map(function(_) {
                    return Object.assign(_, {
                        ast: optimize(_.ast, options, processed)
                    });
                })
            });
        case "INTERSECTION":
        case "UNION":
            var optimizedAST = Object.assign(ast, {
                params: ast.params.map(function(_) {
                    return optimize(_, options, processed);
                })
            });
            if (optimizedAST.params.some(function(_) {
                return _.type === "ANY";
            })) {
                log("cyan", "optimizer", "[A, B, C, Any] -> Any", optimizedAST);
                return T_ANY;
            }
            if (optimizedAST.params.some(function(_) {
                return _.type === "UNKNOWN";
            })) {
                log("cyan", "optimizer", "[A, B, C, Unknown] -> Unknown", optimizedAST);
                return T_UNKNOWN;
            }
            if (optimizedAST.params.every(function(_) {
                var a = generateType(omitStandaloneName(_), options);
                var b = generateType(omitStandaloneName(optimizedAST.params[0]), options);
                return a === b;
            }) && optimizedAST.params.some(function(_) {
                return _.standaloneName !== void 0;
            })) {
                log("cyan", "optimizer", "[A (named), A] -> [A (named)]", optimizedAST);
                optimizedAST.params = optimizedAST.params.filter(function(_) {
                    return _.standaloneName !== void 0;
                });
            }
            var params = uniqBy(optimizedAST.params, function(_) {
                return generateType(_, options);
            });
            if (params.length !== optimizedAST.params.length) {
                log("cyan", "optimizer", "[A, B, B] -> [A, B]", optimizedAST);
                optimizedAST.params = params;
            }
            return Object.assign(optimizedAST, {
                params: optimizedAST.params.map(function(_) {
                    return optimize(_, options, processed);
                })
            });
        default:
            return ast;
    }
}
function omitStandaloneName(ast) {
    switch(ast.type){
        case "ENUM":
            return ast;
        default:
            return _object_spread_props(_object_spread({}, ast), {
                standaloneName: void 0
            });
    }
}
// src/parser.ts
import { findKey, includes, isPlainObject as isPlainObject4, map, memoize as memoize3, omit as omit2 } from "lodash";
import { format as format2 } from "util";
// src/typesOfSchema.ts
import { isPlainObject as isPlainObject3 } from "lodash";
function typesOfSchema(schema) {
    if (schema.tsType) {
        return [
            "CUSTOM_TYPE"
        ];
    }
    var matchedTypes = [];
    var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
    try {
        for(var _iterator = Object.entries(matchers)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
            var _step_value = _sliced_to_array(_step.value, 2), schemaType = _step_value[0], f = _step_value[1];
            if (f(schema)) {
                matchedTypes.push(schemaType);
            }
        }
    } catch (err) {
        _didIteratorError = true;
        _iteratorError = err;
    } finally{
        try {
            if (!_iteratorNormalCompletion && _iterator.return != null) {
                _iterator.return();
            }
        } finally{
            if (_didIteratorError) {
                throw _iteratorError;
            }
        }
    }
    if (!matchedTypes.length) {
        return [
            "UNNAMED_SCHEMA"
        ];
    }
    return matchedTypes;
}
var matchers = {
    ALL_OF: function ALL_OF(schema) {
        return "allOf" in schema;
    },
    ANY: function ANY(schema) {
        if (Object.keys(schema).length === 0) {
            return true;
        }
        return schema.type === "any";
    },
    ANY_OF: function ANY_OF(schema) {
        return "anyOf" in schema;
    },
    BOOLEAN: function BOOLEAN(schema) {
        if ("enum" in schema) {
            return false;
        }
        if (schema.type === "boolean") {
            return true;
        }
        if (!isCompound(schema) && typeof schema.default === "boolean") {
            return true;
        }
        return false;
    },
    CUSTOM_TYPE: function CUSTOM_TYPE() {
        return false;
    },
    NAMED_ENUM: function NAMED_ENUM(schema) {
        return "enum" in schema && "tsEnumNames" in schema;
    },
    NAMED_SCHEMA: function NAMED_SCHEMA(schema) {
        return "$id" in schema && ("patternProperties" in schema || "properties" in schema);
    },
    NEVER: function NEVER(schema) {
        return schema === false;
    },
    NULL: function NULL(schema) {
        return schema.type === "null";
    },
    NUMBER: function NUMBER(schema) {
        if ("enum" in schema) {
            return false;
        }
        if (schema.type === "integer" || schema.type === "number") {
            return true;
        }
        if (!isCompound(schema) && typeof schema.default === "number") {
            return true;
        }
        return false;
    },
    OBJECT: function OBJECT(schema) {
        return schema.type === "object" && !isPlainObject3(schema.additionalProperties) && !schema.allOf && !schema.anyOf && !schema.oneOf && !schema.patternProperties && !schema.properties && !schema.required;
    },
    ONE_OF: function ONE_OF(schema) {
        return "oneOf" in schema;
    },
    REFERENCE: function REFERENCE(schema) {
        return "$ref" in schema;
    },
    STRING: function STRING(schema) {
        if ("enum" in schema) {
            return false;
        }
        if (schema.type === "string") {
            return true;
        }
        if (!isCompound(schema) && typeof schema.default === "string") {
            return true;
        }
        return false;
    },
    TYPED_ARRAY: function TYPED_ARRAY(schema) {
        if (schema.type && schema.type !== "array") {
            return false;
        }
        return "items" in schema;
    },
    UNION: function UNION(schema) {
        return Array.isArray(schema.type);
    },
    UNNAMED_ENUM: function UNNAMED_ENUM(schema) {
        if ("tsEnumNames" in schema) {
            return false;
        }
        if (schema.type && schema.type !== "boolean" && schema.type !== "integer" && schema.type !== "number" && schema.type !== "string") {
            return false;
        }
        return "enum" in schema;
    },
    UNNAMED_SCHEMA: function UNNAMED_SCHEMA() {
        return false;
    },
    UNTYPED_ARRAY: function UNTYPED_ARRAY(schema) {
        return schema.type === "array" && !("items" in schema);
    }
};
// src/parser.ts
function parse(schema, options, keyName) {
    var processed = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : /* @__PURE__ */ new Map(), usedNames = arguments.length > 4 && arguments[4] !== void 0 ? arguments[4] : /* @__PURE__ */ new Set();
    if (isPrimitive(schema)) {
        if (isBoolean(schema)) {
            return parseBooleanSchema(schema, keyName, options);
        }
        return parseLiteral(schema, keyName);
    }
    var types = typesOfSchema(schema);
    if (types.length === 1) {
        var ast2 = parseAsTypeWithCache(schema, types[0], options, keyName, processed, usedNames);
        log("blue", "parser", "Types:", types, "Input:", schema, "Output:", ast2);
        return ast2;
    }
    var ast = parseAsTypeWithCache({
        $id: schema.$id,
        allOf: [],
        description: schema.description,
        title: schema.title
    }, "ALL_OF", options, keyName, processed, usedNames);
    ast.params = types.map(function(type) {
        return(// We hoist description (for comment) and id/title (for standaloneName)
        // to the parent intersection type, so we remove it from the children.
        parseAsTypeWithCache(maybeStripNameHints(schema), type, options, keyName, processed, usedNames));
    });
    log("blue", "parser", "Types:", types, "Input:", schema, "Output:", ast);
    return ast;
}
function parseAsTypeWithCache(schema, type, options, keyName) {
    var processed = arguments.length > 4 && arguments[4] !== void 0 ? arguments[4] : /* @__PURE__ */ new Map(), usedNames = arguments.length > 5 && arguments[5] !== void 0 ? arguments[5] : /* @__PURE__ */ new Set();
    var cachedTypeMap = processed.get(schema);
    if (!cachedTypeMap) {
        cachedTypeMap = /* @__PURE__ */ new Map();
        processed.set(schema, cachedTypeMap);
    }
    var cachedAST = cachedTypeMap.get(type);
    if (cachedAST) {
        return cachedAST;
    }
    var ast = {};
    cachedTypeMap.set(type, ast);
    return Object.assign(ast, parseNonLiteral(schema, type, options, keyName, processed, usedNames));
}
function parseBooleanSchema(schema, keyName, options) {
    if (schema) {
        return {
            keyName: keyName,
            type: options.unknownAny ? "UNKNOWN" : "ANY"
        };
    }
    return {
        keyName: keyName,
        type: "NEVER"
    };
}
function parseLiteral(schema, keyName) {
    return {
        keyName: keyName,
        params: schema,
        type: "LITERAL"
    };
}
function parseNonLiteral(schema, type, options, keyName, processed, usedNames) {
    var definitions = getDefinitionsMemoized(getRootSchema(schema));
    var keyNameFromDefinition = findKey(definitions, function(_) {
        return _ === schema;
    });
    switch(type){
        case "ALL_OF":
            return {
                comment: schema.description,
                deprecated: schema.deprecated,
                keyName: keyName,
                standaloneName: standaloneName(schema, keyNameFromDefinition, usedNames),
                params: schema.allOf.map(function(_) {
                    return parse(_, options, void 0, processed, usedNames);
                }),
                type: "INTERSECTION"
            };
        case "ANY":
            return _object_spread_props(_object_spread({}, options.unknownAny ? T_UNKNOWN : T_ANY), {
                comment: schema.description,
                deprecated: schema.deprecated,
                keyName: keyName,
                standaloneName: standaloneName(schema, keyNameFromDefinition, usedNames)
            });
        case "ANY_OF":
            return {
                comment: schema.description,
                deprecated: schema.deprecated,
                keyName: keyName,
                standaloneName: standaloneName(schema, keyNameFromDefinition, usedNames),
                params: schema.anyOf.map(function(_) {
                    return parse(_, options, void 0, processed, usedNames);
                }),
                type: "UNION"
            };
        case "BOOLEAN":
            return {
                comment: schema.description,
                deprecated: schema.deprecated,
                keyName: keyName,
                standaloneName: standaloneName(schema, keyNameFromDefinition, usedNames),
                type: "BOOLEAN"
            };
        case "CUSTOM_TYPE":
            return {
                comment: schema.description,
                deprecated: schema.deprecated,
                keyName: keyName,
                params: schema.tsType,
                standaloneName: standaloneName(schema, keyNameFromDefinition, usedNames),
                type: "CUSTOM_TYPE"
            };
        case "NAMED_ENUM":
            return {
                comment: schema.description,
                deprecated: schema.deprecated,
                keyName: keyName,
                standaloneName: standaloneName(schema, keyNameFromDefinition !== null && keyNameFromDefinition !== void 0 ? keyNameFromDefinition : keyName, usedNames),
                params: schema.enum.map(function(_, n) {
                    return {
                        ast: parseLiteral(_, void 0),
                        keyName: schema.tsEnumNames[n]
                    };
                }),
                type: "ENUM"
            };
        case "NAMED_SCHEMA":
            return newInterface(schema, options, processed, usedNames, keyName);
        case "NEVER":
            return {
                comment: schema.description,
                deprecated: schema.deprecated,
                keyName: keyName,
                standaloneName: standaloneName(schema, keyNameFromDefinition, usedNames),
                type: "NEVER"
            };
        case "NULL":
            return {
                comment: schema.description,
                deprecated: schema.deprecated,
                keyName: keyName,
                standaloneName: standaloneName(schema, keyNameFromDefinition, usedNames),
                type: "NULL"
            };
        case "NUMBER":
            return {
                comment: schema.description,
                deprecated: schema.deprecated,
                keyName: keyName,
                standaloneName: standaloneName(schema, keyNameFromDefinition, usedNames),
                type: "NUMBER"
            };
        case "OBJECT":
            return {
                comment: schema.description,
                keyName: keyName,
                standaloneName: standaloneName(schema, keyNameFromDefinition, usedNames),
                type: "OBJECT",
                deprecated: schema.deprecated
            };
        case "ONE_OF":
            return {
                comment: schema.description,
                deprecated: schema.deprecated,
                keyName: keyName,
                standaloneName: standaloneName(schema, keyNameFromDefinition, usedNames),
                params: schema.oneOf.map(function(_) {
                    return parse(_, options, void 0, processed, usedNames);
                }),
                type: "UNION"
            };
        case "REFERENCE":
            throw Error(format2("Refs should have been resolved by the resolver!", schema));
        case "STRING":
            return {
                comment: schema.description,
                deprecated: schema.deprecated,
                keyName: keyName,
                standaloneName: standaloneName(schema, keyNameFromDefinition, usedNames),
                type: "STRING"
            };
        case "TYPED_ARRAY":
            if (Array.isArray(schema.items)) {
                var minItems2 = schema.minItems;
                var maxItems2 = schema.maxItems;
                var arrayType = {
                    comment: schema.description,
                    deprecated: schema.deprecated,
                    keyName: keyName,
                    maxItems: maxItems2,
                    minItems: minItems2,
                    standaloneName: standaloneName(schema, keyNameFromDefinition, usedNames),
                    params: schema.items.map(function(_) {
                        return parse(_, options, void 0, processed, usedNames);
                    }),
                    type: "TUPLE"
                };
                if (schema.additionalItems === true) {
                    arrayType.spreadParam = options.unknownAny ? T_UNKNOWN : T_ANY;
                } else if (schema.additionalItems) {
                    arrayType.spreadParam = parse(schema.additionalItems, options, void 0, processed, usedNames);
                }
                return arrayType;
            } else {
                return {
                    comment: schema.description,
                    deprecated: schema.deprecated,
                    keyName: keyName,
                    standaloneName: standaloneName(schema, keyNameFromDefinition, usedNames),
                    params: parse(schema.items, options, "{keyNameFromDefinition}Items", processed, usedNames),
                    type: "ARRAY"
                };
            }
        case "UNION":
            return {
                comment: schema.description,
                deprecated: schema.deprecated,
                keyName: keyName,
                standaloneName: standaloneName(schema, keyNameFromDefinition, usedNames),
                params: schema.type.map(function(type2) {
                    var member = _object_spread_props(_object_spread({}, omit2(schema, "$id", "description", "title")), {
                        type: type2
                    });
                    return parse(maybeStripDefault(member), options, void 0, processed, usedNames);
                }),
                type: "UNION"
            };
        case "UNNAMED_ENUM":
            return {
                comment: schema.description,
                deprecated: schema.deprecated,
                keyName: keyName,
                standaloneName: standaloneName(schema, keyNameFromDefinition, usedNames),
                params: schema.enum.map(function(_) {
                    return parseLiteral(_, void 0);
                }),
                type: "UNION"
            };
        case "UNNAMED_SCHEMA":
            return newInterface(schema, options, processed, usedNames, keyName, keyNameFromDefinition);
        case "UNTYPED_ARRAY":
            var minItems = schema.minItems;
            var maxItems = typeof schema.maxItems === "number" ? schema.maxItems : -1;
            var params = options.unknownAny ? T_UNKNOWN : T_ANY;
            if (minItems > 0 || maxItems >= 0) {
                return {
                    comment: schema.description,
                    deprecated: schema.deprecated,
                    keyName: keyName,
                    maxItems: schema.maxItems,
                    minItems: minItems,
                    // create a tuple of length N
                    params: Array(Math.max(maxItems, minItems) || 0).fill(params),
                    // if there is no maximum, then add a spread item to collect the rest
                    spreadParam: maxItems >= 0 ? void 0 : params,
                    standaloneName: standaloneName(schema, keyNameFromDefinition, usedNames),
                    type: "TUPLE"
                };
            }
            return {
                comment: schema.description,
                deprecated: schema.deprecated,
                keyName: keyName,
                params: params,
                standaloneName: standaloneName(schema, keyNameFromDefinition, usedNames),
                type: "ARRAY"
            };
    }
}
function standaloneName(schema, keyNameFromDefinition, usedNames) {
    var name = schema.title || schema.$id || keyNameFromDefinition;
    if (name) {
        return generateName(name, usedNames);
    }
}
function newInterface(schema, options, processed, usedNames, keyName, keyNameFromDefinition) {
    var name = standaloneName(schema, keyNameFromDefinition, usedNames);
    return {
        comment: schema.description,
        deprecated: schema.deprecated,
        keyName: keyName,
        params: parseSchema(schema, options, processed, usedNames, name),
        standaloneName: name,
        superTypes: parseSuperTypes(schema, options, processed, usedNames),
        type: "INTERFACE"
    };
}
function parseSuperTypes(schema, options, processed, usedNames) {
    var superTypes = schema.extends;
    if (!superTypes) {
        return [];
    }
    return superTypes.map(function(_) {
        return parse(_, options, void 0, processed, usedNames);
    });
}
function parseSchema(schema, options, processed, usedNames, parentSchemaName) {
    var asts = map(schema.properties, function(value, key) {
        return {
            ast: parse(value, options, key, processed, usedNames),
            isPatternProperty: false,
            isRequired: includes(schema.required || [], key),
            isUnreachableDefinition: false,
            keyName: key
        };
    });
    var singlePatternProperty = false;
    if (schema.patternProperties) {
        singlePatternProperty = !schema.additionalProperties && Object.keys(schema.patternProperties).length === 1;
        asts = asts.concat(map(schema.patternProperties, function(value, key) {
            var ast = parse(value, options, key, processed, usedNames);
            var comment = "This interface was referenced by `".concat(parentSchemaName, "`'s JSON-Schema definition\nvia the `patternProperty` \"").concat(key, '".');
            ast.comment = ast.comment ? "".concat(ast.comment, "\n\n").concat(comment) : comment;
            return {
                ast: ast,
                isPatternProperty: !singlePatternProperty,
                isRequired: singlePatternProperty || includes(schema.required || [], key),
                isUnreachableDefinition: false,
                keyName: singlePatternProperty ? "[k: string]" : key
            };
        }));
    }
    if (options.unreachableDefinitions) {
        asts = asts.concat(map(schema.$defs, function(value, key) {
            var ast = parse(value, options, key, processed, usedNames);
            var comment = "This interface was referenced by `".concat(parentSchemaName, "`'s JSON-Schema\nvia the `definition` \"").concat(key, '".');
            ast.comment = ast.comment ? "".concat(ast.comment, "\n\n").concat(comment) : comment;
            return {
                ast: ast,
                isPatternProperty: false,
                isRequired: includes(schema.required || [], key),
                isUnreachableDefinition: true,
                keyName: key
            };
        }));
    }
    switch(schema.additionalProperties){
        case void 0:
        case true:
            if (singlePatternProperty) {
                return asts;
            }
            return asts.concat({
                ast: options.unknownAny ? T_UNKNOWN_ADDITIONAL_PROPERTIES : T_ANY_ADDITIONAL_PROPERTIES,
                isPatternProperty: false,
                isRequired: true,
                isUnreachableDefinition: false,
                keyName: "[k: string]"
            });
        case false:
            return asts;
        default:
            return asts.concat({
                ast: parse(schema.additionalProperties, options, "[k: string]", processed, usedNames),
                isPatternProperty: false,
                isRequired: true,
                isUnreachableDefinition: false,
                keyName: "[k: string]"
            });
    }
}
function getDefinitions(schema) {
    var isSchema = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true, processed = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : /* @__PURE__ */ new Set();
    if (processed.has(schema)) {
        return {};
    }
    processed.add(schema);
    if (Array.isArray(schema)) {
        return schema.reduce(function(prev, cur) {
            return _object_spread({}, prev, getDefinitions(cur, false, processed));
        }, {});
    }
    if (isPlainObject4(schema)) {
        return _object_spread({}, isSchema && hasDefinitions(schema) ? schema.$defs : {}, Object.keys(schema).reduce(function(prev, cur) {
            return _object_spread({}, prev, getDefinitions(schema[cur], false, processed));
        }, {}));
    }
    return {};
}
var getDefinitionsMemoized = memoize3(getDefinitions);
function hasDefinitions(schema) {
    return "$defs" in schema;
}
// src/resolver.ts
import $RefParser from "@bcherny/json-schema-ref-parser";
function dereference(schema, _) {
    return _dereference.apply(this, arguments);
}
function _dereference() {
    _dereference = _async_to_generator(function(schema, param) {
        var cwd, $refOptions, parser, dereferencedPaths, dereferencedSchema;
        return _ts_generator(this, function(_state) {
            switch(_state.label){
                case 0:
                    cwd = param.cwd, $refOptions = param.$refOptions;
                    log("green", "dereferencer", "Dereferencing input schema:", cwd, schema);
                    parser = new $RefParser();
                    dereferencedPaths = /* @__PURE__ */ new WeakMap();
                    return [
                        4,
                        parser.dereference(cwd, schema, _object_spread_props(_object_spread({}, $refOptions), {
                            dereference: _object_spread_props(_object_spread({}, $refOptions.dereference), {
                                onDereference: function onDereference($ref, schema2) {
                                    dereferencedPaths.set(schema2, $ref);
                                }
                            })
                        }))
                    ];
                case 1:
                    dereferencedSchema = _state.sent();
                    return [
                        2,
                        {
                            dereferencedPaths: dereferencedPaths,
                            dereferencedSchema: dereferencedSchema
                        }
                    ];
            }
        });
    });
    return _dereference.apply(this, arguments);
}
// src/validator.ts
var rules2 = /* @__PURE__ */ new Map();
rules2.set("Enum members and tsEnumNames must be of the same length", function(schema) {
    if (schema.enum && schema.tsEnumNames && schema.enum.length !== schema.tsEnumNames.length) {
        return false;
    }
});
rules2.set("tsEnumNames must be an array of strings", function(schema) {
    if (schema.tsEnumNames && schema.tsEnumNames.some(function(_) {
        return typeof _ !== "string";
    })) {
        return false;
    }
});
rules2.set("When both maxItems and minItems are present, maxItems >= minItems", function(schema) {
    var maxItems = schema.maxItems, minItems = schema.minItems;
    if (typeof maxItems === "number" && typeof minItems === "number") {
        return maxItems >= minItems;
    }
});
rules2.set("When maxItems exists, maxItems >= 0", function(schema) {
    var maxItems = schema.maxItems;
    if (typeof maxItems === "number") {
        return maxItems >= 0;
    }
});
rules2.set("When minItems exists, minItems >= 0", function(schema) {
    var minItems = schema.minItems;
    if (typeof minItems === "number") {
        return minItems >= 0;
    }
});
rules2.set("deprecated must be a boolean", function(schema) {
    var typeOfDeprecated = _type_of(schema.deprecated);
    return typeOfDeprecated === "boolean" || typeOfDeprecated === "undefined";
});
function validate(schema, filename) {
    var errors = [];
    rules2.forEach(function(rule, ruleName) {
        traverse(schema, function(schema2, key) {
            if (rule(schema2) === false) {
                errors.push('Error at key "'.concat(key, '" in file "').concat(filename, '": ').concat(ruleName));
            }
            return schema2;
        });
    });
    return errors;
}
// src/index.ts
import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
// src/linker.ts
import { isPlainObject as isPlainObject5 } from "lodash";
function link(schema) {
    var parent = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : null;
    if (!Array.isArray(schema) && !isPlainObject5(schema)) {
        return schema;
    }
    if (schema.hasOwnProperty(Parent)) {
        return schema;
    }
    Object.defineProperty(schema, Parent, {
        enumerable: false,
        value: parent,
        writable: false
    });
    if (Array.isArray(schema)) {
        schema.forEach(function(child) {
            return link(child, schema);
        });
    }
    for(var key in schema){
        link(schema[key], schema);
    }
    return schema;
}
// src/optionValidator.ts
function validateOptions(param) {
    var maxItems = param.maxItems;
    if (maxItems !== void 0 && maxItems < -1) {
        throw RangeError("Expected options.maxItems to be >= -1, but was given ".concat(maxItems, "."));
    }
}
// src/index.ts
var DEFAULT_OPTIONS = {
    $refOptions: {},
    additionalProperties: true,
    // TODO: default to empty schema (as per spec) instead
    bannerComment: "/* eslint-disable */\n/**\n* This file was automatically generated by json-schema-to-typescript.\n* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,\n* and run json-schema-to-typescript to regenerate this file.\n*/",
    cwd: process.cwd(),
    declareExternallyReferenced: true,
    enableConstEnums: true,
    format: true,
    ignoreMinAndMaxItems: false,
    maxItems: 20,
    strictIndexSignatures: false,
    style: {
        bracketSpacing: false,
        printWidth: 120,
        semi: true,
        singleQuote: false,
        tabWidth: 2,
        trailingComma: "none",
        useTabs: false
    },
    unreachableDefinitions: false,
    unknownAny: true
};
function compileFromFile(filename) {
    var options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : DEFAULT_OPTIONS;
    var contents = Try(function() {
        return readFileSync(filename);
    }, function() {
        throw new ReferenceError('Unable to read file "'.concat(filename, '"'));
    });
    var schema = Try(function() {
        return JSON.parse(contents.toString());
    }, function() {
        throw new TypeError('Error parsing JSON in file "'.concat(filename, '"'));
    });
    return compile(schema, stripExtension(filename), _object_spread({
        cwd: dirname2(filename)
    }, options));
}
function compile(schema, name) {
    return _compile.apply(this, arguments);
}
function _compile() {
    _compile = _async_to_generator(function(schema, name) {
        var options, _options, start, _schema, _ref, dereferencedPaths, dereferencedSchema, linked, errors, normalized, parsed, optimized, generated, formatted;
        var _arguments = arguments;
        function time() {
            return "(".concat(Date.now() - start, "ms)");
        }
        return _ts_generator(this, function(_state) {
            switch(_state.label){
                case 0:
                    options = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : {};
                    validateOptions(options);
                    _options = merge({}, DEFAULT_OPTIONS, options);
                    start = Date.now();
                    if (!endsWith(_options.cwd, "/")) {
                        _options.cwd += "/";
                    }
                    _schema = cloneDeep(schema);
                    return [
                        4,
                        dereference(_schema, _options)
                    ];
                case 1:
                    _ref = _state.sent(), dereferencedPaths = _ref.dereferencedPaths, dereferencedSchema = _ref.dereferencedSchema;
                    if (process.env.VERBOSE) {
                        if (isDeepStrictEqual2(_schema, dereferencedSchema)) {
                            log("green", "dereferencer", time(), "✅ No change");
                        } else {
                            log("green", "dereferencer", time(), "✅ Result:", dereferencedSchema);
                        }
                    }
                    linked = link(dereferencedSchema);
                    if (process.env.VERBOSE) {
                        log("green", "linker", time(), "✅ No change");
                    }
                    errors = validate(linked, name);
                    if (errors.length) {
                        errors.forEach(function(_) {
                            return error(_);
                        });
                        throw new ValidationError();
                    }
                    if (process.env.VERBOSE) {
                        log("green", "validator", time(), "✅ No change");
                    }
                    normalized = normalize2(linked, dereferencedPaths, name, _options);
                    log("yellow", "normalizer", time(), "✅ Result:", normalized);
                    parsed = parse(normalized, _options);
                    log("blue", "parser", time(), "✅ Result:", parsed);
                    optimized = optimize(parsed, _options);
                    log("cyan", "optimizer", time(), "✅ Result:", optimized);
                    generated = generate(optimized, _options);
                    log("magenta", "generator", time(), "✅ Result:", generated);
                    formatted = format(generated, _options);
                    log("white", "formatter", time(), "✅ Result:", formatted);
                    return [
                        2,
                        formatted
                    ];
            }
        });
    });
    return _compile.apply(this, arguments);
}
var ValidationError = /*#__PURE__*/ function(Error1) {
    "use strict";
    _inherits(ValidationError, Error1);
    var _super = _create_super(ValidationError);
    function ValidationError() {
        _class_call_check(this, ValidationError);
        return _super.apply(this, arguments);
    }
    return ValidationError;
}(_wrap_native_super(Error));
export { __require, __commonJS, error, pathTransform, DEFAULT_OPTIONS, compileFromFile, compile, ValidationError };
