One standard API for all your file storage. Zero dependencies.
Stream files effortlessly across Node.js, Cloudflare Workers, Bun, and Deno. Swap between Local, S3, and Cloudinary drivers with a single line of code.
One Client. Any Driver.
Switch backends — not your code
The FilewayClientAPI never changes. Only the driver config. Full TypeScript inference adapts to each driver's metadata.
Driver Info
Local
Local filesystem via Node.js streams
import { FilewayClient } from "@fileway/core"
import { LocalDriver } from "@fileway/driver-local"
const client = new FilewayClient({
driver: new LocalDriver({
directory: "./uploads",
baseUrl: "/files",
}),
})
// TypeScript infers result.meta.localPath
const result = await client.upload(stream, {
filename: "profile.jpg",
metadata: { userId: "usr_123" },
})Full TypeScript inference — your IDE knows exactly what each driver returns
Built for scale
Everything you need, nothing you don't
Zero Dependencies Core
Less than 2kB gzipped with zero external node modules. Pure Web Streams, fetch, and Web Crypto.
True Web Streams
Standard ReadableStream<Uint8Array> from upload to driver. No buffers, no memory spikes.
Universal Edge Ready
Deploy anywhere — Node.js 20+, Bun, Deno, Cloudflare Workers, Vercel Edge, Lagon.
Strict Metadata Inference
Each driver exposes typed metadata. Autocomplete adapts to your backend — no runtime surprises.
result.meta.localPath // Local
Composable Middleware
beforeUpload / afterUpload hooks for validation, compression, logging, and thumbnail generation.
Plug-and-play drivers
Each driver implements the BaseDriver contract. Install what you need, nothing more.
@fileway/driver-local
Local filesystem via Node.js streams
@fileway/driver-s3
AWS S3, Cloudflare R2, MinIO, DigitalOcean Spaces
@fileway/driver-cloudinary
Pure fetch + Web Crypto, zero Node dependencies
@fileway/driver-gcs
Google Cloud Storage adapter
Developer Experience
From 50 lines to 5
No more vendor-specific SDKs, stream conversions, or fragile error handling. One API. End-to-end type safety.
// AWS SDK v3 — 50+ lines per provider
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3"
import { Readable } from "node:stream"
const s3 = new S3Client({ region: "us-east-1" })
async function uploadToS3(
buffer: Buffer,
key: string
): Promise<string> {
// Manual stream → buffer conversion
const command = new PutObjectCommand({
Bucket: "my-bucket",
Key: key,
Body: buffer,
})
try {
await s3.send(command)
return `https://s3.amazonaws.com/my-bucket/${key}`
} catch (err) {
// Per-provider error handling
console.error("S3 upload failed:", err)
throw err
}
}import { FilewayClient } from "@fileway/core"
import { S3Driver } from "@fileway/driver-s3"
const client = new FilewayClient({
driver: new S3Driver({
bucket: "my-bucket",
region: "us-east-1",
}),
})
// Accepts ReadableStream<Uint8Array> directly
const result = await client.upload(stream, {
filename: "report.pdf",
})
console.log(result.url) // Fully typedSame client works with Local, S3, Cloudinary, and more. Just swap the driver.