Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ These are fully typed and bound directly on the client:
| `downloadfile` | `(fileid: number, destination: string \| WritableStream<Uint8Array>, options?: DownloadOptions)` | `Promise<FileLocal>` |
| `remoteupload` | `(url: string, folderid?: number, options?: RemoteUploadOptions)` | `Promise<{ metadata: FileMetadata }>` |
| `getthumbsfileids` | `(fileids: number[], receiveThumb: (thumb: ThumbResult) => void, options?: ThumbOptions)` | `Promise<ThumbResult[]>` |
| `getthumbslinks` | `(fileids: number[], options?: ThumbOptions)` | `Promise<ThumbResult[]>` |

## Uploads

Expand Down
2 changes: 2 additions & 0 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export interface Client {
renamefolder(folderid: number, toname: string): Promise<FolderMetadata>
getfilelink(fileid: number): Promise<string>
getthumblink(fileid: number, options?: ThumbOptions): Promise<string>
getthumbslinks(fileids: number[], options?: ThumbOptions): Promise<ThumbResult[]>
sharefolder(
folderid: number,
mail: string,
Expand Down Expand Up @@ -174,6 +175,7 @@ export function createClient(opts: CreateClientOptions): Client {
renamefolder: methods.renamefolder(ctx),
getfilelink: methods.getfilelink(ctx),
getthumblink: methods.getthumblink(ctx),
getthumbslinks: methods.getthumbslinks(ctx),
sharefolder: methods.sharefolder(ctx),
appshare: methods.appshare(ctx),
login: methods.login(ctx),
Expand Down
38 changes: 38 additions & 0 deletions src/methods/getthumbslinks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { ClientContext } from '../client'
import type { ThumbResult } from '../types/api'
import type { ThumbOptions } from '../types/options'

import { assert } from '../util/assert'

interface ThumbsLinksEntry {
result: number
fileid: number
hosts?: string[]
path?: string
}

export function getthumbslinks(ctx: ClientContext) {
return async (fileids: number[], options: ThumbOptions = {}): Promise<ThumbResult[]> => {
assert(Array.isArray(fileids) && fileids.length > 0, '`fileids` must be a non-empty array')

const thumbType = options.thumbType ?? 'auto'
const size = options.size ?? '120x120'
const crop = options.crop ?? true

const res = await ctx.call<{ thumbs: ThumbsLinksEntry[] }>('getthumbslinks', {
fileids: fileids.join(','),
type: thumbType,
size,
crop: crop ? 1 : 0,
})

const thumbs: ThumbResult[] = []
for (const entry of res.thumbs) {
if (entry.result !== 0) continue
const host = entry.hosts?.[0]
if (!host || !entry.path) continue
thumbs.push({ fileid: entry.fileid, url: `https://${host}${entry.path}` })
}
return thumbs
}
}
1 change: 1 addition & 0 deletions src/methods/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export { renamefile } from './renamefile'
export { renamefolder } from './renamefolder'
export { getfilelink } from './getfilelink'
export { getthumblink } from './getthumblink'
export { getthumbslinks } from './getthumbslinks'
export { sharefolder } from './sharefolder'
export { appshare } from './appshare'
export { login } from './login'
Expand Down
92 changes: 92 additions & 0 deletions test/unit/methods/getthumbslinks.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { describe, it, expect, vi } from 'vitest'

import { createClient } from '../../../src/client'
import { apiOk, mockFetch } from '../../fixtures/responses'

const TWO_OK = {
thumbs: [
{ result: 0, fileid: 42, hosts: ['p-host.pcloud.com'], path: '/cBL42/thumb.jpg' },
{ result: 0, fileid: 43, hosts: ['p-host.pcloud.com'], path: '/cBL43/thumb.jpg' },
],
}

describe('getthumbslinks', () => {
it('returns assembled https URLs for all successful entries', async () => {
vi.stubGlobal('fetch', mockFetch(apiOk(TWO_OK)))
const client = createClient({ token: 'test-token' })
const thumbs = await client.getthumbslinks([42, 43])
expect(thumbs).toEqual([
{ fileid: 42, url: 'https://p-host.pcloud.com/cBL42/thumb.jpg' },
{ fileid: 43, url: 'https://p-host.pcloud.com/cBL43/thumb.jpg' },
])
})

it('sends fileids, type=auto, size=120x120, crop=1 by default', async () => {
let capturedUrl = ''
vi.stubGlobal('fetch', (url: string) => {
capturedUrl = url
return Promise.resolve(new Response(JSON.stringify(apiOk(TWO_OK)), { status: 200 }))
})

const client = createClient({ token: 'test-token' })
await client.getthumbslinks([42, 43])
expect(capturedUrl).toContain('fileids=42%2C43')
expect(capturedUrl).toContain('type=auto')
expect(capturedUrl).toContain('size=120x120')
expect(capturedUrl).toContain('crop=1')
})

it('honors custom thumbType, size, and crop=false', async () => {
let capturedUrl = ''
vi.stubGlobal('fetch', (url: string) => {
capturedUrl = url
return Promise.resolve(new Response(JSON.stringify(apiOk(TWO_OK)), { status: 200 }))
})

const client = createClient({ token: 'test-token' })
await client.getthumbslinks([42], { thumbType: 'png', size: '32x32', crop: false })
expect(capturedUrl).toContain('type=png')
expect(capturedUrl).toContain('size=32x32')
expect(capturedUrl).toContain('crop=0')
})

it('drops entries whose per-file result is non-zero', async () => {
vi.stubGlobal(
'fetch',
mockFetch(
apiOk({
thumbs: [
{ result: 0, fileid: 42, hosts: ['p-host.pcloud.com'], path: '/cBL42/thumb.jpg' },
{ result: 2009, fileid: 99 },
],
}),
),
)
const client = createClient({ token: 'test-token' })
const thumbs = await client.getthumbslinks([42, 99])
expect(thumbs).toEqual([{ fileid: 42, url: 'https://p-host.pcloud.com/cBL42/thumb.jpg' }])
})

it('drops entries with empty hosts array', async () => {
vi.stubGlobal(
'fetch',
mockFetch(
apiOk({
thumbs: [
{ result: 0, fileid: 42, hosts: [], path: '/cBL42/thumb.jpg' },
{ result: 0, fileid: 43, hosts: ['p-host.pcloud.com'], path: '/cBL43/thumb.jpg' },
],
}),
),
)
const client = createClient({ token: 'test-token' })
const thumbs = await client.getthumbslinks([42, 43])
expect(thumbs).toEqual([{ fileid: 43, url: 'https://p-host.pcloud.com/cBL43/thumb.jpg' }])
})

it('throws TypeError when fileids is empty', async () => {
const client = createClient({ token: 'test-token' })
await expect(client.getthumbslinks([])).rejects.toThrow(TypeError)
await expect(client.getthumbslinks([])).rejects.toThrow('`fileids` must be a non-empty array')
})
})
Loading