diff --git a/src/adapters/baidu/baidu-adapter.ts b/src/adapters/baidu/baidu-adapter.ts index a8d6f4d..3522430 100644 --- a/src/adapters/baidu/baidu-adapter.ts +++ b/src/adapters/baidu/baidu-adapter.ts @@ -14,6 +14,8 @@ interface BaiduAPIResponse { 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; } - 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 diff --git a/src/shared/version.ts b/src/shared/version.ts index 9abdb64..c202dba 100644 --- a/src/shared/version.ts +++ b/src/shared/version.ts @@ -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 */ /** diff --git a/tests/unit/adapters/baidu-adapter.test.ts b/tests/unit/adapters/baidu-adapter.test.ts new file mode 100644 index 0000000..4c7b2d4 --- /dev/null +++ b/tests/unit/adapters/baidu-adapter.test.ts @@ -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, + }); + }); + }); +}); +