feat(baidu-adapter): 支持/api/list顶层list响应结构并修复文件列表解析

修改BaiduAdapter以兼容不同API响应结构,当list字段在顶层时也能正确解析
修复parentId使用目标路径而非文件路径的问题
添加相关单元测试验证功能
这个提交包含在:
Zain 2025-12-29 18:29:30 +08:00
父节点 a796eca950
当前提交 e718b43757
共有 3 个文件被更改,包括 83 次插入 和 7 次删除

查看文件

@ -14,6 +14,8 @@ interface BaiduAPIResponse<T = any> {
request_id?: number;
taskid?: number;
data?: T;
// Some endpoints (e.g. /api/list) return `list` at top-level instead of inside `data`.
list?: any[];
}
/**
@ -187,12 +189,15 @@ export class BaiduAdapter extends BasePlatformAdapter {
const result: BaiduAPIResponse<{ list: BaiduFileListItem[] }> = await response.json();
if (result.errno !== 0 || !result.data?.list) {
if (result.errno !== 0) {
const errorMsg = getErrorMessage(result.errno);
throw new BaiduAPIError(result.errno, errorMsg, result);
}
const pageFiles = result.data.list;
const pageFiles = (result.data?.list ?? result.list) as BaiduFileListItem[] | undefined;
if (!Array.isArray(pageFiles)) {
throw new Error('无法解析文件列表响应');
}
// Filter out folders (only return files, isdir === 0)
const files = pageFiles
@ -203,7 +208,7 @@ export class BaiduAdapter extends BasePlatformAdapter {
id: String(file.fs_id),
name: file.server_filename,
ext: ext,
parentId: file.path || targetPath,
parentId: targetPath,
size: file.size,
mtime: file.server_mtime ? file.server_mtime * 1000 : Date.now(),
};
@ -332,11 +337,16 @@ export class BaiduAdapter extends BasePlatformAdapter {
const result: BaiduAPIResponse<{ list: BaiduFileListItem[] }> = await response.json();
if (result.errno === 0 && result.data?.list) {
return result.data.list.some(file => file.server_filename === fileName);
if (result.errno !== 0) {
return false;
}
const list = (result.data?.list ?? result.list) as BaiduFileListItem[] | undefined;
if (!Array.isArray(list)) {
return false;
}
return list.some(file => file.server_filename === fileName);
} catch (error) {
logger.error('Failed to check name conflict:', error instanceof Error ? error : new Error(String(error)));
return true; // Conservative on error

查看文件

@ -10,7 +10,7 @@
* 1. Edit version in package.json
* 2. Run: npm run sync:version (or automatically via prebuild/predev)
*
* Generated at: 2025-12-29T09:42:53.807Z
* Generated at: 2025-12-29T10:25:00.256Z
*/
/**

查看文件

@ -0,0 +1,66 @@
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { BaiduAdapter } from '../../../src/adapters/baidu/baidu-adapter';
describe('BaiduAdapter', () => {
let adapter: BaiduAdapter;
let mockFetch: any;
beforeEach(() => {
adapter = new BaiduAdapter({ requestInterval: 0 });
// Mock global fetch used by BasePlatformAdapter.fetchWithTimeout
mockFetch = vi.fn();
global.fetch = mockFetch;
// Avoid relying on MAIN-world injector in unit tests
vi.spyOn(adapter as any, 'extractBdstoken').mockResolvedValue('mock-token');
vi.spyOn(adapter as any, 'rateLimit').mockResolvedValue(undefined);
});
afterEach(() => {
vi.restoreAllMocks();
});
describe('getAllFiles', () => {
it('应该支持 /api/list 顶层 list 响应结构(errno=0)', async () => {
mockFetch.mockResolvedValue({
json: async () => ({
errno: 0,
list: [
{
path: '/test/a.txt',
server_filename: 'a.txt',
fs_id: 1,
md5: 'x',
isdir: 0,
size: 10,
server_mtime: 1700000000,
},
{
path: '/test/folder',
server_filename: 'folder',
fs_id: 2,
md5: 'y',
isdir: 1,
size: 0,
server_mtime: 1700000001,
},
],
}),
});
const files = await adapter.getAllFiles('/test');
expect(files).toHaveLength(1);
expect(files[0]).toEqual({
id: '1',
name: 'a.txt',
ext: '.txt',
parentId: '/test',
size: 10,
mtime: 1700000000 * 1000,
});
});
});
});