File: //lib/node_modules/openclaw/dist/trash-CX7nB-3e.js
import { It as resolvePreferredOpenClawTmpDir } from "./entry.js";
import { n as runExec } from "./exec-G9-WTRVN.js";
import { t as generateSecureToken } from "./secure-random-CRVHgtmO.js";
import { n as openFileWithinRoot, t as SafeOpenError } from "./fs-safe-Cwp1VOPx.js";
import os from "node:os";
import path from "node:path";
import fs from "node:fs";
import fs$1 from "node:fs/promises";
//#region src/browser/paths.ts
const DEFAULT_BROWSER_TMP_DIR = resolvePreferredOpenClawTmpDir();
const DEFAULT_TRACE_DIR = DEFAULT_BROWSER_TMP_DIR;
const DEFAULT_DOWNLOAD_DIR = path.join(DEFAULT_BROWSER_TMP_DIR, "downloads");
const DEFAULT_UPLOAD_DIR = path.join(DEFAULT_BROWSER_TMP_DIR, "uploads");
function resolvePathWithinRoot(params) {
const root = path.resolve(params.rootDir);
const raw = params.requestedPath.trim();
if (!raw) {
if (!params.defaultFileName) return {
ok: false,
error: "path is required"
};
return {
ok: true,
path: path.join(root, params.defaultFileName)
};
}
const resolved = path.resolve(root, raw);
const rel = path.relative(root, resolved);
if (!rel || rel.startsWith("..") || path.isAbsolute(rel)) return {
ok: false,
error: `Invalid path: must stay within ${params.scopeLabel}`
};
return {
ok: true,
path: resolved
};
}
async function resolveExistingPathsWithinRoot(params) {
const rootDir = path.resolve(params.rootDir);
let rootRealPath;
try {
rootRealPath = await fs$1.realpath(rootDir);
} catch {
rootRealPath = void 0;
}
const isInRoot = (relativePath) => Boolean(relativePath) && !relativePath.startsWith("..") && !path.isAbsolute(relativePath);
const resolveExistingRelativePath = async (requestedPath) => {
const raw = requestedPath.trim();
const lexicalPathResult = resolvePathWithinRoot({
rootDir,
requestedPath,
scopeLabel: params.scopeLabel
});
if (lexicalPathResult.ok) return {
ok: true,
relativePath: path.relative(rootDir, lexicalPathResult.path),
fallbackPath: lexicalPathResult.path
};
if (!rootRealPath || !raw || !path.isAbsolute(raw)) return lexicalPathResult;
try {
const resolvedExistingPath = await fs$1.realpath(raw);
const relativePath = path.relative(rootRealPath, resolvedExistingPath);
if (!isInRoot(relativePath)) return lexicalPathResult;
return {
ok: true,
relativePath,
fallbackPath: resolvedExistingPath
};
} catch {
return lexicalPathResult;
}
};
const resolvedPaths = [];
for (const raw of params.requestedPaths) {
const pathResult = await resolveExistingRelativePath(raw);
if (!pathResult.ok) return {
ok: false,
error: pathResult.error
};
let opened;
try {
opened = await openFileWithinRoot({
rootDir,
relativePath: pathResult.relativePath
});
resolvedPaths.push(opened.realPath);
} catch (err) {
if (err instanceof SafeOpenError && err.code === "not-found") {
resolvedPaths.push(pathResult.fallbackPath);
continue;
}
return {
ok: false,
error: `Invalid path: must stay within ${params.scopeLabel} and be a regular non-symlink file`
};
} finally {
await opened?.handle.close().catch(() => {});
}
}
return {
ok: true,
paths: resolvedPaths
};
}
//#endregion
//#region src/browser/trash.ts
async function movePathToTrash(targetPath) {
try {
await runExec("trash", [targetPath], { timeoutMs: 1e4 });
return targetPath;
} catch {
const trashDir = path.join(os.homedir(), ".Trash");
fs.mkdirSync(trashDir, { recursive: true });
const base = path.basename(targetPath);
let dest = path.join(trashDir, `${base}-${Date.now()}`);
if (fs.existsSync(dest)) dest = path.join(trashDir, `${base}-${Date.now()}-${generateSecureToken(6)}`);
fs.renameSync(targetPath, dest);
return dest;
}
}
//#endregion
export { resolveExistingPathsWithinRoot as a, DEFAULT_UPLOAD_DIR as i, DEFAULT_DOWNLOAD_DIR as n, resolvePathWithinRoot as o, DEFAULT_TRACE_DIR as r, movePathToTrash as t };