export type JsonRecord = Record export type DropboxRequestKind = 'rpc' | 'upload' | 'download' export type DropboxRequestInput = { endpoint: string kind?: DropboxRequestKind body?: unknown apiArg?: JsonRecord bytesBase64?: string headers?: Record confirm?: boolean dryRun?: boolean } export type DropboxRequestResult = { ok: boolean status: number statusText: string requestId: string | null headers: Record body: unknown } export function requireRecord(value: unknown, label: string): JsonRecord { if (!value || typeof value !== 'object' || Array.isArray(value)) { throw new Error(`${label} must be an object.`) } return value as JsonRecord } export function requireString( value: unknown, label: string, options: { allowEmpty?: boolean } = {}, ): string { if (typeof value !== 'string' || (!options.allowEmpty && value.length === 0)) { throw new Error(`${label} must be ${options.allowEmpty ? 'a string' : 'a non-empty string'}.`) } return value } export function optionalBoolean(value: unknown, label: string): boolean | undefined { if (value === undefined) return undefined if (typeof value !== 'boolean') throw new Error(`${label} must be a boolean.`) return value } export function optionalNumber(value: unknown, label: string): number | undefined { if (value === undefined) return undefined if (typeof value !== 'number' || !Number.isFinite(value)) { throw new Error(`${label} must be a finite number.`) } return value } export function optionalString(value: unknown, label: string): string | undefined { if (value === undefined) return undefined return requireString(value, label, { allowEmpty: true }) } export function requireDropboxPath( value: unknown, label = 'path', options: { allowRoot?: boolean } = {}, ): string { const path = requireString(value, label, { allowEmpty: options.allowRoot }) if (path !== '' && !path.startsWith('/')) { throw new Error(`${label} must start with "/"${options.allowRoot ? ' or be empty for root' : ''}.`) } return path }