Something went wrong. Try again.
Monorepo for the nibling.run platform
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438// node:path. The algorithms are Node's (lib/path.js): lexical normalization, resolve// against process.cwd(). path.win32 is a full port (path-win32.ts) — it's pure string// logic in Node, true on every host, so it runs the same here.import { makeWin32Path } from "./path-win32";
function assertPath(path: unknown, name = "path"): asserts path is string { if (typeof path !== "string") { const got = path === null ? "null" : path === undefined ? "undefined" : `type ${typeof path} (${String(path)})`; throw Object.assign(new TypeError(`The "${name}" argument must be of type string. Received ${got}`), { code: "ERR_INVALID_ARG_TYPE" }); }}
// ---- matchesGlob ----// Node's own matching (lib/internal/fs/glob.js), not bash/minimatch: a pattern with no// glob metachar is a plain (case-sensitive) string compare; any metachar anywhere// makes the WHOLE match case-insensitive, including its literal segments — a real// quirk, golden-verified against Node 24.16, not a design choice of ours. A trailing// "**" segment must still consume at least one real segment ("a/**" misses "a" but// hits "a/b"); elsewhere "**" may match zero. No path segment's leading "." is ever// matched by a wildcard unless the pattern segment itself starts with ".".const GLOB_MAGIC = /[*?{}[\]]/;
/** {a,b} alternation, expanded into every concrete pattern (no nested braces). */function expandBraces(pattern: string): string[] { const open = pattern.indexOf("{"); if (open === -1) return [pattern]; const close = pattern.indexOf("}", open); if (close === -1) return [pattern]; const prefix = pattern.slice(0, open); const suffix = pattern.slice(close + 1); const out: string[] = []; for (const option of pattern.slice(open + 1, close).split(",")) { out.push(...expandBraces(prefix + option + suffix)); } return out;}
/** One glob segment (no "/"; "**" is handled by the caller) as a regex source. */function compileGlobSegment(seg: string): string { let out = ""; for (let i = 0; i < seg.length; i++) { const c = seg[i]!; if (c === "*") { out += "[^/]*"; while (seg[i + 1] === "*") i++; } else if (c === "?") { out += "[^/]"; } else if (c === "[") { let j = i + 1; let neg = false; if (seg[j] === "!" || seg[j] === "^") { neg = true; j++; } let body = ""; while (j < seg.length && seg[j] !== "]") { body += seg[j]; j++; } if (j >= seg.length) { out += "\\["; continue; } // unmatched "[": literal out += `[${neg ? "^" : ""}${body.replace(/\\/g, "\\\\")}]`; i = j; } else { out += /[.+^${}()|\\]/.test(c) ? `\\${c}` : c; } } return out;}
/** Does `seg` match path segment `s`? Dotfiles are off-limits unless `seg` itself * starts with a literal ".". */function globSegmentMatches(seg: string, s: string): boolean { const guard = seg.startsWith(".") ? "" : "(?!\\.)"; return new RegExp(`^${guard}${compileGlobSegment(seg)}$`, "i").test(s);}
/** "**" may match zero or more segments anywhere it isn't the pattern's last segment. */function globSegsMatch(pats: string[], segs: string[]): boolean { if (pats.length === 0) return segs.length === 0; const p = pats[0]!; if (p === "**") { if (globSegsMatch(pats.slice(1), segs)) return true; return segs.length > 0 && !segs[0]!.startsWith(".") && globSegsMatch(pats, segs.slice(1)); } return segs.length > 0 && globSegmentMatches(p, segs[0]!) && globSegsMatch(pats.slice(1), segs.slice(1));}
/** One expanded (brace-free) pattern against the whole path. */function globOneMatches(pattern: string, segs: string[]): boolean { const pats = pattern.split("/"); if (pats.length > 0 && pats[pats.length - 1] === "**") { const head = pats.slice(0, -1); for (let k = 1; k <= segs.length; k++) { const tail = segs.slice(segs.length - k); if (tail.some((s) => s.startsWith("."))) continue; if (globSegsMatch(head, segs.slice(0, segs.length - k))) return true; } return false; } return globSegsMatch(pats, segs);}
export function matchesGlob(path: unknown, pattern: unknown): boolean { assertPath(path); assertPath(pattern, "pattern"); if (!GLOB_MAGIC.test(pattern)) return path === pattern; const segs = path.split("/"); return expandBraces(pattern).some((p) => globOneMatches(p, segs));}
/** Resolve "." and ".." segments; `allowAboveRoot` keeps leading ".." for relative paths. */function normalizeString(path: string, allowAboveRoot: boolean): string { let res = ""; let lastSegmentLength = 0; let lastSlash = -1; let dots = 0; let code = 0; for (let i = 0; i <= path.length; ++i) { if (i < path.length) code = path.charCodeAt(i); else if (code === 47) break; else code = 47; if (code === 47) { if (lastSlash === i - 1 || dots === 1) { // empty segment or "." } else if (dots === 2) { if (res.length < 2 || lastSegmentLength !== 2 || !res.endsWith("..")) { if (res.length > 2) { const lastSlashIndex = res.lastIndexOf("/"); if (lastSlashIndex === -1) { res = ""; lastSegmentLength = 0; } else { res = res.slice(0, lastSlashIndex); lastSegmentLength = res.length - 1 - res.lastIndexOf("/"); } lastSlash = i; dots = 0; continue; } else if (res.length !== 0) { res = ""; lastSegmentLength = 0; lastSlash = i; dots = 0; continue; } } if (allowAboveRoot) { res += res.length > 0 ? "/.." : ".."; lastSegmentLength = 2; } } else { if (res.length > 0) res += `/${path.slice(lastSlash + 1, i)}`; else res = path.slice(lastSlash + 1, i); lastSegmentLength = i - lastSlash - 1; } lastSlash = i; dots = 0; } else if (code === 46 && dots !== -1) { ++dots; } else { dots = -1; } } return res;}
export interface ParsedPath { root: string; dir: string; base: string; ext: string; name: string;}
export function makePath(cwd: () => string, env: () => Record<string, string | undefined> = () => ({})) { const posix = { sep: "/", delimiter: ":",
resolve(...args: string[]): string { let resolvedPath = ""; let resolvedAbsolute = false; for (let i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) { const path = i >= 0 ? args[i] : cwd(); assertPath(path, `paths[${i}]`); if (path.length === 0) continue; resolvedPath = `${path}/${resolvedPath}`; resolvedAbsolute = path.charCodeAt(0) === 47; } resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute); if (resolvedAbsolute) return `/${resolvedPath}`; return resolvedPath.length > 0 ? resolvedPath : "."; },
normalize(path: string): string { assertPath(path); if (path.length === 0) return "."; const isAbsolute = path.charCodeAt(0) === 47; const trailingSeparator = path.charCodeAt(path.length - 1) === 47; let out = normalizeString(path, !isAbsolute); if (out.length === 0) { if (isAbsolute) return "/"; return trailingSeparator ? "./" : "."; } if (trailingSeparator) out += "/"; return isAbsolute ? `/${out}` : out; },
isAbsolute(path: string): boolean { assertPath(path); return path.length > 0 && path.charCodeAt(0) === 47; },
join(...args: string[]): string { if (args.length === 0) return "."; let joined: string | undefined; for (const arg of args) { assertPath(arg); if (arg.length > 0) joined = joined === undefined ? arg : `${joined}/${arg}`; } return joined === undefined ? "." : posix.normalize(joined); },
relative(from: string, to: string): string { assertPath(from, "from"); assertPath(to, "to"); if (from === to) return ""; from = posix.resolve(from); to = posix.resolve(to); if (from === to) return ""; const fromStart = 1; const fromEnd = from.length; const fromLen = fromEnd - fromStart; const toStart = 1; const toLen = to.length - toStart; const length = fromLen < toLen ? fromLen : toLen; let lastCommonSep = -1; let i = 0; for (; i < length; i++) { const fromCode = from.charCodeAt(fromStart + i); if (fromCode !== to.charCodeAt(toStart + i)) break; else if (fromCode === 47) lastCommonSep = i; } if (i === length) { if (toLen > length) { if (to.charCodeAt(toStart + i) === 47) return to.slice(toStart + i + 1); if (i === 0) return to.slice(toStart + i); } else if (fromLen > length) { if (from.charCodeAt(fromStart + i) === 47) lastCommonSep = i; else if (i === 0) lastCommonSep = 0; } } let out = ""; for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) { if (i === fromEnd || from.charCodeAt(i) === 47) out += out.length === 0 ? ".." : "/.."; } return `${out}${to.slice(toStart + lastCommonSep)}`; },
toNamespacedPath(path: string): string { return path; },
dirname(path: string): string { assertPath(path); if (path.length === 0) return "."; const hasRoot = path.charCodeAt(0) === 47; let end = -1; let matchedSlash = true; for (let i = path.length - 1; i >= 1; --i) { if (path.charCodeAt(i) === 47) { if (!matchedSlash) { end = i; break; } } else { matchedSlash = false; } } if (end === -1) return hasRoot ? "/" : "."; if (hasRoot && end === 1) return "//"; return path.slice(0, end); },
basename(path: string, suffix?: string): string { if (suffix !== undefined) assertPath(suffix, "suffix"); assertPath(path); let start = 0; let end = -1; let matchedSlash = true; if (suffix !== undefined && suffix.length > 0 && suffix.length <= path.length) { if (suffix === path) return ""; let extIdx = suffix.length - 1; let firstNonSlashEnd = -1; for (let i = path.length - 1; i >= 0; --i) { const code = path.charCodeAt(i); if (code === 47) { if (!matchedSlash) { start = i + 1; break; } } else { if (firstNonSlashEnd === -1) { matchedSlash = false; firstNonSlashEnd = i + 1; } if (extIdx >= 0) { if (code === suffix.charCodeAt(extIdx)) { if (--extIdx === -1) end = i; } else { extIdx = -1; end = firstNonSlashEnd; } } } } if (start === end) end = firstNonSlashEnd; else if (end === -1) end = path.length; return path.slice(start, end); } for (let i = path.length - 1; i >= 0; --i) { if (path.charCodeAt(i) === 47) { if (!matchedSlash) { start = i + 1; break; } } else if (end === -1) { matchedSlash = false; end = i + 1; } } return end === -1 ? "" : path.slice(start, end); },
extname(path: string): string { assertPath(path); let startDot = -1; let startPart = 0; let end = -1; let matchedSlash = true; let preDotState = 0; for (let i = path.length - 1; i >= 0; --i) { const code = path.charCodeAt(i); if (code === 47) { if (!matchedSlash) { startPart = i + 1; break; } continue; } if (end === -1) { matchedSlash = false; end = i + 1; } if (code === 46) { if (startDot === -1) startDot = i; else if (preDotState !== 1) preDotState = 1; } else if (startDot !== -1) { preDotState = -1; } } if (startDot === -1 || end === -1 || preDotState === 0 || (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)) { return ""; } return path.slice(startDot, end); },
format(pathObject: Partial<ParsedPath>): string { if (pathObject === null || typeof pathObject !== "object") { throw Object.assign(new TypeError(`The "pathObject" argument must be of type object. Received ${pathObject === null ? "null" : `type ${typeof pathObject}`}`), { code: "ERR_INVALID_ARG_TYPE" }); } const dir = pathObject.dir || pathObject.root; const ext = pathObject.ext ? (pathObject.ext[0] === "." ? pathObject.ext : `.${pathObject.ext}`) : ""; const base = pathObject.base || `${pathObject.name || ""}${ext}`; if (!dir) return base; return dir === pathObject.root ? `${dir}${base}` : `${dir}/${base}`; },
parse(path: string): ParsedPath { assertPath(path); const ret: ParsedPath = { root: "", dir: "", base: "", ext: "", name: "" }; if (path.length === 0) return ret; const isAbsolute = path.charCodeAt(0) === 47; let start: number; if (isAbsolute) { ret.root = "/"; start = 1; } else { start = 0; } let startDot = -1; let startPart = 0; let end = -1; let matchedSlash = true; let i = path.length - 1; let preDotState = 0; for (; i >= start; --i) { const code = path.charCodeAt(i); if (code === 47) { if (!matchedSlash) { startPart = i + 1; break; } continue; } if (end === -1) { matchedSlash = false; end = i + 1; } if (code === 46) { if (startDot === -1) startDot = i; else if (preDotState !== 1) preDotState = 1; } else if (startDot !== -1) { preDotState = -1; } } if (end !== -1) { const start2 = startPart === 0 && isAbsolute ? 1 : startPart; if (startDot === -1 || preDotState === 0 || (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)) { ret.base = ret.name = path.slice(start2, end); } else { ret.name = path.slice(start2, startDot); ret.base = path.slice(start2, end); ret.ext = path.slice(startDot, end); } } if (startPart > 0) ret.dir = path.slice(0, startPart - 1); else if (isAbsolute) ret.dir = "/"; return ret; },
matchesGlob, posix: undefined as unknown, win32: undefined as unknown, }; const win32 = makeWin32Path(cwd, env) as unknown as Record<string, unknown>; Object.assign(win32, { sep: "\\", delimiter: ";", posix, win32 }); posix.posix = posix; posix.win32 = win32; return posix;}