mirror of
https://github.com/luckyyzh/pi-agent-integrated.git
synced 2026-10-03 02:59:35 +00:00
feat: integrate Pi backend and Pi Web
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
export const UPLOAD_CONFLICT_STRATEGIES = ["error", "overwrite", "skip"] as const;
|
||||
export type UploadConflictStrategy = typeof UPLOAD_CONFLICT_STRATEGIES[number];
|
||||
|
||||
const UPLOAD_CONFLICT_STRATEGY_SET = new Set<string>(UPLOAD_CONFLICT_STRATEGIES);
|
||||
|
||||
export interface UploadTargetInspection {
|
||||
conflicts: string[];
|
||||
nonReplaceable: string[];
|
||||
}
|
||||
|
||||
export function parseUploadConflictStrategy(value: string | null): UploadConflictStrategy | null {
|
||||
const candidate = value ?? "error";
|
||||
return UPLOAD_CONFLICT_STRATEGY_SET.has(candidate)
|
||||
? candidate as UploadConflictStrategy
|
||||
: null;
|
||||
}
|
||||
|
||||
export function validateUploadFileNames(fileNames: string[]): string | null {
|
||||
if (fileNames.length === 0) return "No files selected";
|
||||
|
||||
const seen = new Set<string>();
|
||||
for (const fileName of fileNames) {
|
||||
if (!fileName || fileName === "." || fileName === ".." || fileName.includes("\0")) {
|
||||
return `Invalid file name: ${fileName || "(empty)"}`;
|
||||
}
|
||||
if (fileName.includes("/") || fileName.includes("\\") || path.basename(fileName) !== fileName) {
|
||||
return `File names must not contain a path: ${fileName}`;
|
||||
}
|
||||
if (seen.has(fileName)) return `Duplicate file name in upload: ${fileName}`;
|
||||
seen.add(fileName);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function inspectUploadTargets(directory: string, fileNames: string[]): UploadTargetInspection {
|
||||
const conflicts: string[] = [];
|
||||
const nonReplaceable: string[] = [];
|
||||
|
||||
for (const fileName of fileNames) {
|
||||
const destination = path.join(directory, fileName);
|
||||
let stat: fs.Stats;
|
||||
try {
|
||||
stat = fs.lstatSync(destination);
|
||||
} catch (error) {
|
||||
const code = (error as NodeJS.ErrnoException).code;
|
||||
if (code === "ENOENT") continue;
|
||||
throw error;
|
||||
}
|
||||
|
||||
conflicts.push(fileName);
|
||||
if (!stat.isFile() || stat.isSymbolicLink()) nonReplaceable.push(fileName);
|
||||
}
|
||||
|
||||
return { conflicts, nonReplaceable };
|
||||
}
|
||||
Reference in New Issue
Block a user