feat: add file trash metadata API

This commit is contained in:
2026-06-28 17:04:26 +08:00
parent 36846855b6
commit 144d844794
13 changed files with 43 additions and 13 deletions
+4
View File
@@ -25,6 +25,7 @@ describe('VerstakPluginAPI contract', () => {
expect(typeof api.files.createFolder).toBe('function');
expect(typeof api.files.move).toBe('function');
expect(typeof api.files.trash).toBe('function');
expect(typeof api.files.listTrash).toBe('function');
expect(typeof api.files.openExternal).toBe('function');
expect(typeof api.files.showInFolder).toBe('function');
expect(typeof api.workbench.openResource).toBe('function');
@@ -247,6 +248,9 @@ describe('VerstakPluginAPI contract', () => {
expect(trash.originalPath).toBe('PlatformTest/two.txt');
expect(trash.trashId).toBeTruthy();
expect(trash.trashPath).toMatch(/^\.verstak\/trash\/files\/.+\/two\.txt$/);
await expect(api.files.listTrash()).resolves.toEqual([
expect.objectContaining({ originalPath: 'PlatformTest/two.txt', trashId: trash.trashId }),
]);
});
test('files mock rejects non-canonical and reserved paths', async () => {
+2
View File
@@ -14,6 +14,7 @@ import type {
OpenResourceResult,
PluginSettings,
RegisteredContributionPoints,
TrashEntry,
TrashResult,
WriteTextOptions,
} from './types';
@@ -120,6 +121,7 @@ export interface VerstakPluginAPI {
createFolder(relativePath: string): Promise<void>;
move(fromRelativePath: string, toRelativePath: string, options?: MovePathOptions): Promise<void>;
trash(relativePath: string): Promise<TrashResult>;
listTrash(): Promise<TrashEntry[]>;
openExternal(relativePath: string): Promise<void>;
showInFolder(relativePath: string): Promise<void>;
};
+10 -3
View File
@@ -55,6 +55,7 @@ export function createMockPluginAPI(pluginId = 'test.plugin', options: MockPlugi
const commands = new Map<string, PluginCommandHandler>();
const eventHandlers = new Map<string, Array<(event: any) => void>>();
const files = new Map<string, { type: 'file' | 'folder'; content?: string; modifiedAt: string }>();
const trashEntries: Array<{ originalPath: string; trashPath: string; trashId: string; deletedAt: string; originalType: 'file' | 'folder'; basename: string }> = [];
files.set('', { type: 'folder', modifiedAt: new Date().toISOString() });
function normalizePath(path: string, allowRoot = false): string {
@@ -225,16 +226,22 @@ export function createMockPluginAPI(pluginId = 'test.plugin', options: MockPlugi
}),
trash: vi.fn(async (relativePath: string) => {
const path = normalizePath(relativePath);
if (!files.has(path)) throw new Error(`not-found: ${path}`);
files.delete(path);
const node = files.get(path);
if (!node) throw new Error(`not-found: ${path}`);
const trashId = `mock-${Date.now()}`;
return {
const entry = {
originalPath: path,
trashPath: `.verstak/trash/files/${trashId}/${baseName(path)}`,
trashId,
deletedAt: new Date().toISOString(),
originalType: node.type,
basename: baseName(path),
};
files.delete(path);
trashEntries.unshift(entry);
return entry;
}),
listTrash: vi.fn(async () => trashEntries.slice()),
openExternal: vi.fn(async (relativePath: string) => {
const path = normalizePath(relativePath);
if (!files.has(path)) throw new Error(`not-found: ${path}`);
+5
View File
@@ -141,6 +141,11 @@ export interface TrashResult {
deletedAt: string;
}
export interface TrashEntry extends TrashResult {
originalType: FileEntry['type'];
basename: string;
}
// ─── Contribution Points ─────────────────────────────────────
export interface ContributionPoints {