import { clean, exists, getRelativePath, read, readSync } from "./fs-BNC5Fj6t.js";
import "./write-O9QWtBJ_.js";
import { EventEmitter, createLogger } from "./logger-BKPT4rkB.js";
import { transformReservedWord, trim } from "./transformers-CXIKOVl0.js";
import { FileManager, Queue, URLPath, getDefaultBanner, getSource, pLimit as pLimit$1, setUniqueName } from "./FileManager-BDisPxtH.js";
import mod from "node:module";
import path, { join, resolve } from "node:path";
import pc from "picocolors";
import { isDeepEqual } from "remeda";
import g$1 from "node:process";
import os from "node:os";
import { fileURLToPath, pathToFileURL } from "node:url";
import fs, { promises } from "node:fs";
import { coerce, satisfies } from "semver";

//#region src/BaseGenerator.ts
/**
* Abstract class that contains the building blocks for plugins to create their own Generator
* @link idea based on https://github.com/colinhacks/zod/blob/master/src/types.ts#L137
*/
var BaseGenerator = class {
	#options = {};
	#context = {};
	constructor(options, context) {
		if (context) this.#context = context;
		if (options) this.#options = options;
		return this;
	}
	get options() {
		return this.#options;
	}
	get context() {
		return this.#context;
	}
	set options(options) {
		this.#options = {
			...this.#options,
			...options
		};
	}
};

//#endregion
//#region src/config.ts
/**
* Type helper to make it easier to use vite.config.ts accepts a direct UserConfig object, or a function that returns it. The function receives a ConfigEnv object.
*/
function defineConfig(options) {
	return options;
}
function isInputPath(result) {
	return !!result && "path" in result?.input;
}

//#endregion
//#region src/utils/executeStrategies.ts
/**
* Chains promises
*/
function hookSeq(promises$1) {
	return promises$1.filter(Boolean).reduce((promise, func) => {
		if (typeof func !== "function") throw new Error("HookSeq needs a function that returns a promise `() => Promise<unknown>`");
		return promise.then((state) => {
			const calledFunc = func(state);
			if (calledFunc) return calledFunc.then(Array.prototype.concat.bind(state));
		});
	}, Promise.resolve([]));
}
/**
* Chains promises, first non-null result stops and returns
*/
function hookFirst(promises$1, nullCheck = (state) => state !== null) {
	let promise = Promise.resolve(null);
	for (const func of promises$1.filter(Boolean)) promise = promise.then((state) => {
		if (nullCheck(state)) return state;
		return func(state);
	});
	return promise;
}
/**
* Runs an array of promise functions with optional concurrency limit.
*/
function hookParallel(promises$1, concurrency = Number.POSITIVE_INFINITY) {
	const limit = pLimit$1(concurrency);
	const tasks = promises$1.filter(Boolean).map((promise) => limit(() => promise()));
	return Promise.allSettled(tasks);
}

//#endregion
//#region src/PromiseManager.ts
var PromiseManager = class {
	#options = {};
	constructor(options = {}) {
		this.#options = options;
		return this;
	}
	run(strategy, promises$1, { concurrency = Number.POSITIVE_INFINITY } = {}) {
		if (strategy === "seq") return hookSeq(promises$1);
		if (strategy === "first") return hookFirst(promises$1, this.#options.nullCheck);
		if (strategy === "parallel") return hookParallel(promises$1, concurrency);
		throw new Error(`${strategy} not implemented`);
	}
};
function isPromiseRejectedResult(result) {
	return result.status === "rejected";
}

//#endregion
//#region src/errors.ts
var ValidationPluginError = class extends Error {};

//#endregion
//#region src/plugin.ts
function createPlugin(factory) {
	return (options = {}) => {
		return factory(options);
	};
}
const pluginCore = createPlugin((options) => {
	const { fileManager, pluginManager, resolvePath, resolveName, logger } = options;
	return {
		name: "core",
		options,
		key: ["core"],
		context() {
			return {
				get config() {
					return options.config;
				},
				get plugins() {
					return options.getPlugins();
				},
				get plugin() {
					return options.plugin;
				},
				logger,
				fileManager,
				pluginManager,
				async addFile(...files) {
					const resolvedFiles = await fileManager.add(...files);
					if (!Array.isArray(resolvedFiles)) return [resolvedFiles];
					return resolvedFiles;
				},
				resolvePath,
				resolveName
			};
		},
		resolvePath(baseName) {
			const root = path.resolve(options.config.root, options.config.output.path);
			return path.resolve(root, baseName);
		},
		resolveName(name) {
			return name;
		}
	};
});

//#endregion
//#region src/PluginManager.ts
var PluginManager = class {
	plugins = /* @__PURE__ */ new Set();
	fileManager;
	events = new EventEmitter();
	config;
	executed = [];
	logger;
	options;
	#core;
	#usedPluginNames = {};
	#promiseManager;
	constructor(config, options) {
		this.config = config;
		this.options = options;
		this.logger = options.logger;
		this.fileManager = new FileManager();
		this.#promiseManager = new PromiseManager({ nullCheck: (state) => !!state?.result });
		const core = pluginCore({
			config,
			logger: this.logger,
			pluginManager: this,
			fileManager: this.fileManager,
			resolvePath: this.resolvePath.bind(this),
			resolveName: this.resolveName.bind(this),
			getPlugins: this.#getSortedPlugins.bind(this)
		});
		this.#core = this.#parse(core, this, core.context.call(null));
		[this.#core, ...config.plugins || []].forEach((plugin) => {
			const parsedPlugin = this.#parse(plugin, this, this.#core.context);
			this.plugins.add(parsedPlugin);
		});
		return this;
	}
	getFile({ name, mode, extname: extname$1, pluginKey, options }) {
		const baseName = `${name}${extname$1}`;
		const path$1 = this.resolvePath({
			baseName,
			mode,
			pluginKey,
			options
		});
		if (!path$1) throw new Error(`Filepath should be defined for resolvedName "${name}" and pluginKey [${JSON.stringify(pluginKey)}]`);
		return {
			path: path$1,
			baseName,
			meta: { pluginKey },
			sources: []
		};
	}
	resolvePath = (params) => {
		if (params.pluginKey) {
			const paths = this.hookForPluginSync({
				pluginKey: params.pluginKey,
				hookName: "resolvePath",
				parameters: [
					params.baseName,
					params.mode,
					params.options
				],
				message: `Resolving path '${params.baseName}'`
			});
			if (paths && paths?.length > 1) this.logger.emit("debug", {
				date: /* @__PURE__ */ new Date(),
				logs: [`Cannot return a path where the 'pluginKey' ${params.pluginKey ? JSON.stringify(params.pluginKey) : "\""} is not unique enough\n\nPaths: ${JSON.stringify(paths, void 0, 2)}\n\nFalling back on the first item.\n`]
			});
			return paths?.at(0);
		}
		return this.hookFirstSync({
			hookName: "resolvePath",
			parameters: [
				params.baseName,
				params.mode,
				params.options
			],
			message: `Resolving path '${params.baseName}'`
		}).result;
	};
	resolveName = (params) => {
		if (params.pluginKey) {
			const names = this.hookForPluginSync({
				pluginKey: params.pluginKey,
				hookName: "resolveName",
				parameters: [trim(params.name), params.type],
				message: `Resolving name '${params.name}' and type '${params.type}'`
			});
			if (names && names?.length > 1) this.logger.emit("debug", {
				date: /* @__PURE__ */ new Date(),
				logs: [`Cannot return a name where the 'pluginKey' ${params.pluginKey ? JSON.stringify(params.pluginKey) : "\""} is not unique enough\n\nNames: ${JSON.stringify(names, void 0, 2)}\n\nFalling back on the first item.\n`]
			});
			return transformReservedWord(names?.at(0) || params.name);
		}
		const name = this.hookFirstSync({
			hookName: "resolveName",
			parameters: [trim(params.name), params.type],
			message: `Resolving name '${params.name}' and type '${params.type}'`
		}).result;
		return transformReservedWord(name);
	};
	/**
	* Instead of calling `pluginManager.events.on` you can use `pluginManager.on`. This one also has better types.
	*/
	on(eventName, handler) {
		this.events.on(eventName, handler);
	}
	/**
	* Run a specific hookName for plugin x.
	*/
	async hookForPlugin({ pluginKey, hookName, parameters, message }) {
		const plugins = this.getPluginsByKey(hookName, pluginKey);
		this.logger.emit("progress_start", {
			id: hookName,
			size: plugins.length,
			message: "Running plugins..."
		});
		const items = [];
		for (const plugin of plugins) {
			const result = await this.#execute({
				strategy: "hookFirst",
				hookName,
				parameters,
				plugin,
				message
			});
			if (result !== void 0 && result !== null) items.push(result);
		}
		this.logger.emit("progress_stop", { id: hookName });
		return items;
	}
	/**
	* Run a specific hookName for plugin x.
	*/
	hookForPluginSync({ pluginKey, hookName, parameters, message }) {
		return this.getPluginsByKey(hookName, pluginKey).map((plugin) => {
			return this.#executeSync({
				strategy: "hookFirst",
				hookName,
				parameters,
				plugin,
				message
			});
		}).filter(Boolean);
	}
	/**
	* First non-null result stops and will return it's value.
	*/
	async hookFirst({ hookName, parameters, skipped, message }) {
		const plugins = this.#getSortedPlugins(hookName).filter((plugin) => {
			return skipped ? skipped.has(plugin) : true;
		});
		this.logger.emit("progress_start", {
			id: hookName,
			size: plugins.length
		});
		const promises$1 = plugins.map((plugin) => {
			return async () => {
				const value = await this.#execute({
					strategy: "hookFirst",
					hookName,
					parameters,
					plugin,
					message
				});
				return Promise.resolve({
					plugin,
					result: value
				});
			};
		});
		const result = await this.#promiseManager.run("first", promises$1);
		this.logger.emit("progress_stop", { id: hookName });
		return result;
	}
	/**
	* First non-null result stops and will return it's value.
	*/
	hookFirstSync({ hookName, parameters, skipped, message }) {
		let parseResult = null;
		const plugins = this.#getSortedPlugins(hookName).filter((plugin) => {
			return skipped ? skipped.has(plugin) : true;
		});
		for (const plugin of plugins) {
			parseResult = {
				result: this.#executeSync({
					strategy: "hookFirst",
					hookName,
					parameters,
					plugin,
					message
				}),
				plugin
			};
			if (parseResult?.result != null) break;
		}
		return parseResult;
	}
	/**
	* Run all plugins in parallel(order will be based on `this.plugin` and if `pre` or `post` is set).
	*/
	async hookParallel({ hookName, parameters, message }) {
		const plugins = this.#getSortedPlugins(hookName);
		this.logger.emit("progress_start", {
			id: hookName,
			size: plugins.length
		});
		const promises$1 = plugins.map((plugin) => {
			return () => this.#execute({
				strategy: "hookParallel",
				hookName,
				parameters,
				plugin,
				message
			});
		});
		const results = await this.#promiseManager.run("parallel", promises$1, { concurrency: this.options.concurrency });
		results.forEach((result, index) => {
			if (isPromiseRejectedResult(result)) {
				const plugin = this.#getSortedPlugins(hookName)[index];
				this.#catcher(result.reason, plugin, hookName);
			}
		});
		this.logger.emit("progress_stop", { id: hookName });
		return results.filter((result) => result.status === "fulfilled").map((result) => result.value);
	}
	/**
	* Chains plugins
	*/
	async hookSeq({ hookName, parameters, message }) {
		const plugins = this.#getSortedPlugins(hookName);
		this.logger.emit("progress_start", {
			id: hookName,
			size: plugins.length
		});
		const promises$1 = plugins.map((plugin) => {
			return () => this.#execute({
				strategy: "hookSeq",
				hookName,
				parameters,
				plugin,
				message
			});
		});
		await this.#promiseManager.run("seq", promises$1);
		this.logger.emit("progress_stop", { id: hookName });
	}
	#getSortedPlugins(hookName) {
		const plugins = [...this.plugins].filter((plugin) => plugin.name !== "core");
		if (hookName) return plugins.filter((plugin) => hookName in plugin);
		return plugins.map((plugin) => {
			if (plugin.pre) {
				if (!plugin.pre.every((pluginName) => plugins.find((pluginToFind) => pluginToFind.name === pluginName))) throw new ValidationPluginError(`This plugin has a pre set that is not valid(${JSON.stringify(plugin.pre, void 0, 2)})`);
			}
			return plugin;
		}).sort((a, b) => {
			if (b.pre?.includes(a.name)) return 1;
			if (b.post?.includes(a.name)) return -1;
			return 0;
		});
	}
	getPluginByKey(pluginKey) {
		const plugins = [...this.plugins];
		const [searchPluginName] = pluginKey;
		return plugins.find((item) => {
			const [name] = item.key;
			return name === searchPluginName;
		});
	}
	getPluginsByKey(hookName, pluginKey) {
		const plugins = [...this.plugins];
		const [searchPluginName, searchIdentifier] = pluginKey;
		const pluginByPluginName = plugins.filter((plugin) => hookName in plugin).filter((item) => {
			const [name, identifier] = item.key;
			const identifierCheck = identifier?.toString() === searchIdentifier?.toString();
			const nameCheck = name === searchPluginName;
			if (searchIdentifier) return identifierCheck && nameCheck;
			return nameCheck;
		});
		if (!pluginByPluginName?.length) {
			const corePlugin = plugins.find((plugin) => plugin.name === "core" && hookName in plugin);
			if (corePlugin) this.logger.emit("debug", {
				date: /* @__PURE__ */ new Date(),
				logs: [`No hook '${hookName}' for pluginKey '${JSON.stringify(pluginKey)}' found, falling back on the '@kubb/core' plugin`]
			});
			else this.logger.emit("debug", {
				date: /* @__PURE__ */ new Date(),
				logs: [`No hook '${hookName}' for pluginKey '${JSON.stringify(pluginKey)}' found, no fallback found in the '@kubb/core' plugin`]
			});
			return corePlugin ? [corePlugin] : [];
		}
		return pluginByPluginName;
	}
	#addExecutedToCallStack(executer) {
		if (executer) {
			this.events.emit("executed", executer);
			this.executed.push(executer);
			this.logger.emit("progressed", {
				id: executer.hookName,
				message: `${executer.plugin.name}: ${executer.message}`
			});
		}
	}
	/**
	* Run an async plugin hook and return the result.
	* @param hookName Name of the plugin hook. Must be either in `PluginHooks` or `OutputPluginValueHooks`.
	* @param args Arguments passed to the plugin hook.
	* @param plugin The actual pluginObject to run.
	*/
	#execute({ strategy, hookName, parameters, plugin, message }) {
		const hook = plugin[hookName];
		let output;
		if (!hook) return null;
		this.events.emit("executing", {
			strategy,
			hookName,
			parameters,
			plugin,
			message
		});
		return (async () => {
			try {
				if (typeof hook === "function") {
					const result = await Promise.resolve(hook.apply({
						...this.#core.context,
						plugin
					}, parameters));
					output = result;
					this.#addExecutedToCallStack({
						parameters,
						output,
						strategy,
						hookName,
						plugin,
						message
					});
					return result;
				}
				output = hook;
				this.#addExecutedToCallStack({
					parameters,
					output,
					strategy,
					hookName,
					plugin,
					message
				});
				return hook;
			} catch (e) {
				this.#catcher(e, plugin, hookName);
				return null;
			}
		})();
	}
	/**
	* Run a sync plugin hook and return the result.
	* @param hookName Name of the plugin hook. Must be in `PluginHooks`.
	* @param args Arguments passed to the plugin hook.
	* @param plugin The acutal plugin
	* @param replaceContext When passed, the plugin context can be overridden.
	*/
	#executeSync({ strategy, hookName, parameters, plugin, message }) {
		const hook = plugin[hookName];
		let output;
		if (!hook) return null;
		this.events.emit("executing", {
			strategy,
			hookName,
			parameters,
			plugin,
			message
		});
		try {
			if (typeof hook === "function") {
				const fn = hook.apply({
					...this.#core.context,
					plugin
				}, parameters);
				output = fn;
				this.#addExecutedToCallStack({
					parameters,
					output,
					strategy,
					hookName,
					plugin,
					message
				});
				return fn;
			}
			output = hook;
			this.#addExecutedToCallStack({
				parameters,
				output,
				strategy,
				hookName,
				plugin,
				message
			});
			return hook;
		} catch (e) {
			this.#catcher(e, plugin, hookName);
			return null;
		}
	}
	#catcher(cause, plugin, hookName) {
		const text = `${cause.message} (plugin: ${plugin?.name || "unknown"}, hook: ${hookName || "unknown"})`;
		this.logger.emit("error", text, cause);
		this.events.emit("error", cause);
	}
	#parse(plugin, pluginManager, context) {
		const usedPluginNames = pluginManager.#usedPluginNames;
		setUniqueName(plugin.name, usedPluginNames);
		const key = [plugin.name, usedPluginNames[plugin.name]].filter(Boolean);
		if (plugin.context && typeof plugin.context === "function") return {
			...plugin,
			key,
			context: plugin.context.call(context)
		};
		return {
			...plugin,
			key
		};
	}
	static getDependedPlugins(plugins, dependedPluginNames) {
		let pluginNames = [];
		if (typeof dependedPluginNames === "string") pluginNames = [dependedPluginNames];
		else pluginNames = dependedPluginNames;
		return pluginNames.map((pluginName) => {
			const plugin = plugins.find((plugin$1) => plugin$1.name === pluginName);
			if (!plugin) throw new ValidationPluginError(`This plugin depends on the ${pluginName} plugin.`);
			return plugin;
		});
	}
	static get hooks() {
		return [
			"buildStart",
			"resolvePath",
			"resolveName",
			"buildEnd"
		];
	}
};

//#endregion
//#region src/build.ts
async function setup(options) {
	if (options.pluginManager) return options.pluginManager;
	const { config: userConfig, logger = createLogger() } = options;
	if (Array.isArray(userConfig.input)) console.warn(pc.yellow("This feature is still under development — use with caution"));
	try {
		if (isInputPath(userConfig) && !new URLPath(userConfig.input.path).isURL) await exists(userConfig.input.path);
	} catch (e) {
		if (isInputPath(userConfig)) throw new Error(`Cannot read file/URL defined in \`input.path\` or set with \`kubb generate PATH\` in the CLI of your Kubb config ${userConfig.input.path}`, { cause: e });
	}
	const definedConfig = {
		root: userConfig.root || process.cwd(),
		...userConfig,
		output: {
			write: true,
			barrelType: "named",
			extension: { ".ts": ".ts" },
			defaultBanner: "simple",
			...userConfig.output
		},
		plugins: userConfig.plugins
	};
	if (definedConfig.output.clean) {
		await clean(definedConfig.output.path);
		await clean(join(definedConfig.root, ".kubb"));
	}
	return new PluginManager(definedConfig, {
		logger,
		concurrency: 5
	});
}
async function build(options) {
	const { files, pluginManager, error } = await safeBuild(options);
	if (error) throw error;
	return {
		files,
		pluginManager,
		error
	};
}
async function safeBuild(options) {
	const pluginManager = await setup(options);
	const config = pluginManager.config;
	try {
		pluginManager.events.on("executing", ({ plugin, message }) => {
			pluginManager.logger.emit("debug", {
				date: /* @__PURE__ */ new Date(),
				logs: [`Executing pluginKey ${plugin.key?.join(".")} | ${message}`]
			});
		});
		pluginManager.events.on("executed", ({ plugin, message, output }) => {
			pluginManager.logger.emit("debug", {
				date: /* @__PURE__ */ new Date(),
				logs: [`Executed pluginKey ${plugin.key?.join(".")} | ${message} |  ${JSON.stringify(output, void 0, 2)}`]
			});
		});
		await pluginManager.hookParallel({
			hookName: "buildStart",
			parameters: [config],
			message: "buildStart"
		});
		if (config.output.barrelType) {
			const root = resolve(config.root);
			const rootPath = resolve(root, config.output.path, "index.ts");
			const barrelFiles = (await pluginManager.fileManager.getFiles()).filter((file) => {
				return file.sources.some((source) => source.isIndexable);
			});
			const rootFile = {
				path: rootPath,
				baseName: "index.ts",
				exports: barrelFiles.flatMap((file) => {
					const containsOnlyTypes = file.sources?.every((source) => source.isTypeOnly);
					return file.sources?.map((source) => {
						if (!file.path || !source.isIndexable) return;
						const pluginOptions = [...pluginManager.plugins].find((item) => {
							const meta = file.meta;
							return isDeepEqual(item.key, meta?.pluginKey);
						})?.options;
						if (!pluginOptions || pluginOptions?.output?.barrelType === false) return;
						return {
							name: config.output.barrelType === "all" ? void 0 : [source.name],
							path: getRelativePath(rootPath, file.path),
							isTypeOnly: config.output.barrelType === "all" ? containsOnlyTypes : source.isTypeOnly
						};
					}).filter(Boolean);
				}).filter(Boolean),
				sources: [],
				meta: {}
			};
			await pluginManager.fileManager.add(rootFile);
		}
		const files = await pluginManager.fileManager.processFiles({
			root: config.root,
			extension: config.output.extension,
			dryRun: !config.output.write,
			logger: pluginManager.logger
		});
		await pluginManager.hookParallel({
			hookName: "buildEnd",
			message: `Build stopped for ${config.name}`
		});
		await pluginManager.fileManager.clear();
		return {
			files,
			pluginManager
		};
	} catch (e) {
		return {
			files: [],
			pluginManager,
			error: e
		};
	}
}

//#endregion
//#region ../../node_modules/.pnpm/p-limit@4.0.0/node_modules/p-limit/index.js
function pLimit(concurrency) {
	if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) throw new TypeError("Expected `concurrency` to be a number from 1 and up");
	const queue = new Queue();
	let activeCount = 0;
	const next = () => {
		activeCount--;
		if (queue.size > 0) queue.dequeue()();
	};
	const run = async (fn, resolve$1, args) => {
		activeCount++;
		const result = (async () => fn(...args))();
		resolve$1(result);
		try {
			await result;
		} catch {}
		next();
	};
	const enqueue = (fn, resolve$1, args) => {
		queue.enqueue(run.bind(void 0, fn, resolve$1, args));
		(async () => {
			await Promise.resolve();
			if (activeCount < concurrency && queue.size > 0) queue.dequeue()();
		})();
	};
	const generator = (fn, ...args) => new Promise((resolve$1) => {
		enqueue(fn, resolve$1, args);
	});
	Object.defineProperties(generator, {
		activeCount: { get: () => activeCount },
		pendingCount: { get: () => queue.size },
		clearQueue: { value: () => {
			queue.clear();
		} }
	});
	return generator;
}

//#endregion
//#region ../../node_modules/.pnpm/p-locate@6.0.0/node_modules/p-locate/index.js
var EndError = class extends Error {
	constructor(value) {
		super();
		this.value = value;
	}
};
const testElement = async (element, tester) => tester(await element);
const finder = async (element) => {
	const values = await Promise.all(element);
	if (values[1] === true) throw new EndError(values[0]);
	return false;
};
async function pLocate(iterable, tester, { concurrency = Number.POSITIVE_INFINITY, preserveOrder = true } = {}) {
	const limit = pLimit(concurrency);
	const items = [...iterable].map((element) => [element, limit(testElement, element, tester)]);
	const checkLimit = pLimit(preserveOrder ? 1 : Number.POSITIVE_INFINITY);
	try {
		await Promise.all(items.map((element) => checkLimit(finder, element)));
	} catch (error) {
		if (error instanceof EndError) return error.value;
		throw error;
	}
}

//#endregion
//#region ../../node_modules/.pnpm/locate-path@7.2.0/node_modules/locate-path/index.js
const typeMappings = {
	directory: "isDirectory",
	file: "isFile"
};
function checkType(type) {
	if (Object.hasOwnProperty.call(typeMappings, type)) return;
	throw new Error(`Invalid type specified: ${type}`);
}
const matchType = (type, stat) => stat[typeMappings[type]]();
const toPath$1 = (urlOrPath) => urlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath;
async function locatePath(paths, { cwd = g$1.cwd(), type = "file", allowSymlinks = true, concurrency, preserveOrder } = {}) {
	checkType(type);
	cwd = toPath$1(cwd);
	const statFunction = allowSymlinks ? promises.stat : promises.lstat;
	return pLocate(paths, async (path_) => {
		try {
			const stat = await statFunction(path.resolve(cwd, path_));
			return matchType(type, stat);
		} catch {
			return false;
		}
	}, {
		concurrency,
		preserveOrder
	});
}
function locatePathSync(paths, { cwd = g$1.cwd(), type = "file", allowSymlinks = true } = {}) {
	checkType(type);
	cwd = toPath$1(cwd);
	const statFunction = allowSymlinks ? fs.statSync : fs.lstatSync;
	for (const path_ of paths) try {
		const stat = statFunction(path.resolve(cwd, path_), { throwIfNoEntry: false });
		if (!stat) continue;
		if (matchType(type, stat)) return path_;
	} catch {}
}

//#endregion
//#region ../../node_modules/.pnpm/unicorn-magic@0.1.0/node_modules/unicorn-magic/node.js
function toPath(urlOrPath) {
	return urlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath;
}

//#endregion
//#region ../../node_modules/.pnpm/find-up@7.0.0/node_modules/find-up/index.js
const findUpStop = Symbol("findUpStop");
async function findUpMultiple(name, options = {}) {
	let directory = path.resolve(toPath(options.cwd) ?? "");
	const { root } = path.parse(directory);
	const stopAt = path.resolve(directory, toPath(options.stopAt ?? root));
	const limit = options.limit ?? Number.POSITIVE_INFINITY;
	const paths = [name].flat();
	const runMatcher = async (locateOptions) => {
		if (typeof name !== "function") return locatePath(paths, locateOptions);
		const foundPath = await name(locateOptions.cwd);
		if (typeof foundPath === "string") return locatePath([foundPath], locateOptions);
		return foundPath;
	};
	const matches = [];
	while (true) {
		const foundPath = await runMatcher({
			...options,
			cwd: directory
		});
		if (foundPath === findUpStop) break;
		if (foundPath) matches.push(path.resolve(directory, foundPath));
		if (directory === stopAt || matches.length >= limit) break;
		directory = path.dirname(directory);
	}
	return matches;
}
function findUpMultipleSync(name, options = {}) {
	let directory = path.resolve(toPath(options.cwd) ?? "");
	const { root } = path.parse(directory);
	const stopAt = path.resolve(directory, toPath(options.stopAt) ?? root);
	const limit = options.limit ?? Number.POSITIVE_INFINITY;
	const paths = [name].flat();
	const runMatcher = (locateOptions) => {
		if (typeof name !== "function") return locatePathSync(paths, locateOptions);
		const foundPath = name(locateOptions.cwd);
		if (typeof foundPath === "string") return locatePathSync([foundPath], locateOptions);
		return foundPath;
	};
	const matches = [];
	while (true) {
		const foundPath = runMatcher({
			...options,
			cwd: directory
		});
		if (foundPath === findUpStop) break;
		if (foundPath) matches.push(path.resolve(directory, foundPath));
		if (directory === stopAt || matches.length >= limit) break;
		directory = path.dirname(directory);
	}
	return matches;
}
async function findUp(name, options = {}) {
	return (await findUpMultiple(name, {
		...options,
		limit: 1
	}))[0];
}
function findUpSync(name, options = {}) {
	return findUpMultipleSync(name, {
		...options,
		limit: 1
	})[0];
}

//#endregion
//#region src/PackageManager.ts
var PackageManager = class PackageManager {
	static #cache = {};
	#cwd;
	#SLASHES = new Set(["/", "\\"]);
	constructor(workspace) {
		if (workspace) this.#cwd = workspace;
		return this;
	}
	set workspace(workspace) {
		this.#cwd = workspace;
	}
	get workspace() {
		return this.#cwd;
	}
	normalizeDirectory(directory) {
		if (!this.#SLASHES.has(directory[directory.length - 1])) return `${directory}/`;
		return directory;
	}
	getLocation(path$1) {
		let location = path$1;
		if (this.#cwd) location = mod.createRequire(this.normalizeDirectory(this.#cwd)).resolve(path$1);
		return location;
	}
	async import(path$1) {
		try {
			let location = this.getLocation(path$1);
			if (os.platform() === "win32") location = pathToFileURL(location).href;
			const module = await import(location);
			return module?.default ?? module;
		} catch (e) {
			console.error(e);
			return;
		}
	}
	async getPackageJSON() {
		const pkgPath = await findUp(["package.json"], { cwd: this.#cwd });
		if (!pkgPath) return;
		const json = await read(pkgPath);
		return JSON.parse(json);
	}
	getPackageJSONSync() {
		const pkgPath = findUpSync(["package.json"], { cwd: this.#cwd });
		if (!pkgPath) return;
		const json = readSync(pkgPath);
		return JSON.parse(json);
	}
	static setVersion(dependency, version) {
		PackageManager.#cache[dependency] = version;
	}
	#match(packageJSON, dependency) {
		const dependencies = {
			...packageJSON["dependencies"] || {},
			...packageJSON["devDependencies"] || {}
		};
		if (typeof dependency === "string" && dependencies[dependency]) return dependencies[dependency];
		const matchedDependency = Object.keys(dependencies).find((dep) => dep.match(dependency));
		return matchedDependency ? dependencies[matchedDependency] : void 0;
	}
	async getVersion(dependency) {
		if (typeof dependency === "string" && PackageManager.#cache[dependency]) return PackageManager.#cache[dependency];
		const packageJSON = await this.getPackageJSON();
		if (!packageJSON) return;
		return this.#match(packageJSON, dependency);
	}
	getVersionSync(dependency) {
		if (typeof dependency === "string" && PackageManager.#cache[dependency]) return PackageManager.#cache[dependency];
		const packageJSON = this.getPackageJSONSync();
		if (!packageJSON) return;
		return this.#match(packageJSON, dependency);
	}
	async isValid(dependency, version) {
		const packageVersion = await this.getVersion(dependency);
		if (!packageVersion) return false;
		if (packageVersion === version) return true;
		const semVer = coerce(packageVersion);
		if (!semVer) throw new Error(`${packageVersion} is not valid`);
		return satisfies(semVer, version);
	}
	isValidSync(dependency, version) {
		const packageVersion = this.getVersionSync(dependency);
		if (!packageVersion) return false;
		if (version === "next" && packageVersion === version) return true;
		const semVer = coerce(packageVersion);
		if (!semVer) return false;
		return satisfies(semVer, version);
	}
};

//#endregion
export { BaseGenerator, FileManager, PackageManager, PluginManager, PromiseManager, build, createPlugin, build as default, defineConfig, getDefaultBanner, getSource, isInputPath, safeBuild, setup };
//# sourceMappingURL=index.js.map