UNPKG

vlt

Version:
1,793 lines (1,789 loc) 80.5 kB
var global = globalThis; import {Buffer} from "node:buffer"; import {setTimeout,clearTimeout,setImmediate,clearImmediate,setInterval,clearInterval} from "node:timers"; import {createRequire as _vlt_createRequire} from "node:module"; var require = _vlt_createRequire(import.meta.filename); import { LRUCache } from "./chunk-3HSZY4YW.js"; import { GLOBSTAR, Minimatch, Minipass, escape, unescape } from "./chunk-6YRWYWZQ.js"; // ../../node_modules/.pnpm/path-scurry@2.0.0/node_modules/path-scurry/dist/esm/index.js import { posix, win32 } from "node:path"; import { fileURLToPath } from "node:url"; import { lstatSync, readdir as readdirCB, readdirSync, readlinkSync, realpathSync as rps } from "node:fs"; import * as actualFS from "node:fs"; import { lstat, readdir, readlink, realpath } from "node:fs/promises"; var realpathSync = rps.native; var defaultFS = { lstatSync, readdir: readdirCB, readdirSync, readlinkSync, realpathSync, promises: { lstat, readdir, readlink, realpath } }; var fsFromOption = (fsOption) => !fsOption || fsOption === defaultFS || fsOption === actualFS ? defaultFS : { ...defaultFS, ...fsOption, promises: { ...defaultFS.promises, ...fsOption.promises || {} } }; var uncDriveRegexp = /^\\\\\?\\([a-z]:)\\?$/i; var uncToDrive = (rootPath) => rootPath.replace(/\//g, "\\").replace(uncDriveRegexp, "$1\\"); var eitherSep = /[\\\/]/; var UNKNOWN = 0; var IFIFO = 1; var IFCHR = 2; var IFDIR = 4; var IFBLK = 6; var IFREG = 8; var IFLNK = 10; var IFSOCK = 12; var IFMT = 15; var IFMT_UNKNOWN = ~IFMT; var READDIR_CALLED = 16; var LSTAT_CALLED = 32; var ENOTDIR = 64; var ENOENT = 128; var ENOREADLINK = 256; var ENOREALPATH = 512; var ENOCHILD = ENOTDIR | ENOENT | ENOREALPATH; var TYPEMASK = 1023; var entToType = (s) => s.isFile() ? IFREG : s.isDirectory() ? IFDIR : s.isSymbolicLink() ? IFLNK : s.isCharacterDevice() ? IFCHR : s.isBlockDevice() ? IFBLK : s.isSocket() ? IFSOCK : s.isFIFO() ? IFIFO : UNKNOWN; var normalizeCache = /* @__PURE__ */ new Map(); var normalize = (s) => { const c = normalizeCache.get(s); if (c) return c; const n = s.normalize("NFKD"); normalizeCache.set(s, n); return n; }; var normalizeNocaseCache = /* @__PURE__ */ new Map(); var normalizeNocase = (s) => { const c = normalizeNocaseCache.get(s); if (c) return c; const n = normalize(s.toLowerCase()); normalizeNocaseCache.set(s, n); return n; }; var ResolveCache = class extends LRUCache { constructor() { super({ max: 256 }); } }; var ChildrenCache = class extends LRUCache { constructor(maxSize = 16 * 1024) { super({ maxSize, // parent + children sizeCalculation: (a) => a.length + 1 }); } }; var setAsCwd = Symbol("PathScurry setAsCwd"); var PathBase = class { /** * the basename of this path * * **Important**: *always* test the path name against any test string * usingthe {@link isNamed} method, and not by directly comparing this * string. Otherwise, unicode path strings that the system sees as identical * will not be properly treated as the same path, leading to incorrect * behavior and possible security issues. */ name; /** * the Path entry corresponding to the path root. * * @internal */ root; /** * All roots found within the current PathScurry family * * @internal */ roots; /** * a reference to the parent path, or undefined in the case of root entries * * @internal */ parent; /** * boolean indicating whether paths are compared case-insensitively * @internal */ nocase; /** * boolean indicating that this path is the current working directory * of the PathScurry collection that contains it. */ isCWD = false; // potential default fs override #fs; // Stats fields #dev; get dev() { return this.#dev; } #mode; get mode() { return this.#mode; } #nlink; get nlink() { return this.#nlink; } #uid; get uid() { return this.#uid; } #gid; get gid() { return this.#gid; } #rdev; get rdev() { return this.#rdev; } #blksize; get blksize() { return this.#blksize; } #ino; get ino() { return this.#ino; } #size; get size() { return this.#size; } #blocks; get blocks() { return this.#blocks; } #atimeMs; get atimeMs() { return this.#atimeMs; } #mtimeMs; get mtimeMs() { return this.#mtimeMs; } #ctimeMs; get ctimeMs() { return this.#ctimeMs; } #birthtimeMs; get birthtimeMs() { return this.#birthtimeMs; } #atime; get atime() { return this.#atime; } #mtime; get mtime() { return this.#mtime; } #ctime; get ctime() { return this.#ctime; } #birthtime; get birthtime() { return this.#birthtime; } #matchName; #depth; #fullpath; #fullpathPosix; #relative; #relativePosix; #type; #children; #linkTarget; #realpath; /** * This property is for compatibility with the Dirent class as of * Node v20, where Dirent['parentPath'] refers to the path of the * directory that was passed to readdir. For root entries, it's the path * to the entry itself. */ get parentPath() { return (this.parent || this).fullpath(); } /** * Deprecated alias for Dirent['parentPath'] Somewhat counterintuitively, * this property refers to the *parent* path, not the path object itself. * * @deprecated */ get path() { return this.parentPath; } /** * Do not create new Path objects directly. They should always be accessed * via the PathScurry class or other methods on the Path class. * * @internal */ constructor(name, type = UNKNOWN, root, roots, nocase, children, opts) { this.name = name; this.#matchName = nocase ? normalizeNocase(name) : normalize(name); this.#type = type & TYPEMASK; this.nocase = nocase; this.roots = roots; this.root = root || this; this.#children = children; this.#fullpath = opts.fullpath; this.#relative = opts.relative; this.#relativePosix = opts.relativePosix; this.parent = opts.parent; if (this.parent) { this.#fs = this.parent.#fs; } else { this.#fs = fsFromOption(opts.fs); } } /** * Returns the depth of the Path object from its root. * * For example, a path at `/foo/bar` would have a depth of 2. */ depth() { if (this.#depth !== void 0) return this.#depth; if (!this.parent) return this.#depth = 0; return this.#depth = this.parent.depth() + 1; } /** * @internal */ childrenCache() { return this.#children; } /** * Get the Path object referenced by the string path, resolved from this Path */ resolve(path) { if (!path) { return this; } const rootPath = this.getRootString(path); const dir = path.substring(rootPath.length); const dirParts = dir.split(this.splitSep); const result = rootPath ? this.getRoot(rootPath).#resolveParts(dirParts) : this.#resolveParts(dirParts); return result; } #resolveParts(dirParts) { let p = this; for (const part of dirParts) { p = p.child(part); } return p; } /** * Returns the cached children Path objects, if still available. If they * have fallen out of the cache, then returns an empty array, and resets the * READDIR_CALLED bit, so that future calls to readdir() will require an fs * lookup. * * @internal */ children() { const cached = this.#children.get(this); if (cached) { return cached; } const children = Object.assign([], { provisional: 0 }); this.#children.set(this, children); this.#type &= ~READDIR_CALLED; return children; } /** * Resolves a path portion and returns or creates the child Path. * * Returns `this` if pathPart is `''` or `'.'`, or `parent` if pathPart is * `'..'`. * * This should not be called directly. If `pathPart` contains any path * separators, it will lead to unsafe undefined behavior. * * Use `Path.resolve()` instead. * * @internal */ child(pathPart, opts) { if (pathPart === "" || pathPart === ".") { return this; } if (pathPart === "..") { return this.parent || this; } const children = this.children(); const name = this.nocase ? normalizeNocase(pathPart) : normalize(pathPart); for (const p of children) { if (p.#matchName === name) { return p; } } const s = this.parent ? this.sep : ""; const fullpath = this.#fullpath ? this.#fullpath + s + pathPart : void 0; const pchild = this.newChild(pathPart, UNKNOWN, { ...opts, parent: this, fullpath }); if (!this.canReaddir()) { pchild.#type |= ENOENT; } children.push(pchild); return pchild; } /** * The relative path from the cwd. If it does not share an ancestor with * the cwd, then this ends up being equivalent to the fullpath() */ relative() { if (this.isCWD) return ""; if (this.#relative !== void 0) { return this.#relative; } const name = this.name; const p = this.parent; if (!p) { return this.#relative = this.name; } const pv = p.relative(); return pv + (!pv || !p.parent ? "" : this.sep) + name; } /** * The relative path from the cwd, using / as the path separator. * If it does not share an ancestor with * the cwd, then this ends up being equivalent to the fullpathPosix() * On posix systems, this is identical to relative(). */ relativePosix() { if (this.sep === "/") return this.relative(); if (this.isCWD) return ""; if (this.#relativePosix !== void 0) return this.#relativePosix; const name = this.name; const p = this.parent; if (!p) { return this.#relativePosix = this.fullpathPosix(); } const pv = p.relativePosix(); return pv + (!pv || !p.parent ? "" : "/") + name; } /** * The fully resolved path string for this Path entry */ fullpath() { if (this.#fullpath !== void 0) { return this.#fullpath; } const name = this.name; const p = this.parent; if (!p) { return this.#fullpath = this.name; } const pv = p.fullpath(); const fp = pv + (!p.parent ? "" : this.sep) + name; return this.#fullpath = fp; } /** * On platforms other than windows, this is identical to fullpath. * * On windows, this is overridden to return the forward-slash form of the * full UNC path. */ fullpathPosix() { if (this.#fullpathPosix !== void 0) return this.#fullpathPosix; if (this.sep === "/") return this.#fullpathPosix = this.fullpath(); if (!this.parent) { const p2 = this.fullpath().replace(/\\/g, "/"); if (/^[a-z]:\//i.test(p2)) { return this.#fullpathPosix = `//?/${p2}`; } else { return this.#fullpathPosix = p2; } } const p = this.parent; const pfpp = p.fullpathPosix(); const fpp = pfpp + (!pfpp || !p.parent ? "" : "/") + this.name; return this.#fullpathPosix = fpp; } /** * Is the Path of an unknown type? * * Note that we might know *something* about it if there has been a previous * filesystem operation, for example that it does not exist, or is not a * link, or whether it has child entries. */ isUnknown() { return (this.#type & IFMT) === UNKNOWN; } isType(type) { return this[`is${type}`](); } getType() { return this.isUnknown() ? "Unknown" : this.isDirectory() ? "Directory" : this.isFile() ? "File" : this.isSymbolicLink() ? "SymbolicLink" : this.isFIFO() ? "FIFO" : this.isCharacterDevice() ? "CharacterDevice" : this.isBlockDevice() ? "BlockDevice" : ( /* c8 ignore start */ this.isSocket() ? "Socket" : "Unknown" ); } /** * Is the Path a regular file? */ isFile() { return (this.#type & IFMT) === IFREG; } /** * Is the Path a directory? */ isDirectory() { return (this.#type & IFMT) === IFDIR; } /** * Is the path a character device? */ isCharacterDevice() { return (this.#type & IFMT) === IFCHR; } /** * Is the path a block device? */ isBlockDevice() { return (this.#type & IFMT) === IFBLK; } /** * Is the path a FIFO pipe? */ isFIFO() { return (this.#type & IFMT) === IFIFO; } /** * Is the path a socket? */ isSocket() { return (this.#type & IFMT) === IFSOCK; } /** * Is the path a symbolic link? */ isSymbolicLink() { return (this.#type & IFLNK) === IFLNK; } /** * Return the entry if it has been subject of a successful lstat, or * undefined otherwise. * * Does not read the filesystem, so an undefined result *could* simply * mean that we haven't called lstat on it. */ lstatCached() { return this.#type & LSTAT_CALLED ? this : void 0; } /** * Return the cached link target if the entry has been the subject of a * successful readlink, or undefined otherwise. * * Does not read the filesystem, so an undefined result *could* just mean we * don't have any cached data. Only use it if you are very sure that a * readlink() has been called at some point. */ readlinkCached() { return this.#linkTarget; } /** * Returns the cached realpath target if the entry has been the subject * of a successful realpath, or undefined otherwise. * * Does not read the filesystem, so an undefined result *could* just mean we * don't have any cached data. Only use it if you are very sure that a * realpath() has been called at some point. */ realpathCached() { return this.#realpath; } /** * Returns the cached child Path entries array if the entry has been the * subject of a successful readdir(), or [] otherwise. * * Does not read the filesystem, so an empty array *could* just mean we * don't have any cached data. Only use it if you are very sure that a * readdir() has been called recently enough to still be valid. */ readdirCached() { const children = this.children(); return children.slice(0, children.provisional); } /** * Return true if it's worth trying to readlink. Ie, we don't (yet) have * any indication that readlink will definitely fail. * * Returns false if the path is known to not be a symlink, if a previous * readlink failed, or if the entry does not exist. */ canReadlink() { if (this.#linkTarget) return true; if (!this.parent) return false; const ifmt = this.#type & IFMT; return !(ifmt !== UNKNOWN && ifmt !== IFLNK || this.#type & ENOREADLINK || this.#type & ENOENT); } /** * Return true if readdir has previously been successfully called on this * path, indicating that cachedReaddir() is likely valid. */ calledReaddir() { return !!(this.#type & READDIR_CALLED); } /** * Returns true if the path is known to not exist. That is, a previous lstat * or readdir failed to verify its existence when that would have been * expected, or a parent entry was marked either enoent or enotdir. */ isENOENT() { return !!(this.#type & ENOENT); } /** * Return true if the path is a match for the given path name. This handles * case sensitivity and unicode normalization. * * Note: even on case-sensitive systems, it is **not** safe to test the * equality of the `.name` property to determine whether a given pathname * matches, due to unicode normalization mismatches. * * Always use this method instead of testing the `path.name` property * directly. */ isNamed(n) { return !this.nocase ? this.#matchName === normalize(n) : this.#matchName === normalizeNocase(n); } /** * Return the Path object corresponding to the target of a symbolic link. * * If the Path is not a symbolic link, or if the readlink call fails for any * reason, `undefined` is returned. * * Result is cached, and thus may be outdated if the filesystem is mutated. */ async readlink() { const target = this.#linkTarget; if (target) { return target; } if (!this.canReadlink()) { return void 0; } if (!this.parent) { return void 0; } try { const read = await this.#fs.promises.readlink(this.fullpath()); const linkTarget = (await this.parent.realpath())?.resolve(read); if (linkTarget) { return this.#linkTarget = linkTarget; } } catch (er) { this.#readlinkFail(er.code); return void 0; } } /** * Synchronous {@link PathBase.readlink} */ readlinkSync() { const target = this.#linkTarget; if (target) { return target; } if (!this.canReadlink()) { return void 0; } if (!this.parent) { return void 0; } try { const read = this.#fs.readlinkSync(this.fullpath()); const linkTarget = this.parent.realpathSync()?.resolve(read); if (linkTarget) { return this.#linkTarget = linkTarget; } } catch (er) { this.#readlinkFail(er.code); return void 0; } } #readdirSuccess(children) { this.#type |= READDIR_CALLED; for (let p = children.provisional; p < children.length; p++) { const c = children[p]; if (c) c.#markENOENT(); } } #markENOENT() { if (this.#type & ENOENT) return; this.#type = (this.#type | ENOENT) & IFMT_UNKNOWN; this.#markChildrenENOENT(); } #markChildrenENOENT() { const children = this.children(); children.provisional = 0; for (const p of children) { p.#markENOENT(); } } #markENOREALPATH() { this.#type |= ENOREALPATH; this.#markENOTDIR(); } // save the information when we know the entry is not a dir #markENOTDIR() { if (this.#type & ENOTDIR) return; let t = this.#type; if ((t & IFMT) === IFDIR) t &= IFMT_UNKNOWN; this.#type = t | ENOTDIR; this.#markChildrenENOENT(); } #readdirFail(code = "") { if (code === "ENOTDIR" || code === "EPERM") { this.#markENOTDIR(); } else if (code === "ENOENT") { this.#markENOENT(); } else { this.children().provisional = 0; } } #lstatFail(code = "") { if (code === "ENOTDIR") { const p = this.parent; p.#markENOTDIR(); } else if (code === "ENOENT") { this.#markENOENT(); } } #readlinkFail(code = "") { let ter = this.#type; ter |= ENOREADLINK; if (code === "ENOENT") ter |= ENOENT; if (code === "EINVAL" || code === "UNKNOWN") { ter &= IFMT_UNKNOWN; } this.#type = ter; if (code === "ENOTDIR" && this.parent) { this.parent.#markENOTDIR(); } } #readdirAddChild(e, c) { return this.#readdirMaybePromoteChild(e, c) || this.#readdirAddNewChild(e, c); } #readdirAddNewChild(e, c) { const type = entToType(e); const child = this.newChild(e.name, type, { parent: this }); const ifmt = child.#type & IFMT; if (ifmt !== IFDIR && ifmt !== IFLNK && ifmt !== UNKNOWN) { child.#type |= ENOTDIR; } c.unshift(child); c.provisional++; return child; } #readdirMaybePromoteChild(e, c) { for (let p = c.provisional; p < c.length; p++) { const pchild = c[p]; const name = this.nocase ? normalizeNocase(e.name) : normalize(e.name); if (name !== pchild.#matchName) { continue; } return this.#readdirPromoteChild(e, pchild, p, c); } } #readdirPromoteChild(e, p, index, c) { const v = p.name; p.#type = p.#type & IFMT_UNKNOWN | entToType(e); if (v !== e.name) p.name = e.name; if (index !== c.provisional) { if (index === c.length - 1) c.pop(); else c.splice(index, 1); c.unshift(p); } c.provisional++; return p; } /** * Call lstat() on this Path, and update all known information that can be * determined. * * Note that unlike `fs.lstat()`, the returned value does not contain some * information, such as `mode`, `dev`, `nlink`, and `ino`. If that * information is required, you will need to call `fs.lstat` yourself. * * If the Path refers to a nonexistent file, or if the lstat call fails for * any reason, `undefined` is returned. Otherwise the updated Path object is * returned. * * Results are cached, and thus may be out of date if the filesystem is * mutated. */ async lstat() { if ((this.#type & ENOENT) === 0) { try { this.#applyStat(await this.#fs.promises.lstat(this.fullpath())); return this; } catch (er) { this.#lstatFail(er.code); } } } /** * synchronous {@link PathBase.lstat} */ lstatSync() { if ((this.#type & ENOENT) === 0) { try { this.#applyStat(this.#fs.lstatSync(this.fullpath())); return this; } catch (er) { this.#lstatFail(er.code); } } } #applyStat(st) { const { atime, atimeMs, birthtime, birthtimeMs, blksize, blocks, ctime, ctimeMs, dev, gid, ino, mode, mtime, mtimeMs, nlink, rdev, size, uid } = st; this.#atime = atime; this.#atimeMs = atimeMs; this.#birthtime = birthtime; this.#birthtimeMs = birthtimeMs; this.#blksize = blksize; this.#blocks = blocks; this.#ctime = ctime; this.#ctimeMs = ctimeMs; this.#dev = dev; this.#gid = gid; this.#ino = ino; this.#mode = mode; this.#mtime = mtime; this.#mtimeMs = mtimeMs; this.#nlink = nlink; this.#rdev = rdev; this.#size = size; this.#uid = uid; const ifmt = entToType(st); this.#type = this.#type & IFMT_UNKNOWN | ifmt | LSTAT_CALLED; if (ifmt !== UNKNOWN && ifmt !== IFDIR && ifmt !== IFLNK) { this.#type |= ENOTDIR; } } #onReaddirCB = []; #readdirCBInFlight = false; #callOnReaddirCB(children) { this.#readdirCBInFlight = false; const cbs = this.#onReaddirCB.slice(); this.#onReaddirCB.length = 0; cbs.forEach((cb) => cb(null, children)); } /** * Standard node-style callback interface to get list of directory entries. * * If the Path cannot or does not contain any children, then an empty array * is returned. * * Results are cached, and thus may be out of date if the filesystem is * mutated. * * @param cb The callback called with (er, entries). Note that the `er` * param is somewhat extraneous, as all readdir() errors are handled and * simply result in an empty set of entries being returned. * @param allowZalgo Boolean indicating that immediately known results should * *not* be deferred with `queueMicrotask`. Defaults to `false`. Release * zalgo at your peril, the dark pony lord is devious and unforgiving. */ readdirCB(cb, allowZalgo = false) { if (!this.canReaddir()) { if (allowZalgo) cb(null, []); else queueMicrotask(() => cb(null, [])); return; } const children = this.children(); if (this.calledReaddir()) { const c = children.slice(0, children.provisional); if (allowZalgo) cb(null, c); else queueMicrotask(() => cb(null, c)); return; } this.#onReaddirCB.push(cb); if (this.#readdirCBInFlight) { return; } this.#readdirCBInFlight = true; const fullpath = this.fullpath(); this.#fs.readdir(fullpath, { withFileTypes: true }, (er, entries) => { if (er) { this.#readdirFail(er.code); children.provisional = 0; } else { for (const e of entries) { this.#readdirAddChild(e, children); } this.#readdirSuccess(children); } this.#callOnReaddirCB(children.slice(0, children.provisional)); return; }); } #asyncReaddirInFlight; /** * Return an array of known child entries. * * If the Path cannot or does not contain any children, then an empty array * is returned. * * Results are cached, and thus may be out of date if the filesystem is * mutated. */ async readdir() { if (!this.canReaddir()) { return []; } const children = this.children(); if (this.calledReaddir()) { return children.slice(0, children.provisional); } const fullpath = this.fullpath(); if (this.#asyncReaddirInFlight) { await this.#asyncReaddirInFlight; } else { let resolve = () => { }; this.#asyncReaddirInFlight = new Promise((res) => resolve = res); try { for (const e of await this.#fs.promises.readdir(fullpath, { withFileTypes: true })) { this.#readdirAddChild(e, children); } this.#readdirSuccess(children); } catch (er) { this.#readdirFail(er.code); children.provisional = 0; } this.#asyncReaddirInFlight = void 0; resolve(); } return children.slice(0, children.provisional); } /** * synchronous {@link PathBase.readdir} */ readdirSync() { if (!this.canReaddir()) { return []; } const children = this.children(); if (this.calledReaddir()) { return children.slice(0, children.provisional); } const fullpath = this.fullpath(); try { for (const e of this.#fs.readdirSync(fullpath, { withFileTypes: true })) { this.#readdirAddChild(e, children); } this.#readdirSuccess(children); } catch (er) { this.#readdirFail(er.code); children.provisional = 0; } return children.slice(0, children.provisional); } canReaddir() { if (this.#type & ENOCHILD) return false; const ifmt = IFMT & this.#type; if (!(ifmt === UNKNOWN || ifmt === IFDIR || ifmt === IFLNK)) { return false; } return true; } shouldWalk(dirs, walkFilter) { return (this.#type & IFDIR) === IFDIR && !(this.#type & ENOCHILD) && !dirs.has(this) && (!walkFilter || walkFilter(this)); } /** * Return the Path object corresponding to path as resolved * by realpath(3). * * If the realpath call fails for any reason, `undefined` is returned. * * Result is cached, and thus may be outdated if the filesystem is mutated. * On success, returns a Path object. */ async realpath() { if (this.#realpath) return this.#realpath; if ((ENOREALPATH | ENOREADLINK | ENOENT) & this.#type) return void 0; try { const rp = await this.#fs.promises.realpath(this.fullpath()); return this.#realpath = this.resolve(rp); } catch (_) { this.#markENOREALPATH(); } } /** * Synchronous {@link realpath} */ realpathSync() { if (this.#realpath) return this.#realpath; if ((ENOREALPATH | ENOREADLINK | ENOENT) & this.#type) return void 0; try { const rp = this.#fs.realpathSync(this.fullpath()); return this.#realpath = this.resolve(rp); } catch (_) { this.#markENOREALPATH(); } } /** * Internal method to mark this Path object as the scurry cwd, * called by {@link PathScurry#chdir} * * @internal */ [setAsCwd](oldCwd) { if (oldCwd === this) return; oldCwd.isCWD = false; this.isCWD = true; const changed = /* @__PURE__ */ new Set([]); let rp = []; let p = this; while (p && p.parent) { changed.add(p); p.#relative = rp.join(this.sep); p.#relativePosix = rp.join("/"); p = p.parent; rp.push(".."); } p = oldCwd; while (p && p.parent && !changed.has(p)) { p.#relative = void 0; p.#relativePosix = void 0; p = p.parent; } } }; var PathWin32 = class _PathWin32 extends PathBase { /** * Separator for generating path strings. */ sep = "\\"; /** * Separator for parsing path strings. */ splitSep = eitherSep; /** * Do not create new Path objects directly. They should always be accessed * via the PathScurry class or other methods on the Path class. * * @internal */ constructor(name, type = UNKNOWN, root, roots, nocase, children, opts) { super(name, type, root, roots, nocase, children, opts); } /** * @internal */ newChild(name, type = UNKNOWN, opts = {}) { return new _PathWin32(name, type, this.root, this.roots, this.nocase, this.childrenCache(), opts); } /** * @internal */ getRootString(path) { return win32.parse(path).root; } /** * @internal */ getRoot(rootPath) { rootPath = uncToDrive(rootPath.toUpperCase()); if (rootPath === this.root.name) { return this.root; } for (const [compare, root] of Object.entries(this.roots)) { if (this.sameRoot(rootPath, compare)) { return this.roots[rootPath] = root; } } return this.roots[rootPath] = new PathScurryWin32(rootPath, this).root; } /** * @internal */ sameRoot(rootPath, compare = this.root.name) { rootPath = rootPath.toUpperCase().replace(/\//g, "\\").replace(uncDriveRegexp, "$1\\"); return rootPath === compare; } }; var PathPosix = class _PathPosix extends PathBase { /** * separator for parsing path strings */ splitSep = "/"; /** * separator for generating path strings */ sep = "/"; /** * Do not create new Path objects directly. They should always be accessed * via the PathScurry class or other methods on the Path class. * * @internal */ constructor(name, type = UNKNOWN, root, roots, nocase, children, opts) { super(name, type, root, roots, nocase, children, opts); } /** * @internal */ getRootString(path) { return path.startsWith("/") ? "/" : ""; } /** * @internal */ getRoot(_rootPath) { return this.root; } /** * @internal */ newChild(name, type = UNKNOWN, opts = {}) { return new _PathPosix(name, type, this.root, this.roots, this.nocase, this.childrenCache(), opts); } }; var PathScurryBase = class { /** * The root Path entry for the current working directory of this Scurry */ root; /** * The string path for the root of this Scurry's current working directory */ rootPath; /** * A collection of all roots encountered, referenced by rootPath */ roots; /** * The Path entry corresponding to this PathScurry's current working directory. */ cwd; #resolveCache; #resolvePosixCache; #children; /** * Perform path comparisons case-insensitively. * * Defaults true on Darwin and Windows systems, false elsewhere. */ nocase; #fs; /** * This class should not be instantiated directly. * * Use PathScurryWin32, PathScurryDarwin, PathScurryPosix, or PathScurry * * @internal */ constructor(cwd = process.cwd(), pathImpl, sep, { nocase, childrenCacheSize = 16 * 1024, fs = defaultFS } = {}) { this.#fs = fsFromOption(fs); if (cwd instanceof URL || cwd.startsWith("file://")) { cwd = fileURLToPath(cwd); } const cwdPath = pathImpl.resolve(cwd); this.roots = /* @__PURE__ */ Object.create(null); this.rootPath = this.parseRootPath(cwdPath); this.#resolveCache = new ResolveCache(); this.#resolvePosixCache = new ResolveCache(); this.#children = new ChildrenCache(childrenCacheSize); const split = cwdPath.substring(this.rootPath.length).split(sep); if (split.length === 1 && !split[0]) { split.pop(); } if (nocase === void 0) { throw new TypeError("must provide nocase setting to PathScurryBase ctor"); } this.nocase = nocase; this.root = this.newRoot(this.#fs); this.roots[this.rootPath] = this.root; let prev = this.root; let len = split.length - 1; const joinSep = pathImpl.sep; let abs = this.rootPath; let sawFirst = false; for (const part of split) { const l = len--; prev = prev.child(part, { relative: new Array(l).fill("..").join(joinSep), relativePosix: new Array(l).fill("..").join("/"), fullpath: abs += (sawFirst ? "" : joinSep) + part }); sawFirst = true; } this.cwd = prev; } /** * Get the depth of a provided path, string, or the cwd */ depth(path = this.cwd) { if (typeof path === "string") { path = this.cwd.resolve(path); } return path.depth(); } /** * Return the cache of child entries. Exposed so subclasses can create * child Path objects in a platform-specific way. * * @internal */ childrenCache() { return this.#children; } /** * Resolve one or more path strings to a resolved string * * Same interface as require('path').resolve. * * Much faster than path.resolve() when called multiple times for the same * path, because the resolved Path objects are cached. Much slower * otherwise. */ resolve(...paths) { let r = ""; for (let i = paths.length - 1; i >= 0; i--) { const p = paths[i]; if (!p || p === ".") continue; r = r ? `${p}/${r}` : p; if (this.isAbsolute(p)) { break; } } const cached = this.#resolveCache.get(r); if (cached !== void 0) { return cached; } const result = this.cwd.resolve(r).fullpath(); this.#resolveCache.set(r, result); return result; } /** * Resolve one or more path strings to a resolved string, returning * the posix path. Identical to .resolve() on posix systems, but on * windows will return a forward-slash separated UNC path. * * Same interface as require('path').resolve. * * Much faster than path.resolve() when called multiple times for the same * path, because the resolved Path objects are cached. Much slower * otherwise. */ resolvePosix(...paths) { let r = ""; for (let i = paths.length - 1; i >= 0; i--) { const p = paths[i]; if (!p || p === ".") continue; r = r ? `${p}/${r}` : p; if (this.isAbsolute(p)) { break; } } const cached = this.#resolvePosixCache.get(r); if (cached !== void 0) { return cached; } const result = this.cwd.resolve(r).fullpathPosix(); this.#resolvePosixCache.set(r, result); return result; } /** * find the relative path from the cwd to the supplied path string or entry */ relative(entry = this.cwd) { if (typeof entry === "string") { entry = this.cwd.resolve(entry); } return entry.relative(); } /** * find the relative path from the cwd to the supplied path string or * entry, using / as the path delimiter, even on Windows. */ relativePosix(entry = this.cwd) { if (typeof entry === "string") { entry = this.cwd.resolve(entry); } return entry.relativePosix(); } /** * Return the basename for the provided string or Path object */ basename(entry = this.cwd) { if (typeof entry === "string") { entry = this.cwd.resolve(entry); } return entry.name; } /** * Return the dirname for the provided string or Path object */ dirname(entry = this.cwd) { if (typeof entry === "string") { entry = this.cwd.resolve(entry); } return (entry.parent || entry).fullpath(); } async readdir(entry = this.cwd, opts = { withFileTypes: true }) { if (typeof entry === "string") { entry = this.cwd.resolve(entry); } else if (!(entry instanceof PathBase)) { opts = entry; entry = this.cwd; } const { withFileTypes } = opts; if (!entry.canReaddir()) { return []; } else { const p = await entry.readdir(); return withFileTypes ? p : p.map((e) => e.name); } } readdirSync(entry = this.cwd, opts = { withFileTypes: true }) { if (typeof entry === "string") { entry = this.cwd.resolve(entry); } else if (!(entry instanceof PathBase)) { opts = entry; entry = this.cwd; } const { withFileTypes = true } = opts; if (!entry.canReaddir()) { return []; } else if (withFileTypes) { return entry.readdirSync(); } else { return entry.readdirSync().map((e) => e.name); } } /** * Call lstat() on the string or Path object, and update all known * information that can be determined. * * Note that unlike `fs.lstat()`, the returned value does not contain some * information, such as `mode`, `dev`, `nlink`, and `ino`. If that * information is required, you will need to call `fs.lstat` yourself. * * If the Path refers to a nonexistent file, or if the lstat call fails for * any reason, `undefined` is returned. Otherwise the updated Path object is * returned. * * Results are cached, and thus may be out of date if the filesystem is * mutated. */ async lstat(entry = this.cwd) { if (typeof entry === "string") { entry = this.cwd.resolve(entry); } return entry.lstat(); } /** * synchronous {@link PathScurryBase.lstat} */ lstatSync(entry = this.cwd) { if (typeof entry === "string") { entry = this.cwd.resolve(entry); } return entry.lstatSync(); } async readlink(entry = this.cwd, { withFileTypes } = { withFileTypes: false }) { if (typeof entry === "string") { entry = this.cwd.resolve(entry); } else if (!(entry instanceof PathBase)) { withFileTypes = entry.withFileTypes; entry = this.cwd; } const e = await entry.readlink(); return withFileTypes ? e : e?.fullpath(); } readlinkSync(entry = this.cwd, { withFileTypes } = { withFileTypes: false }) { if (typeof entry === "string") { entry = this.cwd.resolve(entry); } else if (!(entry instanceof PathBase)) { withFileTypes = entry.withFileTypes; entry = this.cwd; } const e = entry.readlinkSync(); return withFileTypes ? e : e?.fullpath(); } async realpath(entry = this.cwd, { withFileTypes } = { withFileTypes: false }) { if (typeof entry === "string") { entry = this.cwd.resolve(entry); } else if (!(entry instanceof PathBase)) { withFileTypes = entry.withFileTypes; entry = this.cwd; } const e = await entry.realpath(); return withFileTypes ? e : e?.fullpath(); } realpathSync(entry = this.cwd, { withFileTypes } = { withFileTypes: false }) { if (typeof entry === "string") { entry = this.cwd.resolve(entry); } else if (!(entry instanceof PathBase)) { withFileTypes = entry.withFileTypes; entry = this.cwd; } const e = entry.realpathSync(); return withFileTypes ? e : e?.fullpath(); } async walk(entry = this.cwd, opts = {}) { if (typeof entry === "string") { entry = this.cwd.resolve(entry); } else if (!(entry instanceof PathBase)) { opts = entry; entry = this.cwd; } const { withFileTypes = true, follow = false, filter, walkFilter } = opts; const results = []; if (!filter || filter(entry)) { results.push(withFileTypes ? entry : entry.fullpath()); } const dirs = /* @__PURE__ */ new Set(); const walk = (dir, cb) => { dirs.add(dir); dir.readdirCB((er, entries) => { if (er) { return cb(er); } let len = entries.length; if (!len) return cb(); const next = () => { if (--len === 0) { cb(); } }; for (const e of entries) { if (!filter || filter(e)) { results.push(withFileTypes ? e : e.fullpath()); } if (follow && e.isSymbolicLink()) { e.realpath().then((r) => r?.isUnknown() ? r.lstat() : r).then((r) => r?.shouldWalk(dirs, walkFilter) ? walk(r, next) : next()); } else { if (e.shouldWalk(dirs, walkFilter)) { walk(e, next); } else { next(); } } } }, true); }; const start = entry; return new Promise((res, rej) => { walk(start, (er) => { if (er) return rej(er); res(results); }); }); } walkSync(entry = this.cwd, opts = {}) { if (typeof entry === "string") { entry = this.cwd.resolve(entry); } else if (!(entry instanceof PathBase)) { opts = entry; entry = this.cwd; } const { withFileTypes = true, follow = false, filter, walkFilter } = opts; const results = []; if (!filter || filter(entry)) { results.push(withFileTypes ? entry : entry.fullpath()); } const dirs = /* @__PURE__ */ new Set([entry]); for (const dir of dirs) { const entries = dir.readdirSync(); for (const e of entries) { if (!filter || filter(e)) { results.push(withFileTypes ? e : e.fullpath()); } let r = e; if (e.isSymbolicLink()) { if (!(follow && (r = e.realpathSync()))) continue; if (r.isUnknown()) r.lstatSync(); } if (r.shouldWalk(dirs, walkFilter)) { dirs.add(r); } } } return results; } /** * Support for `for await` * * Alias for {@link PathScurryBase.iterate} * * Note: As of Node 19, this is very slow, compared to other methods of * walking. Consider using {@link PathScurryBase.stream} if memory overhead * and backpressure are concerns, or {@link PathScurryBase.walk} if not. */ [Symbol.asyncIterator]() { return this.iterate(); } iterate(entry = this.cwd, options = {}) { if (typeof entry === "string") { entry = this.cwd.resolve(entry); } else if (!(entry instanceof PathBase)) { options = entry; entry = this.cwd; } return this.stream(entry, options)[Symbol.asyncIterator](); } /** * Iterating over a PathScurry performs a synchronous walk. * * Alias for {@link PathScurryBase.iterateSync} */ [Symbol.iterator]() { return this.iterateSync(); } *iterateSync(entry = this.cwd, opts = {}) { if (typeof entry === "string") { entry = this.cwd.resolve(entry); } else if (!(entry instanceof PathBase)) { opts = entry; entry = this.cwd; } const { withFileTypes = true, follow = false, filter, walkFilter } = opts; if (!filter || filter(entry)) { yield withFileTypes ? entry : entry.fullpath(); } const dirs = /* @__PURE__ */ new Set([entry]); for (const dir of dirs) { const entries = dir.readdirSync(); for (const e of entries) { if (!filter || filter(e)) { yield withFileTypes ? e : e.fullpath(); } let r = e; if (e.isSymbolicLink()) { if (!(follow && (r = e.realpathSync()))) continue; if (r.isUnknown()) r.lstatSync(); } if (r.shouldWalk(dirs, walkFilter)) { dirs.add(r); } } } } stream(entry = this.cwd, opts = {}) { if (typeof entry === "string") { entry = this.cwd.resolve(entry); } else if (!(entry instanceof PathBase)) { opts = entry; entry = this.cwd; } const { withFileTypes = true, follow = false, filter, walkFilter } = opts; const results = new Minipass({ objectMode: true }); if (!filter || filter(entry)) { results.write(withFileTypes ? entry : entry.fullpath()); } const dirs = /* @__PURE__ */ new Set(); const queue = [entry]; let processing = 0; const process2 = () => { let paused = false; while (!paused) { const dir = queue.shift(); if (!dir) { if (processing === 0) results.end(); return; } processing++; dirs.add(dir); const onReaddir = (er, entries, didRealpaths = false) => { if (er) return results.emit("error", er); if (follow && !didRealpaths) { const promises = []; for (const e of entries) { if (e.isSymbolicLink()) { promises.push(e.realpath().then((r) => r?.isUnknown() ? r.lstat() : r)); } } if (promises.length) { Promise.all(promises).then(() => onReaddir(null, entries, true)); return; } } for (const e of entries) { if (e && (!filter || filter(e))) { if (!results.write(withFileTypes ? e : e.fullpath())) { paused = true; } } } processing--; for (const e of entries) { const r = e.realpathCached() || e; if (r.shouldWalk(dirs, walkFilter)) { queue.push(r); } } if (paused && !results.flowing) { results.once("drain", process2); } else if (!sync2) { process2(); } }; let sync2 = true; dir.readdirCB(onReaddir, true); sync2 = false; } }; process2(); return results; } streamSync(entry = this.cwd, opts = {}) { if (typeof entry === "string") { entry = this.cwd.resolve(entry); } else if (!(entry instanceof PathBase)) { opts = entry; entry = this.cwd; } const { withFileTypes = true, follow = false, filter, walkFilter } = opts; const results = new Minipass({ objectMode: true }); const dirs = /* @__PURE__ */ new Set(); if (!filter || filter(entry)) { results.write(withFileTypes ? entry : entry.fullpath()); } const queue = [entry]; let processing = 0; const process2 = () => { let paused = false; while (!paused) { const dir = queue.shift(); if (!dir) { if (processing === 0) results.end(); return; } processing++; dirs.add(dir); const entries = dir.readdirSync(); for (const e of entries) { if (!filter || filter(e)) { if (!results.write(withFileTypes ? e : e.fullpath())) { paused = true; } } } processing--; for (const e of entries) { let r = e; if (e.isSymbolicLink()) { if (!(follow && (r = e.realpathSync()))) continue; if (r.isUnknown()) r.lstatSync(); } if (r.shouldWalk(dirs, walkFilter)) { queue.push(r); } } } if (paused && !results.flowing) results.once("drain", process2); }; process2(); return results; } chdir(path = this.cwd) { const oldCwd = this.cwd; this.cwd = typeof path === "string" ? this.cwd.resolve(path) : path; this.cwd[setAsCwd](oldCwd); } }; var PathScurryWin32 = class extends PathScurryBase { /** * separator for generating path strings */ sep = "\\"; constructor(cwd = process.cwd(), opts = {}) { const { nocase = true } = opts; super(cwd, win32, "\\", { ...opts, nocase }); this.nocase = nocase; for (let p = this.cwd; p; p = p.parent) { p.nocase = this.nocase; } } /** * @internal */ parseRootPath(dir) { return win32.parse(dir).root.toUpperCase(); } /** * @internal */ newRoot(fs) { return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs }); } /** * Return true if the provided path string is an absolute path */ isAbsolute(p) { return p.startsWith("/") || p.startsWith("\\") || /^[a-z]:(\/|\\)/i.test(p); } }; var PathScurryPosix = class extends PathScurryBase { /** * separator for generating path strings */ sep = "/"; constructor(cwd = process.cwd(), opts = {}) { const { nocase = false } = opts; super(cwd, posix, "/", { ...opts, nocase }); this.nocase = nocase; } /** * @internal */ parseRootPath(_dir) { return "/"; } /** * @internal */ newRoot(fs) { return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs }); } /** * Return true if the provided path string is an absolute path */ isAbsolute(p) { return p.startsWith("/"); } }; var PathScurryDarwin = class extends PathScurryPosix { constructor(cwd = process.cwd(), opts = {}) { const { nocase = true } = opts; super(cwd, { ...opts, nocase }); } }; var Path = process.platform === "win32" ? PathWin32 : PathPosix; var PathScurry = process.platform === "win32" ? PathScurryWin32 : process.platform === "darwin" ? PathScurryDarwin : PathScurryPosix; // ../../node_modules/.pnpm/glob@11.0.2/node_modules/glob/dist/esm/glob.js import { fileURLToPath as fileURLToPath2 } from "node:url"; // ../../node_modules/.pnpm/glob@11.0.2/node_modules/glob/dist/esm/pattern.js var isPatternList = (pl) => pl.length >= 1; var isGlobList = (gl) => gl.length >= 1; var Pattern = class _Pattern { #patternList; #globList; #index; length; #platform; #rest; #globString; #isDrive; #isUNC; #isAbsolute; #followGlobstar = true; constructor(patternList, globList, index, platform) { if (!isPatternList(patternList)) { throw new TypeError("empty pattern list"); } if (!isGlobList(globList)) { throw new TypeError("empty glob list"); } if (globList.length !== patternList.length) { throw new TypeError("mismatched pattern list and glob list lengths"); } this.length = patternList.length; if (index < 0 || index >= this.length) { throw new TypeError("index out of range"); } this.#patternList = patternList; this.#globList = globList; this.#index = index; this.#platform = platform; if (this.#index === 0) { if (this.isUNC()) { const [p0, p1, p2, p3, ...prest] = this.#patternList; const [g0, g1, g2, g3, ...grest] = this.#globList; if (prest[0] === "") { prest.shift(); grest.shift(); } const p = [p0, p1, p2, p3, ""].join("/");