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, a Blob, or a React Native-style object with uri, type, and name properties.

  • 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, and quality (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 null or undefined to 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 error and lastUpload state.


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.

Was this page helpful?