Plainleaf 自动发布 / release (push) Failing after 2m4s
Co-Authored-By: Codex <noreply@anthropic.com>
104 lines
2.9 KiB
TypeScript
104 lines
2.9 KiB
TypeScript
import type { FileMeta } from "@silverbulletmd/silverbullet/type/index";
|
|
import { expect, test } from "vitest";
|
|
import { CheckedSpacePrimitives } from "../spaces/checked_space_primitives.ts";
|
|
import type { SpacePrimitives } from "../spaces/space_primitives.ts";
|
|
import {
|
|
createPlainleafShare,
|
|
deletePlainleafSharesForPaths,
|
|
findPlainleafShare,
|
|
listPlainleafShares,
|
|
movePlainleafShares,
|
|
} from "./plainleaf_sharing.ts";
|
|
|
|
class MemoryStorage implements SpacePrimitives {
|
|
files = new Map<string, { data: Uint8Array; meta: FileMeta }>();
|
|
|
|
async fetchFileList() {
|
|
return [...this.files.values()].map((file) => file.meta);
|
|
}
|
|
|
|
async getFileMeta(path: string) {
|
|
const file = this.files.get(path);
|
|
if (!file) throw new Error("missing");
|
|
return file.meta;
|
|
}
|
|
|
|
async readFile(path: string) {
|
|
const file = this.files.get(path);
|
|
if (!file) throw new Error("missing");
|
|
return { data: file.data.slice(), meta: file.meta };
|
|
}
|
|
|
|
async writeFile(path: string, data: Uint8Array) {
|
|
const meta: FileMeta = {
|
|
name: path,
|
|
created: 1,
|
|
lastModified: 2,
|
|
contentType: "application/json",
|
|
size: data.byteLength,
|
|
perm: "rw",
|
|
};
|
|
this.files.set(path, { data: data.slice(), meta });
|
|
return meta;
|
|
}
|
|
|
|
async deleteFile(path: string) {
|
|
if (!this.files.delete(path)) throw new Error("missing");
|
|
}
|
|
}
|
|
|
|
const token = "0123456789abcdef0123456789abcdef";
|
|
|
|
test("creates, finds, moves, and revokes a private share manifest", async () => {
|
|
const storage = new CheckedSpacePrimitives(new MemoryStorage(), false);
|
|
const share = await createPlainleafShare(
|
|
storage,
|
|
{ path: "旅行/计划.md", title: "旅行计划", format: "markdown" },
|
|
new Date("2026-08-13T00:00:00.000Z"),
|
|
token,
|
|
);
|
|
expect(share.token).toBe(token);
|
|
await expect(findPlainleafShare(storage, "旅行/计划.md")).resolves.toEqual(
|
|
share,
|
|
);
|
|
|
|
await expect(
|
|
movePlainleafShares(storage, [
|
|
{
|
|
from: "旅行/计划.md",
|
|
to: "归档/计划.md",
|
|
title: "计划归档",
|
|
},
|
|
]),
|
|
).resolves.toBe(1);
|
|
expect((await listPlainleafShares(storage))[0]).toMatchObject({
|
|
path: "归档/计划.md",
|
|
title: "计划归档",
|
|
token,
|
|
});
|
|
|
|
await expect(
|
|
deletePlainleafSharesForPaths(storage, ["归档/计划.md"]),
|
|
).resolves.toBe(1);
|
|
await expect(listPlainleafShares(storage)).resolves.toEqual([]);
|
|
});
|
|
|
|
test("rejects unsafe paths and ignores damaged manifests", async () => {
|
|
const source = new MemoryStorage();
|
|
const storage = new CheckedSpacePrimitives(source, false);
|
|
await expect(
|
|
createPlainleafShare(
|
|
storage,
|
|
{ path: "../秘密.md", title: "秘密", format: "markdown" },
|
|
new Date(),
|
|
token,
|
|
),
|
|
).rejects.toThrow("安全的分享链接");
|
|
|
|
await source.writeFile(
|
|
".plainleaf/shares/broken.json",
|
|
new TextEncoder().encode("not json"),
|
|
);
|
|
await expect(listPlainleafShares(storage)).resolves.toEqual([]);
|
|
});
|