feat: integrate Pi backend and Pi Web

This commit is contained in:
luckyyzh
2026-07-30 19:37:53 +08:00
commit 7392ab9dd7
1390 changed files with 337197 additions and 0 deletions
+70
View File
@@ -0,0 +1,70 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
async function loadSubject() {
return import("./file-upload.ts");
}
test("validates upload names without accepting paths or duplicates", async () => {
const { validateUploadFileNames } = await loadSubject();
assert.equal(validateUploadFileNames(["one.txt", "two file.md"]), null);
assert.match(validateUploadFileNames(["../secret.txt"]), /must not contain a path/);
assert.match(validateUploadFileNames(["folder\\secret.txt"]), /must not contain a path/);
assert.match(validateUploadFileNames(["same.txt", "same.txt"]), /Duplicate/);
assert.match(validateUploadFileNames([]), /No files/);
});
test("finds conflicts and prevents replacing directories", async (t) => {
const { inspectUploadTargets } = await loadSubject();
const root = fs.mkdtempSync(path.join(os.tmpdir(), "pi-web-upload-"));
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
fs.writeFileSync(path.join(root, "file.txt"), "old");
fs.mkdirSync(path.join(root, "directory"));
assert.deepEqual(
inspectUploadTargets(root, ["new.txt", "file.txt", "directory"]),
{
conflicts: ["file.txt", "directory"],
nonReplaceable: ["directory"],
},
);
});
test("prevents replacing symbolic links", async (t) => {
const { inspectUploadTargets } = await loadSubject();
const root = fs.mkdtempSync(path.join(os.tmpdir(), "pi-web-upload-link-"));
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
fs.writeFileSync(path.join(root, "file.txt"), "old");
try {
fs.symlinkSync("file.txt", path.join(root, "link.txt"));
} catch (error) {
if (error?.code === "EPERM") {
t.skip("Creating symbolic links requires additional privileges on this platform");
return;
}
throw error;
}
assert.deepEqual(
inspectUploadTargets(root, ["link.txt"]),
{
conflicts: ["link.txt"],
nonReplaceable: ["link.txt"],
},
);
});
test("parses only supported conflict strategies", async () => {
const { parseUploadConflictStrategy } = await loadSubject();
assert.equal(parseUploadConflictStrategy(null), "error");
assert.equal(parseUploadConflictStrategy("overwrite"), "overwrite");
assert.equal(parseUploadConflictStrategy("skip"), "skip");
assert.equal(parseUploadConflictStrategy("rename"), null);
});