@molecule/app-file-upload
Core interface · file-upload · App (browser) · v1.0.2 · Apache-2.0
File upload core interface for molecule.dev — progress tracking, validation, multi-file queues
npm install @molecule/app-file-uploadHow it works
@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
Live demos
Running apps built with Molecule that install this package — open the app or study the template.
Reference
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 createUploader anywhere.
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.
Quick Start
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}`),
},
})
Type
core
Installation
npm install @molecule/app-file-upload @molecule/app-bond
API
Interfaces
FileValidation
Validation 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
}
UploadFile
Represents 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
}
UploadDestination
Configuration 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
}
FileUploadEvents
Event 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
}
FileUploadOptions
Configuration 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
}
FileUploadInstance
A 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
}
FileUploadProvider
Contract 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
}
Types
FileUploadStatus
Possible states of a file during the upload lifecycle.
type FileUploadStatus =
'idle' | 'preparing' | 'uploading' | 'processing' | 'complete' | 'error' | 'cancelled'
Functions
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.
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.
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.
Available Providers
| Provider | Package |
|---|---|
| File Upload | @molecule/app-file-upload-filepond |
Injection Notes
Requirements
Peer dependencies:
@molecule/app-bond^1.0.1
Runtime Dependencies
-
@molecule/app-bond -
Client-side
validationis 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'sbaseURLand auth interceptors are not applied: give the full relative path (e.g.'/api/upload'— never an absolutehttp://localhost…host), and pass auth viadestination.headersif the endpoint requires it. -
autoUploaddefaults tofalse— without it, callupload()on the instance or files sit queued forever. -
Wire the bond once at startup (
setProvider(provider)from e.g.@molecule/app-file-upload-filepond);createUploaderthrows with the fix named if nothing is bonded. Any upload UI you render (drop zone, progress, errors) styles viagetClassMap()/cm.*with text throught('key', values, { defaultValue }).
E2E Tests
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:
- Picking a valid file via the picker starts the upload and shows per-file progress through to a completed state.
- Dragging and dropping a file onto the drop zone uploads it the same way.
- The completed upload appears wherever this app uses it (file list, avatar, attachment) — completion is not just a toast.
- A file that fails validation (too large, wrong type) is rejected with a visible message and is never sent to the server.
- With multiple files (if enabled), each file's progress and completion track independently and all complete.
- Canceling/removing a queued or in-flight file stops it and clears it from the queue.