import colors from "ansi-colors";
import fs from "node:fs";
import path from "node:path";
import open from "open";
import { sync } from "cross-spawn";
import * as semver from "semver";
import { getResolvedInput, sendRequest } from "@hey-api/json-schema-ref-parser";
import { fromRef, log, ref } from "@hey-api/codegen-core";
import { EOL } from "node:os";
//#region src/tsConfig.ts
function findPackageJson(initialDir) {
	let dir = initialDir;
	while (dir !== path.dirname(dir)) {
		const candidates = fs.readdirSync(dir).filter((file) => file === "package.json");
		if (candidates[0]) {
			const packageJsonPath = path.join(dir, candidates[0]);
			return JSON.parse(fs.readFileSync(packageJsonPath, { encoding: "utf8" }));
		}
		dir = path.dirname(dir);
	}
}
function loadPackageJson(initialDir) {
	const packageJson = findPackageJson(initialDir);
	const safePackage = {
		bugs: { url: "" },
		name: "",
		version: ""
	};
	if (packageJson && typeof packageJson === "object") {
		if ("name" in packageJson && typeof packageJson.name === "string") safePackage.name = packageJson.name;
		if ("version" in packageJson && typeof packageJson.version === "string") safePackage.version = packageJson.version;
		if ("bugs" in packageJson && packageJson.bugs && typeof packageJson.bugs === "object") {
			if ("url" in packageJson.bugs && typeof packageJson.bugs.url === "string") {
				safePackage.bugs.url = packageJson.bugs.url;
				if (safePackage.bugs.url && !safePackage.bugs.url.endsWith("/")) safePackage.bugs.url += "/";
			}
		}
	}
	if (!safePackage.name) return;
	return safePackage;
}
function findTsConfigPath(baseDir, tsConfigPath) {
	if (tsConfigPath === null) return null;
	if (tsConfigPath) {
		const resolved = path.isAbsolute(tsConfigPath) ? tsConfigPath : path.resolve(baseDir, tsConfigPath);
		return fs.existsSync(resolved) ? resolved : null;
	}
	let dir = baseDir;
	while (dir !== path.dirname(dir)) {
		const candidates = fs.readdirSync(dir).filter((file) => file.startsWith("tsconfig") && file.endsWith(".json")).sort((file) => file === "tsconfig.json" ? -1 : 1);
		if (candidates[0]) return path.join(dir, candidates[0]);
		dir = path.dirname(dir);
	}
	return null;
}
//#endregion
//#region src/cli.ts
const textAscii = `
888   |                           e      888~-_   888
888___|  e88~~8e  Y88b  /        d8b     888   \\  888
888   | d888  88b  Y888/        /Y88b    888    | 888
888   | 8888__888   Y8/        /  Y88b   888   /  888
888   | Y888    ,    Y        /____Y88b  888_-~   888
888   |  "88___/    /        /      Y88b 888      888
                  _/
`;
const asciiToLines = (ascii, options) => {
	const lines = [];
	const padding = Array.from({ length: options?.padding ?? 0 }).fill("");
	lines.push(...padding);
	let maxLineLength = 0;
	let line = "";
	for (const char of ascii) if (char === "\n") {
		if (line) {
			lines.push(line);
			maxLineLength = Math.max(maxLineLength, line.length);
			line = "";
		}
	} else line += char;
	lines.push(...padding);
	return {
		lines,
		maxLineLength
	};
};
/**
* Checks the current environment based on the HEYAPI_CODEGEN_ENV environment variable.
*/
function isEnvironment(value) {
	return process.env.HEYAPI_CODEGEN_ENV === value;
}
function printCliIntro(initialDir, showLogo = false) {
	const packageJson = loadPackageJson(initialDir);
	if (packageJson) {
		if (showLogo) {
			const text = asciiToLines(textAscii, { padding: 1 });
			for (const line of text.lines) console.log(colors.cyan(line));
		}
		const versionString = isEnvironment("development") ? "[DEVELOPMENT]" : `v${packageJson.version}`;
		console.log(colors.gray(`${packageJson.name} ${versionString}`));
	}
	console.log("");
}
//#endregion
//#region src/fs.ts
function ensureDirSync(path) {
	if (!fs.existsSync(path)) fs.mkdirSync(path, { recursive: true });
}
//#endregion
//#region src/error.ts
/**
* Represents a single configuration error.
*
* Used for reporting issues with a specific config instance.
*/
var ConfigError = class extends Error {
	constructor(message) {
		super(message);
		this.name = "ConfigError";
	}
};
/**
* Aggregates multiple config errors with their job indices for reporting.
*/
var ConfigValidationError = class extends Error {
	errors;
	constructor(errors) {
		super(`Found ${errors.length} configuration ${errors.length === 1 ? "error" : "errors"}.`);
		this.name = "ConfigValidationError";
		this.errors = errors;
	}
};
/**
* Represents an error caused by invalid or inaccessible input.
*
* Used for errors like file not found, URL not reachable, etc.
*/
var InputError = class extends Error {
	originalError;
	constructor(message, originalError) {
		super(message);
		this.name = "InputError";
		this.originalError = originalError;
	}
};
/**
* Represents a runtime error originating from a specific job.
*
* Used for reporting job-level failures that are not config validation errors.
*/
var JobError = class extends Error {
	originalError;
	constructor(message, error) {
		super(message);
		this.name = "JobError";
		this.originalError = error;
	}
};
var HeyApiError = class extends Error {
	args;
	event;
	pluginName;
	constructor({ args, error, event, name, pluginName }) {
		const message = error instanceof Error ? error.message : "Unknown error";
		super(message);
		this.args = args;
		this.cause = error.cause;
		this.event = event;
		this.name = name || error.name;
		this.pluginName = pluginName;
		this.stack = error.stack;
	}
};
function logCrashReport(error, logsDir) {
	if (error instanceof ConfigError || error instanceof ConfigValidationError || error instanceof InputError) return;
	if (error instanceof JobError) error = error.originalError.error;
	const logName = `openapi-ts-error-${Date.now()}.log`;
	const fullDir = path.resolve(process.cwd(), logsDir);
	ensureDirSync(fullDir);
	const logPath = path.resolve(fullDir, logName);
	let logContent = `[${(/* @__PURE__ */ new Date()).toISOString()}] `;
	if (error instanceof HeyApiError) {
		logContent += `${error.name} during event "${error.event}"\n`;
		if (error.pluginName) logContent += `Plugin: ${error.pluginName}\n`;
		logContent += `Arguments: ${JSON.stringify(error.args, null, 2)}\n\n`;
	}
	const message = error instanceof Error ? error.message : String(error);
	const stack = error instanceof Error ? error.stack : void 0;
	logContent += `Error: ${message}\n`;
	if (stack) logContent += `Stack:\n${stack}\n`;
	fs.writeFileSync(logPath, logContent);
	return logPath;
}
async function openGitHubIssueWithCrashReport(error, initialDir) {
	const packageJson = loadPackageJson(initialDir);
	if (!packageJson?.bugs.url) return;
	if (error instanceof JobError) error = error.originalError.error;
	let body = "";
	if (error instanceof HeyApiError) {
		if (error.pluginName) body += `**Plugin**: \`${error.pluginName}\`\n`;
		body += `**Event**: \`${error.event}\`\n`;
		body += `**Arguments**:\n\`\`\`ts\n${JSON.stringify(error.args, null, 2)}\n\`\`\`\n\n`;
	}
	const message = error instanceof Error ? error.message : String(error);
	const stack = error instanceof Error ? error.stack : void 0;
	body += `**Error**: \`${message}\`\n`;
	if (stack) body += `\n**Stack Trace**:\n\`\`\`\n${stack}\n\`\`\``;
	const search = new URLSearchParams({
		body,
		labels: "bug 🔥",
		title: "Crash Report"
	});
	await open(`${packageJson.bugs.url}new?${search.toString()}`);
}
function getInputError(error) {
	if (error instanceof InputError) return error;
	if (error instanceof JobError && error.originalError.error instanceof InputError) return error.originalError.error;
}
function printCrashReport({ error, logPath }) {
	if (error instanceof ConfigValidationError && error.errors.length) {
		const groupByJob = /* @__PURE__ */ new Map();
		for (const { error: err, jobIndex } of error.errors) {
			if (!groupByJob.has(jobIndex)) groupByJob.set(jobIndex, []);
			groupByJob.get(jobIndex).push(err);
		}
		for (const [jobIndex, errors] of groupByJob.entries()) {
			const jobPrefix = colors.gray(`[Job ${jobIndex + 1}] `);
			const count = errors.length;
			const baseString = colors.red(`Found ${count} configuration ${count === 1 ? "error" : "errors"}:`);
			console.error(`${jobPrefix}❗️ ${baseString}`);
			errors.forEach((err, index) => {
				const itemPrefixStr = `  [${index + 1}] `;
				const itemPrefix = colors.red(itemPrefixStr);
				console.error(`${jobPrefix}${itemPrefix}${colors.white(err.message)}`);
			});
		}
	} else {
		let jobPrefix = colors.gray("[root] ");
		if (error instanceof JobError) {
			jobPrefix = colors.gray(`[Job ${error.originalError.jobIndex + 1}] `);
			error = error.originalError.error;
		}
		if (error instanceof InputError) {
			const source = error.originalError.source;
			const itemPrefixStr = `  `;
			if (error.message.startsWith("Input request failed")) {
				console.error(`${jobPrefix}${colors.red(`❌ ${error.message}`)}`);
				if (source) console.error(colors.gray(source));
				console.error(colors.gray("\nPlease verify that:"));
				console.error(colors.gray(`${itemPrefixStr}• The URL is correct`));
				console.error(colors.gray(`${itemPrefixStr}• Your API key is valid`));
				console.error(colors.gray(`${itemPrefixStr}• You have network access`));
				return;
			}
			console.error(`${jobPrefix}${colors.red("❌ Input file not found:")}`);
			if (source) console.error(colors.gray(source));
			console.error(colors.gray("\nPlease verify that:"));
			console.error(colors.gray(`${itemPrefixStr}• The file exists`));
			console.error(colors.gray(`${itemPrefixStr}• The path is correct`));
			console.error(colors.gray(`${itemPrefixStr}• You have read permissions`));
			return;
		}
		const baseString = colors.red("Failed with the message:");
		console.error(`${jobPrefix}❌ ${baseString}`);
		const itemPrefix = colors.red(`  `);
		console.error(`${jobPrefix}${itemPrefix}${typeof error === "string" ? error : error instanceof Error ? error.message : "Unknown error"}`);
	}
	if (logPath) {
		const jobPrefix = colors.gray("[root] ");
		console.error(`${jobPrefix}${colors.cyan("📄 Crash log saved to:")} ${colors.gray(logPath)}`);
	}
}
async function shouldReportCrash({ error, isInteractive }) {
	if (!isInteractive || error instanceof ConfigError || error instanceof ConfigValidationError || error instanceof InputError) return false;
	return new Promise((resolve) => {
		const jobPrefix = colors.gray("[root] ");
		console.log(`${jobPrefix}${colors.yellow("📢 Open a GitHub issue with crash details? (y/N):")}`);
		process.stdin.setEncoding("utf8");
		process.stdin.once("data", (data) => {
			resolve(data.trim().toLowerCase() === "y");
		});
	});
}
//#endregion
//#region src/config/engine.ts
function checkNodeVersion() {
	if (typeof Bun !== "undefined") {
		const [major] = Bun.version.split(".").map(Number);
		if (major < 1) throw new ConfigError(`Unsupported Bun version ${Bun.version}. Please use Bun 1.0.0 or newer.`);
	} else if (typeof process !== "undefined" && process.versions?.node) {
		const [major] = process.versions.node.split(".").map(Number);
		if (major < 20) throw new ConfigError(`Unsupported Node version ${process.versions.node}. Please use Node 20 or newer.`);
	}
}
//#endregion
//#region src/normalize/coerce.ts
const COERCER = Symbol("coercer");
/**
* Wraps a function as a coercer — a field-level resolver that receives the
* raw user value and optional context, and returns the resolved field value.
*
* Unlike plain defaults, coercers run unconditionally on every resolution,
* giving full control over the output regardless of what the user provides.
*
* Use when a field's resolved value requires computation, context access,
* or delegation to another config normalizer.
*
* @param fn - Receives the raw input value and resolution context, returns
* the resolved field value.
*
* @example
* ```ts
* // Delegate watch resolution to a nested config normalizer
* watch: coerce((value) => watchConfig(value)),
*
* // Resolve a field from context
* output: coerce((value, ctx) => value ?? ctx.defaultOutput),
* ```
*/
function coerce(fn) {
	return { [COERCER]: fn };
}
function isCoercer(value) {
	return (typeof value === "object" || typeof value === "function") && value !== null && COERCER in value;
}
//#endregion
//#region src/utils/object.ts
function isPlainObject(value) {
	if (typeof value !== "object" || value === null) return false;
	const proto = Object.getPrototypeOf(value);
	return proto === Object.prototype || proto === null;
}
//#endregion
//#region src/normalize/opaque.ts
const OPAQUE = Symbol("opaque");
/**
* Marks a field as opaque — its value is assigned as-is without being
* recursed into or merged as config fields.
*
* Use when a field accepts an arbitrary object that should not be treated
* as a nested config table.
*
* @param defaultValue - The value to use when no input is provided.
* @param fallback - Optional. Called with the full table input when the field
* is absent from the input object. Return `undefined` to fall back to
* `defaultValue`.
*
* @example
* ```ts
* path: opaque<string | object>('', (input) =>
*   input && typeof input === 'object' && !('path' in input)
*     ? input
*     : undefined
* ),
* ```
*/
function opaque(defaultValue, fallback) {
	return fallback ? {
		[OPAQUE]: defaultValue,
		fallback
	} : { [OPAQUE]: defaultValue };
}
function isOpaque(value) {
	return typeof value === "object" && value !== null && OPAQUE in value;
}
//#endregion
//#region src/normalize/value.ts
function resolveTable(input, table, { ancestor = {}, context = {}, resolvedCascade = {}, specAncestor = {} } = {}) {
	const { $cascade: cascadeKeys = [], $coerce, $coerceAny, $finalize, ...entries } = table;
	const result = {};
	for (const [key, defaultVal] of Object.entries(entries)) if (!isCoercer(defaultVal) && !isPlainObject(defaultVal) && !isOpaque(defaultVal)) result[key] = defaultVal;
	if (input !== void 0 && input !== null) {
		if ($coerceAny) Object.assign(result, $coerceAny({
			type: typeof input,
			value: input
		}));
		if (isPlainObject(input)) for (const [key, val] of Object.entries(input)) {
			const defaultVal = entries[key];
			if (!isCoercer(defaultVal) && !isPlainObject(defaultVal) && !isOpaque(defaultVal)) result[key] = val;
		}
		else {
			const handler = $coerce?.[typeof input];
			if (handler) Object.assign(result, handler(input));
		}
	}
	const localContext = { ...context };
	const cascadeEntryKeys = cascadeKeys.filter((k) => k in entries);
	const localResolvedCascade = { ...resolvedCascade };
	for (const key of cascadeKeys) if (!cascadeEntryKeys.includes(key)) localContext[key] = result[key];
	for (const key of cascadeEntryKeys) {
		const userVal = isPlainObject(input) ? input[key] : void 0;
		result[key] = resolveField(entries[key], result[key] ?? userVal, key, {
			ancestor,
			context: localContext,
			resolvedCascade: localResolvedCascade,
			specAncestor
		});
		localContext[key] = result[key];
		if (isPlainObject(result[key])) localResolvedCascade[key] = result[key];
	}
	for (const [key, defaultVal] of Object.entries(entries)) {
		if (cascadeEntryKeys.includes(key)) continue;
		const userVal = isPlainObject(input) ? input[key] : void 0;
		if (isOpaque(defaultVal)) {
			if (result[key] !== void 0) {} else if (userVal !== void 0) result[key] = userVal;
			else if (defaultVal.fallback) {
				const fallbackResult = defaultVal.fallback(input);
				result[key] = fallbackResult !== void 0 ? fallbackResult : defaultVal[OPAQUE];
			} else result[key] = defaultVal[OPAQUE];
			continue;
		}
		result[key] = resolveField(defaultVal, isCoercer(defaultVal) ? result[key] ?? userVal : userVal ?? result[key], key, {
			ancestor,
			context: localContext,
			resolvedCascade: localResolvedCascade,
			specAncestor
		});
	}
	$finalize?.(result, input);
	return result;
}
function collectDeps(spec, resolved, deps) {
	const { $dependencies } = spec;
	if ($dependencies) for (const key of $dependencies) {
		const value = resolved[key];
		if (value && typeof value === "string") deps.add(value);
	}
	for (const [key, specVal] of Object.entries(spec)) {
		if (key.startsWith("$")) continue;
		if (isPlainObject(specVal) && isPlainObject(resolved[key])) collectDeps(specVal, resolved[key], deps);
	}
}
function resolveField(defaultVal, currentVal, key, { ancestor, context, resolvedCascade, specAncestor }) {
	if (isCoercer(defaultVal)) return defaultVal[COERCER](currentVal, context);
	if (isPlainObject(defaultVal)) {
		const cascadeSpec = specAncestor[key];
		const effectiveTable = cascadeSpec ? mergeSpecs(cascadeSpec, defaultVal) : mergeAncestorScalars(ancestor, defaultVal);
		return resolveTable(currentVal !== void 0 ? currentVal : resolvedCascade[key], effectiveTable, {
			ancestor,
			context,
			resolvedCascade,
			specAncestor
		});
	}
	return currentVal !== void 0 ? currentVal : defaultVal;
}
function mergeSpecs(cascadeSpec, localSpec) {
	const result = { ...localSpec };
	for (const [key, cascadeVal] of Object.entries(cascadeSpec)) {
		if (key === "$coerceAny" || key === "$coerce" || key === "$cascade" || key === "$finalize") {
			if (result[key] === void 0) result[key] = cascadeVal;
			continue;
		}
		const localVal = result[key];
		if (isPlainObject(cascadeVal) && isPlainObject(localVal)) result[key] = mergeSpecs(cascadeVal, localVal);
	}
	return result;
}
function mergeAncestorScalars(ancestor, target) {
	const result = { ...target };
	for (const [key, ancestorVal] of Object.entries(ancestor)) {
		if (isPlainObject(ancestorVal)) continue;
		if (result[key] === void 0) result[key] = ancestorVal;
	}
	return result;
}
//#endregion
//#region src/normalize/config.ts
/**
* Creates a typed config normalizer from a resolution table.
*
* @example
* ```ts
* const normalizePlugin = defineConfig<PluginInput, PluginResolved>({
*   $coerce: {
*     boolean: (enabled) => ({ enabled }),
*     function: (name) => ({ name, enabled: true }),
*     string: (name) => ({ name, enabled: true }),
*   },
*   enabled: false,
*   name: '',
*   output: coerce((val, ctx) => val ?? ctx.defaultOutput),
* });
* ```
*/
function defineConfig(table) {
	function normalize(config, externalContext) {
		const resolvedTable = typeof table === "function" ? table(config) : table;
		const { $cascade: cascadeKeys = [], ...entries } = resolvedTable;
		const ancestor = {};
		const specAncestor = {};
		for (const key of cascadeKeys) {
			const entrySpec = entries[key];
			if (!(key in entries)) {
				if (isPopulated(config, key)) ancestor[key] = config[key];
				continue;
			}
			if (isPlainObject(entrySpec)) specAncestor[key] = entrySpec;
			else {
				const partial = resolveTable(config, { [key]: entrySpec });
				if (partial[key] !== void 0) ancestor[key] = partial[key];
			}
		}
		return resolveTable(config, resolvedTable, {
			ancestor,
			context: externalContext ?? {},
			specAncestor
		});
	}
	normalize[COERCER] = (value) => normalize(value);
	return normalize;
}
function isPopulated(config, key) {
	return typeof config === "object" && config !== null && key in config && config[key] !== void 0;
}
//#endregion
//#region src/utils/input/heyApi.ts
const registryRegExp$2 = /^([\w-]+)\/([\w-]+)(?:\?([\w=&.-]*))?$/;
const heyApiRegistryBaseUrl = "https://get.heyapi.dev";
/**
* Creates a full Hey API Registry URL.
*
* @param organization - Hey API organization slug
* @param project - Hey API project slug
* @param queryParams - Optional query parameters
* @returns The full Hey API registry URL.
*/
function getRegistryUrl$2(organization, project, queryParams) {
	return `${heyApiRegistryBaseUrl}/${organization}/${project}${queryParams ? `?${queryParams}` : ""}`;
}
/**
* Parses a Hey API input string and extracts components.
*
* @param input - Hey API configuration input
* @returns Parsed Hey API input components
* @throws Error if the input format is invalid
*/
function parseShorthand$2(input) {
	let organization = input.organization;
	let project = input.project;
	let queryParams;
	if (input.path) {
		const match = input.path.match(registryRegExp$2);
		if (!match) throw new Error(`Invalid Hey API shorthand format. Expected "organization/project?queryParams" or "organization/project", received: ${input.path}`);
		organization = match[1];
		project = match[2];
		queryParams = match[3];
	}
	if (!organization) throw new Error("The Hey API organization cannot be empty.");
	if (!project) throw new Error("The Hey API project cannot be empty.");
	return {
		organization,
		project,
		queryParams
	};
}
/**
* Transforms a Hey API shorthand string to the corresponding API URL.
*
* @param input - Hey API configuration input
* @returns The Hey API Registry URL
*/
function inputToHeyApiPath(input) {
	const parsed = parseShorthand$2(input);
	return {
		path: getRegistryUrl$2(parsed.organization, parsed.project, parsed.queryParams),
		registry: "hey-api"
	};
}
//#endregion
//#region src/utils/input/readme.ts
const registryRegExp$1 = /^(@([\w-]+)\/([\w\-.]+)#)?([\w-]+)$/;
/**
* Creates a full ReadMe API Registry URL.
*
* @param uuid - ReadMe UUID
* @returns The full ReadMe API registry URL.
*/
function getRegistryUrl$1(uuid) {
	return `https://dash.readme.com/api/v1/api-registry/${uuid}`;
}
const namespace$1 = "readme";
/**
* Parses a ReadMe input string and extracts components.
*
* @param shorthand - ReadMe format string (@org/project#uuid or uuid)
* @returns Parsed ReadMe input components
* @throws Error if the input format is invalid
*/
function parseShorthand$1(shorthand) {
	const match = shorthand.match(registryRegExp$1);
	if (!match) throw new Error(`Invalid ReadMe shorthand format. Expected "${namespace$1}:@organization/project#uuid" or "${namespace$1}:uuid", received: ${namespace$1}:${shorthand}`);
	const [, , organization, project, uuid] = match;
	if (!uuid) throw new Error("The ReadMe UUID cannot be empty.");
	return {
		organization,
		project,
		uuid
	};
}
/**
* Transforms a ReadMe shorthand string to the corresponding API URL.
*
* @param input - ReadMe format string
* @returns The ReadMe API Registry URL
*/
function inputToReadmePath(input) {
	const parsed = parseShorthand$1(input.slice(`${namespace$1}:`.length));
	return {
		...parsed,
		path: getRegistryUrl$1(parsed.uuid),
		registry: "readme"
	};
}
//#endregion
//#region src/utils/input/scalar.ts
const registryRegExp = /^(@[\w-]+)\/([\w.-]+)$/;
/**
* Creates a full Scalar API Registry URL.
*
* @param organization - Scalar organization slug
* @param project - Scalar project slug
* @returns The full Scalar API registry URL.
*/
function getRegistryUrl(organization, project) {
	return `https://registry.scalar.com/${organization}/apis/${project}/latest?format=json`;
}
const namespace = "scalar";
/**
* Parses a Scalar input string and extracts components.
*
* @param shorthand - Scalar format string (@org/project)
* @returns Parsed Scalar input components
* @throws Error if the input format is invalid
*/
function parseShorthand(shorthand) {
	const match = shorthand.match(registryRegExp);
	if (!match) throw new Error(`Invalid Scalar shorthand format. Expected "${namespace}:@organization/project", received: ${namespace}:${shorthand}`);
	const [, organization, project] = match;
	if (!organization) throw new Error("The Scalar organization cannot be empty.");
	if (!project) throw new Error("The Scalar project cannot be empty.");
	return {
		organization,
		project
	};
}
/**
* Transforms a Scalar shorthand string to the corresponding API URL.
*
* @param input - Scalar format string
* @returns The Scalar API Registry URL
*/
function inputToScalarPath(input) {
	const parsed = parseShorthand(input.slice(`${namespace}:`.length));
	return {
		...parsed,
		path: getRegistryUrl(parsed.organization, parsed.project),
		registry: "scalar"
	};
}
//#endregion
//#region src/utils/input/index.ts
function inputToApiRegistry(input) {
	if (input.path.startsWith("readme:")) {
		Object.assign(input, inputToReadmePath(input.path));
		return;
	}
	if (input.path.startsWith("scalar:")) {
		Object.assign(input, inputToScalarPath(input.path));
		return;
	}
	if (input.path.startsWith(".")) return;
	if (input.path.startsWith("https://get.heyapi.dev")) {
		input.path = input.path.slice(23);
		Object.assign(input, inputToHeyApiPath(input));
		return;
	}
	const parts = input.path.split("/");
	if (parts.length === 2 && parts.filter(Boolean).length === 2) {
		Object.assign(input, inputToHeyApiPath(input));
		return;
	}
}
//#endregion
//#region src/config/input/input.ts
const watchConfig = defineConfig({
	$coerce: {
		boolean: (v) => ({ enabled: v }),
		number: (v) => ({
			enabled: true,
			interval: v
		})
	},
	enabled: false,
	interval: 1e3,
	timeout: 6e4
});
const inputConfig = defineConfig({
	$coerce: { string: (path) => ({ path }) },
	$finalize(config, input) {
		if (input && typeof input === "object" && "organization" in input && config.path === "") config.path = heyApiRegistryBaseUrl;
	},
	path: opaque("", (input) => input && typeof input === "object" && !("path" in input) && !("organization" in input) ? input : void 0),
	watch: coerce((value) => watchConfig(value))
});
function getInput(userConfig) {
	const userInputs = userConfig.input instanceof Array ? userConfig.input : [userConfig.input];
	const inputs = [];
	for (const userInput of userInputs) {
		const input = inputConfig(userInput);
		if (!input.path) continue;
		if (typeof input.path === "string") inputToApiRegistry(input);
		if (userConfig.watch !== void 0 && input.watch.enabled === false && input.watch.interval === 1e3 && input.watch.timeout === 6e4) input.watch = watchConfig(userConfig.watch);
		inputs.push(input);
	}
	return inputs;
}
//#endregion
//#region src/config/input/path.ts
function compileInputPath(input) {
	const result = {
		...input,
		path: ""
	};
	if (input.path && (typeof input.path !== "string" || input.registry !== "hey-api")) {
		result.path = input.path;
		return result;
	}
	const [basePath, baseQuery] = input.path.split("?");
	const queryPath = (baseQuery || "").split("&").map((part) => part.split("="));
	let path = basePath || "";
	if (path.endsWith("/")) path = path.slice(0, path.length - 1);
	const [, pathUrl] = path.split("://");
	const [baseUrl, organization, project] = (pathUrl || "").split("/");
	result.organization = organization || input.organization;
	result.project = project || input.project;
	const queryParams = [];
	const kApiKey = "api_key";
	result.api_key = queryPath.find(([key]) => key === kApiKey)?.[1] || input.api_key || process.env.HEY_API_TOKEN;
	if (result.api_key) queryParams.push(`${kApiKey}=${result.api_key}`);
	const kBranch = "branch";
	result.branch = queryPath.find(([key]) => key === kBranch)?.[1] || input.branch;
	if (result.branch) queryParams.push(`${kBranch}=${result.branch}`);
	const kCommitSha = "commit_sha";
	result.commit_sha = queryPath.find(([key]) => key === kCommitSha)?.[1] || input.commit_sha;
	if (result.commit_sha) queryParams.push(`${kCommitSha}=${result.commit_sha}`);
	const kTags = "tags";
	result.tags = queryPath.find(([key]) => key === kTags)?.[1]?.split(",") || input.tags;
	if (result.tags?.length) queryParams.push(`${kTags}=${result.tags.join(",")}`);
	const kVersion = "version";
	result.version = queryPath.find(([key]) => key === kVersion)?.[1] || input.version;
	if (result.version) queryParams.push(`${kVersion}=${result.version}`);
	if (!result.organization) throw new Error("missing organization - from which Hey API Platform organization do you want to generate your output?");
	if (!result.project) throw new Error("missing project - from which Hey API Platform project do you want to generate your output?");
	const query = queryParams.join("&");
	const platformUrl = baseUrl || "get.heyapi.dev";
	const isLocalhost = platformUrl.startsWith("localhost");
	const platformUrlWithProtocol = [isLocalhost ? "http" : "https", platformUrl].join("://");
	const compiledPath = isLocalhost ? [
		platformUrlWithProtocol,
		"v1",
		"get",
		result.organization,
		result.project
	].join("/") : [
		platformUrlWithProtocol,
		result.organization,
		result.project
	].join("/");
	result.path = query ? `${compiledPath}?${query}` : compiledPath;
	return result;
}
function logInputPaths(inputPaths, jobIndex) {
	const lines = [];
	const jobPrefix = colors.gray(`[Job ${jobIndex + 1}] `);
	const count = inputPaths.length;
	const baseString = colors.cyan(`Generating from ${count} ${count === 1 ? "input" : "inputs"}:`);
	lines.push(`${jobPrefix}⏳ ${baseString}`);
	inputPaths.forEach((inputPath, index) => {
		const itemPrefixStr = `  [${index + 1}] `;
		const itemPrefix = colors.cyan(itemPrefixStr);
		const detailIndent = " ".repeat(itemPrefixStr.length);
		if (typeof inputPath.path !== "string") {
			lines.push(`${jobPrefix}${itemPrefix}raw OpenAPI specification`);
			return;
		}
		switch (inputPath.registry) {
			case "hey-api": {
				const baseInput = [inputPath.organization, inputPath.project].filter(Boolean).join("/");
				lines.push(`${jobPrefix}${itemPrefix}${baseInput}`);
				if (inputPath.branch) lines.push(`${jobPrefix}${detailIndent}${colors.gray("branch:")} ${colors.green(inputPath.branch)}`);
				if (inputPath.commit_sha) lines.push(`${jobPrefix}${detailIndent}${colors.gray("commit:")} ${colors.green(inputPath.commit_sha)}`);
				if (inputPath.tags?.length) lines.push(`${jobPrefix}${detailIndent}${colors.gray("tags:")} ${colors.green(inputPath.tags.join(", "))}`);
				if (inputPath.version) lines.push(`${jobPrefix}${detailIndent}${colors.gray("version:")} ${colors.green(inputPath.version)}`);
				lines.push(`${jobPrefix}${detailIndent}${colors.gray("registry:")} ${colors.green("Hey API")}`);
				break;
			}
			case "readme": {
				const baseInput = [inputPath.organization, inputPath.project].filter(Boolean).join("/");
				if (!baseInput) lines.push(`${jobPrefix}${itemPrefix}${inputPath.path}`);
				else lines.push(`${jobPrefix}${itemPrefix}${baseInput}`);
				if (inputPath.uuid) lines.push(`${jobPrefix}${detailIndent}${colors.gray("uuid:")} ${colors.green(inputPath.uuid)}`);
				lines.push(`${jobPrefix}${detailIndent}${colors.gray("registry:")} ${colors.green("ReadMe")}`);
				break;
			}
			case "scalar": {
				const baseInput = [inputPath.organization, inputPath.project].filter(Boolean).join("/");
				lines.push(`${jobPrefix}${itemPrefix}${baseInput}`);
				lines.push(`${jobPrefix}${detailIndent}${colors.gray("registry:")} ${colors.green("Scalar")}`);
				break;
			}
			default:
				lines.push(`${jobPrefix}${itemPrefix}${inputPath.path}`);
				break;
		}
	});
	for (const line of lines) console.log(line);
}
//#endregion
//#region src/config/logs.ts
const logsConfig = defineConfig({
	$coerce: { string: (path) => ({ path }) },
	file: true,
	level: "info",
	path: process.cwd()
});
function getLogs(input) {
	return logsConfig(input);
}
//#endregion
//#region src/config/output/postprocess.ts
function postprocessOutput(config, postProcessors, jobPrefix) {
	if (!fs.existsSync(config.path) || !fs.readdirSync(config.path).length) return;
	for (const processor of config.postProcess) {
		const resolved = typeof processor === "string" ? postProcessors[processor] : processor;
		if (!resolved) continue;
		const name = resolved.name ?? resolved.command;
		const args = resolved.args.map((arg) => arg.replace("{{path}}", config.path));
		console.log(`${jobPrefix}🧹 Running ${colors.cyanBright(name)}`);
		const result = sync(resolved.command, args);
		if (result.error) throw new ConfigError(`Post-processor "${name}" failed to run: ${result.error.message}`);
		if (result.status !== null && result.status !== 0) {
			let message = `Post-processor "${name}" exited with code ${result.status}`;
			const stderr = result.stderr?.toString().trim();
			if (stderr) message += `:\n${stderr}`;
			throw new ConfigError(message);
		}
	}
}
//#endregion
//#region src/config/output/source/config.ts
const sourceConfig = defineConfig({
	$coerceAny: ({ value }) => ({ enabled: Boolean(value) }),
	enabled: false,
	extension: "json",
	fileName: "source",
	path: coerce((value) => {
		if (value === true || value === void 0 || value === "") return "";
		if (value === false || value === null) return null;
		return value;
	}),
	serialize: coerce((value) => typeof value === "function" ? value : (input) => JSON.stringify(input, null, 2))
});
//#endregion
//#region src/config/parser/config.ts
const defaultPaginationKeywords = [
	"after",
	"before",
	"cursor",
	"offset",
	"page",
	"start"
];
const parserConfig = defineConfig({
	hooks: {},
	pagination: { keywords: defaultPaginationKeywords },
	transforms: {
		enums: {
			$coerce: { string: (mode) => ({ mode }) },
			$coerceAny: ({ value }) => ({ enabled: Boolean(value) }),
			case: "PascalCase",
			enabled: false,
			mode: "root",
			name: "{{name}}Enum"
		},
		propertiesRequiredByDefault: false,
		readWrite: {
			$coerceAny: ({ value }) => ({ enabled: Boolean(value) }),
			enabled: true,
			requests: {
				$coerce: {
					function: (name) => ({ name }),
					string: (name) => ({ name })
				},
				case: "preserve",
				name: "{{name}}Writable"
			},
			responses: {
				$coerce: {
					function: (name) => ({ name }),
					string: (name) => ({ name })
				},
				case: "preserve",
				name: "{{name}}"
			}
		}
	},
	validate_EXPERIMENTAL: coerce((value) => value === true ? "warn" : value || false)
});
function getParser(input) {
	return parserConfig(input.parser ?? {});
}
//#endregion
//#region src/config/utils/dependencies.ts
const satisfies = (...args) => semver.satisfies(...args);
function dependencyFactory(dependencies) {
	return {
		getVersion: (name) => {
			const version = dependencies[name];
			if (!version) return;
			try {
				let parsed = semver.parse(version);
				if (parsed) return parsed;
				const min = semver.minVersion(version);
				if (min) return min;
				parsed = semver.coerce(version);
				if (parsed) return parsed;
			} catch {}
		},
		isInstalled: (name) => Boolean(dependencies[name]),
		satisfies: (nameOrVersion, range, optionsOrLoose) => {
			const version = typeof nameOrVersion === "string" ? dependencies[nameOrVersion] : nameOrVersion;
			return version ? satisfies(version, range, optionsOrLoose) : false;
		}
	};
}
//#endregion
//#region src/debug/graph.ts
const analyzeStructure = (graph) => {
	let maxDepth = 0;
	let maxChildren = 0;
	const computeDepth = (pointer, depth) => {
		maxDepth = Math.max(maxDepth, depth);
		const children = Array.from(graph.nodes.entries()).filter(([, nodeInfo]) => nodeInfo.parentPointer === pointer).map(([childPointer]) => childPointer);
		maxChildren = Math.max(maxChildren, children.length);
		for (const childPointer of children) computeDepth(childPointer, depth + 1);
	};
	const totalNodes = graph.nodes.size;
	if (graph.nodes.has("#")) computeDepth("#", 1);
	return {
		maxChildren,
		maxDepth,
		totalNodes
	};
};
const exportForVisualization = (graph) => {
	const childrenMap = /* @__PURE__ */ new Map();
	for (const [pointer, nodeInfo] of graph.nodes) {
		if (!nodeInfo.parentPointer) continue;
		if (!childrenMap.has(nodeInfo.parentPointer)) childrenMap.set(nodeInfo.parentPointer, []);
		childrenMap.get(nodeInfo.parentPointer).push(pointer);
	}
	return Array.from(graph.nodes.keys()).map((pointer) => ({
		children: childrenMap.get(pointer)?.length ?? 0,
		childrenPointers: childrenMap.get(pointer) || [],
		pointer
	}));
};
const graph = {
	analyzeStructure,
	exportForVisualization
};
//#endregion
//#region src/ir/parameter.ts
const getPaginationSchema = ({ context, parameter }) => {
	if (!parameter.pagination) return;
	if (parameter.pagination === true) return parameter.schema;
	let schema = parameter.schema;
	if (schema.$ref) schema = context.resolveIrRef(schema.$ref);
	return schema.properties[parameter.pagination];
};
const hasParameterGroupObjectRequired = (parameterGroup) => {
	for (const name in parameterGroup) if (parameterGroup[name].required) return true;
	return false;
};
const hasParametersObjectRequired = (parameters) => {
	if (!parameters) return false;
	if (hasParameterGroupObjectRequired(parameters.cookie)) return true;
	if (hasParameterGroupObjectRequired(parameters.header)) return true;
	if (hasParameterGroupObjectRequired(parameters.path)) return true;
	if (hasParameterGroupObjectRequired(parameters.query)) return true;
	return false;
};
const parameterWithPagination = ({ context, parameters }) => {
	if (!parameters) return;
	for (const name in parameters.cookie) {
		const parameter = parameters.cookie[name];
		if (parameter.pagination) return {
			in: parameter.location,
			name: parameter.pagination === true ? parameter.name : `${parameter.name}.${parameter.pagination}`,
			schema: getPaginationSchema({
				context,
				parameter
			})
		};
	}
	for (const name in parameters.header) {
		const parameter = parameters.header[name];
		if (parameter.pagination) return {
			in: parameter.location,
			name: parameter.pagination === true ? parameter.name : `${parameter.name}.${parameter.pagination}`,
			schema: getPaginationSchema({
				context,
				parameter
			})
		};
	}
	for (const name in parameters.path) {
		const parameter = parameters.path[name];
		if (parameter.pagination) return {
			in: parameter.location,
			name: parameter.pagination === true ? parameter.name : `${parameter.name}.${parameter.pagination}`,
			schema: getPaginationSchema({
				context,
				parameter
			})
		};
	}
	for (const name in parameters.query) {
		const parameter = parameters.query[name];
		if (parameter.pagination) return {
			in: parameter.location,
			name: parameter.pagination === true ? parameter.name : `${parameter.name}.${parameter.pagination}`,
			schema: getPaginationSchema({
				context,
				parameter
			})
		};
	}
};
//#endregion
//#region src/ir/schema.ts
/**
* Ensure we don't produce redundant types, e.g., string | string.
*/
function deduplicateSchema({ detectFormat = true, schema }) {
	if (!schema.items) return schema;
	const uniqueItems = [];
	const typeIds = [];
	for (const item of schema.items) {
		if (!item.type && item.items || schema.type === "tuple") {
			uniqueItems.push(item);
			continue;
		}
		if (!item.type || item.type === "boolean" || item.type === "integer" || item.type === "null" || item.type === "number" || item.type === "string" || item.type === "unknown" || item.type === "void") {
			const constant = item.const !== void 0 ? `const-${item.const}` : "";
			const format = item.format !== void 0 && detectFormat ? `format-${item.format}` : "";
			const constraints = [
				item.minLength !== void 0 ? `minLength-${item.minLength}` : "",
				item.maxLength !== void 0 ? `maxLength-${item.maxLength}` : "",
				item.minimum !== void 0 ? `minimum-${item.minimum}` : "",
				item.maximum !== void 0 ? `maximum-${item.maximum}` : "",
				item.exclusiveMinimum !== void 0 ? `exclusiveMinimum-${item.exclusiveMinimum}` : "",
				item.exclusiveMaximum !== void 0 ? `exclusiveMaximum-${item.exclusiveMaximum}` : "",
				item.minItems !== void 0 ? `minItems-${item.minItems}` : "",
				item.maxItems !== void 0 ? `maxItems-${item.maxItems}` : "",
				item.pattern !== void 0 ? `pattern-${item.pattern}` : ""
			].join("");
			const typeId = `${item.$ref ?? ""}${item.type ?? ""}${constant}${format}${constraints}`;
			if (!typeIds.includes(typeId)) {
				typeIds.push(typeId);
				uniqueItems.push(item);
			}
			continue;
		}
		uniqueItems.push(item);
	}
	const result = { ...schema };
	if (uniqueItems.length <= 1 && result.type !== "array" && result.type !== "enum" && result.type !== "tuple") {
		const liftedSchema = uniqueItems[0];
		result.items = void 0;
		result.logicalOperator = void 0;
		Object.assign(result, liftedSchema);
	} else result.items = uniqueItems;
	if (result.type === "unknown") return {};
	return result;
}
//#endregion
//#region src/ir/utils.ts
/**
* Simply adds `items` to the schema. Also handles setting the logical operator
* and avoids setting it for a single item or tuples.
*/
function addItemsToSchema({ items, logicalOperator = "or", mutateSchemaOneItem = false, schema }) {
	if (!items.length) return schema;
	if (schema.type === "tuple") {
		schema.items = items;
		return schema;
	}
	if (items.length !== 1) {
		schema.items = items;
		schema.logicalOperator = logicalOperator;
		return schema;
	}
	if (mutateSchemaOneItem) {
		Object.assign(schema, items[0]);
		return schema;
	}
	schema.items = items;
	return schema;
}
//#endregion
//#region src/ir/operation.ts
const hasOperationDataRequired = (operation) => {
	if (hasParametersObjectRequired(operation.parameters)) return true;
	if (operation.body?.required) return true;
	return false;
};
const createOperationKey = ({ method, path }) => `${method.toUpperCase()} ${path}`;
const operationPagination = ({ context, operation }) => {
	const body = operation.body;
	if (!body || !body.pagination) return parameterWithPagination({
		context,
		parameters: operation.parameters
	});
	if (body.pagination === true) return {
		in: "body",
		name: "body",
		schema: body.schema
	};
	const schema = body.schema;
	const resolvedSchema = schema.$ref ? context.resolveIrRef(schema.$ref) : schema;
	const paginationProp = ("schema" in resolvedSchema ? resolvedSchema.schema : resolvedSchema)?.properties?.[body.pagination];
	if (!paginationProp) return parameterWithPagination({
		context,
		parameters: operation.parameters
	});
	return {
		in: "body",
		name: body.pagination,
		schema: paginationProp
	};
};
const statusCodeToGroup = ({ statusCode }) => {
	switch (statusCode) {
		case "1XX": return "1XX";
		case "2XX": return "2XX";
		case "3XX": return "3XX";
		case "4XX": return "4XX";
		case "5XX": return "5XX";
		case "default": return "default";
		default: return `${statusCode[0]}XX`;
	}
};
const operationResponsesMap = (operation) => {
	const result = {};
	if (!operation.responses) return result;
	const errors = {
		properties: {},
		type: "object"
	};
	const responses = {
		properties: {},
		type: "object"
	};
	let defaultResponse;
	for (const name in operation.responses) {
		const response = operation.responses[name];
		switch (statusCodeToGroup({ statusCode: name })) {
			case "1XX":
			case "3XX": break;
			case "2XX":
				responses.properties[name] = response.schema;
				break;
			case "4XX":
			case "5XX":
				errors.properties[name] = response.schema;
				break;
			case "default":
				defaultResponse = response;
				break;
		}
	}
	if (defaultResponse) {
		let inferred = false;
		if (!Object.keys(responses.properties).length) {
			responses.properties.default = defaultResponse.schema;
			inferred = true;
		}
		const description = (defaultResponse.schema.description ?? "").toLocaleLowerCase();
		const $ref = (defaultResponse.schema.$ref ?? "").toLocaleLowerCase();
		if (["success"].some((keyword) => description.includes(keyword) || $ref.includes(keyword))) {
			responses.properties.default = defaultResponse.schema;
			inferred = true;
		}
		if (["error", "problem"].some((keyword) => description.includes(keyword) || $ref.includes(keyword))) {
			errors.properties.default = defaultResponse.schema;
			inferred = true;
		}
		if (!inferred) errors.properties.default = defaultResponse.schema;
	}
	const errorKeys = Object.keys(errors.properties);
	if (errorKeys.length) {
		errors.required = errorKeys;
		result.errors = errors;
		let errorUnion = addItemsToSchema({
			items: Object.values(errors.properties),
			mutateSchemaOneItem: true,
			schema: {}
		});
		errorUnion = deduplicateSchema({ schema: errorUnion });
		if (Object.keys(errorUnion).length && errorUnion.type !== "unknown") result.error = errorUnion;
	}
	const responseKeys = Object.keys(responses.properties);
	if (responseKeys.length) {
		responses.required = responseKeys;
		result.responses = responses;
		let responseUnion = addItemsToSchema({
			items: Object.values(responses.properties),
			mutateSchemaOneItem: true,
			schema: {}
		});
		responseUnion = deduplicateSchema({ schema: responseUnion });
		if (Object.keys(responseUnion).length && responseUnion.type !== "unknown") result.response = responseUnion;
	}
	return result;
};
//#endregion
//#region src/utils/naming/naming.ts
const uppercaseRegExp = /[\p{Lu}]/u;
const lowercaseRegExp = /[\p{Ll}]/u;
const identifierRegExp = /([\p{Alpha}\p{N}_]|$)/u;
const separatorsRegExp = /[_.$+:\- `\\[\](){}\\/]+/;
const leadingSeparatorsRegExp = new RegExp(`^${separatorsRegExp.source}`);
const separatorsAndIdentifierRegExp = new RegExp(`${separatorsRegExp.source}${identifierRegExp.source}`, "gu");
const numbersAndIdentifierRegExp = new RegExp(`\\d+${identifierRegExp.source}`, "gu");
const preserveCase = (value, casing) => {
	let isLastCharLower = false;
	let isLastCharUpper = false;
	let isLastLastCharUpper = false;
	let isLastLastCharPreserved = false;
	const separator = casing === "snake_case" || casing === "SCREAMING_SNAKE_CASE" ? "_" : "-";
	for (let index = 0; index < value.length; index++) {
		const character = value[index];
		isLastLastCharPreserved = index > 2 ? value[index - 3] === separator : true;
		let nextIndex = index + 1;
		let nextCharacter = value[nextIndex];
		separatorsRegExp.lastIndex = 0;
		while (nextCharacter && separatorsRegExp.test(nextCharacter)) {
			nextIndex += 1;
			nextCharacter = value[nextIndex];
		}
		const isSeparatorBeforeNextCharacter = nextIndex !== index + 1;
		lowercaseRegExp.lastIndex = 0;
		uppercaseRegExp.lastIndex = 0;
		if (uppercaseRegExp.test(character) && (isLastCharLower || nextCharacter && !isSeparatorBeforeNextCharacter && nextCharacter !== "s" && lowercaseRegExp.test(nextCharacter))) {
			value = `${value.slice(0, index)}${separator}${value.slice(index)}`;
			index++;
			isLastLastCharUpper = isLastCharUpper;
			isLastCharLower = false;
			isLastCharUpper = true;
		} else if (isLastCharUpper && isLastLastCharUpper && lowercaseRegExp.test(character) && !isLastLastCharPreserved && !(character === "s" && (!nextCharacter || nextCharacter.toLocaleLowerCase() !== nextCharacter))) {
			value = `${value.slice(0, index - 1)}${separator}${value.slice(index - 1)}`;
			isLastLastCharUpper = isLastCharUpper;
			isLastCharLower = true;
			isLastCharUpper = false;
		} else {
			const characterLower = character.toLocaleLowerCase();
			const characterUpper = character.toLocaleUpperCase();
			isLastLastCharUpper = isLastCharUpper;
			isLastCharLower = characterLower === character && characterUpper !== character;
			isLastCharUpper = characterUpper === character && characterLower !== character;
		}
	}
	return value;
};
/**
* Convert a string to the specified casing.
*
* @param value - The string to convert
* @param casing - The target casing
* @param options - Additional options
* @returns The converted string
*/
function toCase(value, casing, options = {}) {
	const stripLeadingSeparators = options.stripLeadingSeparators ?? true;
	let result = value.trim();
	if (!result.length || !casing || casing === "preserve") return result;
	if (result.length === 1) {
		separatorsRegExp.lastIndex = 0;
		if (separatorsRegExp.test(result)) return "";
		return casing === "PascalCase" || casing === "SCREAMING_SNAKE_CASE" ? result.toLocaleUpperCase() : result.toLocaleLowerCase();
	}
	if (result !== result.toLocaleLowerCase()) result = preserveCase(result, casing);
	if (stripLeadingSeparators || result[0] !== value[0]) result = result.replace(leadingSeparatorsRegExp, "");
	result = casing === "SCREAMING_SNAKE_CASE" ? result.toLocaleUpperCase() : result.toLocaleLowerCase();
	if (casing === "PascalCase") result = `${result.charAt(0).toLocaleUpperCase()}${result.slice(1)}`;
	if (casing === "snake_case" || casing === "SCREAMING_SNAKE_CASE") {
		result = result.replaceAll(separatorsAndIdentifierRegExp, (match, identifier, offset) => {
			if (offset === 0 && !stripLeadingSeparators) return match;
			return `_${identifier}`;
		});
		if (result[result.length - 1] === "_") result = result.slice(0, result.length - 1);
	} else {
		separatorsAndIdentifierRegExp.lastIndex = 0;
		numbersAndIdentifierRegExp.lastIndex = 0;
		result = result.replaceAll(numbersAndIdentifierRegExp, (match, _, offset) => {
			if ([
				"_",
				"-",
				"."
			].includes(result.charAt(offset + match.length))) return match;
			return match.toLocaleUpperCase();
		});
		result = result.replaceAll(separatorsAndIdentifierRegExp, (match, identifier, offset) => {
			if (offset === 0 && !stripLeadingSeparators && match[0] && value.startsWith(match[0])) return match;
			return identifier.toLocaleUpperCase();
		});
	}
	return result;
}
/**
* Normalize a NamingRule to NamingConfig.
*/
function resolveNaming(rule) {
	if (!rule) return {};
	if (typeof rule === "string" || typeof rule === "function") return { name: rule };
	return rule;
}
/**
* Apply naming configuration to a value.
*
* Casing is applied first, then transformation.
*/
function applyNaming(value, config) {
	let result = value;
	const casing = config.casing ?? config.case;
	if (config.name) if (typeof config.name === "function") result = config.name(result);
	else {
		const separator = !casing || casing === "preserve" ? "" : "-";
		result = config.name.replace("{{name}}", `${separator}${result}${separator}`);
	}
	return toCase(result, casing);
}
//#endregion
//#region src/openApi/shared/utils/operation.ts
const httpMethods = [
	"delete",
	"get",
	"head",
	"options",
	"patch",
	"post",
	"put",
	"trace"
];
/**
* Sanitizes namespace identifiers so they are valid TypeScript identifiers of a certain form.
*
* 1: Remove any leading characters that are illegal as starting character of a typescript identifier.
* 2: Replace illegal characters in remaining part of type name with hyphen (-).
*
* Step 1 should perhaps instead also replace illegal characters with underscore, or prefix with it, like sanitizeEnumName
* does. The way this is now one could perhaps end up removing all characters, if all are illegal start characters. It
* would be sort of a breaking change to do so, though, previously generated code might change then.
*
* JavaScript identifier regexp pattern retrieved from https://developer.mozilla.org/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers
*
* The output of this is expected to be converted to PascalCase
*
* @deprecated
*/
const sanitizeNamespaceIdentifier = (name) => name.replace(/^[^\p{ID_Start}]+/u, "").replace(/[^$\u200c\u200d\p{ID_Continue}]/gu, "-").replace(/[$+]/g, "-");
/**
* Returns an operation ID to use across the application. By default, we try
* to use the provided ID. If it's not provided or the SDK is configured
* to exclude it, we generate operation ID from its location.
*
* @deprecated
*/
function operationToId({ context, count = 1, id, method, path, state }) {
	let result;
	const { output } = context.config;
	const targetCase = (output !== void 0 && typeof output === "object" && "case" in output ? output.case : void 0) ?? "camelCase";
	if (id && (!context.config.plugins["@hey-api/sdk"] || context.config.plugins["@hey-api/sdk"].config.operations && typeof context.config.plugins["@hey-api/sdk"].config.operations !== "function" && typeof context.config.plugins["@hey-api/sdk"].config.operations === "object" && context.config.plugins["@hey-api/sdk"].config.operations.nesting === "operationId")) result = toCase(sanitizeNamespaceIdentifier(id), targetCase);
	else result = toCase(`${method}-${path.replace(/{(.*?)}/g, "by-$1").replace(/[/:+]/g, "-")}`, targetCase);
	if (count > 1) result = `${result}${count}`;
	if (state.ids.has(result)) return operationToId({
		context,
		count: count + 1,
		id,
		method,
		path,
		state
	});
	state.ids.set(result, createOperationKey({
		method,
		path
	}));
	return result;
}
//#endregion
//#region src/debug/ir.ts
const indent = (level) => "  ".repeat(level);
const log$1 = (message, level) => console.log(`${indent(level ?? 0)}${message}`);
const print = (ir, options = {}) => {
	const { depth = 2, section = "all", verbosity = "summary" } = options;
	const printObject = (obj, level, kind = "generic") => {
		if (verbosity === "summary" && obj && typeof obj === "object") if (kind === "responses") {
			const count = Object.keys(obj).length;
			const noun = count === 1 ? "code" : "codes";
			log$1(`responses: ${colors.yellow(`${count} ${noun}`)}`, level);
		} else if (kind === "requestBody") log$1(`requestBody: ${Object.keys(obj).join(", ")}`, level);
		else if (kind === "schema") log$1(`schema keys: ${Object.keys(obj).join(", ")}`, level);
		else log$1(`keys: ${Object.keys(obj).join(", ")}`, level);
		else log$1(JSON.stringify(obj, null, depth), level);
	};
	const printPathItem = (key, item, base = 1) => {
		if ("$ref" in item) {
			log$1(`${colors.cyan(key)} is a $ref → ${colors.yellow(item.$ref)}`, base);
			return;
		}
		for (const method of Object.keys(item)) {
			if (!httpMethods.includes(method)) continue;
			const operation = item[method];
			log$1(`${colors.green(method.toUpperCase())} ${colors.cyan(key)} (${colors.magenta(operation.operationId ?? "")})`, base);
			if (operation.body) printObject(operation.body, base + 1, "requestBody");
			if (operation.responses) printObject(operation.responses, base + 1, "responses");
		}
	};
	const sections = section === "all" ? Object.keys(ir) : [section];
	for (const section of sections) switch (section) {
		case "components":
			if (ir.components?.schemas) {
				log$1(`Components: ${Object.keys(ir.components.schemas).length} schemas`);
				for (const [, schema] of Object.entries(ir.components.schemas)) printObject(schema, 1, "schema");
			}
			break;
		case "paths": {
			const paths = ir.paths || {};
			log$1(`paths (${Object.keys(paths).length} items):`);
			for (const [path, item] of Object.entries(paths)) printPathItem(path, item);
			break;
		}
		case "servers": break;
		case "webhooks": {
			const webhooks = ir.webhooks || {};
			log$1(`webhooks (${Object.keys(webhooks).length} items):`);
			for (const [path, item] of Object.entries(webhooks)) printPathItem(path, item);
			break;
		}
	}
};
//#endregion
//#region src/debug/index.ts
const debugTools = {
	graph,
	ir: { print }
};
//#endregion
//#region src/getSpec.ts
const headersEntries = (headers) => {
	const entries = [];
	headers.forEach((value, key) => {
		entries.push([key, value]);
	});
	return entries;
};
const mergeHeaders = (...headers) => {
	const mergedHeaders = new Headers();
	for (const header of headers) {
		if (!header) continue;
		const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
		for (const [key, value] of iterator) if (value === null) mergedHeaders.delete(key);
		else if (Array.isArray(value)) for (const v of value) mergedHeaders.append(key, v);
		else if (value !== void 0) mergedHeaders.set(key, typeof value === "object" ? JSON.stringify(value) : value);
	}
	return mergedHeaders;
};
/**
* @internal
*/
async function getSpec({ fetchOptions, inputPath, timeout, watch }) {
	const resolvedInput = getResolvedInput({ pathOrUrlOrSchema: inputPath });
	let arrayBuffer;
	let hasChanged;
	let response;
	if (resolvedInput.type === "url") {
		if (watch.lastValue && watch.isHeadMethodSupported !== false) {
			try {
				const request = await sendRequest({
					fetchOptions: {
						method: "HEAD",
						...fetchOptions,
						headers: mergeHeaders(fetchOptions?.headers, watch.headers)
					},
					timeout,
					url: resolvedInput.path
				});
				if (request.response.status >= 300) return {
					error: "not-ok",
					response: request.response
				};
				response = request.response;
			} catch (error) {
				const message = error instanceof Error ? error.message : String(error);
				return {
					error: "not-ok",
					response: new Response(message, { status: 500 })
				};
			}
			if (!response.ok && watch.isHeadMethodSupported) return {
				error: "not-ok",
				response
			};
			if (watch.isHeadMethodSupported === void 0) watch.isHeadMethodSupported = response.ok;
			if (response.status === 304) return {
				error: "not-modified",
				response
			};
			if (hasChanged === void 0) {
				const eTag = response.headers.get("ETag");
				if (eTag) {
					hasChanged = eTag !== watch.headers.get("If-None-Match");
					if (hasChanged) watch.headers.set("If-None-Match", eTag);
				}
			}
			if (hasChanged === void 0) {
				const lastModified = response.headers.get("Last-Modified");
				if (lastModified) {
					hasChanged = lastModified !== watch.headers.get("If-Modified-Since");
					if (hasChanged) watch.headers.set("If-Modified-Since", lastModified);
				}
			}
			if (hasChanged === false) return {
				error: "not-modified",
				response
			};
		}
		try {
			const request = await sendRequest({
				fetchOptions: {
					method: "GET",
					...fetchOptions
				},
				timeout,
				url: resolvedInput.path
			});
			if (request.response.status >= 300) return {
				error: "not-ok",
				response: request.response
			};
			response = request.response;
		} catch (error) {
			const message = error instanceof Error ? error.message : String(error);
			return {
				error: "not-ok",
				response: new Response(message, { status: 500 })
			};
		}
		if (!response.ok) return {
			error: "not-ok",
			response
		};
		arrayBuffer = response.body ? await response.arrayBuffer() : /* @__PURE__ */ new ArrayBuffer(0);
		if (hasChanged === void 0) {
			const content = new TextDecoder().decode(arrayBuffer);
			hasChanged = content !== watch.lastValue;
			watch.lastValue = content;
		}
	} else if (!watch.lastValue) watch.lastValue = resolvedInput.type;
	else hasChanged = false;
	if (hasChanged === false) return {
		error: "not-modified",
		response
	};
	return {
		arrayBuffer,
		resolvedInput
	};
}
//#endregion
//#region src/utils/minHeap.ts
var MinHeap = class {
	declIndex;
	heap = [];
	constructor(declIndex) {
		this.declIndex = declIndex;
	}
	isEmpty() {
		return !this.heap.length;
	}
	pop() {
		const [top] = this.heap;
		if (!this.heap.length) return;
		const last = this.heap.pop();
		if (!this.heap.length) return top;
		this.heap[0] = last;
		this.sinkDown(0);
		return top;
	}
	push(item) {
		this.heap.push(item);
		this.bubbleUp(this.heap.length - 1);
	}
	bubbleUp(index) {
		const heap = this.heap;
		while (index > 0) {
			const parent = Math.floor((index - 1) / 2);
			const parentVal = heap[parent];
			const curVal = heap[index];
			if (this.declIndex.get(parentVal) <= this.declIndex.get(curVal)) break;
			heap[parent] = curVal;
			heap[index] = parentVal;
			index = parent;
		}
	}
	sinkDown(index) {
		const heap = this.heap;
		const len = heap.length;
		while (true) {
			const left = 2 * index + 1;
			const right = 2 * index + 2;
			let smallest = index;
			if (left < len) {
				const leftVal = heap[left];
				const smallestVal = heap[smallest];
				if (this.declIndex.get(leftVal) < this.declIndex.get(smallestVal)) smallest = left;
			}
			if (right < len) {
				const rightVal = heap[right];
				const smallestVal = heap[smallest];
				if (this.declIndex.get(rightVal) < this.declIndex.get(smallestVal)) smallest = right;
			}
			if (smallest === index) break;
			const tmp = heap[smallest];
			heap[smallest] = heap[index];
			heap[index] = tmp;
			index = smallest;
		}
	}
};
//#endregion
//#region src/graph/walk.ts
/**
* Walk the nodes of the graph in declaration (insertion) order.
* This is a cheap alternative to `walkTopological` when dependency ordering
* is not required and the caller only wants nodes in the order they were
* added to the graph.
*/
const walkDeclarations = (graph, callback, options) => {
	if (options?.preferGroups && options.preferGroups.length) {
		const preferGroupsSet = new Set(options.preferGroups);
		const buckets = /* @__PURE__ */ new Map();
		const unmatched = [];
		for (const pointer of graph.nodes.keys()) {
			if (options.matchPointerToGroup) {
				const result = options.matchPointerToGroup(pointer);
				if (result.matched) {
					if (preferGroupsSet.has(result.kind)) {
						let bucket = buckets.get(result.kind);
						if (!bucket) {
							bucket = [];
							buckets.set(result.kind, bucket);
						}
						bucket.push(pointer);
					} else unmatched.push(pointer);
					continue;
				}
			}
			unmatched.push(pointer);
		}
		const emittedGroups = /* @__PURE__ */ new Set();
		for (const kind of options.preferGroups) {
			if (emittedGroups.has(kind)) continue;
			emittedGroups.add(kind);
			const pointers = buckets.get(kind);
			if (pointers) for (const pointer of pointers) callback(pointer, graph.nodes.get(pointer));
		}
		for (const pointer of unmatched) callback(pointer, graph.nodes.get(pointer));
		return;
	}
	for (const [pointer, node] of graph.nodes) callback(pointer, node);
};
/**
* Walks the nodes of the graph in topological order (dependencies before dependents).
* Calls the callback for each node pointer in order.
* Nodes in cycles are grouped together and emitted in arbitrary order within the group.
*
* @param graph - The dependency graph
* @param callback - Function to call for each node pointer
*/
const walkTopological = (graph, callback, options) => {
	const pointers = Array.from(graph.nodes.keys());
	const declIndex = /* @__PURE__ */ new Map();
	const depsOf = /* @__PURE__ */ new Map();
	const inDegree = /* @__PURE__ */ new Map();
	const dependents = /* @__PURE__ */ new Map();
	const heap = new MinHeap(declIndex);
	pointers.forEach((pointer, index) => {
		const priority = options?.getPointerPriority?.(pointer) ?? 10;
		declIndex.set(pointer, priority * 1e6 + index);
		const raw = graph.subtreeDependencies?.get(pointer) ?? /* @__PURE__ */ new Set();
		const deps = /* @__PURE__ */ new Set();
		for (const rawPointer of raw) {
			if (rawPointer === pointer) continue;
			if (graph.nodes.has(rawPointer)) deps.add(rawPointer);
		}
		depsOf.set(pointer, deps);
		inDegree.set(pointer, deps.size);
		for (const d of deps) {
			let dep = dependents.get(d);
			if (!dep) {
				dep = /* @__PURE__ */ new Set();
				dependents.set(d, dep);
			}
			dep.add(pointer);
		}
		if (deps.size === 0) heap.push(pointer);
	});
	const emitted = /* @__PURE__ */ new Set();
	const order = [];
	while (!heap.isEmpty()) {
		const cur = heap.pop();
		if (emitted.has(cur)) continue;
		emitted.add(cur);
		order.push(cur);
		const deps = dependents.get(cur);
		if (!deps) continue;
		for (const dep of deps) {
			const v = (inDegree.get(dep) ?? 0) - 1;
			inDegree.set(dep, v);
			if (v === 0) heap.push(dep);
		}
	}
	const remaining = pointers.filter((pointer) => !emitted.has(pointer));
	remaining.sort((a, b) => declIndex.get(a) - declIndex.get(b));
	for (const pointer of remaining) {
		emitted.add(pointer);
		order.push(pointer);
	}
	let finalOrder = order;
	if (options?.preferGroups && options.preferGroups.length) {
		const groupPriority = /* @__PURE__ */ new Map();
		for (let i = 0; i < options.preferGroups.length; i++) {
			const k = options.preferGroups[i];
			if (k) groupPriority.set(k, i);
		}
		const getGroup = (pointer) => {
			if (options.matchPointerToGroup) {
				const result = options.matchPointerToGroup(pointer);
				if (result.matched) return groupPriority.has(result.kind) ? groupPriority.get(result.kind) : options.preferGroups.length;
			}
			return options.preferGroups.length;
		};
		const orderIndex = /* @__PURE__ */ new Map();
		for (let i = 0; i < order.length; i++) orderIndex.set(order[i], i);
		const groupCache = /* @__PURE__ */ new Map();
		const getCachedGroup = (pointer) => {
			let g = groupCache.get(pointer);
			if (g === void 0) {
				g = getGroup(pointer);
				groupCache.set(pointer, g);
			}
			return g;
		};
		const proposed = [...order].sort((a, b) => {
			const ga = getCachedGroup(a);
			const gb = getCachedGroup(b);
			return ga !== gb ? ga - gb : orderIndex.get(a) - orderIndex.get(b);
		});
		const proposedIndex = /* @__PURE__ */ new Map();
		for (let i = 0; i < proposed.length; i++) proposedIndex.set(proposed[i], i);
		if (!(() => {
			for (const [node, deps] of depsOf) for (const dep of deps) {
				if (getCachedGroup(dep) <= getCachedGroup(node)) continue;
				if (proposedIndex.get(dep) >= proposedIndex.get(node)) return true;
			}
			return false;
		})()) finalOrder = proposed;
	}
	for (const pointer of finalOrder) callback(pointer, graph.nodes.get(pointer));
};
const walk = (graph, callback, options) => {
	if (options?.order === "topological") return walkTopological(graph, callback, options);
	return walkDeclarations(graph, callback, options);
};
//#endregion
//#region src/ir/graph.ts
const irTopLevelKinds = [
	"operation",
	"parameter",
	"requestBody",
	"schema",
	"server",
	"webhook"
];
const irPatterns = {
	operation: /^#\/paths\/[^/]+\/(get|put|post|delete|options|head|patch|trace)$/,
	parameter: /^#\/components\/parameters\/[^/]+$/,
	requestBody: /^#\/components\/requestBodies\/[^/]+$/,
	schema: /^#\/components\/schemas\/[^/]+$/,
	server: /^#\/servers\/(\d+|[^/]+)$/,
	webhook: /^#\/webhooks\/[^/]+\/(get|put|post|delete|options|head|patch|trace)$/
};
/**
* Checks if a pointer matches a known top-level IR component (schema, parameter, etc) and returns match info.
*
* @param pointer - The IR pointer string (e.g., '#/components/schemas/Foo')
* @param kind - (Optional) The component kind to check
* @returns { matched: true, kind: IrTopLevelKind } | { matched: false } - Whether it matched, and the matched kind if so
*/
const matchIrPointerToGroup = (pointer, kind) => {
	if (kind) return irPatterns[kind].test(pointer) ? {
		kind,
		matched: true
	} : { matched: false };
	for (const key of irTopLevelKinds) if (irPatterns[key].test(pointer)) return {
		kind: key,
		matched: true
	};
	return { matched: false };
};
const preferGroups = [
	"server",
	"schema",
	"parameter",
	"requestBody",
	"operation",
	"webhook"
];
const kindPriority = (() => {
	const partial = {};
	for (let i = 0; i < preferGroups.length; i++) {
		const k = preferGroups[i];
		if (k) partial[k] = i;
	}
	for (const k of irTopLevelKinds) if (partial[k] === void 0) partial[k] = preferGroups.length;
	return partial;
})();
const defaultPriority = 10;
const getIrPointerPriority = (pointer) => {
	const result = matchIrPointerToGroup(pointer);
	if (result.matched) return kindPriority[result.kind] ?? defaultPriority;
	return defaultPriority;
};
//#endregion
//#region src/utils/ref.ts
/**
* Returns the reusable component name from `$ref`.
*/
function refToName($ref) {
	const path = jsonPointerToPath($ref);
	return path[path.length - 1];
}
/**
* Encodes a path segment for use in a JSON Pointer (RFC 6901).
*
* - Replaces all '~' with '~0'.
* - Replaces all '/' with '~1'.
*
* This ensures that path segments containing these characters are safely
* represented in JSON Pointer strings.
*
* @param segment - The path segment (string or number) to encode.
* @returns The encoded segment as a string.
*/
function encodeJsonPointerSegment(segment) {
	return String(segment).replaceAll("~", "~0").replaceAll("/", "~1");
}
/**
* Converts a JSON Pointer string (RFC 6901) to an array of path segments.
*
* - Removes the leading '#' if present.
* - Splits the pointer on '/'.
* - Decodes '~1' to '/' and '~0' to '~' in each segment.
* - Returns an empty array for the root pointer ('#' or '').
*
* @param pointer - The JSON Pointer string to convert (e.g., '#/components/schemas/Foo').
* @returns An array of decoded path segments.
*/
function jsonPointerToPath(pointer) {
	let clean = pointer.trim();
	if (clean.startsWith("#")) clean = clean.slice(1);
	if (clean.startsWith("/")) clean = clean.slice(1);
	if (!clean) return [];
	if (!clean.includes("~")) return clean.split("/");
	return clean.split("/").map((part) => part.replaceAll("~1", "/").replaceAll("~0", "~"));
}
/**
* Normalizes a JSON Pointer string to a canonical form.
*
* - Ensures the pointer starts with '#'.
* - Removes trailing slashes (except for root).
* - Collapses multiple consecutive slashes into one.
* - Trims whitespace from the input.
*
* @param pointer - The JSON Pointer string to normalize.
* @returns The normalized JSON Pointer string.
*/
function normalizeJsonPointer(pointer) {
	let normalized = pointer.trim();
	if (!normalized.startsWith("#")) normalized = `#${normalized}`;
	if (normalized.length > 1 && normalized.endsWith("/")) normalized = normalized.slice(0, -1);
	normalized = normalized.replace(/\/+/g, "/");
	return normalized;
}
/**
* Encode path as JSON Pointer (RFC 6901).
*
* @param path
* @returns
*/
function pathToJsonPointer(path) {
	const segments = path.map(encodeJsonPointerSegment).join("/");
	return "#" + (segments ? `/${segments}` : "");
}
/**
* Checks if a $ref or path points to a top-level component (not a deep path reference).
*
* Top-level component references:
* - OpenAPI 3.x: #/components/{type}/{name} (3 segments)
* - OpenAPI 2.0: #/definitions/{name} (2 segments)
*
* Deep path references (4+ segments for 3.x, 3+ for 2.0) should be inlined
* because they don't have corresponding registered symbols.
*
* @param refOrPath - The $ref string or path array to check
* @returns true if the ref points to a top-level component, false otherwise
*/
function isTopLevelComponent(refOrPath) {
	if (typeof refOrPath !== "string") {
		if (refOrPath[0] === "components") return refOrPath.length === 3;
		if (refOrPath[0] === "definitions") return refOrPath.length === 2;
		return false;
	}
	if (refOrPath.startsWith("#/components/")) {
		const typeEnd = refOrPath.indexOf("/", 13);
		if (typeEnd === -1) return false;
		const nameStart = typeEnd + 1;
		return nameStart < refOrPath.length && refOrPath.indexOf("/", nameStart) === -1;
	}
	if (refOrPath.startsWith("#/definitions/")) {
		const nameStart = 14;
		return nameStart < refOrPath.length && refOrPath.indexOf("/", nameStart) === -1;
	}
	return false;
}
function resolveRef({ $ref, spec }) {
	const path = jsonPointerToPath($ref);
	let current = spec;
	for (const part of path) {
		const segment = part;
		if (current[segment] === void 0) throw new Error(`Reference not found: ${$ref}`);
		current = current[segment];
	}
	return current;
}
//#endregion
//#region src/plugins/shared/utils/instance.ts
const defaultGetFilePath = (symbol) => {
	if (!symbol.meta?.pluginName || typeof symbol.meta.pluginName !== "string") return;
	if (symbol.meta.pluginName.startsWith("@hey-api/client-")) return "client";
	if (symbol.meta.pluginName === "@hey-api/typescript") return "types";
	if (symbol.meta.pluginName === "@hey-api/python-sdk") return "sdk";
	if (symbol.meta.pluginName.startsWith("@hey-api/")) return symbol.meta.pluginName.split("/")[1];
	return symbol.meta.pluginName;
};
const defaultGetKind = (operation) => {
	switch (operation.method) {
		case "delete":
		case "patch":
		case "post":
		case "put": return ["mutation"];
		case "get": return ["query"];
		default: return;
	}
};
var PluginInstance = class {
	api;
	config;
	context;
	dependencies = /* @__PURE__ */ new Set();
	eventHooks;
	gen;
	handler;
	name;
	/**
	* The package metadata and utilities for the current context, constructed
	* from the provided dependencies. Used for managing package-related
	* information such as name, version, and dependency resolution during
	* code generation.
	*/
	package;
	/** Symbols declared in the plugin config. */
	symbols;
	constructor(props) {
		this.api = props.api ?? {};
		this.config = props.config;
		this.context = props.context;
		this.dependencies = props.dependencies;
		this.eventHooks = this.buildEventHooks();
		this.gen = props.gen;
		this.handler = props.handler;
		this.name = props.name;
		this.package = props.context.package;
		this.symbols = this.buildSymbols(props.symbols);
	}
	external(resource, meta = {}) {
		return this.gen.symbols.reference({
			...meta,
			category: "external",
			resource
		});
	}
	forEach(...args) {
		if (!this.context.graph) throw new Error("No graph available in context");
		let callback;
		let events;
		let options = {
			getPointerPriority: getIrPointerPriority,
			matchPointerToGroup: matchIrPointerToGroup,
			order: "topological",
			preferGroups
		};
		if (typeof args[args.length - 1] === "function") {
			events = args.slice(0, -1);
			callback = args[args.length - 1];
		} else {
			events = args.slice(0, -2);
			callback = args[args.length - 2];
			options = {
				...options,
				...args[args.length - 1]
			};
		}
		const eventSet = new Set(events.length ? events : irTopLevelKinds);
		walk(this.context.graph, (pointer, nodeInfo) => {
			const result = matchIrPointerToGroup(pointer);
			if (!result.matched || !eventSet.has(result.kind)) return;
			let event;
			const baseEvent = {
				_path: jsonPointerToPath(pointer),
				pointer,
				tags: nodeInfo.tags ? Array.from(nodeInfo.tags) : void 0
			};
			switch (result.kind) {
				case "operation":
					event = {
						...baseEvent,
						method: nodeInfo.key,
						operation: nodeInfo.node,
						path: baseEvent._path[1],
						type: result.kind
					};
					break;
				case "parameter":
					event = {
						...baseEvent,
						name: nodeInfo.key,
						parameter: nodeInfo.node,
						type: result.kind
					};
					break;
				case "requestBody":
					event = {
						...baseEvent,
						name: nodeInfo.key,
						requestBody: nodeInfo.node,
						type: result.kind
					};
					break;
				case "schema":
					event = {
						...baseEvent,
						name: nodeInfo.key,
						schema: nodeInfo.node,
						type: result.kind
					};
					break;
				case "server":
					event = {
						...baseEvent,
						server: nodeInfo.node,
						type: result.kind
					};
					break;
				case "webhook":
					event = {
						...baseEvent,
						key: baseEvent._path[1],
						method: nodeInfo.key,
						operation: nodeInfo.node,
						type: result.kind
					};
					break;
			}
			if (event) try {
				callback(event);
			} catch (error) {
				this.forEachError(error, event);
			}
		}, options);
	}
	getHooks(selector, ...customHooks) {
		const result = [];
		for (const hook of customHooks) if (hook) result.push(hook);
		const local = selector(this.config["~hooks"] ?? {});
		if (local) result.push(local);
		const global = selector(this.context.config.parser.hooks);
		if (global) result.push(global);
		return result;
	}
	/**
	* Retrieves a registered plugin instance by its name from the context. This
	* allows plugins to access other plugins that have been registered in the
	* same context, enabling cross-plugin communication and dependencies.
	*
	* @param name Plugin name as defined in the configuration.
	* @returns The plugin instance if found, undefined otherwise.
	*/
	getPlugin(name) {
		return this.context.plugins[name];
	}
	/**
	* Retrieves a registered plugin instance by its name from the context. This
	* allows plugins to access other plugins that have been registered in the
	* same context, enabling cross-plugin communication and dependencies.
	*
	* @param name Plugin name as defined in the configuration.
	* @returns The plugin instance if found, throw otherwise.
	*/
	getPluginOrThrow(name) {
		const plugin = this.getPlugin(name);
		if (!plugin) throw new Error(`plugin not found ${name}`);
		return plugin;
	}
	hooks = { operation: {
		isMutation: (operation) => this.isOperationKind(operation, "mutation"),
		isQuery: (operation) => this.isOperationKind(operation, "query")
	} };
	/**
	* Registers an intent in the context's intent list.
	*
	* @param intent The intent to be registered.
	* @returns void
	*/
	intent(intent) {
		this.context.intents.push(intent);
	}
	isSymbolRegistered(identifier) {
		return this.gen.symbols.isRegistered(identifier);
	}
	/**
	* Sets or adds a node to the project graph.
	*
	* @param node The node to be added or updated in the project graph.
	* @param index The index at which to update the node. If undefined, the node will be added.
	* @returns The index of the added node or void if updated.
	*/
	node(node, index) {
		for (const hook of this.eventHooks["node:set:before"]) hook({
			node,
			plugin: this
		});
		const result = index !== void 0 ? this.gen.nodes.update(index, node) : this.gen.nodes.add(node);
		for (const hook of this.eventHooks["node:set:after"]) hook({
			node,
			plugin: this
		});
		return result;
	}
	querySymbol(filter) {
		return this.querySymbols(filter)[0];
	}
	querySymbols(filter) {
		return this.gen.symbols.query(filter);
	}
	referenceSymbol(meta) {
		return this.gen.symbols.reference(meta);
	}
	/**
	* Alias for `symbol()` method with single argument.
	*/
	registerSymbol(symbol) {
		return this.symbol(symbol.name, symbol);
	}
	/**
	* Executes plugin's handler function.
	*/
	async run() {
		for (const hook of this.eventHooks["plugin:handler:before"]) hook({ plugin: this });
		await this.handler({ plugin: this });
		for (const hook of this.eventHooks["plugin:handler:after"]) hook({ plugin: this });
	}
	symbol(name, symbol = {}) {
		const meta = { ...symbol.meta };
		if (symbol.external) {
			if (!meta.category) meta.category = "external";
			if (!meta.resource) meta.resource = `${symbol.external}.${name}`;
			const existing = this.querySymbols(meta).find((s) => s.name === name);
			if (existing) return existing;
		}
		const symbolIn = {
			...symbol,
			meta: {
				...symbol.external ? {} : { pluginName: path.isAbsolute(this.name) ? "custom" : this.name },
				...meta
			},
			name
		};
		if (symbolIn.getExportFromFilePath === void 0) symbolIn.getExportFromFilePath = this.getSymbolExportFromFilePath.bind(this);
		if (symbolIn.getFilePath === void 0) symbolIn.getFilePath = this.getSymbolFilePath.bind(this);
		for (const hook of this.eventHooks["symbol:register:before"]) hook({
			plugin: this,
			symbol: symbolIn
		});
		const symbolOut = this.gen.symbols.register(symbolIn);
		for (const hook of this.eventHooks["symbol:register:after"]) hook({
			plugin: this,
			symbol: symbolOut
		});
		return symbolOut;
	}
	/**
	* Registers a symbol only if it does not already exist based on the provided
	* name and metadata. This prevents duplicate symbols from being created in
	* the project.
	*/
	symbolOnce(name, symbol = {}) {
		if (symbol.external) return this.symbol(name, symbol);
		if (symbol.meta) {
			const existing = this.querySymbols(symbol.meta).find((s) => s.name === name);
			if (existing) return existing;
		}
		return this.symbol(name, symbol);
	}
	buildEventHooks() {
		const result = {
			"node:set:after": [],
			"node:set:before": [],
			"plugin:handler:after": [],
			"plugin:handler:before": [],
			"symbol:register:after": [],
			"symbol:register:before": []
		};
		const scopes = [this.config["~hooks"]?.events, this.context.config.parser.hooks.events];
		for (const scope of scopes) {
			if (!scope) continue;
			for (const [key, value] of Object.entries(scope)) if (value) result[key].push(value.bind(scope));
		}
		return result;
	}
	buildSymbols(fn) {
		return fn ? fn(this) : {};
	}
	forEachError(error, event) {
		const originalError = error instanceof Error ? error : new Error(String(error));
		throw new HeyApiError({
			args: [event],
			error: originalError,
			event: event.type,
			name: "Error",
			pluginName: this.name
		});
	}
	getSymbolExportFromFilePath(symbol) {
		for (const hook of this.getHooks((hooks) => hooks.symbols?.getExportFromFilePath)) {
			const result = hook(symbol);
			if (result !== void 0) return result;
		}
		const entryFile = this.context.config.output.indexFile ?? this.context.config.output.entryFile;
		if (symbol.external || !entryFile) return;
		const includeInEntry = this.config.exportFromIndex ?? this.config.includeInEntry;
		if (typeof includeInEntry === "boolean" && !includeInEntry || typeof includeInEntry === "function" && !includeInEntry(symbol)) return;
		const language = symbol.node?.language;
		if (!language) return;
		const moduleEntryName = this.gen.moduleEntryNames[language];
		if (!moduleEntryName) return;
		return [moduleEntryName];
	}
	getSymbolFilePath(symbol) {
		for (const hook of this.getHooks((hooks) => hooks.symbols?.getFilePath)) {
			const result = hook(symbol);
			if (result !== void 0) return result;
		}
		return defaultGetFilePath(symbol);
	}
	isOperationKind(operation, kind) {
		const method = kind === "query" ? "isQuery" : "isMutation";
		const hooks = [
			this.config["~hooks"]?.operations?.[method],
			this.config["~hooks"]?.operations?.getKind,
			this.context.config.parser.hooks.operations?.[method],
			this.context.config.parser.hooks.operations?.getKind,
			defaultGetKind
		];
		for (const hook of hooks) if (hook) {
			const result = hook(operation);
			if (result !== void 0) return typeof result === "boolean" ? result : result.includes(kind);
		}
		return false;
	}
};
//#endregion
//#region src/ir/context.ts
var Context = class {
	/**
	* Configuration for parsing and generating the output. This
	* is a mix of user-provided and default values.
	*/
	config;
	/**
	* The code generation project instance used to manage files, symbols,
	*/
	gen;
	/**
	* The dependency graph built from the intermediate representation.
	*/
	graph;
	/**
	* Intents declared by plugins.
	*/
	intents = [];
	/**
	* Intermediate representation model obtained from `spec`.
	*/
	ir = {};
	/**
	* Logger instance.
	*/
	logger;
	/**
	* The package metadata and utilities for the current context, constructed
	* from the provided dependencies. Used for managing package-related
	* information such as name, version, and dependency resolution during
	* code generation.
	*/
	package;
	/**
	* A map of registered plugin instances, keyed by plugin name. Plugins are
	* registered through the `registerPlugin` method and can be accessed by
	* their configured name from the config.
	*/
	plugins = {};
	/**
	* Resolved specification from `input`.
	*/
	spec;
	constructor({ config, dependencies, logger, project, spec }) {
		this.config = config;
		this.gen = project;
		this.logger = logger;
		this.package = dependencyFactory(dependencies);
		this.spec = spec;
	}
	/**
	* Returns a resolved and dereferenced schema from `spec`.
	*/
	dereference(schema) {
		const resolved = this.resolveRef(schema.$ref);
		const dereferenced = {
			...schema,
			...resolved
		};
		delete dereferenced.$ref;
		return dereferenced;
	}
	/**
	* Registers a new plugin to the global context.
	*
	* @param name Plugin name.
	* @returns Registered plugin instance.
	*/
	registerPlugin(name) {
		const plugin = this.config.plugins[name];
		const instance = new PluginInstance({
			api: plugin.api,
			config: plugin.config,
			context: this,
			dependencies: plugin.dependencies ?? /* @__PURE__ */ new Set(),
			gen: this.gen,
			handler: plugin.handler,
			name: plugin.name,
			symbols: plugin.symbols
		});
		this.plugins[instance.name] = instance;
		return instance;
	}
	/**
	* Registers all plugins in the order specified by the configuration and returns
	* an array of the registered PluginInstance objects. Each plugin is instantiated
	* and added to the context's plugins map.
	*
	* @returns {ReadonlyArray<PluginInstance>} An array of registered plugin instances in order.
	*/
	registerPlugins() {
		return this.config.pluginOrder.map((name) => this.registerPlugin(name));
	}
	resolveIrRef($ref) {
		return resolveRef({
			$ref,
			spec: this.ir
		});
	}
	/**
	* Returns a resolved reference from `spec`.
	*/
	resolveRef($ref) {
		return resolveRef({
			$ref,
			spec: this.spec
		});
	}
};
//#endregion
//#region src/ir/intents.ts
var IntentContext = class {
	spec;
	constructor(spec) {
		this.spec = spec;
	}
	getOperation(path, method) {
		const paths = this.spec.paths;
		if (!paths) return;
		return paths[path]?.[method];
	}
	setExample(operation, example) {
		const source = this.getOperation(operation.path, operation.method);
		if (!source) return;
		source["x-codeSamples"] ||= [];
		source["x-codeSamples"].push(example);
	}
};
//#endregion
//#region src/ir/schema-processor.ts
function createSchemaProcessor() {
	const emitted = /* @__PURE__ */ new Set();
	let contextTags;
	let contextAnchor;
	return {
		get context() {
			return {
				anchor: contextAnchor,
				tags: contextTags
			};
		},
		hasEmitted(path) {
			return emitted.has(pathToJsonPointer(path));
		},
		markEmitted(path) {
			const pointer = pathToJsonPointer(path);
			if (emitted.has(pointer)) return false;
			emitted.add(pointer);
			return true;
		},
		withContext(ctx, fn) {
			const prevTags = contextTags;
			const prevAnchor = contextAnchor;
			contextTags = ctx.tags;
			contextAnchor = ctx.anchor;
			try {
				return fn();
			} finally {
				contextTags = prevTags;
				contextAnchor = prevAnchor;
			}
		}
	};
}
//#endregion
//#region src/ir/schema-walker.ts
/**
* Create a schema walker from a visitor.
*
* The walker handles:
* - Dispatch order ($ref → type → items → fallback)
* - Deduplication of union/intersection schemas
* - Path tracking for child schemas
*/
function createSchemaWalker(visitor) {
	const walk = (schema, ctx) => {
		if (visitor.intercept) {
			const intercepted = visitor.intercept(schema, ctx, walk);
			if (intercepted !== void 0) return intercepted;
		}
		if (schema.$ref) return visitor.reference(schema.$ref, schema, ctx);
		if (schema.type) {
			let result = visitTyped(schema, ctx, visitor, walk);
			if (visitor.postProcess) result = visitor.postProcess(result, schema, ctx);
			return result;
		}
		if (schema.items) {
			const deduplicated = deduplicateSchema({ schema });
			if (!deduplicated.items) return walk(deduplicated, ctx);
			const itemResults = deduplicated.items.map((item, index) => walk(item, {
				...ctx,
				path: ref([
					...fromRef(ctx.path),
					"items",
					index
				])
			}));
			return deduplicated.logicalOperator === "and" ? visitor.intersection(itemResults, deduplicated.items, schema, ctx) : visitor.union(itemResults, deduplicated.items, schema, ctx);
		}
		return visitor.unknown({ type: "unknown" }, ctx);
	};
	return walk;
}
/**
* Dispatch to the appropriate visitor method based on schema type.
*/
function visitTyped(schema, ctx, visitor, walk) {
	switch (schema.type) {
		case "array": return visitor.array(schema, ctx, walk);
		case "boolean": return visitor.boolean(schema, ctx);
		case "enum": return visitor.enum(schema, ctx, walk);
		case "integer": return visitor.integer(schema, ctx);
		case "never": return visitor.never(schema, ctx);
		case "null": return visitor.null(schema, ctx);
		case "number": return visitor.number(schema, ctx);
		case "object": return visitor.object(schema, ctx, walk);
		case "string": return visitor.string(schema, ctx);
		case "tuple": return visitor.tuple(schema, ctx, walk);
		case "undefined": return visitor.undefined(schema, ctx);
		case "unknown": return visitor.unknown(schema, ctx);
		case "void": return visitor.void(schema, ctx);
	}
}
/**
* Helper to create a child context with an extended path.
*/
function childContext(ctx, ...segments) {
	return {
		path: ref([...fromRef(ctx.path), ...segments]),
		plugin: ctx.plugin
	};
}
//#endregion
//#region src/openApi/shared/utils/filter.ts
const namespaceNeedle = "/";
function addNamespace(namespace, value = "") {
	return `${namespace}${namespaceNeedle}${value}`;
}
function removeNamespace(key) {
	const index = key.indexOf(namespaceNeedle);
	return {
		name: key.slice(index + 1),
		namespace: key.slice(0, index)
	};
}
/**
* Converts reference strings from OpenAPI $ref keywords into namespaces.
*
* @example '#/components/schemas/Foo' -> 'schema'
*/
function stringToNamespace(value) {
	switch (value) {
		case "parameters": return "parameter";
		case "requestBodies": return "body";
		case "responses": return "response";
		case "definitions":
		case "schemas": return "schema";
		default: return "unknown";
	}
}
function getResourceDependencies(key, resourceMetadata) {
	const { namespace } = removeNamespace(key);
	if (namespace === "body") return resourceMetadata.requestBodies.get(key)?.dependencies;
	if (namespace === "operation") return resourceMetadata.operations.get(key)?.dependencies;
	if (namespace === "parameter") return resourceMetadata.parameters.get(key)?.dependencies;
	if (namespace === "response") return resourceMetadata.responses.get(key)?.dependencies;
	if (namespace === "schema") return resourceMetadata.schemas.get(key)?.dependencies;
}
function createFiltersSetAndRegExps(type, filters) {
	const keys = [];
	const regexps = [];
	if (filters) for (const value of filters) if (value.startsWith("/") && value.endsWith("/")) regexps.push(new RegExp(value.slice(1, value.length - 1)));
	else keys.push(addNamespace(type, value));
	return {
		regexps,
		set: new Set(keys)
	};
}
function collectFiltersSetFromRegExpsOpenApiV2({ excludeOperations, excludeSchemas, includeOperations, includeSchemas, spec }) {
	if ((excludeOperations.regexps.length || includeOperations.regexps.length) && spec.paths) for (const entry of Object.entries(spec.paths)) {
		const path = entry[0];
		const pathItem = entry[1];
		for (const method of httpMethods) {
			if (!pathItem[method]) continue;
			const key = createOperationKey({
				method,
				path
			});
			if (excludeOperations.regexps.some((regexp) => regexp.test(key))) excludeOperations.set.add(addNamespace("operation", key));
			if (includeOperations.regexps.some((regexp) => regexp.test(key))) includeOperations.set.add(addNamespace("operation", key));
		}
	}
	if (spec.definitions) {
		if (excludeSchemas.regexps.length || includeSchemas.regexps.length) for (const key of Object.keys(spec.definitions)) {
			if (excludeSchemas.regexps.some((regexp) => regexp.test(key))) excludeSchemas.set.add(addNamespace("schema", key));
			if (includeSchemas.regexps.some((regexp) => regexp.test(key))) includeSchemas.set.add(addNamespace("schema", key));
		}
	}
}
function collectFiltersSetFromRegExpsOpenApiV3({ excludeOperations, excludeParameters, excludeRequestBodies, excludeResponses, excludeSchemas, includeOperations, includeParameters, includeRequestBodies, includeResponses, includeSchemas, spec }) {
	if ((excludeOperations.regexps.length || includeOperations.regexps.length) && spec.paths) for (const entry of Object.entries(spec.paths)) {
		const path = entry[0];
		const pathItem = entry[1];
		for (const method of httpMethods) {
			if (!pathItem[method]) continue;
			const key = createOperationKey({
				method,
				path
			});
			if (excludeOperations.regexps.some((regexp) => regexp.test(key))) excludeOperations.set.add(addNamespace("operation", key));
			if (includeOperations.regexps.some((regexp) => regexp.test(key))) includeOperations.set.add(addNamespace("operation", key));
		}
	}
	if (spec.components) {
		if ((excludeParameters.regexps.length || includeParameters.regexps.length) && spec.components.parameters) for (const key of Object.keys(spec.components.parameters)) {
			if (excludeParameters.regexps.some((regexp) => regexp.test(key))) excludeParameters.set.add(addNamespace("parameter", key));
			if (includeParameters.regexps.some((regexp) => regexp.test(key))) includeParameters.set.add(addNamespace("parameter", key));
		}
		if ((excludeRequestBodies.regexps.length || includeRequestBodies.regexps.length) && spec.components.requestBodies) for (const key of Object.keys(spec.components.requestBodies)) {
			if (excludeRequestBodies.regexps.some((regexp) => regexp.test(key))) excludeRequestBodies.set.add(addNamespace("body", key));
			if (includeRequestBodies.regexps.some((regexp) => regexp.test(key))) includeRequestBodies.set.add(addNamespace("body", key));
		}
		if ((excludeResponses.regexps.length || includeResponses.regexps.length) && spec.components.responses) for (const key of Object.keys(spec.components.responses)) {
			if (excludeResponses.regexps.some((regexp) => regexp.test(key))) excludeResponses.set.add(addNamespace("response", key));
			if (includeResponses.regexps.some((regexp) => regexp.test(key))) includeResponses.set.add(addNamespace("response", key));
		}
		if ((excludeSchemas.regexps.length || includeSchemas.regexps.length) && spec.components.schemas) for (const key of Object.keys(spec.components.schemas)) {
			if (excludeSchemas.regexps.some((regexp) => regexp.test(key))) excludeSchemas.set.add(addNamespace("schema", key));
			if (includeSchemas.regexps.some((regexp) => regexp.test(key))) includeSchemas.set.add(addNamespace("schema", key));
		}
	}
}
function collectFiltersSetFromRegExps({ spec, ...filters }) {
	if ("swagger" in spec) collectFiltersSetFromRegExpsOpenApiV2({
		...filters,
		spec
	});
	else collectFiltersSetFromRegExpsOpenApiV3({
		...filters,
		spec
	});
}
function createFilters(config, spec, logger) {
	const eventCreateFilters = logger.timeEvent("create-filters");
	const excludeOperations = createFiltersSetAndRegExps("operation", config?.operations?.exclude);
	const includeOperations = createFiltersSetAndRegExps("operation", config?.operations?.include);
	const excludeParameters = createFiltersSetAndRegExps("parameter", config?.parameters?.exclude);
	const includeParameters = createFiltersSetAndRegExps("parameter", config?.parameters?.include);
	const excludeRequestBodies = createFiltersSetAndRegExps("body", config?.requestBodies?.exclude);
	const includeRequestBodies = createFiltersSetAndRegExps("body", config?.requestBodies?.include);
	const excludeResponses = createFiltersSetAndRegExps("response", config?.responses?.exclude);
	const includeResponses = createFiltersSetAndRegExps("response", config?.responses?.include);
	const excludeSchemas = createFiltersSetAndRegExps("schema", config?.schemas?.exclude);
	const includeSchemas = createFiltersSetAndRegExps("schema", config?.schemas?.include);
	collectFiltersSetFromRegExps({
		excludeOperations,
		excludeParameters,
		excludeRequestBodies,
		excludeResponses,
		excludeSchemas,
		includeOperations,
		includeParameters,
		includeRequestBodies,
		includeResponses,
		includeSchemas,
		spec
	});
	const filters = {
		deprecated: config?.deprecated ?? true,
		operations: {
			exclude: excludeOperations.set,
			include: includeOperations.set
		},
		orphans: config?.orphans ?? false,
		parameters: {
			exclude: excludeParameters.set,
			include: includeParameters.set
		},
		preserveOrder: config?.preserveOrder ?? false,
		requestBodies: {
			exclude: excludeRequestBodies.set,
			include: includeRequestBodies.set
		},
		responses: {
			exclude: excludeResponses.set,
			include: includeResponses.set
		},
		schemas: {
			exclude: excludeSchemas.set,
			include: includeSchemas.set
		},
		tags: {
			exclude: new Set(config?.tags?.exclude),
			include: new Set(config?.tags?.include)
		}
	};
	eventCreateFilters.timeEnd();
	return filters;
}
function hasFilters(config) {
	if (!config) return false;
	if (config.orphans === false || config.deprecated === false) return true;
	return Boolean(config.operations?.exclude?.length || config.operations?.include?.length || config.parameters?.exclude?.length || config.parameters?.include?.length || config.requestBodies?.exclude?.length || config.requestBodies?.include?.length || config.responses?.exclude?.length || config.responses?.include?.length || config.schemas?.exclude?.length || config.schemas?.include?.length || config.tags?.exclude?.length || config.tags?.include?.length);
}
/**
* Collect operations that satisfy the include/exclude filters and schema dependencies.
*
* Must be called after dropping components.
*/
function collectOperations({ filters, parameters, requestBodies, resourceMetadata, responses, schemas }) {
	const finalSet = /* @__PURE__ */ new Set();
	const stack = [...filters.operations.include.size ? filters.operations.include : new Set(resourceMetadata.operations.keys())];
	let index = 0;
	while (index < stack.length) {
		const key = stack[index++];
		if (filters.operations.exclude.has(key) || finalSet.has(key)) continue;
		const node = resourceMetadata.operations.get(key);
		if (!node) continue;
		if (!filters.deprecated && node.deprecated) continue;
		if (filters.tags.exclude.size && node.tags.size && [...filters.tags.exclude].some((tag) => node.tags.has(tag))) continue;
		if (filters.tags.include.size && !new Set([...filters.tags.include].filter((tag) => node.tags.has(tag))).size) continue;
		if ([...node.dependencies].some((dependency) => {
			const { namespace } = removeNamespace(dependency);
			switch (namespace) {
				case "body": return !requestBodies.has(dependency);
				case "parameter": return !parameters.has(dependency);
				case "response": return !responses.has(dependency);
				case "schema":
					if (schemas.has(dependency)) return false;
					if (filters.schemas.exclude.has(dependency)) return true;
					schemas.add(dependency);
					return false;
				default: return false;
			}
		})) continue;
		finalSet.add(key);
	}
	return { operations: finalSet };
}
/**
* Collect parameters that satisfy the include/exclude filters and schema dependencies.
*/
function collectParameters({ filters, resourceMetadata, schemas }) {
	const finalSet = /* @__PURE__ */ new Set();
	const stack = [...filters.parameters.include.size ? filters.parameters.include : new Set(resourceMetadata.parameters.keys())];
	let index = 0;
	while (index < stack.length) {
		const key = stack[index++];
		if (filters.parameters.exclude.has(key) || finalSet.has(key)) continue;
		const node = resourceMetadata.parameters.get(key);
		if (!node) continue;
		if (!filters.deprecated && node.deprecated) continue;
		finalSet.add(key);
		if (!node.dependencies.size) continue;
		for (const dependency of node.dependencies) {
			const { namespace } = removeNamespace(dependency);
			switch (namespace) {
				case "body":
					if (filters.requestBodies.exclude.has(dependency)) finalSet.delete(key);
					else if (!finalSet.has(dependency)) stack.push(dependency);
					break;
				case "schema":
					if (filters.schemas.exclude.has(dependency)) finalSet.delete(key);
					else if (!schemas.has(dependency)) schemas.add(dependency);
					break;
			}
		}
	}
	return { parameters: finalSet };
}
/**
* Collect request bodies that satisfy the include/exclude filters and schema dependencies.
*/
function collectRequestBodies({ filters, resourceMetadata, schemas }) {
	const finalSet = /* @__PURE__ */ new Set();
	const stack = [...filters.requestBodies.include.size ? filters.requestBodies.include : new Set(resourceMetadata.requestBodies.keys())];
	let index = 0;
	while (index < stack.length) {
		const key = stack[index++];
		if (filters.requestBodies.exclude.has(key) || finalSet.has(key)) continue;
		const node = resourceMetadata.requestBodies.get(key);
		if (!node) continue;
		if (!filters.deprecated && node.deprecated) continue;
		finalSet.add(key);
		if (!node.dependencies.size) continue;
		for (const dependency of node.dependencies) {
			const { namespace } = removeNamespace(dependency);
			switch (namespace) {
				case "body":
					if (filters.requestBodies.exclude.has(dependency)) finalSet.delete(key);
					else if (!finalSet.has(dependency)) stack.push(dependency);
					break;
				case "schema":
					if (filters.schemas.exclude.has(dependency)) finalSet.delete(key);
					else if (!schemas.has(dependency)) schemas.add(dependency);
					break;
			}
		}
	}
	return { requestBodies: finalSet };
}
/**
* Collect responses that satisfy the include/exclude filters and schema dependencies.
*/
function collectResponses({ filters, resourceMetadata, schemas }) {
	const finalSet = /* @__PURE__ */ new Set();
	const stack = [...filters.responses.include.size ? filters.responses.include : new Set(resourceMetadata.responses.keys())];
	let index = 0;
	while (index < stack.length) {
		const key = stack[index++];
		if (filters.responses.exclude.has(key) || finalSet.has(key)) continue;
		const node = resourceMetadata.responses.get(key);
		if (!node) continue;
		if (!filters.deprecated && node.deprecated) continue;
		finalSet.add(key);
		if (!node.dependencies.size) continue;
		for (const dependency of node.dependencies) {
			const { namespace } = removeNamespace(dependency);
			switch (namespace) {
				case "body":
					if (filters.requestBodies.exclude.has(dependency)) finalSet.delete(key);
					else if (!finalSet.has(dependency)) stack.push(dependency);
					break;
				case "schema":
					if (filters.schemas.exclude.has(dependency)) finalSet.delete(key);
					else if (!schemas.has(dependency)) schemas.add(dependency);
					break;
			}
		}
	}
	return { responses: finalSet };
}
/**
* Collect schemas that satisfy the include/exclude filters.
*/
function collectSchemas({ filters, resourceMetadata }) {
	const finalSet = /* @__PURE__ */ new Set();
	const stack = [...filters.schemas.include.size ? filters.schemas.include : new Set(resourceMetadata.schemas.keys())];
	let index = 0;
	while (index < stack.length) {
		const key = stack[index++];
		if (filters.schemas.exclude.has(key) || finalSet.has(key)) continue;
		const node = resourceMetadata.schemas.get(key);
		if (!node) continue;
		if (!filters.deprecated && node.deprecated) continue;
		finalSet.add(key);
		if (!node.dependencies.size) continue;
		for (const dependency of node.dependencies) {
			const { namespace } = removeNamespace(dependency);
			switch (namespace) {
				case "schema":
					if (!finalSet.has(dependency) && !filters.schemas.exclude.has(dependency)) stack.push(dependency);
					break;
			}
		}
	}
	return { schemas: finalSet };
}
/**
* Drop parameters that depend on already excluded parameters.
*/
function dropExcludedParameters({ filters, parameters, resourceMetadata }) {
	if (!filters.parameters.exclude.size) return;
	for (const key of parameters) {
		const node = resourceMetadata.parameters.get(key);
		if (!node?.dependencies.size) continue;
		for (const excludedKey of filters.parameters.exclude) if (node.dependencies.has(excludedKey)) {
			parameters.delete(key);
			break;
		}
	}
}
/**
* Drop request bodies that depend on already excluded request bodies.
*/
function dropExcludedRequestBodies({ filters, requestBodies, resourceMetadata }) {
	if (!filters.requestBodies.exclude.size) return;
	for (const key of requestBodies) {
		const node = resourceMetadata.requestBodies.get(key);
		if (!node?.dependencies.size) continue;
		for (const excludedKey of filters.requestBodies.exclude) if (node.dependencies.has(excludedKey)) {
			requestBodies.delete(key);
			break;
		}
	}
}
/**
* Drop responses that depend on already excluded responses.
*/
function dropExcludedResponses({ filters, resourceMetadata, responses }) {
	if (!filters.responses.exclude.size) return;
	for (const key of responses) {
		const node = resourceMetadata.responses.get(key);
		if (!node?.dependencies.size) continue;
		for (const excludedKey of filters.responses.exclude) if (node.dependencies.has(excludedKey)) {
			responses.delete(key);
			break;
		}
	}
}
/**
* Drop schemas that depend on already excluded schemas.
*/
function dropExcludedSchemas({ filters, resourceMetadata, schemas }) {
	if (!filters.schemas.exclude.size) return;
	for (const key of schemas) {
		const node = resourceMetadata.schemas.get(key);
		if (!node?.dependencies.size) continue;
		for (const excludedKey of filters.schemas.exclude) if (node.dependencies.has(excludedKey)) {
			schemas.delete(key);
			break;
		}
	}
}
function dropOrphans({ includedDependencies, operationDependencies, parameters, requestBodies, responses, schemas }) {
	for (const key of schemas) if (!operationDependencies.has(key) && !includedDependencies.has(key)) schemas.delete(key);
	for (const key of parameters) if (!operationDependencies.has(key) && !includedDependencies.has(key)) parameters.delete(key);
	for (const key of requestBodies) if (!operationDependencies.has(key) && !includedDependencies.has(key)) requestBodies.delete(key);
	for (const key of responses) if (!operationDependencies.has(key) && !includedDependencies.has(key)) responses.delete(key);
}
function collectDependencies({ resourceMetadata, seeds }) {
	const finalSet = /* @__PURE__ */ new Set();
	const stack = [...seeds];
	while (stack.length) {
		const key = stack.pop();
		if (finalSet.has(key)) continue;
		finalSet.add(key);
		const dependencies = getResourceDependencies(key, resourceMetadata);
		if (!dependencies?.size) continue;
		for (const dependency of dependencies) if (!finalSet.has(dependency)) stack.push(dependency);
	}
	return { dependencies: finalSet };
}
function collectExplicitDependencies({ filters, resourceMetadata }) {
	const seeds = /* @__PURE__ */ new Set();
	for (const key of filters.parameters.include) if (!filters.parameters.exclude.has(key)) seeds.add(key);
	for (const key of filters.requestBodies.include) if (!filters.requestBodies.exclude.has(key)) seeds.add(key);
	for (const key of filters.responses.include) if (!filters.responses.exclude.has(key)) seeds.add(key);
	for (const key of filters.schemas.include) if (!filters.schemas.exclude.has(key)) seeds.add(key);
	const { dependencies } = collectDependencies({
		resourceMetadata,
		seeds
	});
	for (const key of dependencies) {
		const { namespace } = removeNamespace(key);
		if (namespace === "body" && filters.requestBodies.exclude.has(key) || namespace === "parameter" && filters.parameters.exclude.has(key) || namespace === "response" && filters.responses.exclude.has(key) || namespace === "schema" && filters.schemas.exclude.has(key)) dependencies.delete(key);
	}
	return { explicitDependencies: dependencies };
}
function collectOperationDependencies({ operations, resourceMetadata }) {
	const finalSet = /* @__PURE__ */ new Set();
	const stack = [...new Set([...operations].flatMap((key) => [...resourceMetadata.operations.get(key)?.dependencies ?? []]))];
	let index = 0;
	while (index < stack.length) {
		const key = stack[index++];
		if (finalSet.has(key)) continue;
		finalSet.add(key);
		const dependencies = getResourceDependencies(key, resourceMetadata);
		if (!dependencies?.size) continue;
		for (const dependency of dependencies) if (!finalSet.has(dependency)) stack.push(dependency);
	}
	return { operationDependencies: finalSet };
}
function createFilteredDependencies({ filters, logger, resourceMetadata }) {
	const eventCreateFilteredDependencies = logger.timeEvent("create-filtered-dependencies");
	const { schemas } = collectSchemas({
		filters,
		resourceMetadata
	});
	const { parameters } = collectParameters({
		filters,
		resourceMetadata,
		schemas
	});
	const { requestBodies } = collectRequestBodies({
		filters,
		resourceMetadata,
		schemas
	});
	const { responses } = collectResponses({
		filters,
		resourceMetadata,
		schemas
	});
	dropExcludedSchemas({
		filters,
		resourceMetadata,
		schemas
	});
	dropExcludedParameters({
		filters,
		parameters,
		resourceMetadata
	});
	dropExcludedRequestBodies({
		filters,
		requestBodies,
		resourceMetadata
	});
	dropExcludedResponses({
		filters,
		resourceMetadata,
		responses
	});
	const { operations } = collectOperations({
		filters,
		parameters,
		requestBodies,
		resourceMetadata,
		responses,
		schemas
	});
	if (!filters.orphans && operations.size) {
		const { operationDependencies } = collectOperationDependencies({
			operations,
			resourceMetadata
		});
		const { explicitDependencies } = collectExplicitDependencies({
			filters,
			resourceMetadata
		});
		dropOrphans({
			includedDependencies: explicitDependencies,
			operationDependencies,
			parameters,
			requestBodies,
			responses,
			schemas
		});
	}
	eventCreateFilteredDependencies.timeEnd();
	return {
		operations,
		parameters,
		requestBodies,
		responses,
		schemas
	};
}
//#endregion
//#region src/openApi/shared/graph/meta.ts
/**
* Builds a resource metadata map from a Graph, matching the old Graph interface
* for compatibility with filtering code.
*/
const buildResourceMetadata = (graph, logger) => {
	const eventBuildResourceMetadata = logger.timeEvent("build-resource-metadata");
	const resourceMetadata = {
		operations: /* @__PURE__ */ new Map(),
		parameters: /* @__PURE__ */ new Map(),
		requestBodies: /* @__PURE__ */ new Map(),
		responses: /* @__PURE__ */ new Map(),
		schemas: /* @__PURE__ */ new Map()
	};
	const getDependencies = (pointer) => {
		const dependencies = /* @__PURE__ */ new Set();
		const nodeDependencies = graph.transitiveDependencies.get(pointer);
		if (nodeDependencies?.size) for (const dependency of nodeDependencies) {
			const path = jsonPointerToPath(dependency);
			const type = path[path.length - 2];
			const name = path[path.length - 1];
			if (type && name) {
				const namespace = stringToNamespace(type);
				if (namespace === "unknown") console.warn(`unsupported type: ${type}`);
				dependencies.add(addNamespace(namespace, name));
			}
		}
		return dependencies;
	};
	for (const [pointer, nodeInfo] of graph.nodes) {
		const path = jsonPointerToPath(pointer);
		if (path[0] === "components") {
			if (path.length === 3) {
				if (path[1] === "schemas") {
					const name = path[path.length - 1];
					resourceMetadata.schemas.set(addNamespace("schema", name), {
						dependencies: getDependencies(pointer),
						deprecated: nodeInfo.deprecated ?? false
					});
				} else if (path[1] === "parameters") {
					const name = path[path.length - 1];
					resourceMetadata.parameters.set(addNamespace("parameter", name), {
						dependencies: getDependencies(pointer),
						deprecated: nodeInfo.deprecated ?? false
					});
				} else if (path[1] === "requestBodies") {
					const name = path[path.length - 1];
					resourceMetadata.requestBodies.set(addNamespace("body", name), {
						dependencies: getDependencies(pointer),
						deprecated: nodeInfo.deprecated ?? false
					});
				} else if (path[1] === "responses") {
					const name = path[path.length - 1];
					resourceMetadata.responses.set(addNamespace("response", name), {
						dependencies: getDependencies(pointer),
						deprecated: nodeInfo.deprecated ?? false
					});
				}
			}
			continue;
		}
		if (path[0] === "paths") {
			if (path.length === 3 && httpMethods.includes(path[2])) {
				const method = path[path.length - 1];
				const operationKey = createOperationKey({
					method,
					path: path.slice(1, -1).join("/")
				});
				resourceMetadata.operations.set(addNamespace("operation", operationKey), {
					dependencies: getDependencies(pointer),
					deprecated: nodeInfo.deprecated ?? false,
					tags: nodeInfo.tags ?? /* @__PURE__ */ new Set()
				});
			}
			continue;
		}
		if (path[0] === "definitions") {
			if (path.length === 2) {
				const name = path[path.length - 1];
				resourceMetadata.schemas.set(addNamespace("schema", name), {
					dependencies: getDependencies(pointer),
					deprecated: nodeInfo.deprecated ?? false
				});
			}
			continue;
		}
	}
	eventBuildResourceMetadata.timeEnd();
	return { resourceMetadata };
};
//#endregion
//#region src/openApi/shared/utils/schema.ts
const deepClone = (obj) => JSON.parse(JSON.stringify(obj));
//#endregion
//#region src/openApi/shared/utils/schemaChildRelationships.ts
const childSchemaRelationships = [
	["additionalProperties", "single"],
	["allOf", "array"],
	["anyOf", "array"],
	["contains", "single"],
	["dependentSchemas", "objectMap"],
	["else", "single"],
	["if", "single"],
	["items", "singleOrArray"],
	["oneOf", "array"],
	["patternProperties", "objectMap"],
	["properties", "objectMap"],
	["propertyNames", "single"],
	["then", "single"],
	["unevaluatedProperties", "single"]
];
//#endregion
//#region src/openApi/shared/utils/transforms.ts
const getSchemasObject = (spec) => {
	if (hasComponentsSchemasObject(spec)) return spec.components.schemas;
	if (hasDefinitionsObject(spec)) return spec.definitions;
};
/**
* Checks if the given spec has a valid OpenAPI 3.x components.schemas object.
* Returns true if present, false otherwise.
*/
const hasComponentsSchemasObject = (spec) => typeof spec === "object" && spec !== null && "components" in spec && typeof spec.components === "object" && spec.components !== null && "schemas" in spec.components && typeof spec.components.schemas === "object" && spec.components.schemas !== null;
/**
* Checks if the given spec has a valid OpenAPI 2.0 definitions object.
* Returns true if present, false otherwise.
*/
const hasDefinitionsObject = (spec) => typeof spec === "object" && spec !== null && "definitions" in spec && typeof spec.definitions === "object" && spec.definitions !== null;
//#endregion
//#region src/openApi/shared/transforms/utils.ts
const hasName = (obj, value) => {
	if (obj instanceof Set) return obj.has(value);
	if (obj instanceof Array) return obj.includes(value);
	return value in obj;
};
const getUniqueComponentName = ({ base, components, extraComponents }) => {
	let index = 2;
	let name = base;
	while (hasName(components, name) || extraComponents && hasName(extraComponents, name)) {
		name = `${base}${index}`;
		index += 1;
	}
	return name;
};
const isPathRootSchema = (path) => path.length === 3 && path[0] === "components" && path[1] === "schemas" || path.length === 2 && path[0] === "definitions";
const specToSchemasPointerNamespace = (spec) => {
	if (spec && typeof spec === "object") {
		if ("swagger" in spec) return "#/definitions/";
		if ("openapi" in spec) return "#/components/schemas/";
	}
	return "";
};
//#endregion
//#region src/openApi/shared/transforms/enums.ts
/**
* Generate a unique, structural signature for an enum schema for deduplication.
* Only considers 'type' and sorted 'enum' values, ignoring other fields.
*
* @param schema - The schema object to analyze
* @returns A string signature if the schema is an enum, otherwise undefined
*/
const getEnumSignature = (schema) => {
	if (!schema || typeof schema !== "object" || !("enum" in schema) || !(schema.enum instanceof Array)) return;
	const type = ("type" in schema ? schema.type : void 0) || "";
	const values = [...schema.enum].sort();
	return JSON.stringify({
		type,
		values
	});
};
/**
* Recursively walk all schemas in the OpenAPI spec, visiting every object/array
* that could contain an enum. Calls the visitor with node info for each.
*
* @param key - The key of the current node
* @param node - The current node
* @param parent - The parent node
* @param path - The path to the current node
* @param visitor - Function to call for each visited node
*/
const walkSchemas$1 = ({ key, node, parent, path, visitor }) => {
	if (!node || typeof node !== "object" || node instanceof Array) return;
	const value = node;
	if ("type" in value || "enum" in value || childSchemaRelationships.some(([keyword]) => keyword in value)) visitor({
		key,
		node,
		parent,
		path
	});
	for (const [k, v] of Object.entries(value)) if (typeof v === "object" && v !== null) if (v instanceof Array) v.forEach((item, index) => walkSchemas$1({
		key: index,
		node: item,
		parent: v,
		path: [
			...path,
			k,
			index
		],
		visitor
	}));
	else walkSchemas$1({
		key: k,
		node: v,
		parent: node,
		path: [...path, k],
		visitor
	});
};
/**
* Inlines all root/top-level enums by replacing $refs to them with the actual enum schema,
* and then removes the now-unreferenced root enums from the schemas object.
*
* @param spec - The OpenAPI spec object to transform
*/
const inlineMode = ({ spec }) => {
	const schemasObj = getSchemasObject(spec);
	if (!schemasObj) return;
	const schemasPointerNamespace = specToSchemasPointerNamespace(spec);
	const rootEnums = {};
	for (const [name, schema] of Object.entries(schemasObj)) if (getEnumSignature(schema)) rootEnums[`${schemasPointerNamespace}${name}`] = schema;
	const replaceEnumRefs = (node) => {
		if (node instanceof Array) node.forEach(replaceEnumRefs);
		else if (node && typeof node === "object") for (const [k, v] of Object.entries(node)) if (k === "$ref" && typeof v === "string" && v in rootEnums) {
			Object.assign(node, deepClone(rootEnums[v]));
			delete node["$ref"];
		} else replaceEnumRefs(v);
	};
	replaceEnumRefs(spec);
	for (const pointer of Object.keys(rootEnums)) {
		const path = jsonPointerToPath(pointer);
		const name = path[path.length - 1];
		if (name) delete schemasObj[name];
	}
};
/**
* Promotes all inline enums to reusable root components (if mode is 'root'),
* deduplicates by signature, and replaces inline enums with $refs.
*
* Naming, casing, and deduplication are controlled by the enums transform config.
* Existing root enums are reused if structurally identical.
*
* @param spec - The OpenAPI spec object to transform
* @param config - The enums transform config
*/
const rootMode = ({ config, spec }) => {
	const schemasObj = getSchemasObject(spec);
	if (!schemasObj) return;
	const rootEnumSignatures = {};
	for (const [name, schema] of Object.entries(schemasObj)) {
		const signature = getEnumSignature(schema);
		if (signature) rootEnumSignatures[signature] = name;
	}
	const inlineEnums = [];
	walkSchemas$1({
		key: null,
		node: spec,
		parent: null,
		path: [],
		visitor: (nodeInfo) => {
			if (!isPathRootSchema(nodeInfo.path)) {
				const signature = getEnumSignature(nodeInfo.node);
				if (signature) inlineEnums.push({
					...nodeInfo,
					signature
				});
			}
		}
	});
	const signatureToName = {};
	const signatureToSchema = {};
	for (const { key, node, signature } of inlineEnums) {
		if (signature in signatureToName) continue;
		if (signature in rootEnumSignatures) {
			signatureToName[signature] = rootEnumSignatures[signature];
			continue;
		}
		signatureToName[signature] = getUniqueComponentName({
			base: applyNaming(typeof node === "object" && node && "title" in node && typeof node.title === "string" ? node.title : String(key), config),
			components: schemasObj,
			extraComponents: Object.values(signatureToName)
		});
		signatureToSchema[signature] = node;
	}
	for (const [signature, name] of Object.entries(signatureToName)) {
		const schema = signatureToSchema[signature];
		if (name && !(name in schemasObj) && schema && typeof schema === "object") schemasObj[name] = schema;
	}
	const schemasPointerNamespace = specToSchemasPointerNamespace(spec);
	for (const { key, parent, signature } of inlineEnums) {
		const name = signatureToName[signature];
		if (name && key !== null && parent && typeof parent === "object") parent[key] = { $ref: `${schemasPointerNamespace}${name}` };
	}
};
/**
* Applies the enums transform according to the configured mode ('inline' or 'root').
*
* - In 'inline' mode, all root enums are inlined and removed.
* - In 'root' mode, all inline enums are promoted to root components and deduplicated.
*
* @param config - The enums transform config
* @param spec - The OpenAPI spec object to transform
*/
const enumsTransform = ({ config, spec }) => {
	if (config.mode === "inline") {
		inlineMode({ spec });
		return;
	}
	if (config.mode === "root") {
		rootMode({
			config,
			spec
		});
		return;
	}
};
//#endregion
//#region src/openApi/shared/transforms/propertiesRequiredByDefault.ts
/**
* Recursively walk all schemas in the OpenAPI spec, visiting every object.
* Calls the visitor with node info for each.
*
* @param key - The key of the current node
* @param node - The current node
* @param parent - The parent node
* @param path - The path to the current node
* @param visitor - Function to call for each visited node
*/
const walkSchemas = ({ key, node, parent, path, visitor }) => {
	if (!node || typeof node !== "object" || node instanceof Array) return;
	const value = node;
	if ("type" in value || childSchemaRelationships.some(([keyword]) => keyword in value)) visitor({
		key,
		node,
		parent,
		path
	});
	for (const [k, v] of Object.entries(value)) if (typeof v === "object" && v !== null) if (v instanceof Array) v.forEach((item, index) => walkSchemas({
		key: index,
		node: item,
		parent: v,
		path: [
			...path,
			k,
			index
		],
		visitor
	}));
	else walkSchemas({
		key: k,
		node: v,
		parent: node,
		path: [...path, k],
		visitor
	});
};
/**
* Applies the properties required by default transform
*
* @param spec - The OpenAPI spec object to transform
*/
const propertiesRequiredByDefaultTransform = ({ spec }) => {
	walkSchemas({
		key: null,
		node: spec,
		parent: null,
		path: [],
		visitor: (nodeInfo) => {
			if (nodeInfo.node && typeof nodeInfo.node === "object" && "type" in nodeInfo.node && nodeInfo.node.type === "object" && "properties" in nodeInfo.node && nodeInfo.node.properties && typeof nodeInfo.node.properties === "object" && !("required" in nodeInfo.node)) {
				const propKeys = Object.keys(nodeInfo.node.properties);
				if (propKeys.length) nodeInfo.node.required = propKeys;
			}
		}
	});
};
//#endregion
//#region src/openApi/shared/utils/deepEqual.ts
/**
* Deep equality for JSON-compatible values (objects, arrays, primitives).
* Used to determine whether read/write pruned variants actually differ.
*/
const deepEqual = (a, b) => {
	if (a === b) return true;
	if (!a || !b || typeof a !== "object" || typeof b !== "object") return false;
	if (a.constructor !== b.constructor) return false;
	if (Array.isArray(a)) {
		const arrA = a;
		const arrB = b;
		let len = arrA.length;
		if (len !== arrB.length) return false;
		while (len--) if (!deepEqual(arrA[len], arrB[len])) return false;
		return true;
	}
	const objA = a;
	const objB = b;
	let len = 0;
	for (const key in objA) if (Object.hasOwn(objA, key)) {
		++len;
		if (!Object.hasOwn(objB, key)) return false;
		if (!deepEqual(objA[key], objB[key])) return false;
	}
	return Object.keys(objB).length === len;
};
//#endregion
//#region src/openApi/shared/utils/graph.ts
/**
* Ensures every relevant child node (e.g., properties, items) in the graph has a `scopes` property.
* If a node does not have its own scopes, it inherits from its parent if available.
*
* @param nodes - Map of JSON Pointer to NodeInfo.
*/
const annotateChildScopes = (nodes) => {
	for (const [, nodeInfo] of nodes) {
		if (nodeInfo.scopes) continue;
		if (nodeInfo.parentPointer) {
			const parentInfo = nodes.get(nodeInfo.parentPointer);
			if (parentInfo?.scopes) nodeInfo.scopes = new Set(parentInfo.scopes);
		}
	}
};
/**
* Recursively collects all $ref dependencies in the subtree rooted at `pointer`.
*/
const collectPointerDependencies = ({ cache, graph, pointer, visited }) => {
	if (cache.transitiveDependencies.has(pointer)) return {
		subtreeDependencies: cache.subtreeDependencies.get(pointer) ?? null,
		transitiveDependencies: cache.transitiveDependencies.get(pointer) ?? null
	};
	if (visited.has(pointer)) return {
		subtreeDependencies: null,
		transitiveDependencies: null
	};
	visited.add(pointer);
	if (!graph.nodes.get(pointer)) return {
		subtreeDependencies: null,
		transitiveDependencies: null
	};
	let transitiveDependencies = null;
	let subtreeDependencies = null;
	const nodeDependencies = graph.nodeDependencies.get(pointer);
	if (nodeDependencies) for (const depPointer of nodeDependencies) {
		(transitiveDependencies ??= /* @__PURE__ */ new Set()).add(depPointer);
		(subtreeDependencies ??= /* @__PURE__ */ new Set()).add(depPointer);
		const depResult = collectPointerDependencies({
			cache,
			graph,
			pointer: depPointer,
			visited
		});
		if (depResult.transitiveDependencies) for (const dependency of depResult.transitiveDependencies) transitiveDependencies.add(dependency);
	}
	const children = cache.parentToChildren.get(pointer) ?? [];
	for (const childPointer of children) {
		if (!cache.transitiveDependencies.has(childPointer)) {
			const childResult = collectPointerDependencies({
				cache,
				graph,
				pointer: childPointer,
				visited
			});
			cache.transitiveDependencies.set(childPointer, childResult.transitiveDependencies);
			cache.subtreeDependencies.set(childPointer, childResult.subtreeDependencies);
		}
		const childTransitive = cache.transitiveDependencies.get(childPointer) ?? null;
		const childSubtree = cache.subtreeDependencies.get(childPointer) ?? null;
		if (childTransitive) for (const dependency of childTransitive) (transitiveDependencies ??= /* @__PURE__ */ new Set()).add(dependency);
		if (childSubtree) for (const dependency of childSubtree) (subtreeDependencies ??= /* @__PURE__ */ new Set()).add(dependency);
	}
	cache.transitiveDependencies.set(pointer, transitiveDependencies);
	cache.subtreeDependencies.set(pointer, subtreeDependencies);
	return {
		subtreeDependencies,
		transitiveDependencies
	};
};
/**
* Propagates scopes through the graph using a multi-pass linear scan.
*
* Nodes are visited in reverse DFS-pre-order (bottom-up): children tend to
* appear before their parents so each node can push its scopes to its parent
* within the same pass.  For typical OpenAPI specs (components declared after
* paths) $ref targets also appear before $ref sources in this order, meaning
* both tree propagation and $ref propagation usually converge in a single pass.
*
* The outer `while (changed)` loop guarantees correctness for any ordering:
* it re-runs until no new scope values were added anywhere.  Because scopes
* can only grow (at most 3 values: 'normal', 'read', 'write'), the loop
* terminates in at most a handful of passes even for pathological specs.
*
* @param graph - The Graph structure containing nodes and dependencies.
*/
const propagateScopes = (graph) => {
	const nodesBottomUp = [...graph.nodes].reverse();
	let changed = true;
	while (changed) {
		changed = false;
		for (const [pointer, nodeInfo] of nodesBottomUp) {
			const nodeDeps = graph.nodeDependencies.get(pointer);
			if (nodeDeps) for (const depPointer of nodeDeps) {
				const depInfo = graph.nodes.get(depPointer);
				if (depInfo?.scopes && propagateScopesToNode(depInfo, nodeInfo)) changed = true;
			}
			if (nodeInfo.scopes && nodeInfo.parentPointer) {
				const parentInfo = graph.nodes.get(nodeInfo.parentPointer);
				if (parentInfo && propagateScopesToNode(nodeInfo, parentInfo)) changed = true;
			}
		}
	}
};
/**
* Propagates scopes from one node to another.
* Adds any scopes from fromNodeInfo to toNodeInfo that are not already present.
* Returns true if any scopes were added, false otherwise.
*
* @param fromNodeInfo - The node to propagate scopes from
* @param toNodeInfo - The node to propagate scopes to
* @returns boolean - Whether any scopes were added
*/
const propagateScopesToNode = (fromNodeInfo, toNodeInfo) => {
	if (!fromNodeInfo.scopes) return false;
	if (!toNodeInfo.scopes) toNodeInfo.scopes = /* @__PURE__ */ new Set();
	let changed = false;
	for (const scope of fromNodeInfo.scopes) if (!toNodeInfo.scopes.has(scope)) {
		toNodeInfo.scopes.add(scope);
		changed = true;
	}
	return changed;
};
/**
* Builds a graph of all nodes in an OpenAPI spec, indexed by normalized JSON Pointer,
* and tracks all $ref dependencies and reverse dependencies between nodes.
*
* - All keys in the returned maps are normalized JSON Pointers (RFC 6901, always starting with '#').
* - The `nodes` map allows fast lookup of any node and its parent/key context.
* - The `dependencies` map records, for each node, the set of normalized pointers it references via $ref.
* - After construction, all nodes will have their local and propagated scopes annotated.
*
* @param root The root object (e.g., the OpenAPI spec)
* @returns An object with:
*   - nodes: Map from normalized JSON Pointer string to NodeInfo
*   - dependencies: Map from normalized JSON Pointer string to Set of referenced normalized JSON Pointers
*/
function buildGraph(root, logger) {
	const eventBuildGraph = logger.timeEvent("build-graph");
	const graph = {
		nodeDependencies: /* @__PURE__ */ new Map(),
		nodes: /* @__PURE__ */ new Map(),
		subtreeDependencies: /* @__PURE__ */ new Map(),
		transitiveDependencies: /* @__PURE__ */ new Map()
	};
	const walk = ({ key, node, parentPointer, pointer }) => {
		if (typeof node !== "object" || node === null) return;
		let deprecated;
		let tags;
		if (typeof node === "object" && node !== null) {
			if ("deprecated" in node && typeof node.deprecated === "boolean") deprecated = Boolean(node.deprecated);
			if ("$ref" in node && typeof node.$ref === "string") {
				const refPointer = normalizeJsonPointer(node.$ref);
				if (!graph.nodeDependencies.has(pointer)) graph.nodeDependencies.set(pointer, /* @__PURE__ */ new Set());
				graph.nodeDependencies.get(pointer).add(refPointer);
			}
			if ("tags" in node && Array.isArray(node.tags)) tags = new Set(node.tags.filter((tag) => typeof tag === "string"));
		}
		graph.nodes.set(pointer, {
			deprecated,
			key,
			node,
			parentPointer,
			tags
		});
		if (Array.isArray(node)) node.forEach((item, index) => walk({
			key: index,
			node: item,
			parentPointer: pointer,
			pointer: pointer + "/" + encodeJsonPointerSegment(index)
		}));
		else for (const [childKey, value] of Object.entries(node)) walk({
			key: childKey,
			node: value,
			parentPointer: pointer,
			pointer: pointer + "/" + encodeJsonPointerSegment(childKey)
		});
	};
	walk({
		key: null,
		node: root,
		parentPointer: null,
		pointer: "#"
	});
	const cache = {
		parentToChildren: /* @__PURE__ */ new Map(),
		subtreeDependencies: /* @__PURE__ */ new Map(),
		transitiveDependencies: /* @__PURE__ */ new Map()
	};
	for (const [pointer, nodeInfo] of graph.nodes) {
		const parent = nodeInfo.parentPointer;
		if (parent) {
			let arr = cache.parentToChildren.get(parent);
			if (!arr) {
				arr = [];
				cache.parentToChildren.set(parent, arr);
			}
			arr.push(pointer);
		}
		const { node } = nodeInfo;
		if (typeof node === "object" && node !== null && !Array.isArray(node)) if ("readOnly" in node && node.readOnly === true) nodeInfo.scopes = new Set(["read"]);
		else if ("writeOnly" in node && node.writeOnly === true) nodeInfo.scopes = new Set(["write"]);
		else {
			const lastSlash = pointer.lastIndexOf("/");
			if (lastSlash > 0) {
				const prevSlash = pointer.lastIndexOf("/", lastSlash - 1);
				if (prevSlash >= 0 && pointer.slice(prevSlash + 1, lastSlash) === "properties") nodeInfo.scopes = new Set(["normal"]);
			}
		}
	}
	propagateScopes(graph);
	annotateChildScopes(graph.nodes);
	for (const pointer of graph.nodes.keys()) {
		const result = collectPointerDependencies({
			cache,
			graph,
			pointer,
			visited: /* @__PURE__ */ new Set()
		});
		if (result.transitiveDependencies) graph.transitiveDependencies.set(pointer, result.transitiveDependencies);
		if (result.subtreeDependencies) graph.subtreeDependencies.set(pointer, result.subtreeDependencies);
	}
	eventBuildGraph.timeEnd();
	return { graph };
}
//#endregion
//#region src/openApi/shared/transforms/readWrite.ts
const schemaKeys = new Set([
	"additionalProperties",
	"allOf",
	"anyOf",
	"items",
	"not",
	"oneOf",
	"patternProperties",
	"properties",
	"schema",
	"unevaluatedProperties"
]);
const getComponentContext = (path) => {
	if (path.length === 3 && path[0] === "components") {
		const type = path[1];
		if (type === "parameters") return "write";
		if (type === "requestBodies") return "write";
		if (type === "responses") return "read";
		if (type === "headers") return "read";
	}
	if (path.length === 2) {
		const type = path[0];
		if (type === "parameters") return "write";
		if (type === "responses") return "read";
	}
};
/**
* Capture the original schema objects by pointer before splitting.
* This is used to safely remove only the true originals after splitting,
* even if names are swapped or overwritten by split variants.
*/
const captureOriginalSchemas = (spec, logger) => {
	const event = logger.timeEvent("capture-original-schemas");
	const originals = {};
	if (hasComponentsSchemasObject(spec)) for (const [name, obj] of Object.entries(spec.components.schemas)) originals[`#/components/schemas/${name}`] = obj;
	else if (hasDefinitionsObject(spec)) for (const [name, obj] of Object.entries(spec.definitions)) originals[`#/definitions/${name}`] = obj;
	event.timeEnd();
	return originals;
};
/**
* Inserts split schemas into the spec at the correct location (OpenAPI 3.x or 2.0).
* This function is robust to spec version and will assign all split schemas
* to either components.schemas (OAS3) or definitions (OAS2).
*
* @param spec - The OpenAPI spec object
* @param split - The split schemas (from splitSchemas)
*/
const insertSplitSchemasIntoSpec = ({ logger, spec, split }) => {
	const event = logger.timeEvent("insert-split-schemas-into-spec");
	if (hasComponentsSchemasObject(spec)) Object.assign(spec.components.schemas, split.schemas);
	else if (hasDefinitionsObject(spec)) Object.assign(spec.definitions, split.schemas);
	event.timeEnd();
};
/**
* Prunes a schema by removing all child schemas (in any structural keyword)
* that are marked with the given scope (readOnly/writeOnly), or that are $ref to a schema
* that is exclusively the excluded scope (according to the graph).
*
* Uses childSchemaRelationships for parity with graph traversal.
* Returns true if the schema itself should be removed from its parent.
*
* @param graph - The Graph containing all nodes and their scopes
* @param schema - The schema object to prune
* @param scope - The scope to exclude ('readOnly' or 'writeOnly')
* @returns boolean - Whether the schema should be removed from its parent
*/
const pruneSchemaByScope = (graph, schema, scope) => {
	if (schema && typeof schema === "object") {
		if ("$ref" in schema && typeof schema.$ref === "string") {
			const nodeInfo = graph.nodes.get(schema.$ref);
			if (nodeInfo?.scopes) {
				if (scope === "writeOnly" && nodeInfo.scopes.size === 1 && nodeInfo.scopes.has("write") || scope === "readOnly" && nodeInfo.scopes.size === 1 && nodeInfo.scopes.has("read")) {
					delete schema["$ref"];
					if (!childSchemaRelationships.some(([keyword]) => keyword in schema)) return true;
				}
			}
		}
		for (const [keyword, type] of childSchemaRelationships) {
			if (!(keyword in schema)) continue;
			const value = schema[keyword];
			if (type === "array" && value instanceof Array) {
				for (let index = value.length - 1; index >= 0; index--) {
					const item = value[index];
					if (item && typeof item === "object" && item[scope] === true) value.splice(index, 1);
					else if (pruneSchemaByScope(graph, item, scope)) value.splice(index, 1);
				}
				if (!value.length) delete schema[keyword];
			} else if (type === "objectMap" && typeof value === "object" && value !== null && !(value instanceof Array)) {
				const objMap = value;
				const removedProperties = /* @__PURE__ */ new Set();
				for (const key of Object.keys(objMap)) {
					const prop = objMap[key];
					if (prop && typeof prop === "object" && prop[scope] === true) {
						delete objMap[key];
						if (keyword === "properties") removedProperties.add(key);
					} else if (pruneSchemaByScope(graph, prop, scope)) {
						delete objMap[key];
						if (keyword === "properties") removedProperties.add(key);
					}
				}
				if (removedProperties.size > 0 && keyword === "properties" && "required" in schema && Array.isArray(schema.required)) {
					const filteredRequired = schema.required.filter((prop) => !removedProperties.has(prop));
					if (!filteredRequired.length) delete schema.required;
					else schema.required = filteredRequired;
				}
				if (!Object.keys(objMap).length) delete schema[keyword];
			} else if (type === "single" && typeof value === "object" && value !== null) {
				if (value[scope] === true) delete schema[keyword];
				else if (pruneSchemaByScope(graph, value, scope)) delete schema[keyword];
			} else if (type === "singleOrArray") {
				if (value instanceof Array) {
					for (let index = value.length - 1; index >= 0; index--) {
						const item = value[index];
						if (item && typeof item === "object" && item[scope] === true) value.splice(index, 1);
						else if (pruneSchemaByScope(graph, item, scope)) value.splice(index, 1);
					}
					if (!value.length) delete schema[keyword];
				} else if (typeof value === "object" && value !== null) {
					if (value[scope] === true) delete schema[keyword];
					else if (pruneSchemaByScope(graph, value, scope)) delete schema[keyword];
				}
			}
		}
		if (schema.type === "object" && !childSchemaRelationships.some(([keyword]) => keyword in schema)) return true;
	}
	return false;
};
/**
* Remove only the true original schemas that were split, by object identity.
* This is robust to swaps, overwrites, and name collisions.
*
* @param originalSchemas - Map of original pointers to their schema objects (captured before splitting)
* @param spec - The OpenAPI spec object
* @param split - The split mapping (from splitSchemas)
*/
const removeOriginalSplitSchemas = ({ logger, originalSchemas, spec, split }) => {
	const event = logger.timeEvent("remove-original-split-schemas");
	const schemasObj = getSchemasObject(spec);
	for (const originalPointer of Object.keys(split.mapping)) {
		const path = jsonPointerToPath(originalPointer);
		const name = path[path.length - 1];
		if (typeof name === "string" && schemasObj && Object.prototype.hasOwnProperty.call(schemasObj, name) && schemasObj[name] === originalSchemas[originalPointer]) delete schemasObj[name];
	}
	event.timeEnd();
};
/**
* Create writable variants of parent schemas that have discriminators
* and are referenced by split schemas.
*/
function splitDiscriminatorSchemas({ config, existingNames, schemasPointerNamespace, spec, split }) {
	const schemasObj = getSchemasObject(spec);
	if (!schemasObj) return;
	const parentSchemasToSplit = /* @__PURE__ */ new Map();
	for (const [name, schema] of Object.entries(split.schemas)) {
		const pointer = `${schemasPointerNamespace}${name}`;
		const originalPointer = split.reverseMapping[pointer];
		if (originalPointer) {
			const mapping = split.mapping[originalPointer];
			if (mapping) {
				const contextVariant = mapping.read === pointer ? "read" : mapping.write === pointer ? "write" : null;
				if (contextVariant && schema && typeof schema === "object" && "allOf" in schema && schema.allOf instanceof Array) {
					for (const comp of schema.allOf) if (comp && typeof comp === "object" && "$ref" in comp && typeof comp.$ref === "string") {
						const refPath = jsonPointerToPath(comp.$ref);
						const schemaName = refPath[refPath.length - 1];
						if (typeof schemaName === "string" && schemaName in schemasObj) {
							const resolvedSchema = schemasObj[schemaName];
							if (resolvedSchema && typeof resolvedSchema === "object" && "discriminator" in resolvedSchema && resolvedSchema.discriminator && typeof resolvedSchema.discriminator === "object" && "mapping" in resolvedSchema.discriminator && resolvedSchema.discriminator.mapping && typeof resolvedSchema.discriminator.mapping === "object") {
								if (!parentSchemasToSplit.has(comp.$ref)) parentSchemasToSplit.set(comp.$ref, /* @__PURE__ */ new Set());
								parentSchemasToSplit.get(comp.$ref).add(contextVariant);
							}
						}
					}
				}
			}
		}
	}
	const parentSchemaVariants = /* @__PURE__ */ new Map();
	for (const [parentRef, contexts] of parentSchemasToSplit) {
		const refPath = jsonPointerToPath(parentRef);
		const parentName = refPath[refPath.length - 1];
		if (typeof parentName !== "string" || !(parentName in schemasObj)) continue;
		const parentSchema = schemasObj[parentName];
		if (!parentSchema || typeof parentSchema !== "object") continue;
		const variants = {};
		for (const context of contexts) {
			const variantSchema = deepClone(parentSchema);
			if ("discriminator" in variantSchema && variantSchema.discriminator && typeof variantSchema.discriminator === "object" && "mapping" in variantSchema.discriminator && variantSchema.discriminator.mapping && typeof variantSchema.discriminator.mapping === "object") {
				const mapping = variantSchema.discriminator.mapping;
				const updatedMapping = {};
				for (const [discriminatorValue, originalRef] of Object.entries(mapping)) {
					const map = split.mapping[originalRef];
					if (map) if (context === "read" && map.read) updatedMapping[discriminatorValue] = map.read;
					else if (context === "write" && map.write) updatedMapping[discriminatorValue] = map.write;
					else updatedMapping[discriminatorValue] = originalRef;
					else updatedMapping[discriminatorValue] = originalRef;
				}
				variantSchema.discriminator.mapping = updatedMapping;
			}
			if (context === "write") {
				const writeName = getUniqueComponentName({
					base: applyNaming(parentName, config.requests),
					components: existingNames
				});
				existingNames.add(writeName);
				split.schemas[writeName] = variantSchema;
				variants.write = `${schemasPointerNamespace}${writeName}`;
			}
		}
		parentSchemaVariants.set(parentRef, variants);
	}
	for (const [name, schema] of Object.entries(split.schemas)) {
		const pointer = `${schemasPointerNamespace}${name}`;
		const originalPointer = split.reverseMapping[pointer];
		if (!originalPointer) continue;
		const mapping = split.mapping[originalPointer];
		if (!mapping) continue;
		const contextVariant = mapping.read === pointer ? "read" : mapping.write === pointer ? "write" : null;
		if (contextVariant && schema && typeof schema === "object") {
			if ("allOf" in schema && schema.allOf instanceof Array) for (let i = 0; i < schema.allOf.length; i++) {
				const comp = schema.allOf[i];
				if (comp && typeof comp === "object" && "$ref" in comp && typeof comp.$ref === "string") {
					const variants = parentSchemaVariants.get(comp.$ref);
					if (variants) {
						if (contextVariant === "write" && variants.write) comp.$ref = variants.write;
						else if (contextVariant === "read" && variants.read) comp.$ref = variants.read;
					}
				}
			}
		}
	}
}
/**
* Splits schemas with both 'read' and 'write' scopes into read/write variants.
* Returns the new schemas and a mapping from original pointer to new variant pointers.
*
* @param config - The readWrite transform config
* @param graph - The Graph containing all nodes and their scopes
* @param spec - The OpenAPI spec object
* @returns SplitSchemas - The split schemas and pointer mappings
*/
const splitSchemas = ({ config, graph, logger, spec }) => {
	const event = logger.timeEvent("split-schemas");
	const existingNames = /* @__PURE__ */ new Set();
	const split = {
		mapping: {},
		reverseMapping: {},
		schemas: {}
	};
	const schemasPointerNamespace = specToSchemasPointerNamespace(spec);
	const schemasNamespaceSegments = schemasPointerNamespace.split("/").length - 1;
	/**
	* Extracts the schema name from pointer, but only if it's a top-level schema
	* pointer. Returns an empty string if it's a nested pointer.
	* @param pointer
	* @returns Schema's base name.
	*/
	const pointerToSchema = (pointer) => {
		if (pointer.startsWith(schemasPointerNamespace)) {
			const path = jsonPointerToPath(pointer);
			if (path.length === schemasNamespaceSegments) return path[schemasNamespaceSegments - 1] || "";
		}
		return "";
	};
	for (const pointer of graph.nodes.keys()) {
		const name = pointerToSchema(pointer);
		if (name) existingNames.add(name);
	}
	for (const [pointer, nodeInfo] of graph.nodes) {
		const name = pointerToSchema(pointer);
		if (!name || !(nodeInfo.scopes?.has("read") || nodeInfo.scopes?.has("write")) || !nodeInfo.scopes?.has("normal")) continue;
		const readSchema = deepClone(nodeInfo.node);
		pruneSchemaByScope(graph, readSchema, "writeOnly");
		const readBase = applyNaming(name, config.responses);
		const readName = readBase === name ? readBase : getUniqueComponentName({
			base: readBase,
			components: existingNames
		});
		existingNames.add(readName);
		split.schemas[readName] = readSchema;
		const readPointer = `${schemasPointerNamespace}${readName}`;
		const writeSchema = deepClone(nodeInfo.node);
		pruneSchemaByScope(graph, writeSchema, "readOnly");
		const transitiveDeps = graph.transitiveDependencies.get(pointer) || /* @__PURE__ */ new Set();
		if (!Array.from(transitiveDeps).some((depPointer) => {
			const depNodeInfo = graph.nodes.get(depPointer);
			return depNodeInfo?.scopes?.has("normal") && (depNodeInfo.scopes.has("read") || depNodeInfo.scopes.has("write"));
		}) && deepEqual(readSchema, writeSchema) && deepEqual(readSchema, nodeInfo.node)) continue;
		const writeBase = applyNaming(name, config.requests);
		const writeName = writeBase === name && writeBase !== readName ? writeBase : getUniqueComponentName({
			base: writeBase,
			components: existingNames
		});
		existingNames.add(writeName);
		split.schemas[writeName] = writeSchema;
		const writePointer = `${schemasPointerNamespace}${writeName}`;
		split.mapping[pointer] = {
			read: readPointer,
			write: writePointer
		};
		split.reverseMapping[readPointer] = pointer;
		split.reverseMapping[writePointer] = pointer;
	}
	splitDiscriminatorSchemas({
		config,
		existingNames,
		schemasPointerNamespace,
		spec,
		split
	});
	event.timeEnd();
	return split;
};
/**
* Recursively updates $ref fields in the spec to point to the correct read/write variant
* according to the current context (read/write), using the split mapping.
*
* @param spec - The OpenAPI spec object
* @param split - The split mapping (from splitSchemas)
*/
const updateRefsInSpec = ({ logger, spec, split }) => {
	const event = logger.timeEvent("update-refs-in-spec");
	const schemasPointerNamespace = specToSchemasPointerNamespace(spec);
	const walk = ({ context, currentPointer, inSchema, node, path, visited = /* @__PURE__ */ new Set() }) => {
		if (node instanceof Array) node.forEach((item, index) => walk({
			context,
			currentPointer,
			inSchema,
			node: item,
			path: [...path, index],
			visited
		}));
		else if (node && typeof node === "object") {
			let nextPointer = currentPointer;
			let nextContext = context;
			if (isPathRootSchema(path)) {
				nextPointer = `${schemasPointerNamespace}${path[path.length - 1]}`;
				const originalPointer = split.reverseMapping[nextPointer];
				if (originalPointer) {
					const mapping = split.mapping[originalPointer];
					if (mapping?.read === nextPointer) nextContext = "read";
					else if (mapping?.write === nextPointer) nextContext = "write";
				}
			}
			const compContext = getComponentContext(path);
			if (compContext !== void 0) {
				for (const key in node) {
					if (!Object.prototype.hasOwnProperty.call(node, key)) continue;
					walk({
						context: compContext,
						currentPointer: nextPointer,
						inSchema: false,
						node: node[key],
						path: [...path, key],
						visited
					});
				}
				return;
			}
			for (const key in node) {
				if (!Object.prototype.hasOwnProperty.call(node, key)) continue;
				const value = node[key];
				if (!inSchema) {
					if (key === "requestBody") {
						walk({
							context: "write",
							currentPointer: nextPointer,
							inSchema: false,
							node: value,
							path: [...path, key],
							visited
						});
						continue;
					}
					if (key === "responses") {
						walk({
							context: "read",
							currentPointer: nextPointer,
							inSchema: false,
							node: value,
							path: [...path, key],
							visited
						});
						continue;
					}
					if (key === "parameters" && Array.isArray(value)) {
						value.forEach((param, index) => {
							if (param && typeof param === "object" && "schema" in param) walk({
								context: "write",
								currentPointer: nextPointer,
								inSchema: true,
								node: param.schema,
								path: [
									...path,
									key,
									index,
									"schema"
								],
								visited
							});
							if (param && typeof param === "object" && "content" in param) walk({
								context: "write",
								currentPointer: nextPointer,
								inSchema: false,
								node: param.content,
								path: [
									...path,
									key,
									index,
									"content"
								],
								visited
							});
						});
						continue;
					}
					if (key === "headers" && typeof value === "object" && value !== null) {
						for (const headerKey in value) {
							if (!Object.prototype.hasOwnProperty.call(value, headerKey)) continue;
							walk({
								context: "read",
								currentPointer: nextPointer,
								inSchema: false,
								node: value[headerKey],
								path: [
									...path,
									key,
									headerKey
								],
								visited
							});
						}
						continue;
					}
				}
				if (schemaKeys.has(key)) walk({
					context: nextContext,
					currentPointer: nextPointer,
					inSchema: true,
					node: value,
					path: [...path, key],
					visited
				});
				else if (key === "$ref" && typeof value === "string") {
					const map = split.mapping[value];
					if (map) {
						if (nextContext === "read" && map.read) node[key] = map.read;
						else if (nextContext === "write" && map.write) node[key] = map.write;
						else if (!nextContext && map.read) node[key] = map.read;
					}
				} else if (key === "discriminator" && typeof value === "object" && value !== null) {
					if ("mapping" in value && value.mapping && typeof value.mapping === "object") {
						const updatedMapping = {};
						for (const [discriminatorValue, originalRef] of Object.entries(value.mapping)) {
							const map = split.mapping[originalRef];
							if (map) if (nextContext === "read" && map.read) updatedMapping[discriminatorValue] = map.read;
							else if (nextContext === "write" && map.write) updatedMapping[discriminatorValue] = map.write;
							else updatedMapping[discriminatorValue] = originalRef;
							else updatedMapping[discriminatorValue] = originalRef;
						}
						value.mapping = updatedMapping;
					}
					walk({
						context: nextContext,
						currentPointer: nextPointer,
						inSchema,
						node: value,
						path: [...path, key],
						visited
					});
				} else walk({
					context: nextContext,
					currentPointer: nextPointer,
					inSchema,
					node: value,
					path: [...path, key],
					visited
				});
			}
		}
	};
	walk({
		context: null,
		currentPointer: null,
		inSchema: false,
		node: spec,
		path: []
	});
	event.timeEnd();
};
/**
* Orchestrates the full read/write transform:
* - Captures original schemas
* - Splits schemas into read/write variants
* - Inserts split schemas into the spec
* - Updates $refs throughout the spec
* - Removes original schemas that were split
*
* @param config - The readWrite transform config
* @param spec - The OpenAPI spec object
*/
const readWriteTransform = ({ config, logger, spec }) => {
	const { graph } = buildGraph(spec, logger);
	const originalSchemas = captureOriginalSchemas(spec, logger);
	const split = splitSchemas({
		config,
		graph,
		logger,
		spec
	});
	insertSplitSchemasIntoSpec({
		logger,
		spec,
		split
	});
	updateRefsInSpec({
		logger,
		spec,
		split
	});
	removeOriginalSplitSchemas({
		logger,
		originalSchemas,
		spec,
		split
	});
};
//#endregion
//#region src/openApi/shared/transforms/schemas.ts
/**
* Recursively walks the entire spec object and replaces all $ref strings
* according to the provided rename mapping.
*/
const rewriteRefs = (node, renameMap) => {
	if (node instanceof Array) node.forEach((item) => rewriteRefs(item, renameMap));
	else if (node && typeof node === "object") for (const [key, value] of Object.entries(node)) if (key === "$ref" && typeof value === "string" && value in renameMap) node[key] = renameMap[value];
	else rewriteRefs(value, renameMap);
};
/**
* Renames schema component keys and updates all $ref pointers throughout
* the spec. Handles collisions by skipping renames when the target name
* already exists or conflicts with another rename.
*/
const schemaNameTransform = ({ config, spec }) => {
	if (!config) return;
	const schemasObj = getSchemasObject(spec);
	if (!schemasObj) return;
	const schemasPointerNamespace = specToSchemasPointerNamespace(spec);
	if (!schemasPointerNamespace) return;
	const renameMap = {};
	const newNames = /* @__PURE__ */ new Set();
	const namingConfig = { name: config };
	for (const oldName of Object.keys(schemasObj)) {
		const newName = applyNaming(oldName, namingConfig);
		if (newName === oldName || newName in schemasObj || newNames.has(newName)) continue;
		renameMap[`${schemasPointerNamespace}${oldName}`] = `${schemasPointerNamespace}${newName}`;
		newNames.add(newName);
	}
	for (const [oldPointer, newPointer] of Object.entries(renameMap)) {
		const oldName = oldPointer.slice(schemasPointerNamespace.length);
		const newName = newPointer.slice(schemasPointerNamespace.length);
		const schema = schemasObj[oldName];
		delete schemasObj[oldName];
		schemasObj[newName] = schema;
	}
	if (Object.keys(renameMap).length) rewriteRefs(spec, renameMap);
};
//#endregion
//#region src/openApi/shared/transforms/index.ts
const transformOpenApiSpec = ({ context }) => {
	const { logger } = context;
	const eventTransformOpenApiSpec = logger.timeEvent("transform-openapi-spec");
	if (context.config.parser.transforms.schemaName) schemaNameTransform({
		config: context.config.parser.transforms.schemaName,
		spec: context.spec
	});
	if (context.config.parser.transforms.enums.enabled) enumsTransform({
		config: context.config.parser.transforms.enums,
		spec: context.spec
	});
	if (context.config.parser.transforms.propertiesRequiredByDefault) propertiesRequiredByDefaultTransform({ spec: context.spec });
	if (context.config.parser.transforms.readWrite.enabled) readWriteTransform({
		config: context.config.parser.transforms.readWrite,
		logger,
		spec: context.spec
	});
	eventTransformOpenApiSpec.timeEnd();
};
//#endregion
//#region src/openApi/shared/utils/parameter.ts
const mergeParametersObjects = ({ source, target }) => {
	const result = { ...target };
	if (source) {
		if (source.cookie) if (result.cookie) result.cookie = {
			...result.cookie,
			...source.cookie
		};
		else result.cookie = source.cookie;
		if (source.header) if (result.header) result.header = {
			...result.header,
			...source.header
		};
		else result.header = source.header;
		if (source.path) if (result.path) result.path = {
			...result.path,
			...source.path
		};
		else result.path = source.path;
		if (source.query) if (result.query) result.query = {
			...result.query,
			...source.query
		};
		else result.query = source.query;
	}
	if (!Object.keys(result).length) return;
	return result;
};
//#endregion
//#region src/openApi/shared/utils/security.ts
function securitySchemeSignature(scheme) {
	switch (scheme.type) {
		case "apiKey":
			if (!scheme.in || !scheme.name) return;
			if (scheme.in !== "header" && scheme.in !== "query" && scheme.in !== "cookie") return;
			return `apiKey:${scheme.in}:${scheme.name}`;
		case "basic": return "http:basic";
		case "http": {
			const httpScheme = (scheme.scheme ?? "").toLowerCase();
			if (httpScheme !== "bearer" && httpScheme !== "basic") return;
			return `http:${httpScheme}`;
		}
		case "oauth2":
		case "openIdConnect": return "http:bearer";
		default: return;
	}
}
/**
* Build the set of security keys whose canonical signature collides
* with another scheme. Only these keys should have their name preserved
* on the IR `key` field — schemes with unique signatures don't need
* disambiguation at runtime.
*/
function computeAmbiguousSecurityKeys(schemes) {
	const buckets = /* @__PURE__ */ new Map();
	for (const [name, scheme] of schemes) {
		const signature = securitySchemeSignature(scheme);
		if (!signature) continue;
		const bucket = buckets.get(signature) ?? [];
		bucket.push(name);
		buckets.set(signature, bucket);
	}
	const ambiguous = /* @__PURE__ */ new Set();
	for (const bucket of buckets.values()) {
		if (bucket.length < 2) continue;
		for (const name of bucket) ambiguous.add(name);
	}
	return ambiguous;
}
//#endregion
//#region src/openApi/shared/utils/validator.ts
const isSimpleKey = (key) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key);
const formatPath = (path) => path.map((segment, i) => {
	if (typeof segment === "number") return `[${segment}]`;
	if (i === 0) return segment;
	return isSimpleKey(segment) ? `.${segment}` : `['${segment.replace(/"/g, "\\'")}']`;
}).join("");
const formatValidatorIssue = (issue) => {
	const pathStr = formatPath(issue.path);
	const level = issue.severity === "error" ? colors.bold.red : colors.bold.yellow;
	const highlightedMessage = issue.message.replace(/`([^`]+)`/g, (_, code) => colors.yellow(`\`${code}\``));
	return `${level(`[${issue.severity.toUpperCase()}]`)} ${colors.cyan(pathStr)}: ${highlightedMessage}`;
};
const shouldPrint = ({ context, issue }) => {
	if (context.config.logs.level === "silent") return false;
	if (issue.severity === "error") return context.config.logs.level !== "warn";
	return true;
};
const handleValidatorResult = ({ context, result }) => {
	for (const issue of result.issues) if (shouldPrint({
		context,
		issue
	})) console.log(formatValidatorIssue(issue));
	if (!result.valid) process.exit(1);
};
//#endregion
//#region src/openApi/2.0.x/parser/filter.ts
/**
* Replace source spec with filtered version.
*/
const filterSpec$2 = ({ logger, operations, preserveOrder, schemas, spec }) => {
	const eventFilterSpec = logger.timeEvent("filter-spec");
	if (spec.definitions) {
		const filtered = {};
		if (preserveOrder) {
			for (const [name, source] of Object.entries(spec.definitions)) if (schemas.has(addNamespace("schema", name))) filtered[name] = source;
		} else for (const key of schemas) {
			const { name } = removeNamespace(key);
			const source = spec.definitions[name];
			if (source) filtered[name] = source;
		}
		spec.definitions = filtered;
	}
	if (spec.paths) for (const entry of Object.entries(spec.paths)) {
		const path = entry[0];
		const pathItem = entry[1];
		for (const method of httpMethods) {
			if (!pathItem[method]) continue;
			const key = addNamespace("operation", createOperationKey({
				method,
				path
			}));
			if (!operations.has(key)) delete pathItem[method];
		}
		if (!Object.keys(pathItem).length) delete spec.paths[path];
	}
	eventFilterSpec.timeEnd();
};
//#endregion
//#region src/ir/mediaType.ts
const fileLikeRegExp = /^(application\/(pdf|rtf|msword|vnd\.(ms-|openxmlformats-officedocument\.)|zip|x-(7z|tar|rar|zip|iso)|octet-stream|gzip|x-msdownload|json\+download|xml|x-yaml|x-7z-compressed|x-tar)|text\/(yaml|css|javascript)|audio\/(mpeg|wav)|video\/(mp4|x-matroska)|image\/(vnd\.adobe\.photoshop|svg\+xml))(; ?charset=[^;]+)?$/i;
const jsonMimeRegExp = /^application\/(.*\+)?json(;.*)?$/i;
const multipartFormDataMimeRegExp = /^multipart\/form-data(;.*)?$/i;
const textMimeRegExp = /^text\/[a-z0-9.+-]+(;.*)?$/i;
const xWwwFormUrlEncodedMimeRegExp = /^application\/x-www-form-urlencoded(;.*)?$/i;
const octetStreamMimeRegExp = /^application\/octet-stream(;.*)?$/i;
const isMediaTypeFileLike = ({ mediaType }) => {
	fileLikeRegExp.lastIndex = 0;
	return fileLikeRegExp.test(mediaType);
};
const mediaTypeToIrMediaType = ({ mediaType }) => {
	jsonMimeRegExp.lastIndex = 0;
	if (jsonMimeRegExp.test(mediaType)) return "json";
	multipartFormDataMimeRegExp.lastIndex = 0;
	if (multipartFormDataMimeRegExp.test(mediaType)) return "form-data";
	textMimeRegExp.lastIndex = 0;
	if (textMimeRegExp.test(mediaType)) return "text";
	xWwwFormUrlEncodedMimeRegExp.lastIndex = 0;
	if (xWwwFormUrlEncodedMimeRegExp.test(mediaType)) return "url-search-params";
	octetStreamMimeRegExp.lastIndex = 0;
	if (octetStreamMimeRegExp.test(mediaType)) return "octet-stream";
};
//#endregion
//#region src/openApi/2.0.x/parser/mediaType.ts
const contentToSchema$2 = ({ content }) => {
	const { mediaType, schema } = content;
	if (schema && "$ref" in schema) return { allOf: [{ ...schema }] };
	if (!schema) {
		if (isMediaTypeFileLike({ mediaType })) return {
			format: "binary",
			type: "string"
		};
		return;
	}
	if (schema.type === "string" && !schema.format && isMediaTypeFileLike({ mediaType })) return {
		...schema,
		format: "binary"
	};
	return schema;
};
const mediaTypeObjects$2 = ({ mimeTypes, response }) => {
	const objects = [];
	for (const mediaType of mimeTypes ?? []) objects.push({
		mediaType,
		schema: response.schema,
		type: mediaTypeToIrMediaType({ mediaType })
	});
	return objects;
};
//#endregion
//#region src/ir/pagination.ts
function getPaginationKeywordsRegExp(pagination) {
	const pattern = `^(${pagination.keywords.join("|")})$`;
	return new RegExp(pattern);
}
//#endregion
//#region src/openApi/shared/utils/discriminator.ts
/**
* Converts a string discriminator mapping value to the appropriate type based on
* the actual property type in the schema.
*
* OpenAPI discriminator mappings always use string keys, but the actual discriminator
* property may be a boolean, number, or integer. This function converts the string
* key to the correct runtime value and IR type.
*/
const convertDiscriminatorValue = (value, propertyType) => {
	switch (propertyType) {
		case "boolean": {
			const lowerValue = value.toLowerCase();
			if (lowerValue !== "true" && lowerValue !== "false") {
				console.warn("🚨", `non-boolean discriminator mapping value "${value}" for boolean property, falling back to string`);
				return {
					const: value,
					type: "string"
				};
			}
			return {
				const: lowerValue === "true",
				type: "boolean"
			};
		}
		case "integer": {
			const parsed = Number.parseInt(value, 10);
			if (Number.isNaN(parsed)) {
				console.warn("🚨", `non-numeric discriminator mapping value "${value}" for integer property, falling back to string`);
				return {
					const: value,
					type: "string"
				};
			}
			return {
				const: parsed,
				type: "integer"
			};
		}
		case "number": {
			const parsed = parseFloat(value);
			if (Number.isNaN(parsed)) {
				console.warn("🚨", `non-numeric discriminator mapping value "${value}" for number property, falling back to string`);
				return {
					const: value,
					type: "string"
				};
			}
			return {
				const: parsed,
				type: "number"
			};
		}
		default: return {
			const: value,
			type: "string"
		};
	}
};
const discriminatorValues = ($ref, mapping, shouldUseRefAsValue) => {
	const values = [];
	for (const name in mapping) if (mapping[name] === $ref) values.push(name);
	if (!values.length && (!shouldUseRefAsValue || shouldUseRefAsValue())) return [refToName($ref)];
	return values;
};
//#endregion
//#region src/openApi/2.0.x/parser/schema.ts
function getSchemaType$1(schema) {
	if (schema.type) return schema.type;
	if (schema.properties) return "object";
}
function parseSchemaJsDoc$2({ irSchema, schema }) {
	if (schema.example) irSchema.example = schema.example;
	if (schema.description) irSchema.description = schema.description;
	if (schema.title) irSchema.title = schema.title;
}
function parseSchemaMeta$2({ irSchema, schema }) {
	if (schema.default !== void 0) irSchema.default = schema.default;
	if (schema.exclusiveMaximum) {
		if (schema.maximum !== void 0) irSchema.exclusiveMaximum = schema.maximum;
	} else if (schema.maximum !== void 0) irSchema.maximum = schema.maximum;
	if (schema.exclusiveMinimum) {
		if (schema.minimum !== void 0) irSchema.exclusiveMinimum = schema.minimum;
	} else if (schema.minimum !== void 0) irSchema.minimum = schema.minimum;
	if (schema.format) irSchema.format = schema.format;
	if (schema.maxItems !== void 0) irSchema.maxItems = schema.maxItems;
	if (schema.maxLength !== void 0) irSchema.maxLength = schema.maxLength;
	if (schema.minItems !== void 0) irSchema.minItems = schema.minItems;
	if (schema.minLength !== void 0) irSchema.minLength = schema.minLength;
	if (schema.pattern) irSchema.pattern = schema.pattern;
	if (schema.readOnly) irSchema.accessScope = "read";
}
function parseArray$2({ context, irSchema = {}, schema, state }) {
	if (schema.maxItems && schema.maxItems === schema.minItems) irSchema.type = "tuple";
	else irSchema.type = "array";
	let schemaItems = [];
	if (schema.items) {
		const irItemsSchema = schemaToIrSchema$2({
			context,
			schema: schema.items,
			state
		});
		if (!schemaItems.length && schema.maxItems && schema.maxItems === schema.minItems) schemaItems = Array(schema.maxItems).fill(irItemsSchema);
		else if ("$ref" in schema.items) schemaItems.push(irItemsSchema);
		else {
			const ofArray = schema.items.allOf;
			if (ofArray && ofArray.length > 1 && !schema.items["x-nullable"]) Object.assign(irSchema, irItemsSchema);
			else schemaItems.push(irItemsSchema);
		}
	}
	irSchema = addItemsToSchema({
		items: schemaItems,
		schema: irSchema
	});
	return irSchema;
}
function parseBoolean$2({ irSchema = {} }) {
	irSchema.type = "boolean";
	return irSchema;
}
function parseNumber$2({ irSchema = {}, schema }) {
	irSchema.type = schema.type;
	return irSchema;
}
function parseObject$2({ context, irSchema = {}, schema, state }) {
	irSchema.type = "object";
	let isSchemaPropertiesEmpty = true;
	if (schema.properties) {
		const schemaProperties = {};
		for (const name in schema.properties) {
			isSchemaPropertiesEmpty = false;
			const property = schema.properties[name];
			if (typeof property === "boolean") {} else schemaProperties[name] = schemaToIrSchema$2({
				context,
				schema: property,
				state
			});
		}
		if (!isSchemaPropertiesEmpty) irSchema.properties = schemaProperties;
	}
	if (schema.additionalProperties === void 0) {
		if (!irSchema.properties) irSchema.additionalProperties = { type: "unknown" };
	} else if (typeof schema.additionalProperties === "boolean") {
		if (!(state.inAllOf && schema.additionalProperties === false && (!schema.properties || isSchemaPropertiesEmpty))) irSchema.additionalProperties = { type: schema.additionalProperties ? "unknown" : "never" };
	} else irSchema.additionalProperties = schemaToIrSchema$2({
		context,
		schema: schema.additionalProperties,
		state
	});
	if (schema.required) irSchema.required = schema.required;
	return irSchema;
}
function parseString$2({ irSchema = {} }) {
	irSchema.type = "string";
	return irSchema;
}
function parseExtensions$2({ source, target }) {
	for (const key in source) if (key.startsWith("x-")) target[key] = source[key];
}
function initIrSchema$2({ schema }) {
	const irSchema = {};
	parseSchemaJsDoc$2({
		irSchema,
		schema
	});
	parseExtensions$2({
		source: schema,
		target: irSchema
	});
	return irSchema;
}
function parseAllOf$2({ context, schema, state }) {
	let irSchema = initIrSchema$2({ schema });
	const schemaItems = [];
	const schemaType = getSchemaType$1(schema);
	const compositionSchemas = schema.allOf;
	for (const compositionSchema of compositionSchemas) {
		const originalInAllOf = state.inAllOf;
		if (!("$ref" in compositionSchema)) state.inAllOf = true;
		const irCompositionSchema = schemaToIrSchema$2({
			context,
			schema: compositionSchema,
			state
		});
		state.inAllOf = originalInAllOf;
		if (schema.required) if (irCompositionSchema.required) irCompositionSchema.required.push(...schema.required);
		else irCompositionSchema.required = schema.required;
		schemaItems.push(irCompositionSchema);
		if (compositionSchema.$ref) {
			const ref = context.resolveRef(compositionSchema.$ref);
			if (ref.discriminator && state.$ref) {
				const valueSchemas = discriminatorValues(state.$ref).map((value) => ({
					const: value,
					type: "string"
				}));
				const irDiscriminatorSchema = {
					properties: { [ref.discriminator]: valueSchemas.length > 1 ? {
						items: valueSchemas,
						logicalOperator: "or"
					} : valueSchemas[0] },
					type: "object"
				};
				if (ref.required?.includes(ref.discriminator)) irDiscriminatorSchema.required = [ref.discriminator];
				schemaItems.push(irDiscriminatorSchema);
			}
		}
	}
	if (schemaType === "object") {
		const irObjectSchema = parseOneType$2({
			context,
			schema: {
				...schema,
				type: "object"
			},
			state
		});
		if (irObjectSchema.properties) {
			for (const requiredProperty of irObjectSchema.required ?? []) if (!irObjectSchema.properties[requiredProperty]) for (const compositionSchema of compositionSchemas) {
				const finalCompositionSchema = compositionSchema.$ref ? context.resolveRef(compositionSchema.$ref) : compositionSchema;
				if (getSchemaType$1(finalCompositionSchema) === "object") {
					const irCompositionSchema = parseOneType$2({
						context,
						schema: {
							...finalCompositionSchema,
							type: "object"
						},
						state
					});
					if (irCompositionSchema.properties?.[requiredProperty]) {
						irObjectSchema.properties[requiredProperty] = irCompositionSchema.properties[requiredProperty];
						break;
					}
				}
			}
			schemaItems.push(irObjectSchema);
		}
	}
	irSchema = addItemsToSchema({
		items: schemaItems,
		logicalOperator: "and",
		mutateSchemaOneItem: true,
		schema: irSchema
	});
	if (schema["x-nullable"]) {
		const nestedItems = [{ type: "null" }];
		if (schemaItems.length) nestedItems.unshift(irSchema);
		irSchema = {
			items: nestedItems,
			logicalOperator: "or"
		};
		if (nestedItems[0].deprecated) irSchema.deprecated = nestedItems[0].deprecated;
		if (nestedItems[0].description) irSchema.description = nestedItems[0].description;
	}
	return irSchema;
}
function parseEnum$2({ context, schema, state }) {
	let irSchema = initIrSchema$2({ schema });
	parseSchemaMeta$2({
		irSchema,
		schema
	});
	irSchema.type = "enum";
	const schemaItems = [];
	const xEnumDescriptions = schema["x-enum-descriptions"];
	const xEnumVarnames = schema["x-enum-varnames"];
	const xEnumNames = schema["x-enumNames"];
	for (let index = 0, len = schema.enum.length; index < len; index++) {
		const enumValue = schema.enum[index];
		const typeOfEnumValue = typeof enumValue;
		let enumType;
		if (typeOfEnumValue === "string" || typeOfEnumValue === "number" || typeOfEnumValue === "boolean") enumType = typeOfEnumValue;
		else if (typeOfEnumValue === "object" && Array.isArray(enumValue)) enumType = "array";
		else if (enumValue === null) {
			if (schema["x-nullable"]) enumType = "null";
		} else console.warn("🚨", `unhandled "${typeOfEnumValue}" typeof value "${enumValue}" for enum`, schema.enum);
		if (!enumType) continue;
		const irTypeSchema = parseOneType$2({
			context,
			schema: {
				description: xEnumDescriptions?.[index],
				title: xEnumVarnames?.[index] ?? xEnumNames?.[index],
				type: enumType === "null" ? "string" : enumType
			},
			state
		});
		irTypeSchema.const = enumValue;
		if (enumType === "null") irTypeSchema.type = enumType;
		if (irTypeSchema.type === "array") irTypeSchema.type = "tuple";
		schemaItems.push(irTypeSchema);
	}
	irSchema = addItemsToSchema({
		items: schemaItems,
		schema: irSchema
	});
	return irSchema;
}
function parseRef$2({ context, schema, state }) {
	const irSchema = {};
	if (!isTopLevelComponent(schema.$ref)) {
		if (!state.circularReferenceTracker.has(schema.$ref)) {
			const refSchema = context.resolveRef(schema.$ref);
			const originalRef = state.$ref;
			state.$ref = schema.$ref;
			const irSchema = schemaToIrSchema$2({
				context,
				schema: refSchema,
				state
			});
			state.$ref = originalRef;
			return irSchema;
		}
	}
	irSchema.$ref = schema.$ref;
	irSchema.$ref = irSchema.$ref.replace(/#\/definitions\/([^/]+)/g, "#/components/schemas/$1");
	if (!state.circularReferenceTracker.has(schema.$ref)) {
		const refSchema = context.resolveRef(schema.$ref);
		const originalRef = state.$ref;
		state.$ref = schema.$ref;
		schemaToIrSchema$2({
			context,
			schema: refSchema,
			state
		});
		state.$ref = originalRef;
	}
	return irSchema;
}
function parseNullableType$1({ context, irSchema, schema, state }) {
	if (!irSchema) irSchema = initIrSchema$2({ schema });
	const typeIrSchema = {};
	parseSchemaMeta$2({
		irSchema: typeIrSchema,
		schema
	});
	if (typeIrSchema.default === null) delete typeIrSchema.default;
	irSchema = addItemsToSchema({
		items: [parseOneType$2({
			context,
			irSchema: typeIrSchema,
			schema,
			state
		}), { type: "null" }],
		schema: irSchema
	});
	return irSchema;
}
function parseType$2({ context, schema, state }) {
	const irSchema = initIrSchema$2({ schema });
	parseSchemaMeta$2({
		irSchema,
		schema
	});
	const type = getSchemaType$1(schema);
	if (!type) return irSchema;
	if (schema["x-nullable"]) return parseNullableType$1({
		context,
		irSchema,
		schema: {
			...schema,
			type
		},
		state
	});
	return parseOneType$2({
		context,
		irSchema,
		schema: {
			...schema,
			type
		},
		state
	});
}
function parseOneType$2({ context, irSchema, schema, state }) {
	if (!irSchema) {
		irSchema = initIrSchema$2({ schema });
		parseSchemaMeta$2({
			irSchema,
			schema
		});
	}
	switch (schema.type) {
		case "array": return parseArray$2({
			context,
			irSchema,
			schema,
			state
		});
		case "boolean": return parseBoolean$2({
			context,
			irSchema,
			schema,
			state
		});
		case "integer":
		case "number": return parseNumber$2({
			context,
			irSchema,
			schema,
			state
		});
		case "object": return parseObject$2({
			context,
			irSchema,
			schema,
			state
		});
		case "string": return parseString$2({
			context,
			irSchema,
			schema,
			state
		});
		default: return parseUnknown$2({
			context,
			irSchema,
			schema
		});
	}
}
function parseUnknown$2({ irSchema, schema }) {
	if (!irSchema) irSchema = initIrSchema$2({ schema });
	irSchema.type = "unknown";
	parseSchemaMeta$2({
		irSchema,
		schema
	});
	return irSchema;
}
function schemaToIrSchema$2({ context, schema, state }) {
	if (!state) state = { circularReferenceTracker: /* @__PURE__ */ new Set() };
	if (state.$ref) state.circularReferenceTracker.add(state.$ref);
	if (schema.$ref) return parseRef$2({
		context,
		schema,
		state
	});
	if (schema.enum) return parseEnum$2({
		context,
		schema,
		state
	});
	if (schema.allOf) return parseAllOf$2({
		context,
		schema,
		state
	});
	if (schema.type || schema.properties) return parseType$2({
		context,
		schema,
		state
	});
	return parseUnknown$2({
		context,
		schema
	});
}
function parseSchema$2({ $ref, context, schema }) {
	if (!context.ir.components) context.ir.components = {};
	if (!context.ir.components.schemas) context.ir.components.schemas = {};
	context.ir.components.schemas[refToName($ref)] = schemaToIrSchema$2({
		context,
		schema,
		state: {
			$ref,
			circularReferenceTracker: /* @__PURE__ */ new Set()
		}
	});
}
//#endregion
//#region src/openApi/2.0.x/parser/pagination.ts
const isPaginationType$2 = (schemaType) => schemaType === "boolean" || schemaType === "integer" || schemaType === "number" || schemaType === "string";
const paginationField$2 = ({ context, name, schema }) => {
	if (getPaginationKeywordsRegExp(context.config.parser.pagination).test(name)) return true;
	if ("$ref" in schema) {
		const ref = context.resolveRef(schema.$ref ?? "");
		if ("in" in ref && ref.in) return paginationField$2({
			context,
			name,
			schema: "schema" in ref ? ref.schema : {
				...ref,
				in: void 0
			}
		});
		return paginationField$2({
			context,
			name,
			schema: ref
		});
	}
	if ("in" in schema) {
		if (!schema.in) return false;
		return paginationField$2({
			context,
			name,
			schema: "schema" in schema ? schema.schema : {
				...schema,
				in: void 0
			}
		});
	}
	for (const name in schema.properties) if (getPaginationKeywordsRegExp(context.config.parser.pagination).test(name)) {
		const property = schema.properties[name];
		if (typeof property !== "boolean" && !("$ref" in property)) {
			if (isPaginationType$2(getSchemaType$1(property))) return name;
		}
	}
	for (const allOf of schema.allOf ?? []) {
		const pagination = paginationField$2({
			context,
			name,
			schema: allOf
		});
		if (pagination) return pagination;
	}
	return false;
};
//#endregion
//#region src/openApi/2.0.x/parser/operation.ts
function parseOperationJsDoc$2({ irOperation, operation }) {
	if (operation.deprecated !== void 0) irOperation.deprecated = operation.deprecated;
	if (operation.description) irOperation.description = operation.description;
	if (operation.summary) irOperation.summary = operation.summary;
	if (operation.tags?.length) irOperation.tags = operation.tags;
}
function initIrOperation$2({ context, method, operation, path, state }) {
	const irOperation = {
		id: operationToId({
			context,
			id: operation.operationId,
			method,
			path,
			state
		}),
		method,
		path
	};
	if (operation.operationId) irOperation.operationId = operation.operationId;
	parseOperationJsDoc$2({
		irOperation,
		operation
	});
	parseExtensions$2({
		source: operation,
		target: irOperation
	});
	return irOperation;
}
function operationToIrOperation$2({ ambiguousSecurityKeys, context, method, operation, path, securitySchemesMap, state }) {
	const irOperation = initIrOperation$2({
		context,
		method,
		operation,
		path,
		state
	});
	if (operation.parameters) irOperation.parameters = operation.parameters;
	let isRequestBodyRequired = false;
	const requestBodyObject = {
		mediaType: "",
		schema: {
			properties: {},
			required: [],
			type: "object"
		}
	};
	const requestBodyObjectRequired = [];
	const hasBodyParameter = operation.requestBody?.some((param) => {
		return ("$ref" in param ? context.resolveRef(param.$ref) : param).in === "body";
	});
	for (const requestBodyParameter of operation.requestBody ?? []) {
		const requestBody = "$ref" in requestBodyParameter ? context.resolveRef(requestBodyParameter.$ref) : requestBodyParameter;
		const schema = requestBody.in === "body" ? requestBody.schema : {
			...requestBody,
			format: requestBody.type === "file" ? "binary" : requestBody.format,
			required: void 0,
			type: requestBody.type === "file" ? "string" : requestBody.type
		};
		let mimeTypes = operation.consumes;
		if (!mimeTypes && hasBodyParameter && requestBody.in === "body") mimeTypes = ["application/json"];
		const contents = mediaTypeObjects$2({
			mimeTypes,
			response: { schema }
		});
		const content = contents.find((content) => content.type === "json") || contents[0];
		if (content) {
			const pagination = paginationField$2({
				context,
				name: "",
				schema: content.schema && "$ref" in content.schema ? {
					allOf: [{ ...content.schema }],
					description: requestBody.description
				} : {
					description: requestBody.description,
					...content.schema
				}
			});
			const irSchema = schemaToIrSchema$2({
				context,
				schema: "$ref" in requestBody ? {
					allOf: [{
						...requestBody,
						$ref: requestBody.$ref,
						required: [],
						type: "string"
					}],
					description: requestBody.description
				} : content.schema && "$ref" in content.schema ? {
					allOf: [{ ...content.schema }],
					description: requestBody.description
				} : {
					description: requestBody.description,
					...content.schema
				},
				state: void 0
			});
			requestBodyObject.mediaType = content.mediaType;
			if (requestBody.in === "body") requestBodyObject.schema = irSchema;
			else {
				requestBodyObject.schema.properties[requestBody.name] = irSchema;
				if (requestBody.required) requestBodyObjectRequired.push(requestBody.name);
			}
			if (pagination) requestBodyObject.pagination = pagination;
			if (content.type) requestBodyObject.type = content.type;
		}
		if (requestBody.required) isRequestBodyRequired = true;
	}
	if (requestBodyObject.mediaType) {
		if (requestBodyObjectRequired.length) requestBodyObject.schema.required = requestBodyObjectRequired;
		irOperation.body = requestBodyObject;
		if (isRequestBodyRequired) irOperation.body.required = isRequestBodyRequired;
	}
	for (const name in operation.responses) {
		if (!irOperation.responses) irOperation.responses = {};
		const response = operation.responses[name];
		const responseObject = "$ref" in response ? context.resolveRef(response.$ref) : response;
		const contents = mediaTypeObjects$2({
			mimeTypes: operation.produces ? operation.produces : ["application/json"],
			response: responseObject
		});
		const content = contents.find((content) => content.type === "json") || contents[0];
		if (content) irOperation.responses[name] = {
			mediaType: content.mediaType,
			schema: schemaToIrSchema$2({
				context,
				schema: {
					description: responseObject.description,
					...contentToSchema$2({ content })
				},
				state: void 0
			})
		};
		else irOperation.responses[name] = { schema: {
			description: responseObject.description,
			type: name === "204" ? "void" : "unknown"
		} };
	}
	if (operation.security) {
		const securitySchemeObjects = /* @__PURE__ */ new Map();
		for (const securityRequirementObject of operation.security) for (const name in securityRequirementObject) {
			const securitySchemeObject = securitySchemesMap.get(name);
			if (!securitySchemeObject) continue;
			let irSecuritySchemeObject;
			if (securitySchemeObject.type === "apiKey") irSecuritySchemeObject = securitySchemeObject;
			if (securitySchemeObject.type === "basic") irSecuritySchemeObject = {
				description: securitySchemeObject.description,
				scheme: "basic",
				type: "http"
			};
			if (securitySchemeObject.type === "oauth2") {
				irSecuritySchemeObject = {
					description: securitySchemeObject.description,
					flows: {},
					type: "oauth2"
				};
				switch (securitySchemeObject.flow) {
					case "accessCode":
						irSecuritySchemeObject.flows.authorizationCode = {
							authorizationUrl: securitySchemeObject.authorizationUrl,
							scopes: securitySchemeObject.scopes,
							tokenUrl: securitySchemeObject.tokenUrl
						};
						break;
					case "application":
						irSecuritySchemeObject.flows.clientCredentials = {
							scopes: securitySchemeObject.scopes,
							tokenUrl: securitySchemeObject.tokenUrl
						};
						break;
					case "implicit":
						irSecuritySchemeObject.flows.implicit = {
							authorizationUrl: securitySchemeObject.authorizationUrl,
							scopes: securitySchemeObject.scopes
						};
						break;
					case "password":
						irSecuritySchemeObject.flows.password = {
							scopes: securitySchemeObject.scopes,
							tokenUrl: securitySchemeObject.tokenUrl
						};
						break;
				}
			}
			if (!irSecuritySchemeObject) continue;
			if (ambiguousSecurityKeys.has(name)) irSecuritySchemeObject.key = name;
			securitySchemeObjects.set(name, irSecuritySchemeObject);
		}
		if (securitySchemeObjects.size) irOperation.security = Array.from(securitySchemeObjects.values());
	}
	return irOperation;
}
function parsePathOperation$2({ ambiguousSecurityKeys, context, method, operation, path, securitySchemesMap, state }) {
	if (!context.ir.paths) context.ir.paths = {};
	if (!context.ir.paths[path]) context.ir.paths[path] = {};
	context.ir.paths[path][method] = operationToIrOperation$2({
		ambiguousSecurityKeys,
		context,
		method,
		operation,
		path,
		securitySchemesMap,
		state
	});
}
//#endregion
//#region src/openApi/2.0.x/parser/parameter.ts
/**
* Returns default parameter `explode` based on value of `collectionFormat`.
*/
const defaultExplode$2 = (collectionFormat) => {
	switch (collectionFormat) {
		case "multi": return true;
		default: return false;
	}
};
/**
* Returns default parameter `style` based on value of `in`.
*/
const defaultStyle$2 = (_in) => {
	switch (_in) {
		case "header":
		case "path": return "simple";
		default: return "form";
	}
};
const parametersArrayToObject$2 = ({ context, operation, parameters }) => {
	if (!parameters || !Object.keys(parameters).length) return;
	const parametersObject = {};
	for (const parameterOrReference of parameters) {
		const parameter = "$ref" in parameterOrReference ? context.dereference(parameterOrReference) : parameterOrReference;
		if (parameter.in === "body" || parameter.in === "formData") {
			if (!operation.requestBody) operation.requestBody = [];
			operation.requestBody.push(parameter);
			continue;
		}
		if (!parametersObject[parameter.in]) parametersObject[parameter.in] = {};
		parametersObject[parameter.in][parameter.name.toLocaleLowerCase()] = parameterToIrParameter$2({
			$ref: `#/todo/real/path/to/parameter/${parameter.name}`,
			context,
			parameter
		});
	}
	return parametersObject;
};
const parameterToIrParameter$2 = ({ $ref, context, parameter }) => {
	const schema = parameter;
	const finalSchema = schema && "$ref" in schema ? {
		allOf: [{
			...schema,
			$ref: schema.$ref,
			required: Array.isArray(schema.required) ? schema.required : [],
			type: schema.type
		}],
		description: parameter.description
	} : {
		description: parameter.description,
		...schema,
		required: Array.isArray(schema.required) ? schema.required : [],
		type: schema.type
	};
	const pagination = paginationField$2({
		context,
		name: parameter.name,
		schema: finalSchema
	});
	const style = defaultStyle$2(parameter.in);
	const irParameter = {
		allowReserved: false,
		explode: defaultExplode$2(parameter.collectionFormat),
		location: parameter.in,
		name: parameter.name,
		schema: schemaToIrSchema$2({
			context,
			schema: finalSchema,
			state: {
				$ref,
				circularReferenceTracker: /* @__PURE__ */ new Set()
			}
		}),
		style
	};
	if (parameter.description) irParameter.description = parameter.description;
	if (pagination) irParameter.pagination = pagination;
	if (parameter.required) irParameter.required = parameter.required;
	parseExtensions$2({
		source: parameter,
		target: irParameter
	});
	return irParameter;
};
//#endregion
//#region src/utils/url.ts
const parseUrlRegExp = /^(([^:/?#]+):)?((\/\/)?([^:/?#]*)(:?([^/?#]*)))?([^?#]*)(\?([^#]*))?(#(.*))?/;
function parseUrl(value) {
	const errorResponse = {
		host: "",
		path: "",
		port: "",
		protocol: ""
	};
	parseUrlRegExp.lastIndex = 0;
	const match = value.match(parseUrlRegExp);
	if (!match) return errorResponse;
	const host = match[5] || "";
	if (host === "." || host === "..") return errorResponse;
	const path = match[8] || "";
	const protocol = match[2] || "";
	if (protocol.length === 1) return errorResponse;
	return {
		host,
		path: path === "/" ? "" : path,
		port: match[7] || "",
		protocol
	};
}
//#endregion
//#region src/openApi/2.0.x/parser/server.ts
const parseServers$2 = ({ context }) => {
	let schemes = context.spec.schemes ?? [];
	let host = context.spec.host ?? "";
	const path = context.spec.basePath ?? "";
	for (const input of context.config.input) if (typeof input.path === "string") {
		const url = parseUrl(input.path);
		if (!schemes.length) {
			if (url.protocol) schemes = [url.protocol];
		}
		if (!host) host = `${url.host}${url.port ? `:${url.port}` : ""}`;
	}
	if (!schemes.length) schemes = [""];
	const servers = schemes.map((scheme) => `${scheme ? `${scheme}://` : ""}${host}${path}`).filter(Boolean);
	if (servers.length) context.ir.servers = servers.map((url) => ({ url }));
};
//#endregion
//#region src/openApi/2.0.x/parser/validate.ts
const validateOpenApiSpec$2 = (spec, logger) => {
	const eventValidate = logger.timeEvent("validate");
	const issues = [];
	const operationIds = /* @__PURE__ */ new Map();
	if (spec.paths) for (const entry of Object.entries(spec.paths)) {
		const path = entry[0];
		const pathItem = entry[1];
		for (const method of httpMethods) {
			if (method === "trace") continue;
			const operation = pathItem[method];
			if (!operation) continue;
			const operationKey = createOperationKey({
				method,
				path
			});
			if (operation.operationId) if (!operationIds.has(operation.operationId)) operationIds.set(operation.operationId, operationKey);
			else issues.push({
				code: "duplicate_key",
				context: {
					key: "operationId",
					value: operation.operationId
				},
				message: "Duplicate `operationId` found. Each `operationId` must be unique.",
				path: [
					"paths",
					path,
					method,
					"operationId"
				],
				severity: "error"
			});
		}
	}
	eventValidate.timeEnd();
	return {
		issues,
		valid: !issues.some((issue) => issue.severity === "error")
	};
};
//#endregion
//#region src/openApi/2.0.x/parser/index.ts
const parseV2_0_X = (context) => {
	if (context.config.parser.validate_EXPERIMENTAL) handleValidatorResult({
		context,
		result: validateOpenApiSpec$2(context.spec, context.logger)
	});
	if (hasFilters(context.config.parser.filters)) {
		const filters = createFilters(context.config.parser.filters, context.spec, context.logger);
		const { graph } = buildGraph(context.spec, context.logger);
		const { resourceMetadata } = buildResourceMetadata(graph, context.logger);
		filterSpec$2({
			...createFilteredDependencies({
				filters,
				logger: context.logger,
				resourceMetadata
			}),
			logger: context.logger,
			preserveOrder: filters.preserveOrder,
			spec: context.spec
		});
	}
	transformOpenApiSpec({ context });
	const state = { ids: /* @__PURE__ */ new Map() };
	const securitySchemesMap = /* @__PURE__ */ new Map();
	for (const name in context.spec.securityDefinitions) {
		const securitySchemeObject = context.spec.securityDefinitions[name];
		securitySchemesMap.set(name, securitySchemeObject);
	}
	const ambiguousSecurityKeys = computeAmbiguousSecurityKeys(securitySchemesMap);
	if (context.spec.definitions) for (const name in context.spec.definitions) {
		const $ref = pathToJsonPointer(["definitions", name]);
		const schema = context.spec.definitions[name];
		parseSchema$2({
			$ref,
			context,
			schema
		});
	}
	parseServers$2({ context });
	for (const path in context.spec.paths) {
		if (path.startsWith("x-")) continue;
		const pathItem = context.spec.paths[path];
		const finalPathItem = pathItem.$ref ? {
			...context.resolveRef(pathItem.$ref),
			...pathItem
		} : pathItem;
		const commonOperation = {
			consumes: context.spec.consumes,
			produces: context.spec.produces,
			responses: {},
			security: context.spec.security
		};
		const operationArgs = {
			ambiguousSecurityKeys,
			context,
			operation: {
				...commonOperation,
				parameters: parametersArrayToObject$2({
					context,
					operation: commonOperation,
					parameters: finalPathItem.parameters
				})
			},
			path,
			securitySchemesMap,
			state
		};
		if (finalPathItem.delete) {
			const parameters = mergeParametersObjects({
				source: parametersArrayToObject$2({
					context,
					operation: finalPathItem.delete,
					parameters: finalPathItem.delete.parameters
				}),
				target: operationArgs.operation.parameters
			});
			parsePathOperation$2({
				...operationArgs,
				method: "delete",
				operation: {
					...operationArgs.operation,
					...finalPathItem.delete,
					parameters
				}
			});
		}
		if (finalPathItem.get) {
			const parameters = mergeParametersObjects({
				source: parametersArrayToObject$2({
					context,
					operation: finalPathItem.get,
					parameters: finalPathItem.get.parameters
				}),
				target: operationArgs.operation.parameters
			});
			parsePathOperation$2({
				...operationArgs,
				method: "get",
				operation: {
					...operationArgs.operation,
					...finalPathItem.get,
					parameters
				}
			});
		}
		if (finalPathItem.head) {
			const parameters = mergeParametersObjects({
				source: parametersArrayToObject$2({
					context,
					operation: finalPathItem.head,
					parameters: finalPathItem.head.parameters
				}),
				target: operationArgs.operation.parameters
			});
			parsePathOperation$2({
				...operationArgs,
				method: "head",
				operation: {
					...operationArgs.operation,
					...finalPathItem.head,
					parameters
				}
			});
		}
		if (finalPathItem.options) {
			const parameters = mergeParametersObjects({
				source: parametersArrayToObject$2({
					context,
					operation: finalPathItem.options,
					parameters: finalPathItem.options.parameters
				}),
				target: operationArgs.operation.parameters
			});
			parsePathOperation$2({
				...operationArgs,
				method: "options",
				operation: {
					...operationArgs.operation,
					...finalPathItem.options,
					parameters
				}
			});
		}
		if (finalPathItem.patch) {
			const parameters = mergeParametersObjects({
				source: parametersArrayToObject$2({
					context,
					operation: finalPathItem.patch,
					parameters: finalPathItem.patch.parameters
				}),
				target: operationArgs.operation.parameters
			});
			parsePathOperation$2({
				...operationArgs,
				method: "patch",
				operation: {
					...operationArgs.operation,
					...finalPathItem.patch,
					parameters
				}
			});
		}
		if (finalPathItem.post) {
			const parameters = mergeParametersObjects({
				source: parametersArrayToObject$2({
					context,
					operation: finalPathItem.post,
					parameters: finalPathItem.post.parameters
				}),
				target: operationArgs.operation.parameters
			});
			parsePathOperation$2({
				...operationArgs,
				method: "post",
				operation: {
					...operationArgs.operation,
					...finalPathItem.post,
					parameters
				}
			});
		}
		if (finalPathItem.put) {
			const parameters = mergeParametersObjects({
				source: parametersArrayToObject$2({
					context,
					operation: finalPathItem.put,
					parameters: finalPathItem.put.parameters
				}),
				target: operationArgs.operation.parameters
			});
			parsePathOperation$2({
				...operationArgs,
				method: "put",
				operation: {
					...operationArgs.operation,
					...finalPathItem.put,
					parameters
				}
			});
		}
	}
};
//#endregion
//#region src/openApi/3.0.x/parser/filter.ts
/**
* Replace source spec with filtered version.
*/
const filterSpec$1 = ({ logger, operations, parameters, preserveOrder, requestBodies, responses, schemas, spec }) => {
	const eventFilterSpec = logger.timeEvent("filter-spec");
	if (spec.components) {
		if (spec.components.parameters) {
			const filtered = {};
			if (preserveOrder) {
				for (const [name, source] of Object.entries(spec.components.parameters)) if (parameters.has(addNamespace("parameter", name))) filtered[name] = source;
			} else for (const key of parameters) {
				const { name } = removeNamespace(key);
				const source = spec.components.parameters[name];
				if (source) filtered[name] = source;
			}
			spec.components.parameters = filtered;
		}
		if (spec.components.requestBodies) {
			const filtered = {};
			if (preserveOrder) {
				for (const [name, source] of Object.entries(spec.components.requestBodies)) if (requestBodies.has(addNamespace("body", name))) filtered[name] = source;
			} else for (const key of requestBodies) {
				const { name } = removeNamespace(key);
				const source = spec.components.requestBodies[name];
				if (source) filtered[name] = source;
			}
			spec.components.requestBodies = filtered;
		}
		if (spec.components.responses) {
			const filtered = {};
			if (preserveOrder) {
				for (const [name, source] of Object.entries(spec.components.responses)) if (responses.has(addNamespace("response", name))) filtered[name] = source;
			} else for (const key of responses) {
				const { name } = removeNamespace(key);
				const source = spec.components.responses[name];
				if (source) filtered[name] = source;
			}
			spec.components.responses = filtered;
		}
		if (spec.components.schemas) {
			const filtered = {};
			if (preserveOrder) {
				for (const [name, source] of Object.entries(spec.components.schemas)) if (schemas.has(addNamespace("schema", name))) filtered[name] = source;
			} else for (const key of schemas) {
				const { name } = removeNamespace(key);
				const source = spec.components.schemas[name];
				if (source) filtered[name] = source;
			}
			spec.components.schemas = filtered;
		}
	}
	if (spec.paths) for (const entry of Object.entries(spec.paths)) {
		const path = entry[0];
		const pathItem = entry[1];
		for (const method of httpMethods) {
			if (!pathItem[method]) continue;
			const key = addNamespace("operation", createOperationKey({
				method,
				path
			}));
			if (!operations.has(key)) delete pathItem[method];
		}
		if (!Object.keys(pathItem).length) delete spec.paths[path];
	}
	eventFilterSpec.timeEnd();
};
//#endregion
//#region src/openApi/3.0.x/parser/mediaType.ts
const contentToSchema$1 = ({ content }) => {
	const { mediaType, schema } = content;
	if (schema && "$ref" in schema) return { allOf: [{ ...schema }] };
	if (!schema) {
		if (isMediaTypeFileLike({ mediaType })) return {
			format: "binary",
			type: "string"
		};
		return;
	}
	if (schema.type === "string" && !schema.format && isMediaTypeFileLike({ mediaType })) return {
		...schema,
		format: "binary"
	};
	return schema;
};
const mediaTypeObjects$1 = ({ content }) => {
	const objects = [];
	for (const mediaType in content) objects.push({
		mediaType,
		schema: content[mediaType].schema,
		type: mediaTypeToIrMediaType({ mediaType })
	});
	return objects;
};
//#endregion
//#region src/openApi/3.0.x/parser/schema.ts
function getSchemaType(schema) {
	if (schema.type) return schema.type;
	if (schema.properties) return "object";
}
/**
* Finds the type of a discriminator property by looking it up in the provided schemas.
* Searches through properties and allOf chains to find the property definition.
*/
function findDiscriminatorPropertyType$1({ context, propertyName, schemas }) {
	for (const schema of schemas) {
		const resolved = "$ref" in schema ? context.resolveRef(schema.$ref) : schema;
		const property = resolved.properties?.[propertyName];
		if (property) {
			const resolvedProperty = "$ref" in property ? context.resolveRef(property.$ref) : property;
			if (resolvedProperty.type === "boolean" || resolvedProperty.type === "integer" || resolvedProperty.type === "number") return resolvedProperty.type;
		}
		if (resolved.allOf) {
			const foundType = findDiscriminatorPropertyType$1({
				context,
				propertyName,
				schemas: resolved.allOf
			});
			if (foundType !== "string") return foundType;
		}
	}
	return "string";
}
/**
* Recursively finds discriminators in a schema, including nested allOf compositions.
* This is needed when a schema extends another schema via allOf, and that parent
* schema is itself an allOf composition with discriminators in inline schemas.
*/
function findDiscriminatorsInSchema$1({ context, discriminators = [], schema }) {
	if (schema.discriminator) discriminators.push({
		discriminator: schema.discriminator,
		oneOf: schema.oneOf
	});
	if (schema.allOf) for (const compositionSchema of schema.allOf) {
		let resolvedSchema;
		if ("$ref" in compositionSchema) resolvedSchema = context.resolveRef(compositionSchema.$ref);
		else resolvedSchema = compositionSchema;
		findDiscriminatorsInSchema$1({
			context,
			discriminators,
			schema: resolvedSchema
		});
	}
	return discriminators;
}
/**
* Gets the discriminator value for a schema.
* Returns only the schema's own discriminator value, not child values.
*/
function getAllDiscriminatorValues$1({ discriminator, schemaRef }) {
	const values = [];
	for (const value in discriminator.mapping) if (discriminator.mapping[value] === schemaRef) values.push(value);
	return values;
}
function parseSchemaJsDoc$1({ irSchema, schema }) {
	if (schema.deprecated !== void 0) irSchema.deprecated = schema.deprecated;
	if (schema.example) irSchema.example = schema.example;
	if (schema.description) irSchema.description = schema.description;
	if (schema.title) irSchema.title = schema.title;
}
function parseSchemaMeta$1({ irSchema, schema }) {
	if (schema.default !== void 0) irSchema.default = schema.default;
	if (schema.exclusiveMaximum) {
		if (schema.maximum !== void 0) irSchema.exclusiveMaximum = schema.maximum;
	} else if (schema.maximum !== void 0) irSchema.maximum = schema.maximum;
	if (schema.exclusiveMinimum) {
		if (schema.minimum !== void 0) irSchema.exclusiveMinimum = schema.minimum;
	} else if (schema.minimum !== void 0) irSchema.minimum = schema.minimum;
	if (schema.format) irSchema.format = schema.format;
	if (schema.maxItems !== void 0) irSchema.maxItems = schema.maxItems;
	if (schema.maxLength !== void 0) irSchema.maxLength = schema.maxLength;
	if (schema.minItems !== void 0) irSchema.minItems = schema.minItems;
	if (schema.minLength !== void 0) irSchema.minLength = schema.minLength;
	if (schema.pattern) irSchema.pattern = schema.pattern;
	if (schema.readOnly) irSchema.accessScope = "read";
	else if (schema.writeOnly) irSchema.accessScope = "write";
}
function parseArray$1({ context, irSchema = {}, schema, state }) {
	if (schema.maxItems && schema.maxItems === schema.minItems) irSchema.type = "tuple";
	else irSchema.type = "array";
	let schemaItems = [];
	if (schema.items) {
		const irItemsSchema = schemaToIrSchema$1({
			context,
			schema: schema.items,
			state
		});
		if (!schemaItems.length && schema.maxItems && schema.maxItems === schema.minItems) schemaItems = Array(schema.maxItems).fill(irItemsSchema);
		else if ("$ref" in schema.items) schemaItems.push(irItemsSchema);
		else {
			const ofArray = schema.items.allOf || schema.items.anyOf || schema.items.oneOf;
			if (ofArray && ofArray.length > 1 && !schema.items.nullable) Object.assign(irSchema, irItemsSchema);
			else schemaItems.push(irItemsSchema);
		}
	}
	irSchema = addItemsToSchema({
		items: schemaItems,
		schema: irSchema
	});
	return irSchema;
}
function parseBoolean$1({ irSchema = {} }) {
	irSchema.type = "boolean";
	return irSchema;
}
function parseNumber$1({ irSchema = {}, schema }) {
	irSchema.type = schema.type;
	return irSchema;
}
function parseObject$1({ context, irSchema = {}, schema, state }) {
	irSchema.type = "object";
	let isSchemaPropertiesEmpty = true;
	if (schema.properties) {
		const schemaProperties = {};
		for (const name in schema.properties) {
			isSchemaPropertiesEmpty = false;
			const property = schema.properties[name];
			if (typeof property === "boolean") {} else schemaProperties[name] = schemaToIrSchema$1({
				context,
				schema: property,
				state
			});
		}
		if (!isSchemaPropertiesEmpty) irSchema.properties = schemaProperties;
	}
	if (schema.additionalProperties === void 0) {
		if (!irSchema.properties) irSchema.additionalProperties = { type: "unknown" };
	} else if (typeof schema.additionalProperties === "boolean") {
		if (!(state.inAllOf && schema.additionalProperties === false && (!schema.properties || isSchemaPropertiesEmpty))) irSchema.additionalProperties = { type: schema.additionalProperties ? "unknown" : "never" };
	} else irSchema.additionalProperties = schemaToIrSchema$1({
		context,
		schema: schema.additionalProperties,
		state
	});
	if (schema.required) irSchema.required = schema.required;
	if (schema.discriminator && state.$ref) {
		const values = getAllDiscriminatorValues$1({
			discriminator: schema.discriminator,
			schemaRef: state.$ref
		});
		if (values.length) {
			const propertyType = findDiscriminatorPropertyType$1({
				context,
				propertyName: schema.discriminator.propertyName,
				schemas: [schema]
			});
			const valueSchemas = values.map((value) => convertDiscriminatorValue(value, propertyType));
			if (!irSchema.properties) irSchema.properties = {};
			irSchema.properties[schema.discriminator.propertyName] = valueSchemas.length > 1 ? {
				items: valueSchemas,
				logicalOperator: "or"
			} : valueSchemas[0];
		}
	}
	return irSchema;
}
function parseString$1({ irSchema = {} }) {
	irSchema.type = "string";
	return irSchema;
}
function parseExtensions$1({ source, target }) {
	for (const key in source) if (key.startsWith("x-")) target[key] = source[key];
}
function initIrSchema$1({ schema }) {
	const irSchema = {};
	parseSchemaJsDoc$1({
		irSchema,
		schema
	});
	parseExtensions$1({
		source: schema,
		target: irSchema
	});
	return irSchema;
}
function parseAllOf$1({ context, schema, state }) {
	let irSchema = initIrSchema$1({ schema });
	const schemaItems = [];
	const schemaType = getSchemaType(schema);
	const compositionSchemas = schema.allOf;
	const discriminatorsToAdd = [];
	for (const compositionSchema of compositionSchemas) {
		const originalInAllOf = state.inAllOf;
		if (!("$ref" in compositionSchema)) state.inAllOf = true;
		const irCompositionSchema = schemaToIrSchema$1({
			context,
			schema: compositionSchema,
			state
		});
		state.inAllOf = originalInAllOf;
		if (schema.required) if (irCompositionSchema.required) irCompositionSchema.required.push(...schema.required);
		else irCompositionSchema.required = schema.required;
		schemaItems.push(irCompositionSchema);
		if ("$ref" in compositionSchema) {
			const ref = context.resolveRef(compositionSchema.$ref);
			if (state.$ref) {
				const discriminators = findDiscriminatorsInSchema$1({
					context,
					schema: ref
				});
				for (const { discriminator, oneOf } of discriminators) {
					const values = discriminatorValues(state.$ref, discriminator.mapping, oneOf ? () => oneOf.some((o) => "$ref" in o && o.$ref === state.$ref) : void 0);
					if (!values.length) continue;
					const isExplicitMapping = discriminator.mapping !== void 0 && Object.values(discriminator.mapping).includes(state.$ref);
					const existingIndex = discriminatorsToAdd.findIndex((d) => d.discriminator.propertyName === discriminator.propertyName);
					if (existingIndex !== -1) if (isExplicitMapping && !discriminatorsToAdd[existingIndex].isExplicitMapping) discriminatorsToAdd.splice(existingIndex, 1);
					else continue;
					const isRequired = discriminators.some((d) => d.discriminator.propertyName === discriminator.propertyName && (ref.required?.includes(d.discriminator.propertyName) || ref.allOf && ref.allOf.some((item) => {
						return ("$ref" in item ? context.resolveRef(item.$ref) : item).required?.includes(d.discriminator.propertyName);
					})));
					discriminatorsToAdd.push({
						discriminator,
						isExplicitMapping,
						isRequired,
						values
					});
				}
			}
		}
	}
	for (const { discriminator, isRequired, values } of discriminatorsToAdd) {
		const allValues = getAllDiscriminatorValues$1({
			discriminator,
			schemaRef: state.$ref
		});
		const finalValues = allValues.length ? allValues : values;
		const propertyType = findDiscriminatorPropertyType$1({
			context,
			propertyName: discriminator.propertyName,
			schemas: compositionSchemas
		});
		const valueSchemas = finalValues.map((value) => convertDiscriminatorValue(value, propertyType));
		const discriminatorProperty = valueSchemas.length > 1 ? {
			items: valueSchemas,
			logicalOperator: "or"
		} : valueSchemas[0];
		for (const item of schemaItems) if (item.$ref || item.symbolRef) {
			if ((() => {
				if (!item.$ref) return false;
				try {
					const refSchema = context.resolveRef(item.$ref);
					return refSchema.properties?.[discriminator.propertyName] !== void 0 || refSchema.allOf && refSchema.allOf.some((allOfItem) => {
						return ("$ref" in allOfItem ? context.resolveRef(allOfItem.$ref) : allOfItem).properties?.[discriminator.propertyName] !== void 0;
					});
				} catch {
					return false;
				}
			})()) {
				if (!item.omit) item.omit = [discriminator.propertyName];
				else if (!item.omit.includes(discriminator.propertyName)) item.omit = [...item.omit, discriminator.propertyName];
			}
		}
		let inlineSchema;
		for (let i = schemaItems.length - 1; i >= 0; i--) {
			const item = schemaItems[i];
			if (item.type === "object" || item.properties) {
				inlineSchema = item;
				break;
			}
		}
		if (inlineSchema) {
			if (!inlineSchema.properties) inlineSchema.properties = {};
			inlineSchema.properties[discriminator.propertyName] = discriminatorProperty;
			if (isRequired) {
				if (!inlineSchema.required) inlineSchema.required = [];
				if (!inlineSchema.required.includes(discriminator.propertyName)) inlineSchema.required.push(discriminator.propertyName);
			}
		} else {
			const irDiscriminatorSchema = {
				properties: { [discriminator.propertyName]: discriminatorProperty },
				type: "object"
			};
			if (isRequired) irDiscriminatorSchema.required = [discriminator.propertyName];
			schemaItems.push(irDiscriminatorSchema);
		}
	}
	if (schemaType === "object") {
		const irObjectSchema = parseOneType$1({
			context,
			schema: {
				...schema,
				type: "object"
			},
			state
		});
		if (irObjectSchema.properties) {
			for (const requiredProperty of irObjectSchema.required ?? []) if (!irObjectSchema.properties[requiredProperty]) for (const compositionSchema of compositionSchemas) {
				const finalCompositionSchema = "$ref" in compositionSchema ? context.resolveRef(compositionSchema.$ref) : compositionSchema;
				if (getSchemaType(finalCompositionSchema) === "object") {
					const irCompositionSchema = parseOneType$1({
						context,
						schema: {
							...finalCompositionSchema,
							type: "object"
						},
						state
					});
					if (irCompositionSchema.properties?.[requiredProperty]) {
						irObjectSchema.properties[requiredProperty] = irCompositionSchema.properties[requiredProperty];
						break;
					}
				}
			}
			schemaItems.push(irObjectSchema);
		}
	}
	irSchema = addItemsToSchema({
		items: schemaItems,
		logicalOperator: "and",
		mutateSchemaOneItem: true,
		schema: irSchema
	});
	if (schema.nullable) {
		const nestedItems = [{ type: "null" }];
		if (schemaItems.length) nestedItems.unshift(irSchema);
		irSchema = {
			items: nestedItems,
			logicalOperator: "or"
		};
		if (nestedItems[0].deprecated) irSchema.deprecated = nestedItems[0].deprecated;
		if (nestedItems[0].description) irSchema.description = nestedItems[0].description;
	}
	return irSchema;
}
function parseAnyOf$1({ context, schema, state }) {
	let irSchema = initIrSchema$1({ schema });
	const schemaItems = [];
	const schemaType = getSchemaType(schema);
	const compositionSchemas = schema.anyOf;
	const discriminatorPropertyType = schema.discriminator ? findDiscriminatorPropertyType$1({
		context,
		propertyName: schema.discriminator.propertyName,
		schemas: compositionSchemas
	}) : void 0;
	for (const compositionSchema of compositionSchemas) {
		let irCompositionSchema = schemaToIrSchema$1({
			context,
			schema: compositionSchema,
			state
		});
		if (schema.discriminator && irCompositionSchema.$ref) {
			const valueSchemas = discriminatorValues(irCompositionSchema.$ref, schema.discriminator.mapping).map((value) => convertDiscriminatorValue(value, discriminatorPropertyType));
			irCompositionSchema = {
				items: [{
					properties: { [schema.discriminator.propertyName]: valueSchemas.length > 1 ? {
						items: valueSchemas,
						logicalOperator: "or"
					} : valueSchemas[0] },
					type: "object"
				}, irCompositionSchema],
				logicalOperator: "and"
			};
		}
		schemaItems.push(irCompositionSchema);
	}
	if (schema.nullable) schemaItems.push({ type: "null" });
	irSchema = addItemsToSchema({
		items: schemaItems,
		mutateSchemaOneItem: true,
		schema: irSchema
	});
	if (schemaType === "object") {
		const irObjectSchema = parseOneType$1({
			context,
			schema: {
				...schema,
				type: "object"
			},
			state
		});
		if (irObjectSchema.properties) irSchema = {
			items: [irSchema, irObjectSchema],
			logicalOperator: "and"
		};
	}
	if (schema.discriminator && irSchema.logicalOperator === "or") irSchema.discriminator = { propertyName: schema.discriminator.propertyName };
	return irSchema;
}
function parseEnum$1({ context, schema, state }) {
	let irSchema = initIrSchema$1({ schema });
	parseSchemaMeta$1({
		irSchema,
		schema
	});
	irSchema.type = "enum";
	const schemaItems = [];
	const xEnumDescriptions = schema["x-enum-descriptions"];
	const xEnumVarnames = schema["x-enum-varnames"];
	const xEnumNames = schema["x-enumNames"];
	for (let index = 0, len = schema.enum.length; index < len; index++) {
		const enumValue = schema.enum[index];
		const typeOfEnumValue = typeof enumValue;
		let enumType;
		if (typeOfEnumValue === "string" || typeOfEnumValue === "number" || typeOfEnumValue === "boolean") enumType = typeOfEnumValue;
		else if (typeOfEnumValue === "object" && Array.isArray(enumValue)) enumType = "array";
		else if (enumValue === null) {
			if (schema.nullable) enumType = "null";
		} else console.warn("🚨", `unhandled "${typeOfEnumValue}" typeof value "${enumValue}" for enum`, schema.enum);
		if (!enumType) continue;
		const irTypeSchema = parseOneType$1({
			context,
			schema: {
				description: xEnumDescriptions?.[index],
				title: xEnumVarnames?.[index] ?? xEnumNames?.[index],
				type: enumType === "null" ? "string" : enumType
			},
			state
		});
		irTypeSchema.const = enumValue;
		if (enumType === "null") irTypeSchema.type = enumType;
		if (irTypeSchema.type === "array") irTypeSchema.type = "tuple";
		schemaItems.push(irTypeSchema);
	}
	irSchema = addItemsToSchema({
		items: schemaItems,
		schema: irSchema
	});
	return irSchema;
}
function parseOneOf$1({ context, schema, state }) {
	let irSchema = initIrSchema$1({ schema });
	let schemaItems = [];
	const schemaType = getSchemaType(schema);
	const compositionSchemas = schema.oneOf;
	const discriminatorPropertyType = schema.discriminator ? findDiscriminatorPropertyType$1({
		context,
		propertyName: schema.discriminator.propertyName,
		schemas: compositionSchemas
	}) : void 0;
	for (const compositionSchema of compositionSchemas) {
		let irCompositionSchema = schemaToIrSchema$1({
			context,
			schema: compositionSchema,
			state
		});
		if (schema.discriminator && irCompositionSchema.$ref) {
			const valueSchemas = discriminatorValues(irCompositionSchema.$ref, schema.discriminator.mapping).map((value) => convertDiscriminatorValue(value, discriminatorPropertyType));
			irCompositionSchema = {
				items: [{
					properties: { [schema.discriminator.propertyName]: valueSchemas.length > 1 ? {
						items: valueSchemas,
						logicalOperator: "or"
					} : valueSchemas[0] },
					required: [schema.discriminator.propertyName],
					type: "object"
				}, irCompositionSchema],
				logicalOperator: "and"
			};
		}
		if (irCompositionSchema.logicalOperator === "or" && irCompositionSchema.type !== "array" && irCompositionSchema.items) schemaItems = schemaItems.concat(irCompositionSchema.items);
		else schemaItems.push(irCompositionSchema);
	}
	if (schema.nullable) schemaItems.push({ type: "null" });
	irSchema = addItemsToSchema({
		items: schemaItems,
		mutateSchemaOneItem: true,
		schema: irSchema
	});
	if (schemaType === "object") {
		const irObjectSchema = parseOneType$1({
			context,
			schema: {
				...schema,
				type: "object"
			},
			state
		});
		if (irObjectSchema.properties) irSchema = {
			items: [irSchema, irObjectSchema],
			logicalOperator: "and"
		};
	}
	if (schema.discriminator && irSchema.logicalOperator === "or") irSchema.discriminator = { propertyName: schema.discriminator.propertyName };
	return irSchema;
}
function parseRef$1({ context, schema, state }) {
	if (!isTopLevelComponent(schema.$ref)) {
		if (!state.circularReferenceTracker.has(schema.$ref)) {
			const refSchema = context.resolveRef(schema.$ref);
			const originalRef = state.$ref;
			state.$ref = schema.$ref;
			const irSchema = schemaToIrSchema$1({
				context,
				schema: refSchema,
				state
			});
			state.$ref = originalRef;
			return irSchema;
		}
	}
	const irSchema = {};
	irSchema.$ref = schema.$ref;
	if (!state.circularReferenceTracker.has(schema.$ref)) {
		const refSchema = context.resolveRef(schema.$ref);
		const originalRef = state.$ref;
		state.$ref = schema.$ref;
		schemaToIrSchema$1({
			context,
			schema: refSchema,
			state
		});
		state.$ref = originalRef;
	}
	return irSchema;
}
function parseNullableType({ context, irSchema, schema, state }) {
	if (!irSchema) irSchema = initIrSchema$1({ schema });
	const typeIrSchema = {};
	parseSchemaMeta$1({
		irSchema: typeIrSchema,
		schema
	});
	if (typeIrSchema.default === null) delete typeIrSchema.default;
	irSchema = addItemsToSchema({
		items: [parseOneType$1({
			context,
			irSchema: typeIrSchema,
			schema,
			state
		}), { type: "null" }],
		schema: irSchema
	});
	return irSchema;
}
function parseType$1({ context, schema, state }) {
	const irSchema = initIrSchema$1({ schema });
	parseSchemaMeta$1({
		irSchema,
		schema
	});
	const type = getSchemaType(schema);
	if (!type) return irSchema;
	if (!schema.nullable) return parseOneType$1({
		context,
		irSchema,
		schema: {
			...schema,
			type
		},
		state
	});
	return parseNullableType({
		context,
		irSchema,
		schema: {
			...schema,
			type
		},
		state
	});
}
function parseOneType$1({ context, irSchema, schema, state }) {
	if (!irSchema) {
		irSchema = initIrSchema$1({ schema });
		parseSchemaMeta$1({
			irSchema,
			schema
		});
	}
	switch (schema.type) {
		case "array": return parseArray$1({
			context,
			irSchema,
			schema,
			state
		});
		case "boolean": return parseBoolean$1({
			context,
			irSchema,
			schema,
			state
		});
		case "integer":
		case "number": return parseNumber$1({
			context,
			irSchema,
			schema,
			state
		});
		case "object": return parseObject$1({
			context,
			irSchema,
			schema,
			state
		});
		case "string": return parseString$1({
			context,
			irSchema,
			schema,
			state
		});
		default: return parseUnknown$1({
			context,
			irSchema,
			schema
		});
	}
}
function parseUnknown$1({ irSchema, schema }) {
	if (!irSchema) irSchema = initIrSchema$1({ schema });
	irSchema.type = "unknown";
	parseSchemaMeta$1({
		irSchema,
		schema
	});
	return irSchema;
}
function schemaToIrSchema$1({ context, schema, state }) {
	if (!state) state = { circularReferenceTracker: /* @__PURE__ */ new Set() };
	if (state.$ref) state.circularReferenceTracker.add(state.$ref);
	if ("$ref" in schema) return parseRef$1({
		context,
		schema,
		state
	});
	if (schema.enum) return parseEnum$1({
		context,
		schema,
		state
	});
	if (schema.allOf) return parseAllOf$1({
		context,
		schema,
		state
	});
	if (schema.anyOf) return parseAnyOf$1({
		context,
		schema,
		state
	});
	if (schema.oneOf) return parseOneOf$1({
		context,
		schema,
		state
	});
	if (schema.type || schema.properties) return parseType$1({
		context,
		schema,
		state
	});
	return parseUnknown$1({
		context,
		schema
	});
}
function parseSchema$1({ $ref, context, schema }) {
	if (!context.ir.components) context.ir.components = {};
	if (!context.ir.components.schemas) context.ir.components.schemas = {};
	context.ir.components.schemas[refToName($ref)] = schemaToIrSchema$1({
		context,
		schema,
		state: {
			$ref,
			circularReferenceTracker: /* @__PURE__ */ new Set()
		}
	});
}
//#endregion
//#region src/openApi/3.0.x/parser/pagination.ts
const isPaginationType$1 = (schemaType) => schemaType === "boolean" || schemaType === "integer" || schemaType === "number" || schemaType === "string";
const paginationField$1 = ({ context, name, schema }) => {
	if (getPaginationKeywordsRegExp(context.config.parser.pagination).test(name)) return true;
	if ("$ref" in schema) {
		const ref = context.resolveRef(schema.$ref);
		if ("content" in ref || "in" in ref) {
			let refSchema;
			if ("in" in ref) refSchema = ref.schema;
			if (!refSchema) {
				const contents = mediaTypeObjects$1({ content: ref.content });
				const content = contents.find((content) => content.type === "json") || contents[0];
				if (content?.schema) refSchema = content.schema;
			}
			if (!refSchema) return false;
			return paginationField$1({
				context,
				name,
				schema: refSchema
			});
		}
		return paginationField$1({
			context,
			name,
			schema: ref
		});
	}
	for (const name in schema.properties) if (getPaginationKeywordsRegExp(context.config.parser.pagination).test(name)) {
		const property = schema.properties[name];
		if (typeof property !== "boolean" && !("$ref" in property)) {
			if (isPaginationType$1(getSchemaType(property))) return name;
		}
	}
	for (const allOf of schema.allOf ?? []) {
		const pagination = paginationField$1({
			context,
			name,
			schema: allOf
		});
		if (pagination) return pagination;
	}
	return false;
};
//#endregion
//#region src/openApi/3.0.x/parser/operation.ts
function parseOperationJsDoc$1({ irOperation, operation }) {
	if (operation.deprecated !== void 0) irOperation.deprecated = operation.deprecated;
	if (operation.description) irOperation.description = operation.description;
	if (operation.summary) irOperation.summary = operation.summary;
	if (operation.tags?.length) irOperation.tags = operation.tags;
}
function initIrOperation$1({ context, method, operation, path, state }) {
	const irOperation = {
		id: operationToId({
			context,
			id: operation.operationId,
			method,
			path,
			state
		}),
		method,
		path
	};
	if (operation.operationId) irOperation.operationId = operation.operationId;
	parseOperationJsDoc$1({
		irOperation,
		operation
	});
	parseExtensions$1({
		source: operation,
		target: irOperation
	});
	return irOperation;
}
function operationToIrOperation$1({ ambiguousSecurityKeys, context, method, operation, path, securitySchemesMap, state }) {
	const irOperation = initIrOperation$1({
		context,
		method,
		operation,
		path,
		state
	});
	if (operation.parameters) irOperation.parameters = operation.parameters;
	if (operation.requestBody) {
		const requestBody = "$ref" in operation.requestBody ? context.resolveRef(operation.requestBody.$ref) : operation.requestBody;
		const contents = mediaTypeObjects$1({ content: requestBody.content });
		const content = contents.find((content) => content.type === "json") || contents[0];
		if (content) {
			const pagination = paginationField$1({
				context,
				name: "",
				schema: content.schema && "$ref" in content.schema ? {
					allOf: [{ ...content.schema }],
					description: requestBody.description
				} : {
					description: requestBody.description,
					...content.schema
				}
			});
			irOperation.body = {
				mediaType: content.mediaType,
				schema: schemaToIrSchema$1({
					context,
					schema: "$ref" in operation.requestBody ? {
						allOf: [{ ...operation.requestBody }],
						description: requestBody.description
					} : content.schema && "$ref" in content.schema ? {
						allOf: [{ ...content.schema }],
						description: requestBody.description
					} : {
						description: requestBody.description,
						...content.schema
					},
					state: void 0
				})
			};
			if (pagination) irOperation.body.pagination = pagination;
			if (requestBody.required) irOperation.body.required = requestBody.required;
			if (content.type) irOperation.body.type = content.type;
		}
	}
	for (const name in operation.responses) {
		if (name.startsWith("x-")) continue;
		if (!irOperation.responses) irOperation.responses = {};
		const response = operation.responses[name];
		const responseObject = "$ref" in response ? context.resolveRef(response.$ref) : response;
		const contents = mediaTypeObjects$1({ content: responseObject.content });
		const content = contents.find((content) => content.type === "json") || contents[0];
		if (content) irOperation.responses[name] = {
			mediaType: content.mediaType,
			schema: schemaToIrSchema$1({
				context,
				schema: {
					description: responseObject.description,
					...contentToSchema$1({ content })
				},
				state: void 0
			})
		};
		else irOperation.responses[name] = { schema: {
			description: responseObject.description,
			type: name === "204" ? "void" : "unknown"
		} };
	}
	if (operation.security) {
		const securitySchemeObjects = /* @__PURE__ */ new Map();
		for (const securityRequirementObject of operation.security) for (const name in securityRequirementObject) {
			const securitySchemeObject = securitySchemesMap.get(name);
			if (!securitySchemeObject) continue;
			if (ambiguousSecurityKeys.has(name)) securitySchemeObject.key = name;
			securitySchemeObjects.set(name, securitySchemeObject);
		}
		if (securitySchemeObjects.size) irOperation.security = Array.from(securitySchemeObjects.values());
	}
	return irOperation;
}
function parsePathOperation$1({ ambiguousSecurityKeys, context, method, operation, path, securitySchemesMap, state }) {
	if (!context.ir.paths) context.ir.paths = {};
	if (!context.ir.paths[path]) context.ir.paths[path] = {};
	if (operation.servers) context.ir.servers = [...context.ir.servers ?? [], ...operation.servers];
	context.ir.paths[path][method] = operationToIrOperation$1({
		ambiguousSecurityKeys,
		context,
		method,
		operation,
		path,
		securitySchemesMap,
		state
	});
}
//#endregion
//#region src/openApi/3.0.x/parser/parameter.ts
/**
* Returns default parameter `allowReserved` based on value of `in`.
*/
const defaultAllowReserved$1 = (_in) => {
	switch (_in) {
		case "query": return false;
		default: return;
	}
};
/**
* Returns default parameter `explode` based on value of `style`.
*/
const defaultExplode$1 = (style) => {
	switch (style) {
		case "deepObject":
		case "form": return true;
		default: return false;
	}
};
/**
* Returns default parameter `style` based on value of `in`.
*/
const defaultStyle$1 = (_in) => {
	switch (_in) {
		case "header":
		case "path": return "simple";
		case "cookie":
		case "query": return "form";
	}
};
const parametersArrayToObject$1 = ({ context, parameters }) => {
	if (!parameters || !Object.keys(parameters).length) return;
	const parametersObject = {};
	for (const parameterOrReference of parameters) {
		const parameter = "$ref" in parameterOrReference ? context.dereference(parameterOrReference) : parameterOrReference;
		if (!parametersObject[parameter.in]) parametersObject[parameter.in] = {};
		parametersObject[parameter.in][parameter.name.toLocaleLowerCase()] = parameterToIrParameter$1({
			$ref: `#/todo/real/path/to/parameter/${parameter.name}`,
			context,
			parameter
		});
	}
	return parametersObject;
};
const parameterToIrParameter$1 = ({ $ref, context, parameter }) => {
	let schema = parameter.schema;
	if (!schema) {
		const contents = mediaTypeObjects$1({ content: parameter.content });
		const content = contents.find((content) => content.type === "json") || contents[0];
		if (content) schema = content.schema;
	}
	const finalSchema = schema && "$ref" in schema ? {
		allOf: [{ ...schema }],
		deprecated: parameter.deprecated,
		description: parameter.description
	} : {
		deprecated: parameter.deprecated,
		description: parameter.description,
		...schema
	};
	const pagination = paginationField$1({
		context,
		name: parameter.name,
		schema: finalSchema
	});
	const style = parameter.style || defaultStyle$1(parameter.in);
	const explode = parameter.explode !== void 0 ? parameter.explode : defaultExplode$1(style);
	const irParameter = {
		allowReserved: parameter.allowReserved !== void 0 ? parameter.allowReserved : defaultAllowReserved$1(parameter.in),
		explode,
		location: parameter.in,
		name: parameter.name,
		schema: schemaToIrSchema$1({
			context,
			schema: finalSchema,
			state: {
				$ref,
				circularReferenceTracker: /* @__PURE__ */ new Set()
			}
		}),
		style
	};
	if (parameter.deprecated) irParameter.deprecated = parameter.deprecated;
	if (parameter.description) irParameter.description = parameter.description;
	if (pagination) irParameter.pagination = pagination;
	if (parameter.required) irParameter.required = parameter.required;
	parseExtensions$1({
		source: parameter,
		target: irParameter
	});
	return irParameter;
};
const parseParameter$1 = ({ $ref, context, parameter }) => {
	if (!context.ir.components) context.ir.components = {};
	if (!context.ir.components.parameters) context.ir.components.parameters = {};
	context.ir.components.parameters[refToName($ref)] = parameterToIrParameter$1({
		$ref,
		context,
		parameter
	});
};
//#endregion
//#region src/openApi/3.0.x/parser/requestBody.ts
const requestBodyToIrRequestBody$1 = ({ $ref, context, requestBody }) => {
	const contents = mediaTypeObjects$1({ content: requestBody.content });
	const content = contents.find((content) => content.type === "json") || contents[0];
	const schema = content ? content.schema : void 0;
	const irRequestBody = { schema: schemaToIrSchema$1({
		context,
		schema: {
			description: requestBody.description,
			...schema
		},
		state: {
			$ref,
			circularReferenceTracker: /* @__PURE__ */ new Set()
		}
	}) };
	if (requestBody.description) irRequestBody.description = requestBody.description;
	if (requestBody.required) irRequestBody.required = requestBody.required;
	return irRequestBody;
};
const parseRequestBody$1 = ({ $ref, context, requestBody }) => {
	if (!context.ir.components) context.ir.components = {};
	if (!context.ir.components.requestBodies) context.ir.components.requestBodies = {};
	context.ir.components.requestBodies[refToName($ref)] = requestBodyToIrRequestBody$1({
		$ref,
		context,
		requestBody
	});
};
//#endregion
//#region src/openApi/3.0.x/parser/server.ts
function parseServers$1({ context }) {
	if (context.spec.servers) {
		context.ir.servers = context.spec.servers;
		return;
	}
	for (const input of context.config.input) if (typeof input.path === "string") {
		const url = parseUrl(input.path);
		context.ir.servers = [{ url: `${url.protocol ? `${url.protocol}://` : ""}${url.host}${url.port ? `:${url.port}` : ""}` }];
	}
	if (!context.ir.servers) context.ir.servers = [{ url: "/" }];
}
//#endregion
//#region src/openApi/3.0.x/parser/validate.ts
const validateOpenApiSpec$1 = (spec, logger) => {
	const eventValidate = logger.timeEvent("validate");
	const issues = [];
	const operationIds = /* @__PURE__ */ new Map();
	if (spec.paths) for (const entry of Object.entries(spec.paths)) {
		const path = entry[0];
		const pathItem = entry[1];
		for (const method of httpMethods) {
			const operation = pathItem[method];
			if (!operation) continue;
			const operationKey = createOperationKey({
				method,
				path
			});
			if (operation.operationId) if (!operationIds.has(operation.operationId)) operationIds.set(operation.operationId, operationKey);
			else issues.push({
				code: "duplicate_key",
				context: {
					key: "operationId",
					value: operation.operationId
				},
				message: "Duplicate `operationId` found. Each `operationId` must be unique.",
				path: [
					"paths",
					path,
					method,
					"operationId"
				],
				severity: "error"
			});
		}
	}
	if (spec.servers) {
		if (typeof spec.servers !== "object" || !Array.isArray(spec.servers)) issues.push({
			code: "invalid_type",
			message: "`servers` must be an array.",
			path: [],
			severity: "error"
		});
		for (let index = 0; index < spec.servers.length; index++) {
			const server = spec.servers[index];
			if (!server || typeof server !== "object") issues.push({
				code: "invalid_type",
				context: {
					actual: typeof server,
					expected: "object"
				},
				message: "Each entry in `servers` must be an object.",
				path: ["servers", index],
				severity: "error"
			});
			else if (!server.url) issues.push({
				code: "missing_required_field",
				context: { field: "url" },
				message: "Missing required field `url` in server object.",
				path: ["servers", index],
				severity: "error"
			});
		}
	}
	eventValidate.timeEnd();
	return {
		issues,
		valid: !issues.some((issue) => issue.severity === "error")
	};
};
//#endregion
//#region src/openApi/3.0.x/parser/index.ts
const parseV3_0_X = (context) => {
	if (context.config.parser.validate_EXPERIMENTAL) handleValidatorResult({
		context,
		result: validateOpenApiSpec$1(context.spec, context.logger)
	});
	if (hasFilters(context.config.parser.filters)) {
		const filters = createFilters(context.config.parser.filters, context.spec, context.logger);
		const { graph } = buildGraph(context.spec, context.logger);
		const { resourceMetadata } = buildResourceMetadata(graph, context.logger);
		filterSpec$1({
			...createFilteredDependencies({
				filters,
				logger: context.logger,
				resourceMetadata
			}),
			logger: context.logger,
			preserveOrder: filters.preserveOrder,
			spec: context.spec
		});
	}
	transformOpenApiSpec({ context });
	const state = { ids: /* @__PURE__ */ new Map() };
	const securitySchemesMap = /* @__PURE__ */ new Map();
	if (context.spec.components) {
		for (const name in context.spec.components.securitySchemes) {
			const securityOrReference = context.spec.components.securitySchemes[name];
			const securitySchemeObject = "$ref" in securityOrReference ? context.resolveRef(securityOrReference.$ref) : securityOrReference;
			securitySchemesMap.set(name, securitySchemeObject);
		}
		for (const name in context.spec.components.parameters) {
			const $ref = pathToJsonPointer([
				"components",
				"parameters",
				name
			]);
			const parameterOrReference = context.spec.components.parameters[name];
			parseParameter$1({
				$ref,
				context,
				parameter: "$ref" in parameterOrReference ? context.resolveRef(parameterOrReference.$ref) : parameterOrReference
			});
		}
		for (const name in context.spec.components.requestBodies) {
			const $ref = pathToJsonPointer([
				"components",
				"requestBodies",
				name
			]);
			const requestBodyOrReference = context.spec.components.requestBodies[name];
			parseRequestBody$1({
				$ref,
				context,
				requestBody: "$ref" in requestBodyOrReference ? context.resolveRef(requestBodyOrReference.$ref) : requestBodyOrReference
			});
		}
		for (const name in context.spec.components.schemas) {
			const $ref = pathToJsonPointer([
				"components",
				"schemas",
				name
			]);
			const schema = context.spec.components.schemas[name];
			parseSchema$1({
				$ref,
				context,
				schema
			});
		}
	}
	const ambiguousSecurityKeys = computeAmbiguousSecurityKeys(securitySchemesMap);
	parseServers$1({ context });
	for (const path in context.spec.paths) {
		if (path.startsWith("x-")) continue;
		const pathItem = context.spec.paths[path];
		const finalPathItem = pathItem.$ref ? {
			...context.resolveRef(pathItem.$ref),
			...pathItem
		} : pathItem;
		const operationArgs = {
			ambiguousSecurityKeys,
			context,
			operation: {
				description: finalPathItem.description,
				parameters: parametersArrayToObject$1({
					context,
					parameters: finalPathItem.parameters
				}),
				security: context.spec.security,
				servers: finalPathItem.servers,
				summary: finalPathItem.summary
			},
			path,
			securitySchemesMap,
			state
		};
		if (finalPathItem.delete) parsePathOperation$1({
			...operationArgs,
			method: "delete",
			operation: {
				...operationArgs.operation,
				...finalPathItem.delete,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject$1({
						context,
						parameters: finalPathItem.delete.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalPathItem.get) parsePathOperation$1({
			...operationArgs,
			method: "get",
			operation: {
				...operationArgs.operation,
				...finalPathItem.get,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject$1({
						context,
						parameters: finalPathItem.get.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalPathItem.head) parsePathOperation$1({
			...operationArgs,
			method: "head",
			operation: {
				...operationArgs.operation,
				...finalPathItem.head,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject$1({
						context,
						parameters: finalPathItem.head.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalPathItem.options) parsePathOperation$1({
			...operationArgs,
			method: "options",
			operation: {
				...operationArgs.operation,
				...finalPathItem.options,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject$1({
						context,
						parameters: finalPathItem.options.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalPathItem.patch) parsePathOperation$1({
			...operationArgs,
			method: "patch",
			operation: {
				...operationArgs.operation,
				...finalPathItem.patch,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject$1({
						context,
						parameters: finalPathItem.patch.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalPathItem.post) parsePathOperation$1({
			...operationArgs,
			method: "post",
			operation: {
				...operationArgs.operation,
				...finalPathItem.post,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject$1({
						context,
						parameters: finalPathItem.post.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalPathItem.put) parsePathOperation$1({
			...operationArgs,
			method: "put",
			operation: {
				...operationArgs.operation,
				...finalPathItem.put,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject$1({
						context,
						parameters: finalPathItem.put.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalPathItem.trace) parsePathOperation$1({
			...operationArgs,
			method: "trace",
			operation: {
				...operationArgs.operation,
				...finalPathItem.trace,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject$1({
						context,
						parameters: finalPathItem.trace.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
	}
};
//#endregion
//#region src/openApi/3.1.x/parser/filter.ts
/**
* Replace source spec with filtered version.
*/
const filterSpec = ({ logger, operations, parameters, preserveOrder, requestBodies, responses, schemas, spec }) => {
	const eventFilterSpec = logger.timeEvent("filter-spec");
	if (spec.components) {
		if (spec.components.parameters) {
			const filtered = {};
			if (preserveOrder) {
				for (const [name, source] of Object.entries(spec.components.parameters)) if (parameters.has(addNamespace("parameter", name))) filtered[name] = source;
			} else for (const key of parameters) {
				const { name } = removeNamespace(key);
				const source = spec.components.parameters[name];
				if (source) filtered[name] = source;
			}
			spec.components.parameters = filtered;
		}
		if (spec.components.requestBodies) {
			const filtered = {};
			if (preserveOrder) {
				for (const [name, source] of Object.entries(spec.components.requestBodies)) if (requestBodies.has(addNamespace("body", name))) filtered[name] = source;
			} else for (const key of requestBodies) {
				const { name } = removeNamespace(key);
				const source = spec.components.requestBodies[name];
				if (source) filtered[name] = source;
			}
			spec.components.requestBodies = filtered;
		}
		if (spec.components.responses) {
			const filtered = {};
			if (preserveOrder) {
				for (const [name, source] of Object.entries(spec.components.responses)) if (responses.has(addNamespace("response", name))) filtered[name] = source;
			} else for (const key of responses) {
				const { name } = removeNamespace(key);
				const source = spec.components.responses[name];
				if (source) filtered[name] = source;
			}
			spec.components.responses = filtered;
		}
		if (spec.components.schemas) {
			const filtered = {};
			if (preserveOrder) {
				for (const [name, source] of Object.entries(spec.components.schemas)) if (schemas.has(addNamespace("schema", name))) filtered[name] = source;
			} else for (const key of schemas) {
				const { name } = removeNamespace(key);
				const source = spec.components.schemas[name];
				if (source) filtered[name] = source;
			}
			spec.components.schemas = filtered;
		}
	}
	if (spec.paths) for (const entry of Object.entries(spec.paths)) {
		const path = entry[0];
		const pathItem = entry[1];
		for (const method of httpMethods) {
			if (!pathItem[method]) continue;
			const key = addNamespace("operation", createOperationKey({
				method,
				path
			}));
			if (!operations.has(key)) delete pathItem[method];
		}
		if (!Object.keys(pathItem).length) delete spec.paths[path];
	}
	eventFilterSpec.timeEnd();
};
//#endregion
//#region src/openApi/3.1.x/parser/mediaType.ts
const contentToSchema = ({ content }) => {
	const { mediaType, schema } = content;
	if (!schema) {
		if (isMediaTypeFileLike({ mediaType })) return {
			format: "binary",
			type: "string"
		};
		return;
	}
	if (schema.type === "string" && !schema.format && isMediaTypeFileLike({ mediaType })) return {
		...schema,
		format: "binary"
	};
	return schema;
};
const mediaTypeObjects = ({ content }) => {
	const objects = [];
	for (const mediaType in content) objects.push({
		mediaType,
		schema: content[mediaType].schema,
		type: mediaTypeToIrMediaType({ mediaType })
	});
	return objects;
};
//#endregion
//#region src/openApi/3.1.x/parser/schema.ts
function getSchemaTypes(schema) {
	if (typeof schema.type === "string") return [schema.type];
	if (schema.type) return schema.type;
	if (schema.properties) return ["object"];
	return [];
}
/**
* Finds the type of a discriminator property by looking it up in the provided schemas.
* Searches through properties and allOf chains to find the property definition.
*/
function findDiscriminatorPropertyType({ context, propertyName, schemas }) {
	for (const schema of schemas) {
		const resolved = schema.$ref ? context.resolveRef(schema.$ref) : schema;
		const property = resolved.properties?.[propertyName];
		if (property === true) continue;
		if (property) {
			const resolvedProperty = property.$ref ? context.resolveRef(property.$ref) : property;
			const propertyTypes = Array.isArray(resolvedProperty.type) ? resolvedProperty.type : resolvedProperty.type ? [resolvedProperty.type] : [];
			for (const propType of propertyTypes) if (propType === "boolean" || propType === "integer" || propType === "number") return propType;
		}
		if (resolved.allOf) {
			const foundType = findDiscriminatorPropertyType({
				context,
				propertyName,
				schemas: resolved.allOf
			});
			if (foundType !== "string") return foundType;
		}
	}
	return "string";
}
/**
* Recursively finds discriminators in a schema, including nested allOf compositions.
* This is needed when a schema extends another schema via allOf, and that parent
* schema is itself an allOf composition with discriminators in inline schemas.
*/
function findDiscriminatorsInSchema({ context, discriminators = [], schema }) {
	if (schema.discriminator) discriminators.push({
		discriminator: schema.discriminator,
		oneOf: schema.oneOf
	});
	if (schema.allOf) for (const compositionSchema of schema.allOf) {
		let resolvedSchema;
		if (compositionSchema.$ref) resolvedSchema = context.resolveRef(compositionSchema.$ref);
		else resolvedSchema = compositionSchema;
		findDiscriminatorsInSchema({
			context,
			discriminators,
			schema: resolvedSchema
		});
	}
	return discriminators;
}
/**
* Gets the discriminator value for a schema.
* Returns only the schema's own discriminator value, not child values.
*/
function getAllDiscriminatorValues({ discriminator, schemaRef }) {
	const values = [];
	for (const value in discriminator.mapping) if (discriminator.mapping[value] === schemaRef) values.push(value);
	return values;
}
function parseSchemaJsDoc({ irSchema, schema }) {
	if (schema.deprecated !== void 0) irSchema.deprecated = schema.deprecated;
	if (schema.example) irSchema.example = schema.example;
	if (schema.description) irSchema.description = schema.description;
	if (schema.title) irSchema.title = schema.title;
}
function parseSchemaMeta({ irSchema, schema }) {
	if (schema.const !== void 0) {
		irSchema.const = schema.const;
		if (!schema.type) if (schema.const === null) irSchema.type = "null";
		else switch (typeof schema.const) {
			case "bigint":
			case "number":
				irSchema.type = "number";
				break;
			case "boolean":
				irSchema.type = "boolean";
				break;
			case "string":
				irSchema.type = "string";
				break;
		}
	}
	if (schema.default !== void 0) irSchema.default = schema.default;
	if (schema.exclusiveMaximum !== void 0) irSchema.exclusiveMaximum = schema.exclusiveMaximum;
	if (schema.exclusiveMinimum !== void 0) irSchema.exclusiveMinimum = schema.exclusiveMinimum;
	if (schema.format) irSchema.format = schema.format;
	else if (schema.contentMediaType && isMediaTypeFileLike({ mediaType: schema.contentMediaType })) irSchema.format = "binary";
	if (schema.maximum !== void 0) irSchema.maximum = schema.maximum;
	if (schema.maxItems !== void 0) irSchema.maxItems = schema.maxItems;
	if (schema.maxLength !== void 0) irSchema.maxLength = schema.maxLength;
	if (schema.minimum !== void 0) irSchema.minimum = schema.minimum;
	if (schema.minItems !== void 0) irSchema.minItems = schema.minItems;
	if (schema.minLength !== void 0) irSchema.minLength = schema.minLength;
	if (schema.pattern) irSchema.pattern = schema.pattern;
	if (schema.readOnly) irSchema.accessScope = "read";
	else if (schema.writeOnly) irSchema.accessScope = "write";
}
function parseArray({ context, irSchema = {}, schema, state }) {
	if (schema.prefixItems && schema.prefixItems.length || schema.maxItems && schema.maxItems === schema.minItems || schema.const !== void 0) irSchema.type = "tuple";
	else irSchema.type = "array";
	let schemaItems = [];
	for (const item of schema.prefixItems ?? []) {
		const irItemSchema = schemaToIrSchema({
			context,
			schema: item,
			state
		});
		schemaItems.push(irItemSchema);
	}
	if (schema.items) {
		const irItemsSchema = schemaToIrSchema({
			context,
			schema: schema.items,
			state
		});
		if (!schemaItems.length && schema.maxItems && schema.maxItems === schema.minItems) schemaItems = Array(schema.maxItems).fill(irItemsSchema);
		else {
			const ofArray = schema.items.allOf || schema.items.anyOf || schema.items.oneOf;
			if (ofArray && ofArray.length > 1 && !getSchemaTypes(schema.items).includes("null")) Object.assign(irSchema, irItemsSchema);
			else schemaItems.push(irItemsSchema);
		}
	}
	irSchema = addItemsToSchema({
		items: schemaItems,
		schema: irSchema
	});
	return irSchema;
}
function parseBoolean({ irSchema = {} }) {
	irSchema.type = "boolean";
	return irSchema;
}
function parseNull({ irSchema = {} }) {
	irSchema.type = "null";
	return irSchema;
}
function parseNumber({ irSchema = {}, schema }) {
	irSchema.type = schema.type;
	return irSchema;
}
function parseObject({ context, irSchema = {}, schema, state }) {
	irSchema.type = "object";
	let isSchemaPropertiesEmpty = true;
	if (schema.properties) {
		const schemaProperties = {};
		for (const name in schema.properties) {
			isSchemaPropertiesEmpty = false;
			const property = schema.properties[name];
			if (typeof property === "boolean") {} else schemaProperties[name] = schemaToIrSchema({
				context,
				schema: property,
				state
			});
		}
		if (!isSchemaPropertiesEmpty) irSchema.properties = schemaProperties;
	}
	let isPatternPropertiesEmpty = true;
	if (schema.patternProperties) {
		const patternProperties = {};
		for (const pattern in schema.patternProperties) {
			const patternSchema = schema.patternProperties[pattern];
			patternProperties[pattern] = schemaToIrSchema({
				context,
				schema: patternSchema,
				state
			});
			isPatternPropertiesEmpty = false;
		}
		if (!isPatternPropertiesEmpty) irSchema.patternProperties = patternProperties;
	}
	if (schema.additionalProperties === void 0) {
		if (!irSchema.properties) irSchema.additionalProperties = { type: "unknown" };
	} else if (typeof schema.additionalProperties === "boolean") {
		if (!(state.inAllOf && schema.additionalProperties === false && (!schema.properties || isSchemaPropertiesEmpty) && (!schema.patternProperties || isPatternPropertiesEmpty))) irSchema.additionalProperties = { type: schema.additionalProperties ? "unknown" : "never" };
	} else irSchema.additionalProperties = schemaToIrSchema({
		context,
		schema: schema.additionalProperties,
		state
	});
	if (schema.propertyNames) irSchema.propertyNames = schemaToIrSchema({
		context,
		schema: schema.propertyNames,
		state
	});
	if (schema.required) irSchema.required = schema.required;
	if (schema.discriminator && state.$ref) {
		const values = getAllDiscriminatorValues({
			discriminator: schema.discriminator,
			schemaRef: state.$ref
		});
		if (values.length) {
			const propertyType = findDiscriminatorPropertyType({
				context,
				propertyName: schema.discriminator.propertyName,
				schemas: [schema]
			});
			const valueSchemas = values.map((value) => convertDiscriminatorValue(value, propertyType));
			if (!irSchema.properties) irSchema.properties = {};
			irSchema.properties[schema.discriminator.propertyName] = valueSchemas.length > 1 ? {
				items: valueSchemas,
				logicalOperator: "or"
			} : valueSchemas[0];
		}
	}
	return irSchema;
}
function parseString({ irSchema = {} }) {
	irSchema.type = "string";
	return irSchema;
}
function parseExtensions({ source, target }) {
	for (const key in source) if (key.startsWith("x-")) target[key] = source[key];
}
function initIrSchema({ schema }) {
	const irSchema = {};
	parseSchemaJsDoc({
		irSchema,
		schema
	});
	parseExtensions({
		source: schema,
		target: irSchema
	});
	return irSchema;
}
function parseAllOf({ context, schema, state }) {
	let irSchema = initIrSchema({ schema });
	parseSchemaMeta({
		irSchema,
		schema
	});
	const schemaItems = [];
	const schemaTypes = getSchemaTypes(schema);
	const compositionSchemas = schema.allOf;
	const discriminatorsToAdd = [];
	for (const compositionSchema of compositionSchemas) {
		const originalInAllOf = state.inAllOf;
		if (!("$ref" in compositionSchema)) state.inAllOf = true;
		const irCompositionSchema = schemaToIrSchema({
			context,
			schema: compositionSchema,
			state
		});
		state.inAllOf = originalInAllOf;
		if (schema.required) if (irCompositionSchema.required) irCompositionSchema.required.push(...schema.required);
		else irCompositionSchema.required = schema.required;
		schemaItems.push(irCompositionSchema);
		if (compositionSchema.$ref) {
			const ref = context.resolveRef(compositionSchema.$ref);
			if (state.$ref) {
				const discriminators = findDiscriminatorsInSchema({
					context,
					schema: ref
				});
				for (const { discriminator, oneOf } of discriminators) {
					const values = discriminatorValues(state.$ref, discriminator.mapping, oneOf ? () => oneOf.some((o) => "$ref" in o && o.$ref === state.$ref) : void 0);
					if (!values.length) continue;
					const isExplicitMapping = discriminator.mapping !== void 0 && Object.values(discriminator.mapping).includes(state.$ref);
					const existingIndex = discriminatorsToAdd.findIndex((d) => d.discriminator.propertyName === discriminator.propertyName);
					if (existingIndex !== -1) if (isExplicitMapping && !discriminatorsToAdd[existingIndex].isExplicitMapping) discriminatorsToAdd.splice(existingIndex, 1);
					else continue;
					const isRequired = discriminators.some((d) => d.discriminator.propertyName === discriminator.propertyName && (ref.required?.includes(d.discriminator.propertyName) || ref.allOf && ref.allOf.some((item) => {
						return (item.$ref ? context.resolveRef(item.$ref) : item).required?.includes(d.discriminator.propertyName);
					})));
					discriminatorsToAdd.push({
						discriminator,
						isExplicitMapping,
						isRequired,
						values
					});
				}
			}
		}
	}
	for (const { discriminator, isRequired, values } of discriminatorsToAdd) {
		const allValues = getAllDiscriminatorValues({
			discriminator,
			schemaRef: state.$ref
		});
		const finalValues = allValues.length ? allValues : values;
		const propertyType = findDiscriminatorPropertyType({
			context,
			propertyName: discriminator.propertyName,
			schemas: compositionSchemas
		});
		const valueSchemas = finalValues.map((value) => convertDiscriminatorValue(value, propertyType));
		const discriminatorProperty = valueSchemas.length > 1 ? {
			items: valueSchemas,
			logicalOperator: "or"
		} : valueSchemas[0];
		for (const item of schemaItems) if (item.$ref || item.symbolRef) {
			if ((() => {
				if (!item.$ref) return false;
				try {
					const refSchema = context.resolveRef(item.$ref);
					return refSchema.properties?.[discriminator.propertyName] !== void 0 || refSchema.allOf && refSchema.allOf.some((allOfItem) => {
						return (allOfItem.$ref ? context.resolveRef(allOfItem.$ref) : allOfItem).properties?.[discriminator.propertyName] !== void 0;
					});
				} catch {
					return false;
				}
			})()) {
				if (!item.omit) item.omit = [discriminator.propertyName];
				else if (!item.omit.includes(discriminator.propertyName)) item.omit = [...item.omit, discriminator.propertyName];
			}
		}
		let inlineSchema;
		for (let i = schemaItems.length - 1; i >= 0; i--) {
			const item = schemaItems[i];
			if (item.type === "object" || item.properties) {
				inlineSchema = item;
				break;
			}
		}
		if (inlineSchema) {
			if (!inlineSchema.properties) inlineSchema.properties = {};
			inlineSchema.properties[discriminator.propertyName] = discriminatorProperty;
			if (isRequired) {
				if (!inlineSchema.required) inlineSchema.required = [];
				if (!inlineSchema.required.includes(discriminator.propertyName)) inlineSchema.required.push(discriminator.propertyName);
			}
		} else {
			const irDiscriminatorSchema = {
				properties: { [discriminator.propertyName]: discriminatorProperty },
				type: "object"
			};
			if (isRequired) irDiscriminatorSchema.required = [discriminator.propertyName];
			schemaItems.push(irDiscriminatorSchema);
		}
	}
	if (schemaTypes.includes("object")) {
		const irObjectSchema = parseOneType({
			context,
			schema: {
				...schema,
				type: "object"
			},
			state
		});
		if (irObjectSchema.properties) {
			for (const requiredProperty of irObjectSchema.required ?? []) if (!irObjectSchema.properties[requiredProperty]) for (const compositionSchema of compositionSchemas) {
				const finalCompositionSchema = compositionSchema.$ref ? context.resolveRef(compositionSchema.$ref) : compositionSchema;
				if (getSchemaTypes(finalCompositionSchema).includes("object")) {
					const irCompositionSchema = parseOneType({
						context,
						schema: {
							...finalCompositionSchema,
							type: "object"
						},
						state
					});
					if (irCompositionSchema.properties?.[requiredProperty]) {
						irObjectSchema.properties[requiredProperty] = irCompositionSchema.properties[requiredProperty];
						break;
					}
				}
			}
			schemaItems.push(irObjectSchema);
		}
	}
	irSchema = addItemsToSchema({
		items: schemaItems,
		logicalOperator: "and",
		mutateSchemaOneItem: true,
		schema: irSchema
	});
	if (schemaTypes.includes("null")) {
		const nestedItems = [{ type: "null" }];
		if (schemaItems.length) nestedItems.unshift(irSchema);
		irSchema = {
			items: nestedItems,
			logicalOperator: "or"
		};
	}
	return irSchema;
}
function parseAnyOf({ context, schema, state }) {
	let irSchema = initIrSchema({ schema });
	parseSchemaMeta({
		irSchema,
		schema
	});
	const schemaItems = [];
	const schemaTypes = getSchemaTypes(schema);
	const compositionSchemas = schema.anyOf;
	const discriminatorPropertyType = schema.discriminator ? findDiscriminatorPropertyType({
		context,
		propertyName: schema.discriminator.propertyName,
		schemas: compositionSchemas
	}) : void 0;
	for (const compositionSchema of compositionSchemas) {
		let irCompositionSchema = schemaToIrSchema({
			context,
			schema: compositionSchema,
			state
		});
		if (schema.discriminator && irCompositionSchema.$ref) {
			const valueSchemas = discriminatorValues(irCompositionSchema.$ref, schema.discriminator.mapping).map((value) => convertDiscriminatorValue(value, discriminatorPropertyType));
			irCompositionSchema = {
				items: [{
					properties: { [schema.discriminator.propertyName]: valueSchemas.length > 1 ? {
						items: valueSchemas,
						logicalOperator: "or"
					} : valueSchemas[0] },
					type: "object"
				}, irCompositionSchema],
				logicalOperator: "and"
			};
		}
		schemaItems.push(irCompositionSchema);
	}
	if (schemaTypes.includes("null")) schemaItems.push({ type: "null" });
	irSchema = addItemsToSchema({
		items: schemaItems,
		mutateSchemaOneItem: true,
		schema: irSchema
	});
	if (schemaTypes.includes("object")) {
		const irObjectSchema = parseOneType({
			context,
			schema: {
				...schema,
				type: "object"
			},
			state
		});
		if (irObjectSchema.properties) irSchema = {
			items: [irSchema, irObjectSchema],
			logicalOperator: "and"
		};
	}
	if (schema.discriminator && irSchema.logicalOperator === "or") irSchema.discriminator = { propertyName: schema.discriminator.propertyName };
	return irSchema;
}
function parseEnum({ context, schema, state }) {
	let irSchema = initIrSchema({ schema });
	parseSchemaMeta({
		irSchema,
		schema
	});
	irSchema.type = "enum";
	const schemaItems = [];
	const schemaTypes = getSchemaTypes(schema);
	const xEnumDescriptions = schema["x-enum-descriptions"];
	const xEnumVarnames = schema["x-enum-varnames"];
	const xEnumNames = schema["x-enumNames"];
	for (let index = 0, len = schema.enum.length; index < len; index++) {
		const enumValue = schema.enum[index];
		const typeOfEnumValue = typeof enumValue;
		let enumType;
		if (typeOfEnumValue === "string" || typeOfEnumValue === "number" || typeOfEnumValue === "boolean") enumType = typeOfEnumValue;
		else if (typeOfEnumValue === "object" && Array.isArray(enumValue)) enumType = "array";
		else if (enumValue === null) {
			if (schemaTypes.includes("null")) enumType = "null";
		} else console.warn("🚨", `unhandled "${typeOfEnumValue}" typeof value "${enumValue}" for enum`, schema.enum);
		if (!enumType) continue;
		const irTypeSchema = parseOneType({
			context,
			schema: {
				const: enumValue,
				description: xEnumDescriptions?.[index],
				title: xEnumVarnames?.[index] ?? xEnumNames?.[index],
				type: enumType
			},
			state
		});
		schemaItems.push(irTypeSchema);
	}
	irSchema = addItemsToSchema({
		items: schemaItems,
		schema: irSchema
	});
	return irSchema;
}
function parseOneOf({ context, schema, state }) {
	let irSchema = initIrSchema({ schema });
	parseSchemaMeta({
		irSchema,
		schema
	});
	let schemaItems = [];
	const schemaTypes = getSchemaTypes(schema);
	const compositionSchemas = schema.oneOf;
	const discriminatorPropertyType = schema.discriminator ? findDiscriminatorPropertyType({
		context,
		propertyName: schema.discriminator.propertyName,
		schemas: compositionSchemas
	}) : void 0;
	for (const compositionSchema of compositionSchemas) {
		let irCompositionSchema = schemaToIrSchema({
			context,
			schema: compositionSchema,
			state
		});
		if (schema.discriminator && irCompositionSchema.$ref) {
			const valueSchemas = discriminatorValues(irCompositionSchema.$ref, schema.discriminator.mapping).map((value) => convertDiscriminatorValue(value, discriminatorPropertyType));
			irCompositionSchema = {
				items: [{
					properties: { [schema.discriminator.propertyName]: valueSchemas.length > 1 ? {
						items: valueSchemas,
						logicalOperator: "or"
					} : valueSchemas[0] },
					required: [schema.discriminator.propertyName],
					type: "object"
				}, irCompositionSchema],
				logicalOperator: "and"
			};
		}
		if (irCompositionSchema.logicalOperator === "or" && irCompositionSchema.type !== "array" && irCompositionSchema.items) schemaItems = schemaItems.concat(irCompositionSchema.items);
		else schemaItems.push(irCompositionSchema);
	}
	if (schemaTypes.includes("null")) schemaItems.push({ type: "null" });
	irSchema = addItemsToSchema({
		items: schemaItems,
		mutateSchemaOneItem: true,
		schema: irSchema
	});
	if (schemaTypes.includes("object")) {
		const irObjectSchema = parseOneType({
			context,
			schema: {
				...schema,
				type: "object"
			},
			state
		});
		if (irObjectSchema.properties) irSchema = {
			items: [irSchema, irObjectSchema],
			logicalOperator: "and"
		};
	}
	if (schema.discriminator && irSchema.logicalOperator === "or") irSchema.discriminator = { propertyName: schema.discriminator.propertyName };
	return irSchema;
}
function parseRef({ context, schema, state }) {
	if (!isTopLevelComponent(schema.$ref)) {
		if (!state.circularReferenceTracker.has(schema.$ref)) {
			const refSchema = context.resolveRef(schema.$ref);
			const originalRef = state.$ref;
			state.$ref = schema.$ref;
			const irSchema = schemaToIrSchema({
				context,
				schema: refSchema,
				state
			});
			state.$ref = originalRef;
			return irSchema;
		}
	}
	let irSchema = initIrSchema({ schema });
	parseSchemaMeta({
		irSchema,
		schema
	});
	const irRefSchema = {};
	irRefSchema.$ref = schema.$ref;
	if (!state.circularReferenceTracker.has(schema.$ref)) {
		const refSchema = context.resolveRef(schema.$ref);
		const originalRef = state.$ref;
		state.$ref = schema.$ref;
		schemaToIrSchema({
			context,
			schema: refSchema,
			state
		});
		state.$ref = originalRef;
	}
	const schemaItems = [];
	schemaItems.push(irRefSchema);
	if (schema.type && typeof schema.type !== "string") {
		if (schema.type.includes("null")) schemaItems.push({ type: "null" });
	}
	irSchema = addItemsToSchema({
		items: schemaItems,
		mutateSchemaOneItem: true,
		schema: irSchema
	});
	return irSchema;
}
function parseOneType({ context, irSchema, schema, state }) {
	if (!irSchema) {
		irSchema = initIrSchema({ schema });
		parseSchemaMeta({
			irSchema,
			schema
		});
	}
	switch (schema.type) {
		case "array": return parseArray({
			context,
			irSchema,
			schema,
			state
		});
		case "boolean": return parseBoolean({
			context,
			irSchema,
			schema
		});
		case "integer":
		case "number": return parseNumber({
			context,
			irSchema,
			schema
		});
		case "null": return parseNull({
			context,
			irSchema,
			schema
		});
		case "object": return parseObject({
			context,
			irSchema,
			schema,
			state
		});
		case "string": return parseString({
			context,
			irSchema,
			schema
		});
		default: return parseUnknown({
			context,
			irSchema,
			schema
		});
	}
}
function parseManyTypes({ context, irSchema, schema, state }) {
	if (!irSchema) irSchema = initIrSchema({ schema });
	const typeIrSchema = {};
	parseSchemaMeta({
		irSchema: typeIrSchema,
		schema
	});
	if (schema.type.includes("null") && typeIrSchema.default === null) delete typeIrSchema.default;
	const schemaItems = [];
	for (const type of schema.type) if (type === "null") schemaItems.push({ type: "null" });
	else {
		const irTypeSchema = parseOneType({
			context,
			irSchema: { ...typeIrSchema },
			schema: {
				...schema,
				type
			},
			state
		});
		schemaItems.push(irTypeSchema);
	}
	irSchema = addItemsToSchema({
		items: schemaItems,
		schema: irSchema
	});
	return irSchema;
}
function parseType({ context, schema, state }) {
	const irSchema = initIrSchema({ schema });
	parseSchemaMeta({
		irSchema,
		schema
	});
	const schemaTypes = getSchemaTypes(schema);
	if (schemaTypes.length === 1) return parseOneType({
		context,
		irSchema,
		schema: {
			...schema,
			type: schemaTypes[0]
		},
		state
	});
	return parseManyTypes({
		context,
		irSchema,
		schema: {
			...schema,
			type: schemaTypes
		},
		state
	});
}
function parseUnknown({ irSchema, schema }) {
	if (!irSchema) irSchema = initIrSchema({ schema });
	irSchema.type = "unknown";
	parseSchemaMeta({
		irSchema,
		schema
	});
	return irSchema;
}
function schemaToIrSchema({ context, schema, state }) {
	if (!state) state = { circularReferenceTracker: /* @__PURE__ */ new Set() };
	if (state.$ref) state.circularReferenceTracker.add(state.$ref);
	if (schema.$ref) return parseRef({
		context,
		schema,
		state
	});
	if (schema.enum) return parseEnum({
		context,
		schema,
		state
	});
	if (schema.allOf) return parseAllOf({
		context,
		schema,
		state
	});
	if (schema.anyOf) return parseAnyOf({
		context,
		schema,
		state
	});
	if (schema.oneOf) return parseOneOf({
		context,
		schema,
		state
	});
	if (schema.type || schema.properties) return parseType({
		context,
		schema,
		state
	});
	if (schema.contentMediaType && isMediaTypeFileLike({ mediaType: schema.contentMediaType })) return parseType({
		context,
		schema: {
			...schema,
			type: "string"
		},
		state
	});
	return parseUnknown({
		context,
		schema
	});
}
function parseSchema({ $ref, context, schema }) {
	if (!context.ir.components) context.ir.components = {};
	if (!context.ir.components.schemas) context.ir.components.schemas = {};
	context.ir.components.schemas[refToName($ref)] = schemaToIrSchema({
		context,
		schema,
		state: {
			$ref,
			circularReferenceTracker: /* @__PURE__ */ new Set()
		}
	});
}
//#endregion
//#region src/openApi/3.1.x/parser/pagination.ts
const isPaginationType = (schemaTypes) => schemaTypes.includes("boolean") || schemaTypes.includes("integer") || schemaTypes.includes("number") || schemaTypes.includes("string");
const paginationField = ({ context, name, schema }) => {
	if (getPaginationKeywordsRegExp(context.config.parser.pagination).test(name)) return true;
	if (schema.$ref) {
		const ref = context.resolveRef(schema.$ref);
		if ("content" in ref || "in" in ref) {
			let refSchema;
			if ("in" in ref) refSchema = ref.schema;
			if (!refSchema) {
				const contents = mediaTypeObjects({ content: ref.content });
				const content = contents.find((content) => content.type === "json") || contents[0];
				if (content?.schema) refSchema = content.schema;
			}
			if (!refSchema) return false;
			return paginationField({
				context,
				name,
				schema: refSchema
			});
		}
		return paginationField({
			context,
			name,
			schema: ref
		});
	}
	for (const name in schema.properties) if (getPaginationKeywordsRegExp(context.config.parser.pagination).test(name)) {
		const property = schema.properties[name];
		if (typeof property !== "boolean") {
			const schemaTypes = getSchemaTypes(property);
			if (!schemaTypes.length) {
				const nonNullCompositionSchemas = (property.anyOf ?? property.oneOf ?? []).filter((schema) => schema.type !== "null");
				if (nonNullCompositionSchemas.length === 1) {
					if (isPaginationType(getSchemaTypes(nonNullCompositionSchemas[0]))) return name;
				}
			}
			if (isPaginationType(schemaTypes)) return name;
		}
	}
	for (const allOf of schema.allOf ?? []) {
		const pagination = paginationField({
			context,
			name,
			schema: allOf
		});
		if (pagination) return pagination;
	}
	return false;
};
//#endregion
//#region src/openApi/3.1.x/parser/operation.ts
function parseOperationJsDoc({ irOperation, operation }) {
	if (operation.deprecated !== void 0) irOperation.deprecated = operation.deprecated;
	if (operation.description) irOperation.description = operation.description;
	if (operation.summary) irOperation.summary = operation.summary;
	if (operation.tags?.length) irOperation.tags = operation.tags;
}
function initIrOperation({ context, method, operation, path, state }) {
	const irOperation = {
		id: operationToId({
			context,
			id: operation.operationId,
			method,
			path,
			state
		}),
		method,
		path
	};
	if (operation.operationId) irOperation.operationId = operation.operationId;
	parseOperationJsDoc({
		irOperation,
		operation
	});
	parseExtensions({
		source: operation,
		target: irOperation
	});
	return irOperation;
}
function operationToIrOperation({ ambiguousSecurityKeys, context, method, operation, path, securitySchemesMap, state }) {
	const irOperation = initIrOperation({
		context,
		method,
		operation,
		path,
		state
	});
	if (operation.parameters) irOperation.parameters = operation.parameters;
	if (operation.requestBody) {
		const requestBody = "$ref" in operation.requestBody ? context.resolveRef(operation.requestBody.$ref) : operation.requestBody;
		const contents = mediaTypeObjects({ content: requestBody.content });
		const content = contents.find((content) => content.type === "json") || contents[0];
		if (content) {
			const pagination = paginationField({
				context,
				name: "",
				schema: {
					description: requestBody.description,
					...content.schema
				}
			});
			irOperation.body = {
				mediaType: content.mediaType,
				schema: schemaToIrSchema({
					context,
					schema: {
						description: requestBody.description,
						..."$ref" in operation.requestBody ? operation.requestBody : content.schema
					},
					state: void 0
				})
			};
			if (pagination) irOperation.body.pagination = pagination;
			if (requestBody.required) irOperation.body.required = requestBody.required;
			if (content.type) irOperation.body.type = content.type;
		}
	}
	for (const name in operation.responses) {
		if (name.startsWith("x-")) continue;
		if (!irOperation.responses) irOperation.responses = {};
		const response = operation.responses[name];
		const responseObject = "$ref" in response ? context.resolveRef(response.$ref) : response;
		const contents = mediaTypeObjects({ content: responseObject.content });
		const content = contents.find((content) => content.type === "json") || contents[0];
		if (content) irOperation.responses[name] = {
			mediaType: content.mediaType,
			schema: schemaToIrSchema({
				context,
				schema: {
					description: responseObject.description,
					...contentToSchema({ content })
				},
				state: void 0
			})
		};
		else irOperation.responses[name] = { schema: {
			description: responseObject.description,
			type: name === "204" ? "void" : "unknown"
		} };
	}
	if (operation.security) {
		const securitySchemeObjects = /* @__PURE__ */ new Map();
		for (const securityRequirementObject of operation.security) for (const name in securityRequirementObject) {
			const securitySchemeObject = securitySchemesMap.get(name);
			if (!securitySchemeObject) continue;
			if (ambiguousSecurityKeys.has(name)) securitySchemeObject.key = name;
			securitySchemeObjects.set(name, securitySchemeObject);
		}
		if (securitySchemeObjects.size) irOperation.security = Array.from(securitySchemeObjects.values());
	}
	return irOperation;
}
function parseOperationObject({ ambiguousSecurityKeys, context, method, operation, path, securitySchemesMap, state }) {
	if (operation.servers) context.ir.servers = [...context.ir.servers ?? [], ...operation.servers];
	return { parsed: operationToIrOperation({
		ambiguousSecurityKeys,
		context,
		method,
		operation,
		path,
		securitySchemesMap,
		state
	}) };
}
function parsePathOperation({ context, method, path, ...options }) {
	if (!context.ir.paths) context.ir.paths = {};
	if (!context.ir.paths[path]) context.ir.paths[path] = {};
	const { parsed } = parseOperationObject({
		context,
		method,
		path,
		...options
	});
	context.ir.paths[path][method] = parsed;
}
function parseWebhookOperation({ context, key, method, ...options }) {
	if (!context.ir.webhooks) context.ir.webhooks = {};
	if (!context.ir.webhooks[key]) context.ir.webhooks[key] = {};
	const { parsed } = parseOperationObject({
		context,
		method,
		path: key,
		...options
	});
	context.ir.webhooks[key][method] = parsed;
}
//#endregion
//#region src/openApi/3.1.x/parser/parameter.ts
/**
* Returns default parameter `allowReserved` based on value of `in`.
*/
const defaultAllowReserved = (_in) => {
	switch (_in) {
		case "query": return false;
		default: return;
	}
};
/**
* Returns default parameter `explode` based on value of `style`.
*/
const defaultExplode = (style) => {
	switch (style) {
		case "deepObject":
		case "form": return true;
		default: return false;
	}
};
/**
* Returns default parameter `style` based on value of `in`.
*/
const defaultStyle = (_in) => {
	switch (_in) {
		case "header":
		case "path": return "simple";
		case "cookie":
		case "query": return "form";
	}
};
const parametersArrayToObject = ({ context, parameters }) => {
	if (!parameters || !Object.keys(parameters).length) return;
	const parametersObject = {};
	for (const parameterOrReference of parameters) {
		const parameter = "$ref" in parameterOrReference ? context.dereference(parameterOrReference) : parameterOrReference;
		if (!parametersObject[parameter.in]) parametersObject[parameter.in] = {};
		parametersObject[parameter.in][parameter.name.toLocaleLowerCase()] = parameterToIrParameter({
			$ref: `#/todo/real/path/to/parameter/${parameter.name}`,
			context,
			parameter
		});
	}
	return parametersObject;
};
const parameterToIrParameter = ({ $ref, context, parameter }) => {
	let schema = parameter.schema;
	if (!schema) {
		const contents = mediaTypeObjects({ content: parameter.content });
		const content = contents.find((content) => content.type === "json") || contents[0];
		if (content) schema = content.schema;
	}
	const finalSchema = {
		deprecated: parameter.deprecated,
		description: parameter.description,
		...schema
	};
	const pagination = paginationField({
		context,
		name: parameter.name,
		schema: finalSchema
	});
	const style = parameter.style || defaultStyle(parameter.in);
	const explode = parameter.explode !== void 0 ? parameter.explode : defaultExplode(style);
	const irParameter = {
		allowReserved: parameter.allowReserved !== void 0 ? parameter.allowReserved : defaultAllowReserved(parameter.in),
		explode,
		location: parameter.in,
		name: parameter.name,
		schema: schemaToIrSchema({
			context,
			schema: finalSchema,
			state: {
				$ref,
				circularReferenceTracker: /* @__PURE__ */ new Set()
			}
		}),
		style
	};
	if (parameter.deprecated) irParameter.deprecated = parameter.deprecated;
	if (parameter.description) irParameter.description = parameter.description;
	if (pagination) irParameter.pagination = pagination;
	if (parameter.required) irParameter.required = parameter.required;
	parseExtensions({
		source: parameter,
		target: irParameter
	});
	return irParameter;
};
const parseParameter = ({ $ref, context, parameter }) => {
	if (!context.ir.components) context.ir.components = {};
	if (!context.ir.components.parameters) context.ir.components.parameters = {};
	context.ir.components.parameters[refToName($ref)] = parameterToIrParameter({
		$ref,
		context,
		parameter
	});
};
//#endregion
//#region src/openApi/3.1.x/parser/requestBody.ts
const requestBodyToIrRequestBody = ({ $ref, context, requestBody }) => {
	const contents = mediaTypeObjects({ content: requestBody.content });
	const content = contents.find((content) => content.type === "json") || contents[0];
	const schema = content ? content.schema : void 0;
	const irRequestBody = { schema: schemaToIrSchema({
		context,
		schema: {
			description: requestBody.description,
			...schema
		},
		state: {
			$ref,
			circularReferenceTracker: /* @__PURE__ */ new Set()
		}
	}) };
	if (requestBody.description) irRequestBody.description = requestBody.description;
	if (requestBody.required) irRequestBody.required = requestBody.required;
	return irRequestBody;
};
const parseRequestBody = ({ $ref, context, requestBody }) => {
	if (!context.ir.components) context.ir.components = {};
	if (!context.ir.components.requestBodies) context.ir.components.requestBodies = {};
	context.ir.components.requestBodies[refToName($ref)] = requestBodyToIrRequestBody({
		$ref,
		context,
		requestBody
	});
};
//#endregion
//#region src/openApi/3.1.x/parser/server.ts
const parseServers = ({ context }) => {
	if (context.spec.servers) {
		context.ir.servers = context.spec.servers;
		return;
	}
	for (const input of context.config.input) if (typeof input.path === "string") {
		const url = parseUrl(input.path);
		context.ir.servers = [{ url: `${url.protocol ? `${url.protocol}://` : ""}${url.host}${url.port ? `:${url.port}` : ""}` }];
	}
	if (!context.ir.servers) context.ir.servers = [{ url: "/" }];
};
//#endregion
//#region src/openApi/3.1.x/parser/validate.ts
const validateOpenApiSpec = (spec, logger) => {
	const eventValidate = logger.timeEvent("validate");
	const issues = [];
	const operationIds = /* @__PURE__ */ new Map();
	if (spec.paths) for (const entry of Object.entries(spec.paths)) {
		const path = entry[0];
		const pathItem = entry[1];
		for (const method of httpMethods) {
			const operation = pathItem[method];
			if (!operation) continue;
			const operationKey = createOperationKey({
				method,
				path
			});
			if (operation.operationId) if (!operationIds.has(operation.operationId)) operationIds.set(operation.operationId, operationKey);
			else issues.push({
				code: "duplicate_key",
				context: {
					key: "operationId",
					value: operation.operationId
				},
				message: "Duplicate `operationId` found. Each `operationId` must be unique.",
				path: [
					"paths",
					path,
					method,
					"operationId"
				],
				severity: "error"
			});
		}
	}
	if (spec.servers) {
		if (typeof spec.servers !== "object" || !Array.isArray(spec.servers)) issues.push({
			code: "invalid_type",
			message: "`servers` must be an array.",
			path: [],
			severity: "error"
		});
		for (let index = 0; index < spec.servers.length; index++) {
			const server = spec.servers[index];
			if (!server || typeof server !== "object") issues.push({
				code: "invalid_type",
				context: {
					actual: typeof server,
					expected: "object"
				},
				message: "Each entry in `servers` must be an object.",
				path: ["servers", index],
				severity: "error"
			});
			else if (!server.url) issues.push({
				code: "missing_required_field",
				context: { field: "url" },
				message: "Missing required field `url` in server object.",
				path: ["servers", index],
				severity: "error"
			});
		}
	}
	eventValidate.timeEnd();
	return {
		issues,
		valid: !issues.some((issue) => issue.severity === "error")
	};
};
//#endregion
//#region src/openApi/3.1.x/parser/webhook.ts
function parseWebhooks({ ambiguousSecurityKeys, context, securitySchemesMap }) {
	const state = { ids: /* @__PURE__ */ new Map() };
	for (const key in context.spec.webhooks) {
		const webhook = context.spec.webhooks[key];
		const finalWebhook = "$ref" in webhook ? {
			...context.resolveRef(webhook.$ref),
			...webhook
		} : webhook;
		const operationArgs = {
			ambiguousSecurityKeys,
			context,
			key,
			operation: {
				description: finalWebhook.description,
				parameters: parametersArrayToObject({
					context,
					parameters: finalWebhook.parameters
				}),
				security: context.spec.security,
				servers: finalWebhook.servers,
				summary: finalWebhook.summary
			},
			securitySchemesMap,
			state
		};
		if (finalWebhook.delete) parseWebhookOperation({
			...operationArgs,
			method: "delete",
			operation: {
				...operationArgs.operation,
				...finalWebhook.delete,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject({
						context,
						parameters: finalWebhook.delete.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalWebhook.get) parseWebhookOperation({
			...operationArgs,
			method: "get",
			operation: {
				...operationArgs.operation,
				...finalWebhook.get,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject({
						context,
						parameters: finalWebhook.get.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalWebhook.head) parseWebhookOperation({
			...operationArgs,
			method: "head",
			operation: {
				...operationArgs.operation,
				...finalWebhook.head,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject({
						context,
						parameters: finalWebhook.head.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalWebhook.options) parseWebhookOperation({
			...operationArgs,
			method: "options",
			operation: {
				...operationArgs.operation,
				...finalWebhook.options,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject({
						context,
						parameters: finalWebhook.options.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalWebhook.patch) parseWebhookOperation({
			...operationArgs,
			method: "patch",
			operation: {
				...operationArgs.operation,
				...finalWebhook.patch,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject({
						context,
						parameters: finalWebhook.patch.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalWebhook.post) parseWebhookOperation({
			...operationArgs,
			method: "post",
			operation: {
				...operationArgs.operation,
				...finalWebhook.post,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject({
						context,
						parameters: finalWebhook.post.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalWebhook.put) parseWebhookOperation({
			...operationArgs,
			method: "put",
			operation: {
				...operationArgs.operation,
				...finalWebhook.put,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject({
						context,
						parameters: finalWebhook.put.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalWebhook.trace) parseWebhookOperation({
			...operationArgs,
			method: "trace",
			operation: {
				...operationArgs.operation,
				...finalWebhook.trace,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject({
						context,
						parameters: finalWebhook.trace.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
	}
}
//#endregion
//#region src/openApi/3.1.x/parser/index.ts
const parseV3_1_X = (context) => {
	if (context.config.parser.validate_EXPERIMENTAL) handleValidatorResult({
		context,
		result: validateOpenApiSpec(context.spec, context.logger)
	});
	if (hasFilters(context.config.parser.filters)) {
		const filters = createFilters(context.config.parser.filters, context.spec, context.logger);
		const { graph } = buildGraph(context.spec, context.logger);
		const { resourceMetadata } = buildResourceMetadata(graph, context.logger);
		filterSpec({
			...createFilteredDependencies({
				filters,
				logger: context.logger,
				resourceMetadata
			}),
			logger: context.logger,
			preserveOrder: filters.preserveOrder,
			spec: context.spec
		});
	}
	transformOpenApiSpec({ context });
	const state = { ids: /* @__PURE__ */ new Map() };
	const securitySchemesMap = /* @__PURE__ */ new Map();
	if (context.spec.components) {
		for (const name in context.spec.components.securitySchemes) {
			const securityOrReference = context.spec.components.securitySchemes[name];
			const securitySchemeObject = "$ref" in securityOrReference ? context.resolveRef(securityOrReference.$ref) : securityOrReference;
			securitySchemesMap.set(name, securitySchemeObject);
		}
		for (const name in context.spec.components.parameters) {
			const $ref = pathToJsonPointer([
				"components",
				"parameters",
				name
			]);
			const parameterOrReference = context.spec.components.parameters[name];
			parseParameter({
				$ref,
				context,
				parameter: "$ref" in parameterOrReference ? context.resolveRef(parameterOrReference.$ref) : parameterOrReference
			});
		}
		for (const name in context.spec.components.requestBodies) {
			const $ref = pathToJsonPointer([
				"components",
				"requestBodies",
				name
			]);
			const requestBodyOrReference = context.spec.components.requestBodies[name];
			parseRequestBody({
				$ref,
				context,
				requestBody: "$ref" in requestBodyOrReference ? context.resolveRef(requestBodyOrReference.$ref) : requestBodyOrReference
			});
		}
		for (const name in context.spec.components.schemas) {
			const $ref = pathToJsonPointer([
				"components",
				"schemas",
				name
			]);
			const schema = context.spec.components.schemas[name];
			parseSchema({
				$ref,
				context,
				schema
			});
		}
	}
	const ambiguousSecurityKeys = computeAmbiguousSecurityKeys(securitySchemesMap);
	parseServers({ context });
	for (const path in context.spec.paths) {
		if (path.startsWith("x-")) continue;
		const pathItem = context.spec.paths[path];
		const finalPathItem = pathItem.$ref ? {
			...context.resolveRef(pathItem.$ref),
			...pathItem
		} : pathItem;
		const operationArgs = {
			ambiguousSecurityKeys,
			context,
			operation: {
				description: finalPathItem.description,
				parameters: parametersArrayToObject({
					context,
					parameters: finalPathItem.parameters
				}),
				security: context.spec.security,
				servers: finalPathItem.servers,
				summary: finalPathItem.summary
			},
			path,
			securitySchemesMap,
			state
		};
		if (finalPathItem.delete) parsePathOperation({
			...operationArgs,
			method: "delete",
			operation: {
				...operationArgs.operation,
				...finalPathItem.delete,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject({
						context,
						parameters: finalPathItem.delete.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalPathItem.get) parsePathOperation({
			...operationArgs,
			method: "get",
			operation: {
				...operationArgs.operation,
				...finalPathItem.get,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject({
						context,
						parameters: finalPathItem.get.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalPathItem.head) parsePathOperation({
			...operationArgs,
			method: "head",
			operation: {
				...operationArgs.operation,
				...finalPathItem.head,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject({
						context,
						parameters: finalPathItem.head.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalPathItem.options) parsePathOperation({
			...operationArgs,
			method: "options",
			operation: {
				...operationArgs.operation,
				...finalPathItem.options,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject({
						context,
						parameters: finalPathItem.options.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalPathItem.patch) parsePathOperation({
			...operationArgs,
			method: "patch",
			operation: {
				...operationArgs.operation,
				...finalPathItem.patch,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject({
						context,
						parameters: finalPathItem.patch.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalPathItem.post) parsePathOperation({
			...operationArgs,
			method: "post",
			operation: {
				...operationArgs.operation,
				...finalPathItem.post,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject({
						context,
						parameters: finalPathItem.post.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalPathItem.put) parsePathOperation({
			...operationArgs,
			method: "put",
			operation: {
				...operationArgs.operation,
				...finalPathItem.put,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject({
						context,
						parameters: finalPathItem.put.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
		if (finalPathItem.trace) parsePathOperation({
			...operationArgs,
			method: "trace",
			operation: {
				...operationArgs.operation,
				...finalPathItem.trace,
				parameters: mergeParametersObjects({
					source: parametersArrayToObject({
						context,
						parameters: finalPathItem.trace.parameters
					}),
					target: operationArgs.operation.parameters
				})
			}
		});
	}
	parseWebhooks({
		ambiguousSecurityKeys,
		context,
		securitySchemesMap
	});
};
//#endregion
//#region src/openApi/index.ts
/**
* @internal
* Parse the resolved OpenAPI specification. This will populate and return
* `context` with intermediate representation obtained from the parsed spec.
*/
function parseOpenApiSpec(context) {
	if ("swagger" in context.spec) {
		parseV2_0_X(context);
		return context;
	}
	if (satisfies(context.spec.openapi, ">=3.0.0 <3.1.0")) {
		parseV3_0_X(context);
		return context;
	}
	if (satisfies(context.spec.openapi, ">=3.1.0")) {
		parseV3_1_X(context);
		return context;
	}
	throw new Error("Unsupported OpenAPI specification");
}
//#endregion
//#region src/openApi/shared/locations/operation.ts
/**
* Built-in strategies for operations.
*/
const OperationStrategy = {
	/**
	* Creates one root container per operation tag.
	*
	* Operations with multiple tags appear in multiple root containers.
	* Operations without tags use the fallback root container.
	*
	* @example
	* // Operation with tags: ['users', 'admin']
	* // Path function returns: ['list']
	* // Result: [{ path: ['users', 'list'], shell }, { path: ['admin', 'list'], shell }]
	*/
	byTags: (config) => (operation) => {
		const tags = operation.tags && operation.tags.length ? operation.tags : [config.fallback];
		const pathSegments = (config.path ?? OperationPath.id())(operation);
		return tags.map((tag) => [tag, ...pathSegments]);
	},
	/**
	* Creates flat functions without any container.
	*
	* Each operation becomes a standalone function at the root level.
	* No shell is applied.
	*
	* @example
	* // Operation id: 'getUsers'
	* // Result: [{ path: ['getUsers'] }]
	*/
	flat: (config) => (operation) => {
		const pathSegments = (config?.path ?? OperationPath.id())(operation);
		return [[pathSegments[pathSegments.length - 1]]];
	},
	/**
	* Places all operations under a single root container.
	*
	* @example
	* // Root: 'Sdk', path function returns: ['users', 'list']
	* // Result: [{ path: ['Sdk', 'users', 'list'], shell }]
	*/
	single: (config) => (operation) => {
		const pathSegments = (config.path ?? OperationPath.id())(operation);
		return [[config.root, ...pathSegments]];
	}
};
/**
* Built-in path derivation helpers for operations.
*/
const OperationPath = {
	/**
	* Splits operationId by delimiters to create nested paths.
	*
	* @example
	* // operationId: 'users.accounts.list'
	* // Result: ['users', 'accounts', 'list']
	*
	* @example
	* // operationId: 'users/accounts/getAll'
	* // Result: ['users', 'accounts', 'getAll']
	*/
	fromOperationId: (config) => (operation) => {
		const fallback = config?.fallback ?? OperationPath.id();
		if (!operation.operationId) return fallback(operation);
		const delimiters = config?.delimiters ?? /[./]/;
		const segments = operation.operationId.split(delimiters).filter(Boolean);
		return !segments.length ? fallback(operation) : segments;
	},
	/**
	* Splits path by delimiters to create nested paths.
	*
	* Can include the method as a prefix or suffix segment.
	*
	* @example
	* // path: '/users/{id}/accounts', method: 'get', delimiters: /[\/{}]+/, methodPosition: 'none'
	* // Result: ['users', 'id', 'accounts']
	*
	* @example
	* // path: '/users/{id}/accounts', method: 'get', delimiters: /[\/{}]+/, methodPosition: 'prefix'
	* // Result: ['get', 'users', 'id', 'accounts']
	*
	* @example
	* // path: '/users/{id}/accounts', method: 'get', delimiters: /[\/{}]+/, methodPosition: 'suffix'
	* // Result: ['users', 'id', 'accounts', 'get']
	*/
	fromPath: (config) => (operation) => {
		const delimiters = config?.delimiters ?? /[./]/;
		const segments = operation.path.split(delimiters).filter(Boolean);
		switch (config?.methodPosition) {
			case "prefix":
				segments.unshift(operation.method.toLowerCase());
				break;
			case "suffix":
				segments.push(operation.method.toLowerCase());
				break;
			default: break;
		}
		return segments;
	},
	/**
	* Uses operation.id as a single path segment.
	*
	* @example
	* // operation.id: 'getUserById'
	* // Result: ['getUserById']
	*/
	id: () => (operation) => [operation.id]
};
//#endregion
//#region src/openApi/shared/utils/patch.ts
async function patchOpenApiSpec({ patchOptions, spec: _spec }) {
	if (!patchOptions) return;
	const spec = _spec;
	if (typeof patchOptions === "function") {
		await patchOptions(spec);
		return;
	}
	if (patchOptions.input) await patchOptions.input(spec);
	if ("swagger" in spec) {
		if (patchOptions.version && spec.swagger) spec.swagger = typeof patchOptions.version === "string" ? patchOptions.version : patchOptions.version(spec.swagger);
		if (patchOptions.meta && spec.info) patchOptions.meta(spec.info);
		if (patchOptions.schemas && spec.definitions) if (typeof patchOptions.schemas === "function") {
			for (const [key, schema] of Object.entries(spec.definitions)) if (schema && typeof schema === "object") await patchOptions.schemas(key, schema);
		} else for (const key in patchOptions.schemas) {
			const schema = spec.definitions[key];
			if (!schema || typeof schema !== "object") continue;
			const patchFn = patchOptions.schemas[key];
			await patchFn(schema);
		}
		if (patchOptions.operations && spec.paths) if (typeof patchOptions.operations === "function") for (const [path, pathItem] of Object.entries(spec.paths)) {
			if (!pathItem || typeof pathItem !== "object") continue;
			for (const method of [
				"get",
				"put",
				"post",
				"delete",
				"options",
				"head",
				"patch",
				"trace"
			]) {
				const operation = pathItem[method];
				if (!operation || typeof operation !== "object") continue;
				await patchOptions.operations(method, path, operation);
			}
		}
		else for (const key in patchOptions.operations) {
			const [method, path] = key.split(" ");
			if (!method || !path) continue;
			const pathItem = spec.paths[path];
			if (!pathItem) continue;
			const operation = pathItem[method.toLocaleLowerCase()] || pathItem[method.toLocaleUpperCase()];
			if (!operation || typeof operation !== "object") continue;
			const patchFn = patchOptions.operations[key];
			await patchFn(operation);
		}
		return;
	}
	if (patchOptions.version && spec.openapi) spec.openapi = typeof patchOptions.version === "string" ? patchOptions.version : patchOptions.version(spec.openapi);
	if (patchOptions.meta && spec.info) patchOptions.meta(spec.info);
	if (spec.components) {
		if (patchOptions.schemas && spec.components.schemas) if (typeof patchOptions.schemas === "function") {
			for (const [key, schema] of Object.entries(spec.components.schemas)) if (schema && typeof schema === "object") await patchOptions.schemas(key, schema);
		} else for (const key in patchOptions.schemas) {
			const schema = spec.components.schemas[key];
			if (!schema || typeof schema !== "object") continue;
			const patchFn = patchOptions.schemas[key];
			await patchFn(schema);
		}
		if (patchOptions.parameters && spec.components.parameters) for (const key in patchOptions.parameters) {
			const schema = spec.components.parameters[key];
			if (!schema || typeof schema !== "object") continue;
			const patchFn = patchOptions.parameters[key];
			patchFn(schema);
		}
		if (patchOptions.requestBodies && spec.components.requestBodies) for (const key in patchOptions.requestBodies) {
			const schema = spec.components.requestBodies[key];
			if (!schema || typeof schema !== "object") continue;
			const patchFn = patchOptions.requestBodies[key];
			patchFn(schema);
		}
		if (patchOptions.responses && spec.components.responses) for (const key in patchOptions.responses) {
			const schema = spec.components.responses[key];
			if (!schema || typeof schema !== "object") continue;
			const patchFn = patchOptions.responses[key];
			patchFn(schema);
		}
	}
	if (patchOptions.operations && spec.paths) if (typeof patchOptions.operations === "function") for (const [path, pathItem] of Object.entries(spec.paths)) {
		if (!pathItem || typeof pathItem !== "object") continue;
		for (const method of [
			"get",
			"put",
			"post",
			"delete",
			"options",
			"head",
			"patch",
			"trace"
		]) {
			const operation = pathItem[method];
			if (!operation || typeof operation !== "object") continue;
			await patchOptions.operations(method, path, operation);
		}
	}
	else for (const key in patchOptions.operations) {
		const [method, path] = key.split(" ");
		if (!method || !path) continue;
		const pathItem = spec.paths[path];
		if (!pathItem) continue;
		const operation = pathItem[method.toLocaleLowerCase()] || pathItem[method.toLocaleUpperCase()];
		if (!operation || typeof operation !== "object") continue;
		const patchFn = patchOptions.operations[key];
		await patchFn(operation);
	}
}
//#endregion
//#region src/plugins/duplicate.ts
function stableStringify(value) {
	return JSON.stringify(value, (_, v) => {
		if (typeof v === "function") return `[function:${v.toString()}]`;
		if (v && typeof v === "object" && !Array.isArray(v)) return Object.fromEntries(Object.entries(v).sort(([a], [b]) => a.localeCompare(b)));
		return v;
	});
}
function normalizePluginEntry(plugin) {
	if (typeof plugin === "string") return {
		name: plugin,
		serialized: "{}"
	};
	const { name, ...config } = plugin;
	return {
		name,
		serialized: stableStringify(config)
	};
}
function warnOnConflictingDuplicatePlugins(plugins) {
	const seen = /* @__PURE__ */ new Map();
	for (const plugin of plugins) {
		const { name, serialized } = normalizePluginEntry(plugin);
		if (!name) continue;
		const previous = seen.get(name);
		if (previous !== void 0 && previous !== serialized) log.warn(`Plugin "${name}" is configured multiple times. Only the last instance will take effect.`);
		seen.set(name, serialized);
	}
}
//#endregion
//#region src/plugins/shared/utils/config.ts
function definePluginConfig(pluginConfig) {
	return (userConfig) => ({
		...pluginConfig,
		config: {
			...pluginConfig.config,
			...userConfig ?? {}
		},
		/**
		* Cast name to `any` so it doesn't throw type error in `plugins` array.
		* We could allow any `string` as plugin `name` in the object syntax, but
		* that TypeScript trick would cause all string methods to appear as
		* suggested auto completions, which is undesirable.
		*/
		name: pluginConfig.name
	});
}
//#endregion
//#region src/plugins/symbol.ts
/**
* Helper function to build the input for symbol registration, applying naming hooks if provided.
*/
function buildSymbolIn({ plugin, ...ctx }) {
	const hooks = plugin.getHooks((hooks) => hooks.symbols?.getName);
	for (const hook of hooks) {
		const result = hook(ctx);
		if (typeof result === "function") {
			const name = result(ctx);
			if (name) return {
				meta: ctx.meta,
				name
			};
		} else if (typeof result === "string") return {
			meta: ctx.meta,
			name: ctx.naming ? applyNaming(result, ctx.naming) : result
		};
	}
	return {
		meta: ctx.meta,
		name: ctx.naming ? applyNaming(ctx.name, ctx.naming) : ctx.name
	};
}
//#endregion
//#region src/plugins/validator.ts
/**
* The ordered list of standard HTTP request layer keys.
*/
const requestValidatorLayers = [
	"body",
	"headers",
	"path",
	"query"
];
/**
* Resolves the effective configuration for a single layer by merging the
* layer's defaults with any explicit overrides supplied in `layers`.
*
* @param layers - Optional map of per-layer overrides.
* @param key - The layer key to resolve.
* @param defaultValues - Required fallback values for every layer key.
* @returns The fully-resolved layer configuration.
*/
function resolveValidatorLayer(layers, key, defaultValues) {
	const override = Object.fromEntries(Object.entries(layers?.[key] ?? {}).filter(([, v]) => v !== void 0));
	return {
		...defaultValues[key],
		...override
	};
}
//#endregion
//#region src/utils/escape.ts
function escapeComment(value) {
	return value.replace(/\*\//g, "*").replace(/\/\*/g, "*").replace(/\r?\n(.*)/g, (_l, w) => EOL + w.trim());
}
//#endregion
//#region src/utils/exports.ts
/**
* Utilities shared across the package.
*/
const utils = {
	/**
	* @deprecated use `toCase` instead
	*/
	stringCase({ case: casing, stripLeadingSeparators, value }) {
		return toCase(value, casing, { stripLeadingSeparators });
	},
	/**
	* Converts the given string to the specified casing.
	*/
	toCase
};
//#endregion
//#region src/utils/header.ts
/**
* Converts an {@link OutputHeader} value to a string prefix for file content.
*/
function outputHeaderToPrefix(ctx) {
	const { defaultValue, header, project } = ctx;
	let lines = typeof header === "function" ? header({
		defaultValue,
		project
	}) : header;
	if (lines === void 0) lines = defaultValue;
	if (lines === null) return "";
	lines = typeof lines === "string" ? lines.split(/\r?\n/) : lines.flatMap((line) => line.split(/\r?\n/));
	const content = lines.join("\n");
	return content ? `${content}\n\n` : "";
}
//#endregion
//#region src/utils/path.ts
/**
* After these structural segments, the next segment has a known role.
* This is what makes a property literally named "properties" safe —
* it occupies the name position, never the structural position.
*/
const STRUCTURAL_ROLE = {
	items: "index",
	patternProperties: "name",
	properties: "name"
};
/**
* These structural segments have no following name/index —
* they are the terminal structural node. Append a suffix
* to disambiguate from the parent.
*/
const STRUCTURAL_SUFFIX = { additionalProperties: "Value" };
/**
* Root context configuration.
*/
const ROOT_CONTEXT = {
	components: {
		names: 1,
		skip: 2
	},
	definitions: {
		names: 1,
		skip: 1
	},
	paths: {
		names: 2,
		skip: 1
	},
	webhooks: {
		names: 2,
		skip: 1
	}
};
/**
* Sanitizes a path segment for use in a derived name.
*
* Handles API path segments like `/api/v1/users/{id}` → `ApiV1UsersId`.
*/
function sanitizeSegment(segment) {
	const str = String(segment);
	if (str.startsWith("/")) return str.split("/").filter(Boolean).map((part) => {
		const clean = part.replace(/[{}]/g, "");
		return clean.charAt(0).toUpperCase() + clean.slice(1);
	}).join("");
	return str;
}
/**
* Derives a composite name from a path.
*
* Examples:
*   .../User                                    → 'User'
*   .../User/properties/address                 → 'UserAddress'
*   .../User/properties/properties              → 'UserProperties'
*   .../User/properties/address/properties/city → 'UserAddressCity'
*   .../Pet/additionalProperties                → 'PetValue'
*   .../Order/properties/items/items/0          → 'OrderItems'
*   paths//event/get/properties/query           → 'EventGetQuery'
*
* With anchor:
*   paths//event/get/properties/query, { anchor: 'event.subscribe' }
*                                               → 'event.subscribe-Query'
*/
function pathToName(path, options) {
	const names = [];
	let index = 0;
	const rootContext = ROOT_CONTEXT[path[0]];
	if (rootContext) {
		index = rootContext.skip;
		if (options?.anchor) {
			names.push(options.anchor);
			index += rootContext.names;
		} else for (let n = 0; n < rootContext.names && index < path.length; n++) {
			names.push(sanitizeSegment(path[index]));
			index++;
		}
	} else if (options?.anchor) {
		names.push(options.anchor);
		index++;
	} else if (index < path.length) {
		names.push(sanitizeSegment(path[index]));
		index++;
	}
	while (index < path.length) {
		const segment = String(path[index]);
		const role = STRUCTURAL_ROLE[segment];
		if (role === "name") {
			index++;
			if (index < path.length) names.push(sanitizeSegment(path[index]));
		} else if (role === "index") {
			index++;
			if (index < path.length && typeof path[index] === "number") index++;
			continue;
		} else if (STRUCTURAL_SUFFIX[segment]) names.push(STRUCTURAL_SUFFIX[segment]);
		index++;
	}
	return names.join("-");
}
//#endregion
export { COERCER, ConfigError, ConfigValidationError, Context, HeyApiError, InputError, IntentContext, JobError, MinHeap, OperationPath, OperationStrategy, PluginInstance, addItemsToSchema, applyNaming, buildGraph, buildSymbolIn, checkNodeVersion, childContext, coerce, collectDeps, compileInputPath, createOperationKey, createSchemaProcessor, createSchemaWalker, debugTools, deduplicateSchema, defaultPaginationKeywords, defineConfig, definePluginConfig, dependencyFactory, encodeJsonPointerSegment, ensureDirSync, escapeComment, findPackageJson, findTsConfigPath, getInput, getInputError, getLogs, getParser, getSpec, hasOperationDataRequired, hasParameterGroupObjectRequired, hasParametersObjectRequired, heyApiRegistryBaseUrl, inputToApiRegistry, isCoercer, isEnvironment, isPlainObject, isTopLevelComponent, jsonPointerToPath, loadPackageJson, logCrashReport, logInputPaths, normalizeJsonPointer, openGitHubIssueWithCrashReport, operationPagination, operationResponsesMap, outputHeaderToPrefix, parameterWithPagination, parseOpenApiSpec, parseUrl, parseV2_0_X, parseV3_0_X, parseV3_1_X, patchOpenApiSpec, pathToJsonPointer, pathToName, postprocessOutput, printCliIntro, printCrashReport, refToName, requestValidatorLayers, resolveNaming, resolveRef, resolveValidatorLayer, satisfies, shouldReportCrash, sourceConfig, statusCodeToGroup, toCase, utils, warnOnConflictingDuplicatePlugins };

//# sourceMappingURL=index.mjs.map