Skip to content

src/list-folder.ts

91 lines · 3.1 KB · TypeScript
Raw
/**
 * List a Dropbox folder, or continue a previous page with `cursor`.
 * Use an empty path for the account root.
 *
 * @param params.path - Folder path starting with `/`, or `''` for root.
 * @param params.cursor - Previous `list_folder` cursor to continue paging.
 * @param params.limit - Page size from 1 through 2000.
 * @param params.recursive - When true, include nested entries.
 * @returns `{ entries, cursor, has_more }`.
 *
 * @example
 * import listFolder from 'kody:@kentcdodds/dropbox/list-folder'
 * const page = await listFolder({ path: '', limit: 100 })
 */

import { dropboxRpc } from './request.ts'
import type { JsonRecord } from './types.ts'
import {
	optionalBoolean,
	optionalNumber,
	optionalString,
	requireDropboxPath,
	requireRecord,
} from './types.ts'

export type ListFolderInput = {
	path?: string
	cursor?: string
	recursive?: boolean
	includeDeleted?: boolean
	includeMediaInfo?: boolean
	includeNonDownloadableFiles?: boolean
	limit?: number
}

export type ListFolderResult = {
	entries: JsonRecord[]
	cursor: string
	has_more: boolean
}

/**
 * List a Dropbox folder, or continue a previous page with `cursor`.
 * Use an empty path for the account root.
 *
 * @param params.path - Folder path starting with `/`, or `''` for root.
 * @param params.cursor - Previous `list_folder` cursor to continue paging.
 * @param params.limit - Page size from 1 through 2000.
 * @param params.recursive - When true, include nested entries.
 * @returns `{ entries, cursor, has_more }`.
 *
 * @example
 * import listFolder from 'kody:@kentcdodds/dropbox/list-folder'
 * const page = await listFolder({ path: '', limit: 100 })
 */
export async function listFolder(input: ListFolderInput = {}): Promise<ListFolderResult> {
	const cursor = optionalString(input.cursor, 'cursor')
	if (cursor) {
		return dropboxRpc<ListFolderResult>('files/list_folder/continue', { cursor })
	}

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

	return dropboxRpc<ListFolderResult>('files/list_folder', {
		path,
		recursive: optionalBoolean(input.recursive, 'recursive') ?? false,
		include_deleted: optionalBoolean(input.includeDeleted, 'includeDeleted') ?? false,
		include_media_info: optionalBoolean(input.includeMediaInfo, 'includeMediaInfo') ?? false,
		include_non_downloadable_files:
			optionalBoolean(input.includeNonDownloadableFiles, 'includeNonDownloadableFiles') ??
			true,
		...(limit === undefined ? {} : { limit }),
	})
}

/**
 * List a Dropbox folder or continue a previous page with `cursor`.
 * Use an empty path for the account root.
 * @example
 * import listFolder from 'kody:@kentcdodds/dropbox/list-folder'
 * const page = await listFolder({ path: '', limit: 100 })
 */
export default async function listFolderEntrypoint(
	params: Partial<ListFolderInput> & Record<string, unknown> = {},
) {
	return listFolder(requireRecord(params, 'list-folder') as ListFolderInput)
}