dax
Version:
Cross platform shell tools inspired by zx.
1,767 lines (1,761 loc) • 585 kB
JavaScript
var __defProp = Object.defineProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
// npm/esm/_dnt.polyfills.js
if (!Object.hasOwn) {
Object.defineProperty(Object, "hasOwn", {
value: function(object, property) {
if (object == null) {
throw new TypeError("Cannot convert undefined or null to object");
}
return Object.prototype.hasOwnProperty.call(Object(object), property);
},
configurable: true,
enumerable: false,
writable: true
});
}
if (Promise.withResolvers === void 0) {
Promise.withResolvers = () => {
const out = {};
out.promise = new Promise((resolve_, reject_) => {
out.resolve = resolve_;
out.reject = reject_;
});
return out;
};
}
function findLastIndex(self, callbackfn, that) {
const boundFunc = that === void 0 ? callbackfn : callbackfn.bind(that);
let index = self.length - 1;
while (index >= 0) {
const result = boundFunc(self[index], index, self);
if (result) {
return index;
}
index--;
}
return -1;
}
function findLast(self, callbackfn, that) {
const index = self.findLastIndex(callbackfn, that);
return index === -1 ? void 0 : self[index];
}
if (!Array.prototype.findLastIndex) {
Array.prototype.findLastIndex = function(callbackfn, that) {
return findLastIndex(this, callbackfn, that);
};
}
if (!Array.prototype.findLast) {
Array.prototype.findLast = function(callbackfn, that) {
return findLast(this, callbackfn, that);
};
}
if (!Uint8Array.prototype.findLastIndex) {
Uint8Array.prototype.findLastIndex = function(callbackfn, that) {
return findLastIndex(this, callbackfn, that);
};
}
if (!Uint8Array.prototype.findLast) {
Uint8Array.prototype.findLast = function(callbackfn, that) {
return findLast(this, callbackfn, that);
};
}
var { MAX_SAFE_INTEGER } = Number;
var iteratorSymbol = Symbol.iterator;
var asyncIteratorSymbol = Symbol.asyncIterator;
var IntrinsicArray = Array;
var tooLongErrorMessage = "Input is too long and exceeded Number.MAX_SAFE_INTEGER times.";
function isConstructor(obj) {
if (obj != null) {
const prox = new Proxy(obj, {
construct() {
return prox;
}
});
try {
new prox();
return true;
} catch (err) {
return false;
}
} else {
return false;
}
}
async function fromAsync(items, mapfn, thisArg) {
const itemsAreIterable = asyncIteratorSymbol in items || iteratorSymbol in items;
if (itemsAreIterable) {
const result = isConstructor(this) ? new this() : IntrinsicArray(0);
let i = 0;
for await (const v of items) {
if (i > MAX_SAFE_INTEGER) {
throw TypeError(tooLongErrorMessage);
} else if (mapfn) {
result[i] = await mapfn.call(thisArg, v, i);
} else {
result[i] = v;
}
i++;
}
result.length = i;
return result;
} else {
const { length } = items;
const result = isConstructor(this) ? new this(length) : IntrinsicArray(length);
let i = 0;
while (i < length) {
if (i > MAX_SAFE_INTEGER) {
throw TypeError(tooLongErrorMessage);
}
const v = await items[i];
if (mapfn) {
result[i] = await mapfn.call(thisArg, v, i);
} else {
result[i] = v;
}
i++;
}
result.length = i;
return result;
}
}
if (!Array.fromAsync) {
Array.fromAsync = fromAsync;
}
// npm/esm/_dnt.shims.js
import { TextDecoder } from "node:util";
import { TextDecoder as TextDecoder2 } from "node:util";
import { ReadableStream, WritableStream, TextDecoderStream, TransformStream } from "node:stream/web";
import { ReadableStream as ReadableStream2, WritableStream as WritableStream2, TextDecoderStream as TextDecoderStream2, TransformStream as TransformStream2 } from "node:stream/web";
var dntGlobals = {
TextDecoder,
ReadableStream,
WritableStream,
TextDecoderStream,
TransformStream
};
var dntGlobalThis = createMergeProxy(globalThis, dntGlobals);
function createMergeProxy(baseObj, extObj) {
return new Proxy(baseObj, {
get(_target, prop, _receiver) {
if (prop in extObj) {
return extObj[prop];
} else {
return baseObj[prop];
}
},
set(_target, prop, value) {
if (prop in extObj) {
delete extObj[prop];
}
baseObj[prop] = value;
return true;
},
deleteProperty(_target, prop) {
let success = false;
if (prop in extObj) {
delete extObj[prop];
success = true;
}
if (prop in baseObj) {
delete baseObj[prop];
success = true;
}
return success;
},
ownKeys(_target) {
const baseKeys = Reflect.ownKeys(baseObj);
const extKeys = Reflect.ownKeys(extObj);
const extKeysSet = new Set(extKeys);
return [...baseKeys.filter((k) => !extKeysSet.has(k)), ...extKeys];
},
defineProperty(_target, prop, desc) {
if (prop in extObj) {
delete extObj[prop];
}
Reflect.defineProperty(baseObj, prop, desc);
return true;
},
getOwnPropertyDescriptor(_target, prop) {
if (prop in extObj) {
return Reflect.getOwnPropertyDescriptor(extObj, prop);
} else {
return Reflect.getOwnPropertyDescriptor(baseObj, prop);
}
},
has(_target, prop) {
return prop in extObj || prop in baseObj;
}
});
}
// npm/esm/deps/jsr.io/@std/fmt/1.0.10/colors.js
var { Deno } = dntGlobalThis;
var noColor = typeof Deno?.noColor === "boolean" ? Deno.noColor : false;
var enabled = !noColor;
function code(open3, close) {
return {
open: `\x1B[${open3.join(";")}m`,
close: `\x1B[${close}m`,
regexp: new RegExp(`\\x1b\\[${close}m`, "g")
};
}
function run(str, code2) {
return enabled ? `${code2.open}${str.replace(code2.regexp, code2.open)}${code2.close}` : str;
}
function bold(str) {
return run(str, code([1], 22));
}
function dim(str) {
return run(str, code([2], 22));
}
function italic(str) {
return run(str, code([3], 23));
}
function red(str) {
return run(str, code([31], 39));
}
function green(str) {
return run(str, code([32], 39));
}
function yellow(str) {
return run(str, code([33], 39));
}
function blue(str) {
return run(str, code([34], 39));
}
function cyan(str) {
return run(str, code([36], 39));
}
function white(str) {
return run(str, code([37], 39));
}
function gray(str) {
return brightBlack(str);
}
function brightBlack(str) {
return run(str, code([90], 39));
}
var ANSI_REGEXP = new RegExp([
"[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)",
"(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TXZcf-nq-uy=><~]))"
].join("|"), "g");
// npm/esm/deps/jsr.io/@david/which/0.7.1/mod.js
var denoGlobal = globalThis.Deno;
var nodeProcess = globalThis.process;
var nodeFs;
function getNodeFs() {
return nodeFs ??= nodeProcess.getBuiltinModule("node:fs");
}
var RealEnvironment = class {
env(key) {
if (denoGlobal?.env) {
return denoGlobal.env.get(key);
}
return nodeProcess.env[key];
}
async stat(path6) {
if (denoGlobal?.stat) {
return await denoGlobal.stat(path6);
}
const info = await getNodeFs().promises.stat(path6);
return { isFile: info.isFile() };
}
statSync(path6) {
if (denoGlobal?.statSync) {
return denoGlobal.statSync(path6);
}
const info = getNodeFs().statSync(path6);
return { isFile: info.isFile() };
}
async lstat(path6) {
if (denoGlobal?.lstat) {
return await denoGlobal.lstat(path6);
}
const info = await getNodeFs().promises.lstat(path6);
return { isFile: info.isFile(), isSymlink: info.isSymbolicLink() };
}
lstatSync(path6) {
if (denoGlobal?.lstatSync) {
return denoGlobal.lstatSync(path6);
}
const info = getNodeFs().lstatSync(path6);
return { isFile: info.isFile(), isSymlink: info.isSymbolicLink() };
}
async readLink(path6) {
if (denoGlobal?.readLink) {
return await denoGlobal.readLink(path6);
}
return await getNodeFs().promises.readlink(path6);
}
readLinkSync(path6) {
if (denoGlobal?.readLinkSync) {
return denoGlobal.readLinkSync(path6);
}
return getNodeFs().readlinkSync(path6);
}
get isWindows() {
if (denoGlobal?.build?.os) {
return denoGlobal.build.os === "windows";
}
return nodeProcess.platform === "win32";
}
};
async function which(command, environment = new RealEnvironment()) {
if (commandHasPathSeparator(command, environment.isWindows)) {
if (await pathMatches(environment, command)) {
return command;
}
const pathExts = getPathExts(command, environment);
if (pathExts == null) {
return void 0;
}
for (const pathExt of pathExts) {
const filePath = command + pathExt;
if (await pathMatches(environment, filePath)) {
return filePath;
}
}
return void 0;
}
const systemInfo = getSystemInfo(command, environment);
if (systemInfo == null) {
return void 0;
}
for (const pathItem of systemInfo.pathItems) {
const filePath = pathItem + command;
if (systemInfo.pathExts) {
environment.requestPermission?.(pathItem);
for (const pathExt of systemInfo.pathExts) {
const filePath2 = pathItem + command + pathExt;
if (await pathMatches(environment, filePath2)) {
return filePath2;
}
}
} else if (await pathMatches(environment, filePath)) {
return filePath;
}
}
return void 0;
}
async function pathMatches(environment, path6) {
try {
return (await environment.stat(path6)).isFile;
} catch (statErr) {
if (isDenoPermissionDeniedError(statErr)) {
throw statErr;
}
if (environment.isWindows && isEaccesError(statErr)) {
return await followSymlinkChain(environment, path6);
}
return false;
}
}
async function followSymlinkChain(environment, path6) {
let current = path6;
for (let hops = 0; hops < 40; hops++) {
let info;
try {
info = await environment.lstat(current);
} catch (err) {
if (isDenoPermissionDeniedError(err)) {
throw err;
}
return false;
}
if (info.isFile)
return true;
if (!info.isSymlink)
return false;
let target;
try {
target = await environment.readLink(current);
} catch (err) {
if (isDenoPermissionDeniedError(err)) {
throw err;
}
return false;
}
current = resolveLinkTarget(current, target);
}
return false;
}
function whichSync(command, environment = new RealEnvironment()) {
if (commandHasPathSeparator(command, environment.isWindows)) {
if (pathMatchesSync(environment, command)) {
return command;
}
const pathExts = getPathExts(command, environment);
if (pathExts == null) {
return void 0;
}
for (const pathExt of pathExts) {
const filePath = command + pathExt;
if (pathMatchesSync(environment, filePath)) {
return filePath;
}
}
return void 0;
}
const systemInfo = getSystemInfo(command, environment);
if (systemInfo == null) {
return void 0;
}
for (const pathItem of systemInfo.pathItems) {
const filePath = pathItem + command;
if (systemInfo.pathExts) {
environment.requestPermission?.(pathItem);
for (const pathExt of systemInfo.pathExts) {
const filePath2 = pathItem + command + pathExt;
if (pathMatchesSync(environment, filePath2)) {
return filePath2;
}
}
} else if (pathMatchesSync(environment, filePath)) {
return filePath;
}
}
return void 0;
}
function pathMatchesSync(environment, path6) {
try {
return environment.statSync(path6).isFile;
} catch (statErr) {
if (isDenoPermissionDeniedError(statErr)) {
throw statErr;
}
if (environment.isWindows && isEaccesError(statErr)) {
return followSymlinkChainSync(environment, path6);
}
return false;
}
}
function followSymlinkChainSync(environment, path6) {
let current = path6;
for (let hops = 0; hops < 40; hops++) {
let info;
try {
info = environment.lstatSync(current);
} catch (err) {
if (isDenoPermissionDeniedError(err)) {
throw err;
}
return false;
}
if (info.isFile)
return true;
if (!info.isSymlink)
return false;
let target;
try {
target = environment.readLinkSync(current);
} catch (err) {
if (isDenoPermissionDeniedError(err)) {
throw err;
}
return false;
}
current = resolveLinkTarget(current, target);
}
return false;
}
function resolveLinkTarget(linkPath, target) {
if (isAbsolutePath(target)) {
return target;
}
const sepIdx = Math.max(linkPath.lastIndexOf("/"), linkPath.lastIndexOf("\\"));
const dir = sepIdx >= 0 ? linkPath.slice(0, sepIdx + 1) : "";
return dir + target;
}
function isAbsolutePath(p) {
if (p.startsWith("/") || p.startsWith("\\"))
return true;
return /^[A-Za-z]:[\\/]/.test(p);
}
function isEaccesError(err) {
return err != null && typeof err === "object" && "code" in err && err.code === "EACCES";
}
function isDenoPermissionDeniedError(err) {
const permissionDeniedError = denoGlobal?.errors?.PermissionDenied;
return permissionDeniedError != null && err instanceof permissionDeniedError;
}
function getSystemInfo(command, environment) {
const isWindows5 = environment.isWindows;
const path6 = environment.env("PATH");
const pathSeparator = isWindows5 ? "\\" : "/";
if (path6 == null) {
return void 0;
}
return {
pathItems: splitEnvValue(path6, isWindows5).map((item) => normalizeDir(item, pathSeparator)),
pathExts: getPathExts(command, environment),
isNameMatch: isWindows5 ? (a, b) => a.toLowerCase() === b.toLowerCase() : (a, b) => a === b
};
}
function getPathExts(command, environment) {
if (!environment.isWindows) {
return void 0;
}
const pathExtText = environment.env("PATHEXT") ?? ".EXE;.CMD;.BAT;.COM";
const pathExts = splitEnvValue(pathExtText, true);
const lowerCaseCommand = command.toLowerCase();
for (const pathExt of pathExts) {
if (lowerCaseCommand.endsWith(pathExt.toLowerCase())) {
return void 0;
}
}
return pathExts;
}
function commandHasPathSeparator(command, isWindows5) {
return command.includes("/") || isWindows5 && command.includes("\\");
}
function splitEnvValue(value, isWindows5) {
const envValueSeparator = isWindows5 ? ";" : ":";
return value.split(envValueSeparator).map((item) => item.trim()).filter((item) => item.length > 0);
}
function normalizeDir(dirPath, pathSeparator) {
if (pathSeparator === "\\" && dirPath.includes("/")) {
dirPath = normalizeWindowsSeparators(dirPath, pathSeparator);
}
if (!dirPath.endsWith(pathSeparator)) {
dirPath += pathSeparator;
}
return dirPath;
}
function normalizeWindowsSeparators(dirPath, pathSeparator) {
const isUncRoot = /^[/\\]{2}/.test(dirPath);
const head = isUncRoot ? pathSeparator + pathSeparator : "";
const rest = isUncRoot ? dirPath.slice(2) : dirPath;
return head + rest.replaceAll("/", pathSeparator).replace(/\\+/g, pathSeparator);
}
// npm/esm/deps/jsr.io/@david/path/0.3.2/path.js
function checkWindows() {
const global = dntGlobalThis;
const platform = global.process?.platform;
if (typeof platform === "string")
return platform.startsWith("win");
const os = global.Deno?.build?.os;
if (typeof os === "string")
return os === "windows";
return global.navigator?.platform?.startsWith("Win") ?? false;
}
var isWindows = checkWindows();
function assertPath(path6) {
if (typeof path6 !== "string") {
throw new TypeError(`Path must be a string, received "${JSON.stringify(path6)}"`);
}
}
function stripSuffix(name, suffix) {
if (suffix.length >= name.length) {
return name;
}
const lenDiff = name.length - suffix.length;
for (let i = suffix.length - 1; i >= 0; --i) {
if (name.charCodeAt(lenDiff + i) !== suffix.charCodeAt(i)) {
return name;
}
}
return name.slice(0, -suffix.length);
}
function lastPathSegment(path6, isSep, start = 0) {
let matchedNonSeparator = false;
let end = path6.length;
for (let i = path6.length - 1; i >= start; --i) {
if (isSep(path6.charCodeAt(i))) {
if (matchedNonSeparator) {
start = i + 1;
break;
}
} else if (!matchedNonSeparator) {
matchedNonSeparator = true;
end = i + 1;
}
}
return path6.slice(start, end);
}
function assertArgs(path6, suffix) {
assertPath(path6);
if (path6.length === 0)
return path6;
if (typeof suffix !== "string") {
throw new TypeError(`Suffix must be a string, received "${JSON.stringify(suffix)}"`);
}
}
function assertArg(url) {
url = url instanceof URL ? url : new URL(url);
if (url.protocol !== "file:") {
throw new TypeError(`URL must be a file URL: received "${url.protocol}"`);
}
return url;
}
function fromFileUrl(url) {
url = assertArg(url);
return decodeURIComponent(url.pathname.replace(/%(?![0-9A-Fa-f]{2})/g, "%25"));
}
function stripTrailingSeparators(segment, isSep) {
if (segment.length <= 1) {
return segment;
}
let end = segment.length;
for (let i = segment.length - 1; i > 0; i--) {
if (isSep(segment.charCodeAt(i))) {
end = i;
} else {
break;
}
}
return segment.slice(0, end);
}
var CHAR_UPPERCASE_A = 65;
var CHAR_LOWERCASE_A = 97;
var CHAR_UPPERCASE_Z = 90;
var CHAR_LOWERCASE_Z = 122;
var CHAR_DOT = 46;
var CHAR_FORWARD_SLASH = 47;
var CHAR_BACKWARD_SLASH = 92;
var CHAR_COLON = 58;
function isPosixPathSeparator(code2) {
return code2 === CHAR_FORWARD_SLASH;
}
function basename(path6, suffix = "") {
if (path6 instanceof URL) {
path6 = fromFileUrl(path6);
}
assertArgs(path6, suffix);
const lastSegment = lastPathSegment(path6, isPosixPathSeparator);
const strippedSegment = stripTrailingSeparators(lastSegment, isPosixPathSeparator);
return suffix ? stripSuffix(strippedSegment, suffix) : strippedSegment;
}
function isPosixPathSeparator2(code2) {
return code2 === CHAR_FORWARD_SLASH;
}
function isPathSeparator(code2) {
return code2 === CHAR_FORWARD_SLASH || code2 === CHAR_BACKWARD_SLASH;
}
function isWindowsDeviceRoot(code2) {
return code2 >= CHAR_LOWERCASE_A && code2 <= CHAR_LOWERCASE_Z || code2 >= CHAR_UPPERCASE_A && code2 <= CHAR_UPPERCASE_Z;
}
function fromFileUrl2(url) {
url = assertArg(url);
let path6 = decodeURIComponent(url.pathname.replace(/\//g, "\\").replace(/%(?![0-9A-Fa-f]{2})/g, "%25")).replace(/^\\*([A-Za-z]:)(\\|$)/, "$1\\");
if (url.hostname !== "") {
path6 = `\\\\${url.hostname}${path6}`;
}
return path6;
}
function basename2(path6, suffix = "") {
if (path6 instanceof URL) {
path6 = fromFileUrl2(path6);
}
assertArgs(path6, suffix);
let start = 0;
if (path6.length >= 2) {
const drive = path6.charCodeAt(0);
if (isWindowsDeviceRoot(drive)) {
if (path6.charCodeAt(1) === CHAR_COLON)
start = 2;
}
}
const lastSegment = lastPathSegment(path6, isPathSeparator, start);
const strippedSegment = stripTrailingSeparators(lastSegment, isPathSeparator);
return suffix ? stripSuffix(strippedSegment, suffix) : strippedSegment;
}
function basename3(path6, suffix = "") {
return isWindows ? basename2(path6, suffix) : basename(path6, suffix);
}
function assertArg2(path6) {
assertPath(path6);
if (path6.length === 0)
return ".";
}
function dirname(path6) {
if (path6 instanceof URL) {
path6 = fromFileUrl(path6);
}
assertArg2(path6);
let end = -1;
let matchedNonSeparator = false;
for (let i = path6.length - 1; i >= 1; --i) {
if (isPosixPathSeparator(path6.charCodeAt(i))) {
if (matchedNonSeparator) {
end = i;
break;
}
} else {
matchedNonSeparator = true;
}
}
if (end === -1) {
return isPosixPathSeparator(path6.charCodeAt(0)) ? "/" : ".";
}
return stripTrailingSeparators(path6.slice(0, end), isPosixPathSeparator);
}
function dirname2(path6) {
if (path6 instanceof URL) {
path6 = fromFileUrl2(path6);
}
assertArg2(path6);
const len = path6.length;
let rootEnd = -1;
let end = -1;
let matchedSlash = true;
let offset = 0;
const code2 = path6.charCodeAt(0);
if (len > 1) {
if (isPathSeparator(code2)) {
rootEnd = offset = 1;
if (isPathSeparator(path6.charCodeAt(1))) {
let j = 2;
let last = j;
for (; j < len; ++j) {
if (isPathSeparator(path6.charCodeAt(j)))
break;
}
if (j < len && j !== last) {
last = j;
for (; j < len; ++j) {
if (!isPathSeparator(path6.charCodeAt(j)))
break;
}
if (j < len && j !== last) {
last = j;
for (; j < len; ++j) {
if (isPathSeparator(path6.charCodeAt(j)))
break;
}
if (j === len) {
return path6;
}
if (j !== last) {
rootEnd = offset = j + 1;
}
}
}
}
} else if (isWindowsDeviceRoot(code2)) {
if (path6.charCodeAt(1) === CHAR_COLON) {
rootEnd = offset = 2;
if (len > 2) {
if (isPathSeparator(path6.charCodeAt(2)))
rootEnd = offset = 3;
}
}
}
} else if (isPathSeparator(code2)) {
return path6;
}
for (let i = len - 1; i >= offset; --i) {
if (isPathSeparator(path6.charCodeAt(i))) {
if (!matchedSlash) {
end = i;
break;
}
} else {
matchedSlash = false;
}
}
if (end === -1) {
if (rootEnd === -1)
return ".";
else
end = rootEnd;
}
return stripTrailingSeparators(path6.slice(0, end), isPosixPathSeparator2);
}
function dirname3(path6) {
return isWindows ? dirname2(path6) : dirname(path6);
}
function extname(path6) {
if (path6 instanceof URL) {
path6 = fromFileUrl(path6);
}
assertPath(path6);
let startDot = -1;
let startPart = 0;
let end = -1;
let matchedSlash = true;
let preDotState = 0;
for (let i = path6.length - 1; i >= 0; --i) {
const code2 = path6.charCodeAt(i);
if (isPosixPathSeparator(code2)) {
if (!matchedSlash) {
startPart = i + 1;
break;
}
continue;
}
if (end === -1) {
matchedSlash = false;
end = i + 1;
}
if (code2 === CHAR_DOT) {
if (startDot === -1)
startDot = i;
else if (preDotState !== 1)
preDotState = 1;
} else if (startDot !== -1) {
preDotState = -1;
}
}
if (startDot === -1 || end === -1 || // We saw a non-dot character immediately before the dot
preDotState === 0 || // The (right-most) trimmed path component is exactly '..'
preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
return "";
}
return path6.slice(startDot, end);
}
function extname2(path6) {
if (path6 instanceof URL) {
path6 = fromFileUrl2(path6);
}
assertPath(path6);
let start = 0;
let startDot = -1;
let startPart = 0;
let end = -1;
let matchedSlash = true;
let preDotState = 0;
if (path6.length >= 2 && path6.charCodeAt(1) === CHAR_COLON && isWindowsDeviceRoot(path6.charCodeAt(0))) {
start = startPart = 2;
}
for (let i = path6.length - 1; i >= start; --i) {
const code2 = path6.charCodeAt(i);
if (isPathSeparator(code2)) {
if (!matchedSlash) {
startPart = i + 1;
break;
}
continue;
}
if (end === -1) {
matchedSlash = false;
end = i + 1;
}
if (code2 === CHAR_DOT) {
if (startDot === -1)
startDot = i;
else if (preDotState !== 1)
preDotState = 1;
} else if (startDot !== -1) {
preDotState = -1;
}
}
if (startDot === -1 || end === -1 || // We saw a non-dot character immediately before the dot
preDotState === 0 || // The (right-most) trimmed path component is exactly '..'
preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
return "";
}
return path6.slice(startDot, end);
}
function extname3(path6) {
return isWindows ? extname2(path6) : extname(path6);
}
function fromFileUrl3(url) {
return isWindows ? fromFileUrl2(url) : fromFileUrl(url);
}
function isAbsolute(path6) {
assertPath(path6);
return path6.length > 0 && isPosixPathSeparator(path6.charCodeAt(0));
}
function isAbsolute2(path6) {
assertPath(path6);
const len = path6.length;
if (len === 0)
return false;
const code2 = path6.charCodeAt(0);
if (isPathSeparator(code2)) {
return true;
} else if (isWindowsDeviceRoot(code2)) {
if (len > 2 && path6.charCodeAt(1) === CHAR_COLON) {
if (isPathSeparator(path6.charCodeAt(2)))
return true;
}
}
return false;
}
function isAbsolute3(path6) {
return isWindows ? isAbsolute2(path6) : isAbsolute(path6);
}
function assertArg4(path6) {
assertPath(path6);
if (path6.length === 0)
return ".";
}
function normalizeString(path6, allowAboveRoot, separator, isPathSeparator2) {
let res = "";
let lastSegmentLength = 0;
let lastSlash = -1;
let dots = 0;
let code2;
for (let i = 0; i <= path6.length; ++i) {
if (i < path6.length)
code2 = path6.charCodeAt(i);
else if (isPathSeparator2(code2))
break;
else
code2 = CHAR_FORWARD_SLASH;
if (isPathSeparator2(code2)) {
if (lastSlash === i - 1 || dots === 1) {
} else if (lastSlash !== i - 1 && dots === 2) {
if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== CHAR_DOT || res.charCodeAt(res.length - 2) !== CHAR_DOT) {
if (res.length > 2) {
const lastSlashIndex = res.lastIndexOf(separator);
if (lastSlashIndex === -1) {
res = "";
lastSegmentLength = 0;
} else {
res = res.slice(0, lastSlashIndex);
lastSegmentLength = res.length - 1 - res.lastIndexOf(separator);
}
lastSlash = i;
dots = 0;
continue;
} else if (res.length === 2 || res.length === 1) {
res = "";
lastSegmentLength = 0;
lastSlash = i;
dots = 0;
continue;
}
}
if (allowAboveRoot) {
if (res.length > 0)
res += `${separator}..`;
else
res = "..";
lastSegmentLength = 2;
}
} else {
if (res.length > 0)
res += separator + path6.slice(lastSlash + 1, i);
else
res = path6.slice(lastSlash + 1, i);
lastSegmentLength = i - lastSlash - 1;
}
lastSlash = i;
dots = 0;
} else if (code2 === CHAR_DOT && dots !== -1) {
++dots;
} else {
dots = -1;
}
}
return res;
}
function normalize(path6) {
if (path6 instanceof URL) {
path6 = fromFileUrl(path6);
}
assertArg4(path6);
const isAbsolute42 = isPosixPathSeparator(path6.charCodeAt(0));
const trailingSeparator = isPosixPathSeparator(path6.charCodeAt(path6.length - 1));
path6 = normalizeString(path6, !isAbsolute42, "/", isPosixPathSeparator);
if (path6.length === 0 && !isAbsolute42)
path6 = ".";
if (path6.length > 0 && trailingSeparator)
path6 += "/";
if (isAbsolute42)
return `/${path6}`;
return path6;
}
function join(path6, ...paths) {
if (path6 === void 0)
return ".";
if (path6 instanceof URL) {
path6 = fromFileUrl(path6);
}
paths = path6 ? [
path6,
...paths
] : paths;
paths.forEach((path22) => assertPath(path22));
const joined = paths.filter((path22) => path22.length > 0).join("/");
return joined === "" ? "." : normalize(joined);
}
function normalize2(path6) {
if (path6 instanceof URL) {
path6 = fromFileUrl2(path6);
}
assertArg4(path6);
const len = path6.length;
let rootEnd = 0;
let device;
let isAbsolute42 = false;
const code2 = path6.charCodeAt(0);
if (len > 1) {
if (isPathSeparator(code2)) {
isAbsolute42 = true;
if (isPathSeparator(path6.charCodeAt(1))) {
let j = 2;
let last = j;
for (; j < len; ++j) {
if (isPathSeparator(path6.charCodeAt(j)))
break;
}
if (j < len && j !== last) {
const firstPart = path6.slice(last, j);
last = j;
for (; j < len; ++j) {
if (!isPathSeparator(path6.charCodeAt(j)))
break;
}
if (j < len && j !== last) {
last = j;
for (; j < len; ++j) {
if (isPathSeparator(path6.charCodeAt(j)))
break;
}
if (j === len) {
return `\\\\${firstPart}\\${path6.slice(last)}\\`;
} else if (j !== last) {
device = `\\\\${firstPart}\\${path6.slice(last, j)}`;
rootEnd = j;
}
}
}
} else {
rootEnd = 1;
}
} else if (isWindowsDeviceRoot(code2)) {
if (path6.charCodeAt(1) === CHAR_COLON) {
device = path6.slice(0, 2);
rootEnd = 2;
if (len > 2) {
if (isPathSeparator(path6.charCodeAt(2))) {
isAbsolute42 = true;
rootEnd = 3;
}
}
}
}
} else if (isPathSeparator(code2)) {
return "\\";
}
let tail;
if (rootEnd < len) {
tail = normalizeString(path6.slice(rootEnd), !isAbsolute42, "\\", isPathSeparator);
} else {
tail = "";
}
if (tail.length === 0 && !isAbsolute42)
tail = ".";
if (tail.length > 0 && isPathSeparator(path6.charCodeAt(len - 1))) {
tail += "\\";
}
if (device === void 0) {
if (isAbsolute42) {
if (tail.length > 0)
return `\\${tail}`;
else
return "\\";
}
return tail;
} else if (isAbsolute42) {
if (tail.length > 0)
return `${device}\\${tail}`;
else
return `${device}\\`;
}
return device + tail;
}
function join2(path6, ...paths) {
if (path6 instanceof URL) {
path6 = fromFileUrl2(path6);
}
paths = path6 ? [
path6,
...paths
] : paths;
paths.forEach((path22) => assertPath(path22));
paths = paths.filter((path22) => path22.length > 0);
if (paths.length === 0)
return ".";
let needsReplace = true;
let slashCount = 0;
const firstPart = paths[0];
if (isPathSeparator(firstPart.charCodeAt(0))) {
++slashCount;
const firstLen = firstPart.length;
if (firstLen > 1) {
if (isPathSeparator(firstPart.charCodeAt(1))) {
++slashCount;
if (firstLen > 2) {
if (isPathSeparator(firstPart.charCodeAt(2)))
++slashCount;
else {
needsReplace = false;
}
}
}
}
}
let joined = paths.join("\\");
if (needsReplace) {
for (; slashCount < joined.length; ++slashCount) {
if (!isPathSeparator(joined.charCodeAt(slashCount)))
break;
}
if (slashCount >= 2)
joined = `\\${joined.slice(slashCount)}`;
}
return normalize2(joined);
}
function join3(path6, ...paths) {
return isWindows ? join2(path6, ...paths) : join(path6, ...paths);
}
function normalize3(path6) {
return isWindows ? normalize2(path6) : normalize(path6);
}
function cwd(errorMessage) {
const global = dntGlobalThis;
const getCwd = global.process?.cwd ?? global.Deno?.cwd;
if (typeof getCwd !== "function") {
throw new TypeError(errorMessage);
}
return getCwd();
}
function resolve(...pathSegments) {
let resolvedPath = "";
let resolvedAbsolute = false;
for (let i = pathSegments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
let path6;
if (i >= 0)
path6 = pathSegments[i];
else {
path6 = cwd("Resolved a relative path without a current working directory (CWD)");
}
assertPath(path6);
if (path6.length === 0) {
continue;
}
resolvedPath = `${path6}/${resolvedPath}`;
resolvedAbsolute = isPosixPathSeparator(path6.charCodeAt(0));
}
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute, "/", isPosixPathSeparator);
if (resolvedAbsolute) {
if (resolvedPath.length > 0)
return `/${resolvedPath}`;
else
return "/";
} else if (resolvedPath.length > 0)
return resolvedPath;
else
return ".";
}
function assertArgs2(from, to) {
assertPath(from);
assertPath(to);
if (from === to)
return "";
}
function relative(from, to) {
assertArgs2(from, to);
from = resolve(from);
to = resolve(to);
if (from === to)
return "";
let fromStart = 1;
const fromEnd = from.length;
for (; fromStart < fromEnd; ++fromStart) {
if (!isPosixPathSeparator(from.charCodeAt(fromStart)))
break;
}
const fromLen = fromEnd - fromStart;
let toStart = 1;
const toEnd = to.length;
for (; toStart < toEnd; ++toStart) {
if (!isPosixPathSeparator(to.charCodeAt(toStart)))
break;
}
const toLen = toEnd - toStart;
const length = fromLen < toLen ? fromLen : toLen;
let lastCommonSep = -1;
let i = 0;
for (; i <= length; ++i) {
if (i === length) {
if (toLen > length) {
if (isPosixPathSeparator(to.charCodeAt(toStart + i))) {
return to.slice(toStart + i + 1);
} else if (i === 0) {
return to.slice(toStart + i);
}
} else if (fromLen > length) {
if (isPosixPathSeparator(from.charCodeAt(fromStart + i))) {
lastCommonSep = i;
} else if (i === 0) {
lastCommonSep = 0;
}
}
break;
}
const fromCode = from.charCodeAt(fromStart + i);
const toCode = to.charCodeAt(toStart + i);
if (fromCode !== toCode)
break;
else if (isPosixPathSeparator(fromCode))
lastCommonSep = i;
}
let out = "";
for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
if (i === fromEnd || isPosixPathSeparator(from.charCodeAt(i))) {
if (out.length === 0)
out += "..";
else
out += "/..";
}
}
if (out.length > 0)
return out + to.slice(toStart + lastCommonSep);
else {
toStart += lastCommonSep;
if (isPosixPathSeparator(to.charCodeAt(toStart)))
++toStart;
return to.slice(toStart);
}
}
function resolve2(...pathSegments) {
let resolvedDevice = "";
let resolvedTail = "";
let resolvedAbsolute = false;
for (let i = pathSegments.length - 1; i >= -1; i--) {
let path6;
if (i >= 0) {
path6 = pathSegments[i];
} else if (!resolvedDevice) {
path6 = cwd("Resolved a drive-letter-less path without a current working directory (CWD)");
} else {
path6 = cwd("Resolved a relative path without a current working directory (CWD)");
if (path6 === void 0 || path6.slice(0, 3).toLowerCase() !== `${resolvedDevice.toLowerCase()}\\`) {
path6 = `${resolvedDevice}\\`;
}
}
assertPath(path6);
const len = path6.length;
if (len === 0)
continue;
let rootEnd = 0;
let device = "";
let isAbsolute42 = false;
const code2 = path6.charCodeAt(0);
if (len > 1) {
if (isPathSeparator(code2)) {
isAbsolute42 = true;
if (isPathSeparator(path6.charCodeAt(1))) {
let j = 2;
let last = j;
for (; j < len; ++j) {
if (isPathSeparator(path6.charCodeAt(j)))
break;
}
if (j < len && j !== last) {
const firstPart = path6.slice(last, j);
last = j;
for (; j < len; ++j) {
if (!isPathSeparator(path6.charCodeAt(j)))
break;
}
if (j < len && j !== last) {
last = j;
for (; j < len; ++j) {
if (isPathSeparator(path6.charCodeAt(j)))
break;
}
if (j === len) {
device = `\\\\${firstPart}\\${path6.slice(last)}`;
rootEnd = j;
} else if (j !== last) {
device = `\\\\${firstPart}\\${path6.slice(last, j)}`;
rootEnd = j;
}
}
}
} else {
rootEnd = 1;
}
} else if (isWindowsDeviceRoot(code2)) {
if (path6.charCodeAt(1) === CHAR_COLON) {
device = path6.slice(0, 2);
rootEnd = 2;
if (len > 2) {
if (isPathSeparator(path6.charCodeAt(2))) {
isAbsolute42 = true;
rootEnd = 3;
}
}
}
}
} else if (isPathSeparator(code2)) {
rootEnd = 1;
isAbsolute42 = true;
}
if (device.length > 0 && resolvedDevice.length > 0 && device.toLowerCase() !== resolvedDevice.toLowerCase()) {
continue;
}
if (resolvedDevice.length === 0 && device.length > 0) {
resolvedDevice = device;
}
if (!resolvedAbsolute) {
resolvedTail = `${path6.slice(rootEnd)}\\${resolvedTail}`;
resolvedAbsolute = isAbsolute42;
}
if (resolvedAbsolute && resolvedDevice.length > 0)
break;
}
resolvedTail = normalizeString(resolvedTail, !resolvedAbsolute, "\\", isPathSeparator);
return resolvedDevice + (resolvedAbsolute ? "\\" : "") + resolvedTail || ".";
}
function relative2(from, to) {
assertArgs2(from, to);
const fromOrig = resolve2(from);
const toOrig = resolve2(to);
if (fromOrig === toOrig)
return "";
from = fromOrig.toLowerCase();
to = toOrig.toLowerCase();
if (from === to)
return "";
let fromStart = 0;
let fromEnd = from.length;
for (; fromStart < fromEnd; ++fromStart) {
if (from.charCodeAt(fromStart) !== CHAR_BACKWARD_SLASH)
break;
}
for (; fromEnd - 1 > fromStart; --fromEnd) {
if (from.charCodeAt(fromEnd - 1) !== CHAR_BACKWARD_SLASH)
break;
}
const fromLen = fromEnd - fromStart;
let toStart = 0;
let toEnd = to.length;
for (; toStart < toEnd; ++toStart) {
if (to.charCodeAt(toStart) !== CHAR_BACKWARD_SLASH)
break;
}
for (; toEnd - 1 > toStart; --toEnd) {
if (to.charCodeAt(toEnd - 1) !== CHAR_BACKWARD_SLASH)
break;
}
const toLen = toEnd - toStart;
const length = fromLen < toLen ? fromLen : toLen;
let lastCommonSep = -1;
let i = 0;
for (; i <= length; ++i) {
if (i === length) {
if (toLen > length) {
if (to.charCodeAt(toStart + i) === CHAR_BACKWARD_SLASH) {
return toOrig.slice(toStart + i + 1);
} else if (i === 2) {
return toOrig.slice(toStart + i);
}
}
if (fromLen > length) {
if (from.charCodeAt(fromStart + i) === CHAR_BACKWARD_SLASH) {
lastCommonSep = i;
} else if (i === 2) {
lastCommonSep = 3;
}
}
break;
}
const fromCode = from.charCodeAt(fromStart + i);
const toCode = to.charCodeAt(toStart + i);
if (fromCode !== toCode)
break;
else if (fromCode === CHAR_BACKWARD_SLASH)
lastCommonSep = i;
}
if (i !== length && lastCommonSep === -1) {
return toOrig;
}
let out = "";
if (lastCommonSep === -1)
lastCommonSep = 0;
for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
if (i === fromEnd || from.charCodeAt(i) === CHAR_BACKWARD_SLASH) {
if (out.length === 0)
out += "..";
else
out += "\\..";
}
}
if (out.length > 0) {
return out + toOrig.slice(toStart + lastCommonSep, toEnd);
} else {
toStart += lastCommonSep;
if (toOrig.charCodeAt(toStart) === CHAR_BACKWARD_SLASH)
++toStart;
return toOrig.slice(toStart, toEnd);
}
}
function relative3(from, to) {
return isWindows ? relative2(from, to) : relative(from, to);
}
function resolve3(...pathSegments) {
return isWindows ? resolve2(...pathSegments) : resolve(...pathSegments);
}
var WHITESPACE_ENCODINGS = {
" ": "%09",
"\n": "%0A",
"\v": "%0B",
"\f": "%0C",
"\r": "%0D",
" ": "%20"
};
function encodeWhitespace(string) {
return string.replaceAll(/[\s]/g, (c) => {
return WHITESPACE_ENCODINGS[c] ?? c;
});
}
function toFileUrl(path6) {
if (!isAbsolute(path6)) {
throw new TypeError(`Path must be absolute: received "${path6}"`);
}
const url = new URL("file:///");
url.pathname = encodeWhitespace(path6.replace(/%/g, "%25").replace(/\\/g, "%5C"));
return url;
}
function toFileUrl2(path6) {
if (!isAbsolute2(path6)) {
throw new TypeError(`Path must be absolute: received "${path6}"`);
}
const [, hostname, pathname] = path6.match(/^(?:[/\\]{2}([^/\\]+)(?=[/\\](?:[^/\\]|$)))?(.*)/);
const url = new URL("file:///");
url.pathname = encodeWhitespace(pathname.replace(/%/g, "%25"));
if (hostname !== void 0 && hostname !== "localhost") {
url.hostname = hostname;
if (!url.hostname) {
throw new TypeError(`Invalid hostname: "${url.hostname}"`);
}
}
return url;
}
function toFileUrl3(path6) {
return isWindows ? toFileUrl2(path6) : toFileUrl(path6);
}
// npm/esm/deps/jsr.io/@david/path/0.3.2/_fs.js
import fs from "node:fs";
import fsPromises from "node:fs/promises";
import { dirname as dirname4, join as join4 } from "node:path";
function isNotFoundError(err) {
return err?.code === "ENOENT";
}
function createNotFoundError(message) {
const err = new Error(message);
err.code = "ENOENT";
return err;
}
function isWindows2() {
return process.platform === "win32";
}
var FsFile = class {
/** @internal */
_fd;
/** @internal */
constructor(fd) {
this._fd = fd;
}
/** Writes data to the file, resolving to the number of bytes written.
*
* Strings are encoded as UTF-8.
*/
write(data) {
const bytes3 = typeof data === "string" ? new TextEncoder().encode(data) : data;
return new Promise((resolve8, reject) => {
fs.write(this._fd, bytes3, 0, bytes3.length, null, (err, written) => {
if (err)
reject(err);
else
resolve8(written);
});
});
}
/** Synchronously writes data to the file, returning the number of bytes written.
*
* Strings are encoded as UTF-8.
*/
writeSync(data) {
const bytes3 = typeof data === "string" ? new TextEncoder().encode(data) : data;
return fs.writeSync(this._fd, bytes3, 0, bytes3.length);
}
/** Reads into `buf`, resolving to the number of bytes read (0 at EOF). */
read(buf) {
return new Promise((resolve8, reject) => {
fs.read(this._fd, buf, 0, buf.length, null, (err, bytesRead) => {
if (err)
reject(err);
else
resolve8(bytesRead);
});
});
}
/** Synchronously reads into `buf`, returning the number of bytes read (0 at EOF). */
readSync(buf) {
return fs.readSync(this._fd, buf, 0, buf.length, null);
}
/** Closes the file handle. */
close() {
fs.closeSync(this._fd);
}
/** A writable stream that writes to this file. */
get writable() {
const fd = this._fd;
return new WritableStream2({
write(chunk) {
return new Promise((resolve8, reject) => {
fs.write(fd, chunk, 0, chunk.length, null, (err) => {
if (err)
reject(err);
else
resolve8();
});
});
}
});
}
/** A readable stream that reads from this file. */
get readable() {
const fd = this._fd;
return new ReadableStream2({
pull(controller) {
return new Promise((resolve8, reject) => {
const buf = new Uint8Array(16384);
fs.read(fd, buf, 0, buf.length, null, (err, bytesRead) => {
if (err) {
reject(err);
return;
}
if (bytesRead === 0) {
controller.close();
} else {
controller.enqueue(buf.subarray(0, bytesRead));
}
resolve8();
});
});
}
});
}
};
function stat(path6) {
return fsPromises.stat(path6);
}
function statSync(path6) {
return fs.statSync(path6);
}
function lstat(path6) {
return fsPromises.lstat(path6);
}
function lstatSync(path6) {
return fs.lstatSync(path6);
}
function realPath(path6) {
return fsPromises.realpath(path6);
}
function realPathSync(path6) {
return fs.realpathSync(path6);
}
async function mkdirFn(path6, options) {
await fsPromises.mkdir(path6, options);
}
function mkdirSyncFn(path6, options) {
fs.mkdirSync(path6, options);
}
async function linkFn(oldPath, newPath) {
await fsPromises.link(oldPath, newPath);
}
function linkSyncFn(oldPath, newPath) {
fs.linkSync(oldPath, newPath);
}
async function symlinkFn(target, path6, type) {
await fsPromises.symlink(target, path6, type?.type);
}
function symlinkSyncFn(target, path6, type) {
fs.symlinkSync(target, path6, type?.type);
}
async function* readDir(path6) {
const entries = await fsPromises.readdir(path6, { withFileTypes: true });
yield* entries;
}
function* readDirSync(path6) {
yield* fs.readdirSync(path6, { withFileTypes: true });
}
async function readFile(path6, options) {
return new Uint8Array(await fsPromises.readFile(path6, { signal: options?.signal }));
}
function readFileSync(path6) {
return new Uint8Array(fs.readFileSync(path6));
}
function readTextFile(path6, options) {
return fsPromises.readFile(path6, {
encoding: "utf8",
signal: options?.signal
});
}
function readTextFileSync(path6) {
return fs.readFileSync(path6, "utf8");
}
async function chmod(path6, mode) {
await fsPromises.chmod(path6, mode);
}
function chmodSync(path6, mode) {
fs.chmodSync(path6, mode);
}
async function chown(path6, uid, gid) {
await fsPromises.chown(path6, uid ?? -1, gid ?? -1);
}
function chownSync(path6, uid, gid) {
fs.chownSync(path6, uid ?? -1, gid ?? -1);
}
function openFile(path6, options) {
return new Promise((resolve8, reject) => {
fs.open(path6, openOptionsToFlags(options), options?.mode, (err, fd) => {
if (err)
reject(err);
else
resolve8(new FsFile(fd));
});
});
}
function openFileSync(path6, options) {
const fd = fs.openSync(path6, openOptionsToFlags(options), options?.mode);
return new FsFile(fd);
}
function createFile(path6) {
return openFile(path6, {
write: true,
create: true,
truncate: true,
read: true
});
}
function createFileSync(path6) {
return openFileSync(path6, {
write: true,
create: true,
truncate: true,
read: true
});
}
async function remove(path6, options) {
if (options?.recursive) {
await fsPromises.rm(path6, { recursive: true });
return;
}
const info = await fsPromises.lstat(path6);
if (info.isDirectory()) {
await fsPromises.rmdir(path6);
} else {
await fsPromises.unlink(path6);
}
}
function removeSync(path6, options) {
if (options?.recursive) {
fs.rmSync(path6, { recursive: true });
return;
}
const info = fs.lstatSync(path6);
if (info.isDirectory()) {
fs.rmdirSync(path6);
} else {
fs.unlinkSync(path6);
}
}
async function copyFileFn(src, dest) {
await fsPromises.copyFile(src, dest);
}
function copyFileSyncFn(src, dest) {
fs.copyFileSync(src, dest);
}
async function renameFn(oldPath, newPath) {
await fsPromises.rename(oldPath, newPath);
}
function renameSyncFn(oldPath, newPath) {
fs.renameSync(oldPath, newPath);
}
async function ensureDir(path6) {
await mkdirFn(path6, { recursive: true });
}
function ensureDirSync(path6) {
mkdirSyncFn(path6, { recursive: true });
}
async function ensureFile(path6) {
const info = await lstatOrUndefined(path6);
if (info != null) {
if (info.isFile())
return;
throw new Error(`Path '${path6}' already exists and is not a file.`);
}
await mkdirFn(dirname4(path6), { recursive: true });
(await createFile(path6)).close();
}
function ensureFileSync(path6) {
const info = lstatOrUndefinedSync(path6);
if (info != null) {
if (info.isFile())
return;
throw new Error(`Path '${path6}' already exists and is not a file.`);
}
mkdirSyncFn(dirname4(path6), { recursive: true });
createFileSync(path6).close();
}
async function emptyDir(path6) {
try {
const entries = [];
for await (const entry of readDir(path6)) {
entries.push(entry);
}
for (const entry of entries) {
await remove(join4(path6, entry.name), { recursive: true });
}
} catch (err) {
if (!isNotFoundError(err))
throw err;
await mkdirFn(path6, { recursive: true });
}
}
function emptyDirSync(path6) {
try {
const entries = [...readDirSync(path6)];
for (const entry of entries) {
removeSync(join4(path6, entry.name), { recursive: true });
}
} catch (err) {
if (!isNotFoundError(err))
throw err;
mkdirSyncFn(path6, { recursive: true });
}
}
async function copy(src, dest, options) {
const overwrite = options?.overwrite ?? false;
const srcInfo = await stat(src);
await copyRecursive(src, dest, srcInfo, overwrite);
}
function copySync(src, dest, options) {
const overwrite = options?.overwrite ?? false;
const srcInfo = statSync(src);
copyRecursiveSync(src, dest, srcInfo, overwrite);
}
async function copyRecursive(src, dest, srcInfo, overwrite) {
let destInfo = await lstatOrUndefined(dest);
if (destInfo != null && !overwrite) {
throw new Error(`'${dest}' already exists.`);
}
if (srcInfo.isDirectory()) {
if (destInfo != null && !destInfo.isDirectory()) {
await remove(dest);
destInfo = void 0;
}
if (destInfo == null) {
await mkdirFn(dest, { recursive: true });
}
for await (const entry of readDir(src)) {
const srcChild = join4(src, entry.name);
const destChild = join4(dest, entry.name);
const childInfo = await stat(srcChild);
await copyRecursive(srcChild, destChild, childInfo, overwrite);
}
} else {
if (destInfo != null && destInfo.isDirectory()) {
throw new Error(`Cannot overwrite directory