Skip to content

Built for people who want to own their automations. Join the waitlist for an invite.

Package listing

@kentcdodds/dropbox

src/types.ts

72 lines · 2.0 KB · TypeScript
export type JsonRecord = Record<string, unknown>

export type DropboxRequestKind = 'rpc' | 'upload' | 'download'

export type DropboxRequestInput = {
	endpoint: string
	kind?: DropboxRequestKind
	body?: unknown
	apiArg?: JsonRecord
	bytesBase64?: string
	headers?: Record<string, string>
	confirm?: boolean
	dryRun?: boolean
}

export type DropboxRequestResult = {
	ok: boolean
	status: number
	statusText: string
	requestId: string | null
	headers: Record<string, string>
	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
}