- 🚀 Smart Upload Strategy - Automatic selection between direct and chunked upload based on file size
- 📦 Dynamic Chunking - Adaptive chunk size adjustment based on network conditions (similar to TCP slow start)
- ⚡ Instant Upload - Hash-based deduplication for instant uploads (秒传)
- 🔄 Resumable Upload - Continue uploads from where you left off with IndexedDB persistence
- 🎯 Framework Agnostic - Core layer works with any framework
- ⚛️ React Support - Hooks and components for React applications
- 💚 Vue Support - Composables and components for Vue applications
- �️ Highly Extensible - Plugin system for custom functionality
- 🔒 Type Safe - Written in TypeScript with full type definitions
- 🧪 Well Tested - Comprehensive unit and property-based tests
- @chunkflowjs/protocol - Protocol layer with type definitions and API interfaces
- @chunkflowjs/shared - Shared utilities (event system, concurrency, file utils, storage)
- @chunkflowjs/core - Core upload engine with state machine and task management
- @chunkflowjs/upload-client-react - React adapter with hooks
- @chunkflowjs/upload-client-vue - Vue adapter with composables
- @chunkflowjs/upload-component-react - Ready-to-use React components
- @chunkflowjs/upload-component-vue - Ready-to-use Vue components
- @chunkflowjs/upload-server - Server-side SDK with storage adapters
# For React projects
pnpm add @chunkflowjs/core @chunkflowjs/upload-client-react
# For Vue projects
pnpm add @chunkflowjs/core @chunkflowjs/upload-client-vueimport { UploadProvider, useUpload } from "@chunkflowjs/upload-client-react";
import { createFetchAdapter } from "@chunkflowjs/core";
const adapter = createFetchAdapter({
baseURL: "http://localhost:3000/api",
});
function App() {
return (
<UploadProvider requestAdapter={adapter}>
<UploadComponent />
</UploadProvider>
);
}
function UploadComponent() {
const { upload, status, progress } = useUpload({
onSuccess: (fileUrl) => console.log("Upload complete:", fileUrl),
onError: (error) => console.error("Upload failed:", error),
});
return (
<div>
<input
type="file"
onChange={(e) => {
const file = e.target.files?.[0];
if (file) upload(file);
}}
/>
<div>Status: {status}</div>
<div>Progress: {progress.percentage}%</div>
</div>
);
}<script setup>
import { useUpload } from "@chunkflowjs/upload-client-vue";
const { upload, status, progress } = useUpload({
onSuccess: (fileUrl) => console.log("Upload complete:", fileUrl),
onError: (error) => console.error("Upload failed:", error),
});
const handleFileChange = (event) => {
const file = event.target.files?.[0];
if (file) upload(file);
};
</script>
<template>
<div>
<input type="file" @change="handleFileChange" />
<div>Status: {{ status }}</div>
<div>Progress: {{ progress.percentage }}%</div>
</div>
</template>ChunkFlow Upload SDK follows a layered architecture:
┌─────────────────────────────────────────────────────────────┐
│ Applications │
│ Playground (Demo) │ Server (Nest.js) │ Website (Docs) │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ Component Layer │
│ React Components │ Vue Components │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ Client Adapter Layer │
│ React Hooks │ Vue Composables │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ Core Layer │
│ Upload Manager │ Upload Task │ Plugin System │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ Shared Layer │
│ Event System │ Concurrency │ File Utils │ Storage │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ Protocol Layer │
│ Type Definitions │ API Interfaces │
└─────────────────────────────────────────────────────────────┘
Full documentation is available at: https://sunny-117.github.io/chunkflow/
This project uses a monorepo structure managed by pnpm workspaces and Turbo.
- Node.js >= 18.0.0
- pnpm >= 9.0.0
# Install dependencies
pnpm install
# Build all packages
pnpm build
# Run tests
pnpm test
# Lint code
pnpm lint
# Format code
pnpm formatchunkflow/
├── packages/ # SDK packages
│ ├── protocol/ # Protocol layer
│ ├── shared/ # Shared utilities
│ ├── core/ # Core upload engine
│ ├── upload-client-react/ # React adapter
│ ├── upload-client-vue/ # Vue adapter
│ ├── upload-component-react/ # React components
│ ├── upload-component-vue/ # Vue components
│ └── upload-server/ # Server SDK
├── apps/ # Applications
│ ├── server/ # Nest.js server
│ ├── playground/ # Demo application
│ └── website/ # Documentation site
├── pnpm-workspace.yaml # Workspace configuration
├── turbo.json # Turbo configuration
└── package.json # Root package.json
The project uses a dual testing approach:
- Unit Tests - Test specific examples and edge cases
- Property-Based Tests - Test universal properties across random inputs using fast-check
# Run all tests
pnpm test
# Run tests in watch mode
pnpm test:watch
# Run tests with coverage
pnpm test -- --coverageContributions are welcome! Please read our contributing guidelines before submitting a PR.
MIT © Sunny-117
- mitt - Event emitter
- p-limit - Concurrency control
- spark-md5 - MD5 hashing
- fast-check - Property-based testing
Made with ❤️ by Sunny-117