Files API
The files namespace on FFDBClient provides methods for uploading, listing, downloading, updating, and deleting files stored in S3-compatible object storage. The React package adds hooks with automatic URL refresh and loading state.
Namespace: FilesNamespace
type FilesNamespace = {
upload: (
file: File | Blob | { uri: string; type: string; name: string },
opts?: UploadOptions,
) => Promise<FileRecord>
list: (folder?: string) => Promise<FileListResult>
getUrl: (fileId: string) => Promise<FileUrl>
update: (
fileId: string,
metadata: Partial<Pick<FileRecord,
'name' | 'description' | 'folder_path' | 'visibility' | 'privacy'
>>,
) => Promise<FileRecord>
delete: (fileId: string) => Promise<{ deleted: boolean }>
}
files.upload
Uploads a file to S3 via presigned URL and returns the confirmed file record.
const record = await files.upload(file, options?)
Parameters
- Name
file- Type
- File | Blob | { uri, type, name }
- Description
The file to upload. Accepts a browser
File, aBlob, or a React Native-style object withuri,type, andnameproperties.
- Name
options- Type
- UploadOptions
- Description
Optional configuration for the upload. See below.
UploadOptions
type UploadOptions = {
name?: string
folderPath?: string
visibility?: 'public' | 'private'
privacy?: 'private' | 'org' | 'team'
description?: string
maxSizeBytes?: number
allowedMimeTypes?: string[]
compress?: boolean
compressOptions?: CompressOptions
}
- Name
name- Type
- string
- Description
Override the file name. Defaults to the original file name.
- Name
folderPath- Type
- string
- Description
Target folder path. Defaults to
'/'.
- Name
visibility- Type
- 'public' | 'private'
- Description
'public'files are accessible via a direct URL.'private'files require a presigned download URL. Defaults to'private'.
- Name
privacy- Type
- 'private' | 'org' | 'team'
- Description
'private': only the uploader can access.'org': all org members.'team': team members only. Defaults to'org'.
- Name
description- Type
- string
- Description
Optional description stored with the file metadata.
- Name
maxSizeBytes- Type
- number
- Description
Per-upload override for the global max file size limit.
- Name
allowedMimeTypes- Type
- string[]
- Description
Per-upload override for the global allowed MIME types.
- Name
compress- Type
- boolean
- Description
Enable client-side image compression before upload. Browser only.
- Name
compressOptions- Type
- CompressOptions
- Description
Compression settings:
maxWidth,maxHeight, andquality(0-1).
Returns
Promise<FileRecord> — the confirmed file record with all metadata.
Example
// Browser File input
const input = document.querySelector<HTMLInputElement>('#file-input')
const record = await files.upload(input!.files![0], {
folderPath: '/uploads',
compress: true,
})
// React Native
const record = await files.upload(
{ uri: 'file:///path/to/photo.jpg', type: 'image/jpeg', name: 'photo.jpg' },
{ folderPath: '/photos', privacy: 'private' },
)
files.list
Lists files in a folder that the current user has permission to read.
const result = await files.list(folder?)
Parameters
- Name
folder- Type
- string
- Description
Filter by folder path. Omit to list all accessible files.
Returns
type FileListResult = {
files: FileRecord[]
total: number
}
files.getUrl
Gets a download URL for a file. Public files return a direct URL; private files return a presigned URL with an expiry.
const result = await files.getUrl(fileId)
Returns
type FileUrl = {
url: string
expiresAt: number | null
public: boolean
}
files.update
Updates file metadata. Only the fields you include are changed.
const updated = await files.update(fileId, metadata)
Parameters
- Name
fileId- Type
- string
- Description
The ID of the file to update.
- Name
metadata- Type
- object
- Description
Partial object with any of:
name,description,folder_path,visibility,privacy.
Returns
Promise<FileRecord> — the updated file record.
files.delete
Soft-deletes a file and removes the S3 object.
const result = await files.delete(fileId)
Returns
Promise<{ deleted: boolean }>
React hooks
Import from ffdb-client/react. All hooks require an <FFDBProvider> ancestor.
useFileUrl
Fetches a presigned download URL and automatically refreshes it before expiry.
function useFileUrl(
fileId: string | null | undefined,
options?: UseFileUrlOptions,
): UseFileUrlResult
- Name
fileId- Type
- string | null | undefined
- Description
The file ID. Pass
nullorundefinedto skip fetching.
- Name
options.enabled- Type
- boolean
- Description
Whether the hook should fetch. Defaults to
true.
- Name
options.refreshBeforeExpiryMs- Type
- number
- Description
How many milliseconds before expiry to trigger a refresh. Defaults to
60000(1 minute).
Returns: UseFileUrlResult
type UseFileUrlResult = {
url: string | null
isPublic: boolean
isLoading: boolean
error: Error | null
refetch: () => Promise<void>
}
Example
import { useFileUrl } from 'ffdb-client/react'
function ProfileImage({ fileId }: { fileId: string }) {
const { url, isLoading, error } = useFileUrl(fileId)
if (isLoading) return <Skeleton />
if (error) return <span>Failed to load image</span>
return <img src={url!} alt="Profile" />
}
useFileList
Lists files in a folder with loading state and automatic refetch.
function useFileList(
folder?: string,
options?: UseFileListOptions,
): UseFileListResult
- Name
folder- Type
- string
- Description
Filter by folder path. Omit for all files.
- Name
options.enabled- Type
- boolean
- Description
Whether the hook should fetch. Defaults to
true.
- Name
options.refetchOnFocus- Type
- boolean
- Description
Re-fetch when the browser tab regains focus. Defaults to
true.
- Name
options.refetchInterval- Type
- number
- Description
Poll interval in milliseconds. Off by default.
Returns: UseFileListResult
type UseFileListResult = {
files: FileRecord[]
total: number
isLoading: boolean
isFetching: boolean
error: Error | null
refetch: () => Promise<void>
}
useUpload
Wraps files.upload with loading and error state for UI feedback.
function useUpload(): UseUploadResult
Returns: UseUploadResult
type UseUploadResult = {
upload: (
file: File | Blob | { uri: string; type: string; name: string },
opts?: UploadOptions,
) => Promise<FileRecord>
isUploading: boolean
error: Error | null
lastUpload: FileRecord | null
reset: () => void
}
- Name
upload- Type
- function
- Description
Call with a file and options. Returns the confirmed
FileRecord. Also throws on failure.
- Name
isUploading- Type
- boolean
- Description
True while an upload is in progress.
- Name
error- Type
- Error | null
- Description
The error from the most recent failed upload, or
null.
- Name
lastUpload- Type
- FileRecord | null
- Description
The record from the most recent successful upload.
- Name
reset- Type
- function
- Description
Clears
errorandlastUploadstate.
useFiles
Returns the raw files namespace from the client. Mirrors useDB() and useAuth().
function useFiles(): FilesNamespace
Throws if called outside of an <FFDBProvider> or before the client has initialized.
Error type: FileStorageError
All file operations throw FileStorageError (extends Error) with a code property for programmatic handling.
import { FileStorageError } from 'ffdb-client'
Error codes
- Name
FILE_UPLOAD_DISABLED- Description
File storage is not enabled. An admin needs to configure S3 and enable uploads in Settings.
- Name
S3_ERROR- Description
The backend could not communicate with S3. Check endpoint, credentials, and bucket configuration.
- Name
OFFLINE- Description
No network connection. File operations (except metadata queries via local cache) require connectivity.
- Name
FILE_TOO_LARGE- Description
File exceeds the configured max size (or per-upload override).
- Name
MIME_TYPE_NOT_ALLOWED- Description
File type is not in the allowed MIME types list.
- Name
PERMISSION_DENIED- Description
User lacks the required folder permission.
- Name
STORAGE_LIMIT_EXCEEDED- Description
Org storage quota reached.
- Name
S3_UPLOAD_FAILED- Description
Direct S3 upload failed. Presigned URL may have expired — retry the upload.
- Name
CLIENT_NOT_READY- Description
The FFDB client hasn't initialized yet. Ensure your code runs after
<FFDBProvider>has loaded.
Types
FileRecord
type FileRecord = {
id: string
name: string
s3_key: string
size_bytes: number
mime_type: string
folder_path: string
visibility: 'public' | 'private'
privacy: 'private' | 'org' | 'team'
description: string | null
uploaded_by: string
org_id: string | null
team_id: string | null
status: 'pending' | 'confirmed' | 'deleted'
created_at: number
updated_at: number
}
CompressOptions
type CompressOptions = {
maxWidth?: number
maxHeight?: number
quality?: number
}
quality is a number between 0 and 1. PNG files keep their format; other image types are converted to JPEG during compression.