← All @molecule/* packages · App templates
@molecule/app-file-uploadCore interface · file-upload · App (browser) · v1.0.1 · Apache-2.0
File upload core interface for molecule.dev — progress tracking, validation, multi-file queues
npm install @molecule/app-file-upload@molecule/app-file-upload is the file-upload core interface on the app (browser) side: the API your app calls, with no vendor inside.
Choose the implementation by bonding one of its 1 provider: @molecule/app-file-upload-filepond.
import { createUploader } from '@molecule/app-file-upload'
const uploader = createUploader({
destination: { url: '/api/upload' },
validation: { maxSize: 10 * 1024 * 1024, acceptedTypes: ['image/*'] },
multiple: true,
autoUpload: true,
events: {
onComplete: (file) => console.log(`Uploaded: ${file.name}`),
},
})Providers (1): @molecule/app-file-upload-filepond
Works with: @molecule/app-bond
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
File upload core interface for molecule.dev.
Provides a framework-agnostic contract for file uploads with progress
tracking, validation, drag-and-drop support, and multi-file queues.
Bond a provider (e.g. @molecule/app-file-upload-filepond) at startup,
then use {@link createUploader} anywhere.
import { createUploader } from '@molecule/app-file-upload'
const uploader = createUploader({
destination: { url: '/api/upload' },
validation: { maxSize: 10 * 1024 * 1024, acceptedTypes: ['image/*'] },
multiple: true,
autoUpload: true,
events: {
onComplete: (file) => console.log(`Uploaded: ${file.name}`),
},
})
core
npm install @molecule/app-file-upload @molecule/app-bond
FileUploadEventsEvent callbacks for the file upload lifecycle.
interface FileUploadEvents {
/** Called when files are added to the upload queue. */
onFilesAdded?: (files: UploadFile[]) => void
/** Called when a file is removed from the queue. */
onFileRemoved?: (file: UploadFile) => void
/** Called when a file's upload progress changes. */
onProgress?: (file: UploadFile, progress: number) => void
/** Called when a file upload completes successfully. */
onComplete?: (file: UploadFile) => void
/** Called when a file upload fails. */
onError?: (file: UploadFile, error: string) => void
/** Called when all files in the queue have been processed. */
onAllComplete?: (files: UploadFile[]) => void
/** Called when a file fails validation. */
onValidationError?: (file: UploadFile, errors: string[]) => void
}
FileUploadInstanceA live file upload instance exposing queue management and upload control.
interface FileUploadInstance {
// -- Queue management ---------------------------------------------------
/**
* Adds files to the upload queue.
*
* @param files - Files to add (browser `File` objects).
* @returns The `UploadFile` representations that were added (after validation).
*/
addFiles(files: File[]): UploadFile[]
/**
* Removes a file from the upload queue.
*
* @param fileId - The ID of the file to remove.
*/
removeFile(fileId: string): void
/** Removes all files from the upload queue. */
clearFiles(): void
/** Returns all files currently in the upload queue. */
getFiles(): UploadFile[]
/**
* Returns a single file by ID, or `undefined` if not found.
*
* @param fileId - The ID of the file to retrieve.
* @returns The file, or `undefined`.
*/
getFile(fileId: string): UploadFile | undefined
// -- Upload control -----------------------------------------------------
/** Starts uploading all queued files that are in `'idle'` status. */
upload(): void
/**
* Cancels the upload for a specific file.
*
* @param fileId - The ID of the file whose upload to cancel.
*/
cancelUpload(fileId: string): void
/** Cancels all active uploads. */
cancelAll(): void
/**
* Retries a failed upload.
*
* @param fileId - The ID of the file to retry.
*/
retry(fileId: string): void
/** Retries all failed uploads. */
retryAll(): void
// -- State queries ------------------------------------------------------
/** Returns `true` if any file is currently uploading. */
isUploading(): boolean
/**
* Returns the overall upload progress as a percentage (0–100)
* across all files.
*/
getTotalProgress(): number
// -- Lifecycle ----------------------------------------------------------
/** Releases resources held by the upload instance. */
destroy(): void
}
FileUploadOptionsConfiguration for creating a file upload instance.
interface FileUploadOptions {
/** Upload destination configuration. */
destination: UploadDestination
/** File validation constraints. */
validation?: FileValidation
/** Whether to allow multiple file selection. Defaults to `true`. */
multiple?: boolean
/** Whether to start uploading immediately when files are added. Defaults to `false`. */
autoUpload?: boolean
/** Maximum number of concurrent uploads. Defaults to `3`. */
maxConcurrent?: number
/** Whether to generate image previews for image files. Defaults to `false`. */
imagePreview?: boolean
/** Maximum width/height in pixels for image previews. Defaults to `200`. */
imagePreviewMaxSize?: number
/** Event callbacks. */
events?: FileUploadEvents
}
FileUploadProviderContract that bond packages must implement to provide file upload functionality.
interface FileUploadProvider {
/**
* Creates a new file upload instance from the given options.
*
* @param options - Upload configuration including destination, validation, and events.
* @returns A file upload instance for managing queued files and uploads.
*/
createUploader(options: FileUploadOptions): FileUploadInstance
}
FileValidationValidation constraints applied to files before uploading.
interface FileValidation {
/** Maximum file size in bytes. */
maxSize?: number
/** Minimum file size in bytes. */
minSize?: number
/** Accepted MIME types (e.g. `['image/png', 'image/jpeg']`). */
acceptedTypes?: string[]
/** Accepted file extensions including the dot (e.g. `['.png', '.jpg']`). */
acceptedExtensions?: string[]
/** Maximum number of files allowed when multi-file is enabled. */
maxFiles?: number
/**
* Custom validation function. Return `null` for valid, or an error
* message string for invalid.
*
* @param file - The file to validate.
* @returns `null` if valid, or an error message string.
*/
custom?: (file: UploadFile) => string | null
}
UploadDestinationConfiguration for where and how files are uploaded.
interface UploadDestination {
/** Target URL for the upload request. */
url: string
/** HTTP method to use. Defaults to `'POST'`. */
method?: 'POST' | 'PUT' | 'PATCH'
/** Additional HTTP headers to include with the upload request. */
headers?: Record<string, string>
/** Form field name for the file data. Defaults to `'file'`. */
fieldName?: string
/** Additional form data to include with the upload request. */
additionalData?: Record<string, string>
/**
* Custom function to extract the result identifier from the upload
* response. Called after a successful upload.
*
* @param response - The raw response body.
* @returns The result identifier string.
*/
parseResponse?: (response: unknown) => string
}
UploadFileRepresents a file in the upload queue, including metadata and progress.
interface UploadFile {
/** Unique identifier for this file within the upload instance. */
id: string
/** Original file name. */
name: string
/** File size in bytes. */
size: number
/** MIME type of the file. */
type: string
/** Current upload status. */
status: FileUploadStatus
/** Upload progress as a percentage (0–100). */
progress: number
/** Error message if `status` is `'error'`. */
error?: string
/** URL or identifier of the uploaded file after completion. */
result?: string
/** The source `File` object when available (browser environments). */
source?: File
/** Optional thumbnail/preview data URL for image files. */
preview?: string
}
FileUploadStatusPossible states of a file during the upload lifecycle.
type FileUploadStatus =
'idle' | 'preparing' | 'uploading' | 'processing' | 'complete' | 'error' | 'cancelled'
createUploader(options)Creates a new file upload instance using the bonded provider.
function createUploader(options: FileUploadOptions): FileUploadInstance
options — Upload configuration including destination, validation, and events.Returns: A file upload instance for managing queued files and uploads.
getProvider()Retrieves the bonded file upload provider, throwing if none is configured.
function getProvider(): FileUploadProvider
Returns: The bonded file upload provider.
hasProvider()Checks whether a file upload provider is currently bonded.
function hasProvider(): boolean
Returns: true if a file upload provider is bonded.
setProvider(provider)Registers a file upload provider as the active singleton. Called by bond
packages (e.g. @molecule/app-file-upload-filepond) during app startup.
function setProvider(provider: FileUploadProvider): void
provider — The file upload provider implementation to bond.| Provider | Package |
|---|---|
| File Upload | @molecule/app-file-upload-filepond |
Peer dependencies:
@molecule/app-bond ^1.0.1@molecule/app-bond
Client-side validation is UX, NOT a security boundary. It gives instant
feedback, but a request can skip the uploader entirely — the SERVER must
re-validate size, type, and content of every upload, and enforce authorization.
Uploads do NOT go through the app's HTTP client. The provider sends
directly to destination.url, so the HTTP client's baseURL and auth
interceptors are not applied: give the full relative path (e.g. '/api/upload'
— never an absolute http://localhost… host), and pass auth via
destination.headers if the endpoint requires it.
autoUpload defaults to false — without it, call upload() on the instance
or files sit queued forever.
Wire the bond once at startup (setProvider(provider) from e.g.
@molecule/app-file-upload-filepond); createUploader throws with the fix
named if nothing is bonded. Any upload UI you render (drop zone, progress,
errors) styles via getClassMap()/cm.* with text through
t('key', values, { defaultValue }).
Integration checklist — drive the real UI (live preview, no mocks), adapt each item to this app's actual screens/flows, and check every box off one by one. A box you can't check is an integration bug to fix — not a skip: