UNPKG

@visulima/find-cache-dir

Version:

Finds the common standard cache directory

819 lines (801 loc) 21.2 kB
import { createRequire as __cjs_createRequire } from "node:module"; const __cjs_require = __cjs_createRequire(import.meta.url); const __cjs_getProcess = typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" ? globalThis.process : process; const __cjs_getBuiltinModule = (module) => { // Check if we're in Node.js and version supports getBuiltinModule if (typeof __cjs_getProcess !== "undefined" && __cjs_getProcess.versions && __cjs_getProcess.versions.node) { const [major, minor] = __cjs_getProcess.versions.node.split(".").map(Number); // Node.js 20.16.0+ and 22.3.0+ if (major > 22 || (major === 22 && minor >= 3) || (major === 20 && minor >= 16)) { return __cjs_getProcess.getBuiltinModule(module); } } // Fallback to createRequire return __cjs_require(module); }; const { existsSync } = __cjs_getBuiltinModule("node:fs"); const { env, cwd: cwd$1 } = __cjs_getProcess; const { createRequire } = __cjs_getBuiltinModule("node:module"); const F_OK = 0; const W_OK = 2; const FIND_UP_STOP = /* @__PURE__ */ Symbol("findUpStop"); const assertValidFileOrDirectoryPath = (fileOrDirectoryPath) => { if (!fileOrDirectoryPath || !(fileOrDirectoryPath instanceof URL) && typeof fileOrDirectoryPath !== "string") { throw new TypeError("Path must be a non-empty string or URL."); } }; const getFileInfoType = (fileInfo) => { if (fileInfo.isFile()) { return "file"; } if (fileInfo.isDirectory()) { return "dir"; } if (fileInfo.isSymbolicLink()) { return "symlink"; } return void 0; }; const __cjs_require$5 = createRequire(import.meta.url); const __cjs_getProcess$5 = typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" ? globalThis.process : process; const __cjs_getBuiltinModule$5 = (module) => { if (typeof __cjs_getProcess$5 !== "undefined" && __cjs_getProcess$5.versions && __cjs_getProcess$5.versions.node) { const [major, minor] = __cjs_getProcess$5.versions.node.split(".").map(Number); if (major > 22 || major === 22 && minor >= 3 || major === 20 && minor >= 16) { return __cjs_getProcess$5.getBuiltinModule(module); } } return __cjs_require$5(module); }; const { lstatSync: lstatSync$1, mkdirSync } = __cjs_getBuiltinModule$5("node:fs"); const ensureDirSync = (directory) => { assertValidFileOrDirectoryPath(directory); try { const fileInfo = lstatSync$1(directory); if (!fileInfo.isDirectory()) { throw new Error(`Ensure path exists, expected 'dir', got '${getFileInfoType(fileInfo)}'`); } return; } catch (error) { if (error.code !== "ENOENT") { throw error; } } try { mkdirSync(directory, { recursive: true }); } catch (error) { if (error.code !== "EEXIST") { throw error; } const fileInfo = lstatSync$1(directory); if (!fileInfo.isDirectory()) { throw new Error(`Ensure path exists, expected 'dir', got '${getFileInfoType(fileInfo)}'`); } } }; const DRIVE_LETTER_START_RE = /^[A-Z]:\//i; const normalizeWindowsPath = (input = "") => { if (!input) { return input; } return input.replaceAll("\\", "/").replace(DRIVE_LETTER_START_RE, (r) => r.toUpperCase()); }; const UNC_REGEX = /^[/\\]{2}/; const IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Z]:[/\\]/i; const DRIVE_LETTER_RE = /^[A-Z]:$/i; const EXTNAME_RE = /.(\.[^./]+)$/; const PATH_ROOT_RE = /^[/\\]|^[a-z]:[/\\]/i; const cwd = () => { if (typeof process.cwd === "function") { return process.cwd().replaceAll("\\", "/"); } return "/"; }; const normalizeString = (path2, allowAboveRoot) => { let result = ""; let lastSegmentLength = 0; let lastSlash = -1; let dots = 0; let char; for (let index = 0; index <= path2.length; ++index) { if (index < path2.length) { char = path2[index]; } else if (char === "/") { break; } else { char = "/"; } if (char === "/") { if (lastSlash === index - 1 || dots === 1) ; else if (dots === 2) { if (result.length < 2 || lastSegmentLength !== 2 || !result.endsWith(".") || result.at(-2) !== ".") { if (result.length > 2) { const lastSlashIndex = result.lastIndexOf("/"); if (lastSlashIndex === -1) { result = ""; lastSegmentLength = 0; } else { result = result.slice(0, lastSlashIndex); lastSegmentLength = result.length - 1 - result.lastIndexOf("/"); } lastSlash = index; dots = 0; continue; } else if (result.length > 0) { result = ""; lastSegmentLength = 0; lastSlash = index; dots = 0; continue; } } if (allowAboveRoot) { result += result.length > 0 ? "/.." : ".."; lastSegmentLength = 2; } } else { if (result.length > 0) { result += `/${path2.slice(lastSlash + 1, index)}`; } else { result = path2.slice(lastSlash + 1, index); } lastSegmentLength = index - lastSlash - 1; } lastSlash = index; dots = 0; } else if (char === "." && dots !== -1) { ++dots; } else { dots = -1; } } return result; }; const isAbsolute = (path2) => IS_ABSOLUTE_RE.test(path2); const normalize = function(path2) { if (path2.length === 0) { return "."; } path2 = normalizeWindowsPath(path2); const isUNCPath = UNC_REGEX.exec(path2); const isPathAbsolute = isAbsolute(path2); const trailingSeparator = path2.at(-1) === "/"; path2 = normalizeString(path2, !isPathAbsolute); if (path2.length === 0) { if (isPathAbsolute) { return "/"; } return trailingSeparator ? "./" : "."; } if (trailingSeparator) { path2 += "/"; } if (DRIVE_LETTER_RE.test(path2)) { path2 += "/"; } if (isUNCPath) { if (!isPathAbsolute) { return `//./${path2}`; } return `//${path2}`; } return isPathAbsolute && !isAbsolute(path2) ? `/${path2}` : path2; }; const join = (...segments) => { let path2 = ""; for (const seg of segments) { if (!seg) { continue; } if (path2.length > 0) { const pathTrailing = path2[path2.length - 1] === "/"; const segLeading = seg[0] === "/"; const both = pathTrailing && segLeading; if (both) { path2 += seg.slice(1); } else { path2 += pathTrailing || segLeading ? seg : `/${seg}`; } } else { path2 += seg; } } return normalize(path2); }; const resolve = function(...arguments_) { arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument)); let resolvedPath = ""; let resolvedAbsolute = false; for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) { const path2 = index >= 0 ? arguments_[index] : cwd(); if (!path2 || path2.length === 0) { continue; } resolvedPath = `${path2}/${resolvedPath}`; resolvedAbsolute = isAbsolute(path2); } resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute); if (resolvedAbsolute && !isAbsolute(resolvedPath)) { return `/${resolvedPath}`; } return resolvedPath.length > 0 ? resolvedPath : "."; }; const extname = function(p) { const match = EXTNAME_RE.exec(normalizeWindowsPath(p)); return match?.[1] ?? ""; }; const dirname = (path2) => { const segments = normalizeWindowsPath(path2).replace(/\/$/, "").split("/").slice(0, -1); if (segments.length === 1 && DRIVE_LETTER_RE.test(segments[0])) { segments[0] += "/"; } return segments.join("/") || (isAbsolute(path2) ? "/" : "."); }; const basename = (path2, extension) => { const lastSegment = normalizeWindowsPath(path2).split("/").pop(); if (extension && lastSegment.endsWith(extension)) { return lastSegment.slice(0, -extension.length); } return lastSegment; }; const parse = function(p) { const root = PATH_ROOT_RE.exec(p)?.[0]?.replaceAll("\\", "/") ?? ""; const base = basename(p); const extension = extname(base); return { base, dir: dirname(p), ext: extension, name: base.slice(0, base.length - extension.length), root }; }; const __cjs_require$4 = createRequire(import.meta.url); const __cjs_getProcess$4 = typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" ? globalThis.process : process; const __cjs_getBuiltinModule$4 = (module) => { if (typeof __cjs_getProcess$4 !== "undefined" && __cjs_getProcess$4.versions && __cjs_getProcess$4.versions.node) { const [major, minor] = __cjs_getProcess$4.versions.node.split(".").map(Number); if (major > 22 || major === 22 && minor >= 3 || major === 20 && minor >= 16) { return __cjs_getProcess$4.getBuiltinModule(module); } } return __cjs_require$4(module); }; const { fileURLToPath: fileURLToPath$2 } = __cjs_getBuiltinModule$4("node:url"); function getDefaultExportFromCjs(x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x; } var binaryExtensions$1; var hasRequiredBinaryExtensions; function requireBinaryExtensions() { if (hasRequiredBinaryExtensions) return binaryExtensions$1; hasRequiredBinaryExtensions = 1; binaryExtensions$1 = [ "3dm", "3ds", "3g2", "3gp", "7z", "a", "aac", "adp", "afdesign", "afphoto", "afpub", "ai", "aif", "aiff", "alz", "ape", "apk", "appimage", "ar", "arj", "asf", "au", "avi", "bak", "baml", "bh", "bin", "bk", "bmp", "btif", "bz2", "bzip2", "cab", "caf", "cgm", "class", "cmx", "cpio", "cr2", "cr3", "cur", "dat", "dcm", "deb", "dex", "djvu", "dll", "dmg", "dng", "doc", "docm", "docx", "dot", "dotm", "dra", "DS_Store", "dsk", "dts", "dtshd", "dvb", "dwg", "dxf", "ecelp4800", "ecelp7470", "ecelp9600", "egg", "eol", "eot", "epub", "exe", "f4v", "fbs", "fh", "fla", "flac", "flatpak", "fli", "flv", "fpx", "fst", "fvt", "g3", "gh", "gif", "graffle", "gz", "gzip", "h261", "h263", "h264", "icns", "ico", "ief", "img", "ipa", "iso", "jar", "jpeg", "jpg", "jpgv", "jpm", "jxr", "key", "ktx", "lha", "lib", "lvp", "lz", "lzh", "lzma", "lzo", "m3u", "m4a", "m4v", "mar", "mdi", "mht", "mid", "midi", "mj2", "mka", "mkv", "mmr", "mng", "mobi", "mov", "movie", "mp3", "mp4", "mp4a", "mpeg", "mpg", "mpga", "mxu", "nef", "npx", "numbers", "nupkg", "o", "odp", "ods", "odt", "oga", "ogg", "ogv", "otf", "ott", "pages", "pbm", "pcx", "pdb", "pdf", "pea", "pgm", "pic", "png", "pnm", "pot", "potm", "potx", "ppa", "ppam", "ppm", "pps", "ppsm", "ppsx", "ppt", "pptm", "pptx", "psd", "pya", "pyc", "pyo", "pyv", "qt", "rar", "ras", "raw", "resources", "rgb", "rip", "rlc", "rmf", "rmvb", "rpm", "rtf", "rz", "s3m", "s7z", "scpt", "sgi", "shar", "snap", "sil", "sketch", "slk", "smv", "snk", "so", "stl", "suo", "sub", "swf", "tar", "tbz", "tbz2", "tga", "tgz", "thmx", "tif", "tiff", "tlz", "ttc", "ttf", "txz", "udf", "uvh", "uvi", "uvm", "uvp", "uvs", "uvu", "viv", "vob", "war", "wav", "wax", "wbmp", "wdp", "weba", "webm", "webp", "whl", "wim", "wm", "wma", "wmv", "wmx", "woff", "woff2", "wrm", "wvx", "xbm", "xif", "xla", "xlam", "xls", "xlsb", "xlsm", "xlsx", "xlt", "xltm", "xltx", "xm", "xmind", "xpi", "xpm", "xwd", "xz", "z", "zip", "zipx" ]; return binaryExtensions$1; } var binaryExtensionsExports = /* @__PURE__ */ requireBinaryExtensions(); const binaryExtensions = /* @__PURE__ */ getDefaultExportFromCjs(binaryExtensionsExports); new Set(binaryExtensions); const toPath = (urlOrPath) => normalizeWindowsPath(urlOrPath instanceof URL ? fileURLToPath$2(urlOrPath) : urlOrPath); const __cjs_require$3 = createRequire(import.meta.url); const __cjs_getProcess$3 = typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" ? globalThis.process : process; const __cjs_getBuiltinModule$3 = (module) => { if (typeof __cjs_getProcess$3 !== "undefined" && __cjs_getProcess$3.versions && __cjs_getProcess$3.versions.node) { const [major, minor] = __cjs_getProcess$3.versions.node.split(".").map(Number); if (major > 22 || major === 22 && minor >= 3 || major === 20 && minor >= 16) { return __cjs_getProcess$3.getBuiltinModule(module); } } return __cjs_require$3(module); }; const { stat, lstat } = __cjs_getBuiltinModule$3("node:fs/promises"); const { fileURLToPath: fileURLToPath$1 } = __cjs_getBuiltinModule$3("node:url"); const findUp = async (name, options = {}) => { const cwd = options.cwd ? toPath(options.cwd) : process.cwd(); let directory = resolve(cwd); const { root } = parse(directory); const stopPath = toPath(options.stopAt ?? root); const stopAt = resolve(directory, stopPath); const type = options.type ?? "file"; const getMatchers = async function(currentDirectory) { { return [name]; } }; if (options.allowSymlinks === void 0) { options.allowSymlinks = true; } const statFunction = options.allowSymlinks ? stat : lstat; while (directory && directory !== stopAt && directory !== root) { for await (let fileName of await getMatchers()) { if (fileName === FIND_UP_STOP) { return void 0; } if (fileName === void 0) { continue; } if (Buffer.isBuffer(fileName)) { fileName = fileName.toString(); } else if (fileName instanceof URL) { fileName = fileURLToPath$1(fileName); } const filePath = isAbsolute(fileName) ? fileName : resolve(directory, fileName); try { const stats = await statFunction(filePath); if (type === "file" && stats.isFile() || type === "directory" && stats.isDirectory()) { return filePath; } } catch { } } directory = dirname(directory); } return void 0; }; const __cjs_require$2 = createRequire(import.meta.url); const __cjs_getProcess$2 = typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" ? globalThis.process : process; const __cjs_getBuiltinModule$2 = (module) => { if (typeof __cjs_getProcess$2 !== "undefined" && __cjs_getProcess$2.versions && __cjs_getProcess$2.versions.node) { const [major, minor] = __cjs_getProcess$2.versions.node.split(".").map(Number); if (major > 22 || major === 22 && minor >= 3 || major === 20 && minor >= 16) { return __cjs_getProcess$2.getBuiltinModule(module); } } return __cjs_require$2(module); }; const { statSync, lstatSync } = __cjs_getBuiltinModule$2("node:fs"); const { fileURLToPath } = __cjs_getBuiltinModule$2("node:url"); const findUpSync = (name, options = {}) => { const cwd = options.cwd ? toPath(options.cwd) : process.cwd(); let directory = resolve(cwd); const { root } = parse(directory); const stopPath = toPath(options.stopAt ?? root); const stopAt = resolve(directory, stopPath); const type = options.type ?? "file"; const getMatchers = function(currentDirectory) { { return [name]; } }; if (options.allowSymlinks === void 0) { options.allowSymlinks = true; } const statFunction = options.allowSymlinks ? statSync : lstatSync; while (directory && directory !== stopAt && directory !== root) { for (let fileName of getMatchers()) { if (fileName === FIND_UP_STOP) { return void 0; } if (fileName === void 0) { continue; } if (Buffer.isBuffer(fileName)) { fileName = fileName.toString(); } else if (fileName instanceof URL) { fileName = fileURLToPath(fileName); } const filePath = isAbsolute(fileName) ? fileName : resolve(directory, fileName); try { const stats = statFunction(filePath); if (type === "file" && stats.isFile() || type === "directory" && stats.isDirectory()) { return filePath; } } catch { } } directory = dirname(directory); } return void 0; }; const __cjs_require$1 = createRequire(import.meta.url); const __cjs_getProcess$1 = typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" ? globalThis.process : process; const __cjs_getBuiltinModule$1 = (module) => { if (typeof __cjs_getProcess$1 !== "undefined" && __cjs_getProcess$1.versions && __cjs_getProcess$1.versions.node) { const [major, minor] = __cjs_getProcess$1.versions.node.split(".").map(Number); if (major > 22 || major === 22 && minor >= 3 || major === 20 && minor >= 16) { return __cjs_getProcess$1.getBuiltinModule(module); } } return __cjs_require$1(module); }; const { access } = __cjs_getBuiltinModule$1("node:fs/promises"); async function isAccessible(path, mode = F_OK) { assertValidFileOrDirectoryPath(path); path = toPath(path); try { await access(path, mode); return true; } catch { return false; } } const { accessSync } = __cjs_getBuiltinModule("node:fs"); function isAccessibleSync(path, mode = F_OK) { assertValidFileOrDirectoryPath(path); path = toPath(path); try { accessSync(path, mode); return true; } catch { return false; } } class NotFoundError extends Error { /** * Creates a new instance. * @param message */ constructor(message) { super(`ENOENT: ${message}`); } // eslint-disable-next-line class-methods-use-this get code() { return "ENOENT"; } // eslint-disable-next-line class-methods-use-this,@typescript-eslint/explicit-module-boundary-types set code(_name) { throw new Error("Cannot overwrite code ENOENT"); } // eslint-disable-next-line class-methods-use-this get name() { return "NotFoundError"; } // eslint-disable-next-line class-methods-use-this,@typescript-eslint/explicit-module-boundary-types set name(_name) { throw new Error("Cannot overwrite name of NotFoundError"); } } const useDirectory = (directory, options) => { if (options?.create) { ensureDirSync(directory); } return directory; }; const findCacheDirectory = async (name, options) => { if (env.CACHE_DIR && !["0", "1", "false", "true"].includes(env.CACHE_DIR)) { return useDirectory(join(env.CACHE_DIR, name), options); } const rootDirectory = await findUp("package.json", { cwd: options?.cwd ?? cwd$1(), type: "file" }); if (!rootDirectory) { if (options?.throwError) { throw new NotFoundError("No such file or directory found."); } return void 0; } const nodeModulesDirectory = join(dirname(rootDirectory), "node_modules"); const cacheDirectory = join(nodeModulesDirectory, ".cache"); const cacheNameDirectory = join(cacheDirectory, name); if (existsSync(cacheNameDirectory) && !await isAccessible(cacheNameDirectory, W_OK)) { return void 0; } if (existsSync(cacheDirectory) && !await isAccessible(cacheDirectory, W_OK)) { return void 0; } if (existsSync(nodeModulesDirectory) && !await isAccessible(nodeModulesDirectory, W_OK)) { return void 0; } return useDirectory(cacheNameDirectory, options); }; const findCacheDirectorySync = (name, options) => { if (env.CACHE_DIR && !["0", "1", "false", "true"].includes(env.CACHE_DIR)) { return useDirectory(join(env.CACHE_DIR, name), options); } const rootDirectory = findUpSync("package.json", { cwd: options?.cwd ?? cwd$1(), type: "file" }); if (!rootDirectory) { if (options?.throwError) { throw new NotFoundError("No such file or directory found."); } return void 0; } const nodeModulesDirectory = join(dirname(rootDirectory), "node_modules"); const cacheDirectory = join(nodeModulesDirectory, ".cache"); const cacheNameDirectory = join(cacheDirectory, name); if (existsSync(cacheNameDirectory) && !isAccessibleSync(cacheNameDirectory, W_OK)) { return void 0; } if (existsSync(cacheDirectory) && !isAccessibleSync(cacheDirectory, W_OK)) { return void 0; } if (existsSync(nodeModulesDirectory) && !isAccessibleSync(nodeModulesDirectory, W_OK)) { return void 0; } return useDirectory(cacheNameDirectory, options); }; const findCacheDir = findCacheDirectory; const findCacheDirSync = findCacheDirectorySync; export { findCacheDir, findCacheDirSync };