import { builtinModules } from "node:module";
import { existsSync, promises } from "node:fs";
import process from "node:process";
import { fileURLToPath, pathToFileURL } from "node:url";
import { dirname, join, resolve } from "pathe";

//#region src/utils.ts
const isWindows = process.platform === "win32";
const drive = isWindows ? process.cwd()[0] : null;
const driveOpposite = drive ? drive === drive.toUpperCase() ? drive.toLowerCase() : drive.toUpperCase() : null;
const driveRegexp = drive ? /* @__PURE__ */ new RegExp(`(?:^|/@fs/)${drive}(\:[\\/])`) : null;
const driveOppositeRegext = driveOpposite ? /* @__PURE__ */ new RegExp(`(?:^|/@fs/)${driveOpposite}(\:[\\/])`) : null;
function slash(str) {
	return str.replace(/\\/g, "/");
}
const bareImportRE = /^(?![a-z]:)[\w@](?!.*:\/\/)/i;
function isBareImport(id) {
	return bareImportRE.test(id);
}
const VALID_ID_PREFIX = "/@id/";
function normalizeRequestId(id, base) {
	if (base && id.startsWith(withTrailingSlash(base))) id = `/${id.slice(base.length)}`;
	if (driveRegexp && !driveRegexp?.test(id) && driveOppositeRegext?.test(id)) id = id.replace(driveOppositeRegext, `${drive}$1`);
	if (id.startsWith("file://")) {
		const { file, postfix } = splitFileAndPostfix(id);
		return fileURLToPath(file) + postfix;
	}
	return id.replace(/^\/@id\/__x00__/, "\0").replace(/^\/@id\//, "").replace(/^__vite-browser-external:/, "").replace(/\?v=\w+/, "?").replace(/&v=\w+/, "").replace(/\?t=\w+/, "?").replace(/&t=\w+/, "").replace(/\?import/, "?").replace(/&import/, "").replace(/\?&/, "?").replace(/\?+$/, "");
}
const postfixRE = /[?#].*$/;
function cleanUrl(url) {
	return url.replace(postfixRE, "");
}
function splitFileAndPostfix(path) {
	const file = cleanUrl(path);
	return {
		file,
		postfix: path.slice(file.length)
	};
}
const internalRequestRegexp = /* @__PURE__ */ new RegExp(`^/?(?:${["@vite/client", "@vite/env"].join("|")})$`);
function isInternalRequest(id) {
	return internalRequestRegexp.test(id);
}
const prefixedBuiltins = new Set([
	"node:sea",
	"node:sqlite",
	"node:test",
	"node:test/reporters"
]);
const builtins = new Set([
	...builtinModules,
	"assert/strict",
	"diagnostics_channel",
	"dns/promises",
	"fs/promises",
	"path/posix",
	"path/win32",
	"readline/promises",
	"stream/consumers",
	"stream/promises",
	"stream/web",
	"timers/promises",
	"util/types",
	"wasi"
]);
function normalizeModuleId(id) {
	if (prefixedBuiltins.has(id)) return id;
	if (id.startsWith("file://")) return fileURLToPath(id);
	return id.replace(/\\/g, "/").replace(/^\/@fs\//, isWindows ? "" : "/").replace(/^node:/, "").replace(/^\/+/, "/");
}
function isPrimitive(v) {
	return v !== Object(v);
}
function toFilePath(id, root) {
	let { absolute, exists } = (() => {
		if (id.startsWith("/@fs/")) return {
			absolute: id.slice(4),
			exists: true
		};
		if (!id.startsWith(withTrailingSlash(root)) && id.startsWith("/")) {
			const resolved = resolve(root, id.slice(1));
			if (existsSync(cleanUrl(resolved))) return {
				absolute: resolved,
				exists: true
			};
		} else if (id.startsWith(withTrailingSlash(root)) && existsSync(cleanUrl(id))) return {
			absolute: id,
			exists: true
		};
		return {
			absolute: id,
			exists: false
		};
	})();
	if (absolute.startsWith("//")) absolute = absolute.slice(1);
	return {
		path: isWindows && absolute.startsWith("/") ? slash(fileURLToPath(pathToFileURL(absolute.slice(1)).href)) : absolute,
		exists
	};
}
const NODE_BUILTIN_NAMESPACE = "node:";
function isNodeBuiltin(id) {
	if (prefixedBuiltins.has(id)) return true;
	return builtins.has(id.startsWith(NODE_BUILTIN_NAMESPACE) ? id.slice(5) : id);
}
/**
* Convert `Arrayable<T>` to `Array<T>`
*
* @category Array
*/
function toArray(array) {
	if (array === null || array === void 0) array = [];
	if (Array.isArray(array)) return array;
	return [array];
}
function getCachedData(cache, basedir, originalBasedir) {
	const pkgData = cache.get(getFnpdCacheKey(basedir));
	if (pkgData) {
		traverseBetweenDirs(originalBasedir, basedir, (dir) => {
			cache.set(getFnpdCacheKey(dir), pkgData);
		});
		return pkgData;
	}
}
function setCacheData(cache, data, basedir, originalBasedir) {
	cache.set(getFnpdCacheKey(basedir), data);
	traverseBetweenDirs(originalBasedir, basedir, (dir) => {
		cache.set(getFnpdCacheKey(dir), data);
	});
}
function getFnpdCacheKey(basedir) {
	return `fnpd_${basedir}`;
}
/**
* Traverse between `longerDir` (inclusive) and `shorterDir` (exclusive) and call `cb` for each dir.
* @param longerDir Longer dir path, e.g. `/User/foo/bar/baz`
* @param shorterDir Shorter dir path, e.g. `/User/foo`
*/
function traverseBetweenDirs(longerDir, shorterDir, cb) {
	while (longerDir !== shorterDir) {
		cb(longerDir);
		longerDir = dirname(longerDir);
	}
}
function withTrailingSlash(path) {
	if (path[path.length - 1] !== "/") return `${path}/`;
	return path;
}
function createImportMetaEnvProxy() {
	const booleanKeys = [
		"DEV",
		"PROD",
		"SSR"
	];
	return new Proxy(process.env, {
		get(_, key) {
			if (typeof key !== "string") return;
			if (booleanKeys.includes(key)) return !!process.env[key];
			return process.env[key];
		},
		set(_, key, value) {
			if (typeof key !== "string") return true;
			if (booleanKeys.includes(key)) process.env[key] = value ? "1" : "";
			else process.env[key] = value;
			return true;
		}
	});
}
const packageCache = /* @__PURE__ */ new Map();
async function findNearestPackageData(basedir) {
	const originalBasedir = basedir;
	while (basedir) {
		const cached = getCachedData(packageCache, basedir, originalBasedir);
		if (cached) return cached;
		const pkgPath = join(basedir, "package.json");
		if ((await promises.stat(pkgPath).catch(() => {}))?.isFile()) {
			const pkgData = JSON.parse(await promises.readFile(pkgPath, "utf8"));
			if (packageCache) setCacheData(packageCache, pkgData, basedir, originalBasedir);
			return pkgData;
		}
		const nextBasedir = dirname(basedir);
		if (nextBasedir === basedir) break;
		basedir = nextBasedir;
	}
	return {};
}

//#endregion
export { withTrailingSlash as _, getCachedData as a, isNodeBuiltin as c, normalizeModuleId as d, normalizeRequestId as f, toFilePath as g, toArray as h, findNearestPackageData as i, isPrimitive as l, slash as m, cleanUrl as n, isBareImport as o, setCacheData as p, createImportMetaEnvProxy as r, isInternalRequest as s, VALID_ID_PREFIX as t, isWindows as u };