Skip to content
← Public packages

@kody/dropbox

Reusable Dropbox OAuth helpers for account, metadata, search, file transfer, sharing, and generic API requests.

src/search.ts

72 lines · 2.0 KB · TypeScript
import { dropboxRpc } from './request.ts'
import type { JsonRecord } from './types.ts'
import {
	optionalBoolean,
	optionalNumber,
	optionalString,
	requireDropboxPath,
	requireRecord,
	requireString,
} from './types.ts'

export type SearchDropboxInput = {
	query?: string
	cursor?: string
	path?: string
	maxResults?: number
	filenameOnly?: boolean
}

export type SearchDropboxResult = {
	matches: JsonRecord[]
	has_more: boolean
	cursor?: string
}

/**
 * Search Dropbox files and folders by query.
 * @param input.query - Dropbox search query string.
 * @returns Search matches from Dropbox.
 * @example
 * import searchDropbox from 'kody:@kody/dropbox/search'
 * const hits = await searchDropbox({ query: 'quarterly plan' })
 */
export async function searchDropbox(
	input: SearchDropboxInput,
): Promise<SearchDropboxResult> {
	const cursor = optionalString(input.cursor, 'cursor')
	if (cursor) {
		return dropboxRpc<SearchDropboxResult>('files/search/continue_v2', { cursor })
	}

	const query = requireString(input.query, 'query')
	const path = requireDropboxPath(input.path ?? '', 'path', { allowRoot: true })
	const maxResults = optionalNumber(input.maxResults, 'maxResults')
	if (
		maxResults !== undefined &&
		(!Number.isInteger(maxResults) || maxResults < 1 || maxResults > 1000)
	) {
		throw new Error('maxResults must be an integer from 1 through 1000.')
	}

	return dropboxRpc<SearchDropboxResult>('files/search_v2', {
		query,
		options: {
			path,
			filename_only: optionalBoolean(input.filenameOnly, 'filenameOnly') ?? false,
			...(maxResults === undefined ? {} : { max_results: maxResults }),
		},
	})
}

/**
 * Search Dropbox file and folder names, or continue with a previous cursor.
 * @example
 * import search from 'kody:@kody/dropbox/search'
 * const results = await search({ query: 'invoice', path: '/documents' })
 */
export default async function searchDropboxEntrypoint(
	params: Partial<SearchDropboxInput> & Record<string, unknown> = {},
) {
	return searchDropbox(requireRecord(params, 'search') as SearchDropboxInput)
}