/** * Upload UTF-8 text or base64 bytes to Dropbox. Pick this for small files * (`text` or `bytesBase64` under 120 KiB binary). Larger `bytesBase64` payloads * auto-delegate to `./upload-large` (upload session) in the same call. Put * `bytesBase64` in execute `params`, never inline in `code`. Requires `confirm: true`. * * @param params.path - Destination Dropbox path starting with `/` (prefer `/Apps/Kody/...`). * @param params.text - UTF-8 text body (mutually exclusive with `bytesBase64`). * @param params.bytesBase64 - Base64 file bytes (mutually exclusive with `text`). * @param params.mode - `add` (default) or `overwrite`. * @param params.confirm - Required `true` to perform the mutating call. * @param params.dryRun - When true, return the planned request without calling Dropbox. * @returns Dropbox upload metadata, or a dry-run preview. * * @example * import upload from 'kody:@kentcdodds/dropbox/upload' * const result = await upload({ * path: '/Apps/Kody/notes/hello.txt', * text: 'Hello', * mode: 'overwrite', * confirm: true, * }) */ import { decodeBase64, encodeTextBase64 } from './base64.ts' import { UPLOAD_SINGLE_MAX_BYTES } from './paths.ts' import { request } from './request.ts' import { uploadLarge } from './upload-large.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 } /** * Upload UTF-8 text or base64 bytes to Dropbox. Pick this for small files * (`text` or `bytesBase64` under 120 KiB binary). Larger `bytesBase64` payloads * auto-delegate to `./upload-large` (upload session) in the same call. Put * `bytesBase64` in execute `params`, never inline in `code`. Requires `confirm: true`. * * @param params.path - Destination Dropbox path starting with `/` (prefer `/Apps/Kody/...`). * @param params.text - UTF-8 text body (mutually exclusive with `bytesBase64`). * @param params.bytesBase64 - Base64 file bytes (mutually exclusive with `text`). * @param params.mode - `add` (default) or `overwrite`. * @param params.confirm - Required `true` to perform the mutating call. * @param params.dryRun - When true, return the planned request without calling Dropbox. * @returns Dropbox upload metadata, or a dry-run preview. * * @example * import upload from 'kody:@kentcdodds/dropbox/upload' * const result = await upload({ * path: '/Apps/Kody/notes/hello.txt', * text: 'Hello', * mode: 'overwrite', * confirm: true, * }) */ export async function upload( input: UploadInput, ): Promise { 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 ?? '') const byteLength = decodeBase64(bytesBase64).byteLength if (byteLength > UPLOAD_SINGLE_MAX_BYTES) { const delegated = await uploadLarge({ path, bytesBase64, mode, autorename: input.autorename, mute: input.mute, strictConflict: input.strictConflict, confirm: input.confirm, dryRun: input.dryRun, }) if (input.dryRun && delegated && typeof delegated === 'object') { return { ...delegated, delegatedFrom: './upload', reason: `Decoded bytes (${byteLength}) exceed UPLOAD_SINGLE_MAX_BYTES (${UPLOAD_SINGLE_MAX_BYTES}); using upload session.`, } } return delegated } 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, }) } /** * Upload UTF-8 text or base64 bytes to Dropbox. * Requires `confirm: true`; use `dryRun: true` to preview the request. * Over-threshold binary payloads auto-delegate to `./upload-large`. * @example * import upload from 'kody:@kentcdodds/dropbox/upload' * const result = await upload({ * path: '/Apps/Kody/notes/hello.txt', * text: 'Hello', * mode: 'overwrite', * confirm: true, * }) */ export default async function uploadEntrypoint( params: Partial & Record = {}, ) { return upload(requireRecord(params, 'upload') as UploadInput) }