import { request } from './request.ts'
import type { DropboxRequestResult, JsonRecord } from './types.ts'
import {
optionalBoolean,
optionalString,
requireDropboxPath,
requireRecord,
} from './types.ts'
export type UploadInput = {
path: string
text?: string
bytesBase64?: string
mode?: 'add' | 'overwrite'
autorename?: boolean
mute?: boolean
strictConflict?: boolean
confirm?: boolean
dryRun?: boolean
}
export async function upload(
input: UploadInput,
): Promise<DropboxRequestResult | JsonRecord> {
const path = requireDropboxPath(input.path)
const text = optionalString(input.text, 'text')
const suppliedBase64 = optionalString(input.bytesBase64, 'bytesBase64')
if ((text === undefined) === (suppliedBase64 === undefined)) {
throw new Error('Provide exactly one of text or bytesBase64.')
}
const mode = input.mode ?? 'add'
if (mode !== 'add' && mode !== 'overwrite') {
throw new Error('mode must be "add" or "overwrite".')
}
const bytesBase64 = suppliedBase64 ?? encodeTextBase64(text ?? '')
return request({
endpoint: 'files/upload',
kind: 'upload',
apiArg: {
path,
mode,
autorename: optionalBoolean(input.autorename, 'autorename') ?? false,
mute: optionalBoolean(input.mute, 'mute') ?? false,
strict_conflict: optionalBoolean(input.strictConflict, 'strictConflict') ?? false,
},
bytesBase64,
confirm: input.confirm,
dryRun: input.dryRun,
})
}
function encodeTextBase64(value: string): string {
const bytes = new TextEncoder().encode(value)
const chunks: string[] = []
const chunkSize = 0x8000
for (let index = 0; index < bytes.length; index += chunkSize) {
chunks.push(String.fromCharCode(...bytes.subarray(index, index + chunkSize)))
}
return btoa(chunks.join(''))
}
/**
* Upload UTF-8 text or base64 bytes to Dropbox.
* Requires `confirm: true`; use `dryRun: true` to preview the request.
* @example
* import upload from 'kody:@kentcdodds/dropbox/upload'
* const result = await upload({
* path: '/notes/hello.txt',
* text: 'Hello',
* mode: 'overwrite',
* confirm: true,
* })
*/
export default async function uploadEntrypoint(
params: Partial<UploadInput> & Record<string, unknown> = {},
) {
return upload(requireRecord(params, 'upload') as UploadInput)
}