@universal-uploader/core
v1.1.1
Published
Zero-dependency browser file upload library with Web Streams, Fetch Duplex, XHR fallback, progress tracking, chunked uploads, and automatic retries.
Downloads
670
Maintainers
Readme
@universal-uploader/core
📦 NPM | 🔗 Main README | ⚛️ React
Core file upload orchestrator. Three adaptive strategies, one unified API.
Three Upload Methods
1. Fetch Stream (1 request, O(1) memory)
Perfect for small/medium files on modern browsers.
const { result } = await upload({
url: '/api/upload',
file,
options: { method: 'stream' },
});2. Fetch Chunked (N requests, resumable)
Best for large files with precise progress and resumption.
const { result } = await upload({
url: '/api/upload',
file,
options: {
method: 'stream chunked',
chunkSize: 1024 * 1024, // 1MB
onProgress: (p) => console.log(p.percentage),
},
});3. XHR Chunked (N requests, legacy support)
Broadest compatibility with byte-level progress.
const { result } = await upload({
url: '/api/upload',
file,
options: {
method: 'xhr chunked',
chunkSize: 512 * 1024,
},
});Auto-Select (Default)
const { result, uploadMethod } = await upload({
url: '/api/upload',
file,
options: {
method: 'auto', // Resolves to 'stream' or 'xhr chunked' based on browser support
},
});
console.log(uploadMethod); // 'stream' | 'stream chunked' | 'xhr chunked'Installation
npm install @universal-uploader/core
yarn add @universal-uploader/core
pnpm add @universal-uploader/coreNPM: https://www.npmjs.com/package/@universal-uploader/core
Upload Control
const { result, actions, uploadMethod } = await upload({ url, file, options });
const { abort, pause, resume, refresh } = actions;
console.log(uploadMethod); // Resolved upload strategy (never 'auto')
pause(); // Status: "paused" (resumable)
resume(); // Continue from offset
abort(); // Status: "aborted" (terminal)
refresh(); // Full restart from initial optionsConfiguration
interface UploadOptions {
method?: 'stream' | 'stream chunked' | 'xhr chunked' | 'auto';
chunkSize?: number; // 512KB default
retryCount?: number; // 3 default
retryDelay?: number | ((attempt: number) => number);
customHeaders?: Record<string, string>;
withCredentials?: boolean;
offset?: number;
onProgress?: (p: { loaded: number; total: number; percentage: number }) => void;
onComplete?: () => void;
onError?: (error: Error) => void;
onRetry?: () => void;
onPause?: () => void;
onResume?: () => void;
onAbort?: (error: DOMException) => void;
throwOnError?: boolean | ((error: unknown) => boolean); // false default
}Types
import type {
UploadResult, // { ok: boolean; total: number; status: 'success' | 'error' | ... }
UploadStatus, // 'idle' | 'uploading' | 'paused' | 'success' | 'error' | 'aborted'
UploadMethod, // 'auto' | 'stream' | 'stream chunked' | 'xhr chunked'
UploadResponseWithMethod, // UploadResponse & { uploadMethod: UploadMethod }
OnProgressParams, // { loaded: number; total: number; percentage: number }
UploadOptions,
UploadParams
} from '@universal-uploader/core';Error Handling
// Automatic retry with exponential backoff
const { result } = await upload({
url: '/api/upload',
file,
options: {
retryCount: 5,
retryDelay: (attempt) => Math.pow(2, attempt) * 1000,
},
});
// Throw on error
try {
const { result } = await upload({
url: '/api/upload',
file,
options: { throwOnError: true },
});
} catch (err) {
console.error(err);
}Browser Support
- Chrome/Edge: Fetch Stream ✅
- Firefox: Fetch Stream ✅
- Safari/IE: XHR Fallback (auto-detected) ✅
Performance
- < 10 kB gzipped
- Zero dependencies
- 100% TypeScript
- Constant memory (Stream) or bounded (Chunked)
License
MIT
