npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ultra-fileio

v0.5.1

Published

A powerful and flexible file upload library for Next.js with support for S3, Prisma, and Drizzle.

Readme

Ultra FileIO

Production-ready file upload library for Next.js with ORM-agnostic architecture

npm version License: MIT

A complete file upload solution for Next.js that works seamlessly with Prisma, Drizzle, Cloudflare R2, and AWS S3. Built with TypeScript, fully type-safe, and production-ready.

✨ Features

  • 🎯 CLI Tool - Automatic setup with npx ultra-fileio init (supports Next.js, extensible for more)
  • 🚀 Next.js App Router - Built-in route handlers for instant integration
  • 🔧 ORM Agnostic - Works with Prisma, Drizzle, or any ORM via repository pattern
  • ☁️ Cloud Storage - Cloudflare R2 and AWS S3 compatible
  • 🛡️ Type Safe - Full TypeScript + Zod validation
  • 🪝 Lifecycle Hooks - Before/after hooks for logging, auditing, custom logic
  • 🖼️ Image Optimization - Automatic compression and thumbnail generation with Sharp
  • 📦 Presigned URLs - Direct client-to-storage uploads for large files
  • Production Ready - Proper error handling, bulk operations, and best practices

📦 Installation

npm install ultra-fileio
# or
pnpm add ultra-fileio
# or
yarn add ultra-fileio

Install Required Dependencies

npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner sharp zod

🚀 Quick Start

Automatic Setup (Recommended)

Use the CLI to automatically set up Ultra FileIO in your Next.js App Router project:

npx ultra-fileio init

This will:

  • ✅ Auto-detect your framework and package manager
  • ✅ Install all required dependencies
  • ✅ Create API route handlers
  • ✅ Set up Prisma schema and migrations
  • ✅ Generate configuration files

Manual Setup

If you prefer manual setup or need more control, follow these steps:

1. Environment Setup

# .env.local
S3_ACCOUNT_ID="your-account-id"
S3_ACCESS_KEY_ID="your-access-key"
S3_SECRET_ACCESS_KEY="your-secret-key"
S3_BUCKET_NAME="your-bucket-name"
S3_PUBLIC_URL="https://your-bucket.r2.dev"
S3_REGION="auto"

DATABASE_URL="postgresql://..."

2. Add Database Schema

model User {
  id        String   @id @default(cuid())
  email     String   @unique
  name      String?
  createdAt DateTime @default(now()) @map("created_at")

  files File[]

  @@map("users")
}

model File {
  id               String   @id @default(cuid())
  r2Key            String   @unique @map("r2_key")
  originalFilename String   @map("original_filename")
  fileSize         Int      @map("file_size")
  publicUrl        String   @map("public_url")
  uploadedBy       String   @map("uploaded_by")
  createdAt        DateTime @default(now()) @map("created_at")

  uploader User @relation(fields: [uploadedBy], references: [id], onDelete: Cascade)

  @@index([r2Key])
  @@index([uploadedBy])
  @@index([createdAt])
  @@map("files")
}
import { pgTable, text, timestamp, uuid, varchar, index, bigint } from 'drizzle-orm/pg-core'

export const files = pgTable('files', {
  id: uuid('id').primaryKey().defaultRandom(),
  r2Key: text('r2_key').notNull().unique(),
  originalFilename: varchar('original_filename', { length: 512 }).notNull(),
  fileSize: bigint('file_size', { mode: 'number' }).notNull(),
  publicUrl: text('public_url').notNull(),
  uploadedBy: uuid('uploaded_by').notNull(),
  createdAt: timestamp('created_at').defaultNow().notNull(),
}, (table) => ({
  r2KeyIdx: index('files_r2_key_idx').on(table.r2Key),
  uploadedByIdx: index('files_uploaded_by_idx').on(table.uploadedBy),
  createdAtIdx: index('files_created_at_idx').on(table.createdAt),
}))

3. Create API Route

// app/api/fileuploads/[[...fileuploads]]/route.ts
import { FlexibleFileService, PrismaFileRepository, isR2Configured } from 'ultra-fileio'
import { fileUploadsHandler } from 'ultra-fileio/server'
import { getUserId } from '@/lib/get-user'
import { prisma } from '@/lib/prisma'

const fileRepository = new PrismaFileRepository(prisma)
let fileService: FlexibleFileService | null = null

if (isR2Configured) {
  fileService = new FlexibleFileService(fileRepository)
}

export const { GET, POST, PUT, PATCH, DELETE } = fileUploadsHandler({
  fileService,
  fileRepository,
  getUserId,
  basePath: '/api/fileuploads',
})

4. Upload from Client

The usePresignedUpload hook handles the complex three-step process:

  1. Get Presigned URL: Requests a temporary upload URL from your API.
  2. Direct Upload: Uploads the file directly to storage using the presigned URL.
  3. Save Record: Saves the file metadata to your database.
import { usePresignedUpload } from 'ultra-fileio/client';

const { upload, uploading, progress, error } = usePresignedUpload({
  category: 'avatars',
  onSuccess: (file) => console.log('Uploaded:', file),
});

🎯 API Endpoints

The catch-all route [[...fileuploads]] creates these endpoints:

| Method | Endpoint | Description | |--------|----------|-------------| | POST | /api/fileuploads | Upload a file | | GET | /api/fileuploads | List all user files | | GET | /api/fileuploads/{id} | Get file details | | DELETE | /api/fileuploads/{id} | Delete a file | | POST | /api/fileuploads/presigned | Get presigned URL | | POST | /api/fileuploads/complete | Complete presigned upload |

📖 Documentation

💡 Examples

Check out the complete Next.js example with:

  • ✅ File upload with drag-and-drop
  • ✅ File list with delete
  • ✅ Prisma database integration
  • ✅ R2/S3 storage
  • ✅ Image optimization
  • ✅ TypeScript throughout

🏗️ Project Structure

ultra-fileio/
├── cli/                      # CLI tool
│   ├── index.ts              # CLI entry point
│   ├── types.ts              # TypeScript types
│   ├── frameworks/           # Framework-specific setup
│   │   └── nextjs.ts
│   ├── templates/            # File templates
│   │   └── nextjs.ts
│   └── utils/                # Utilities
│       ├── package-manager.ts
│       └── files.ts
├── src/
│   ├── index.ts              # Main exports
│   ├── file.service.ts       # File service (ORM agnostic)
│   ├── file.module.ts        # R2/S3 storage service
│   ├── file.schema.ts        # Zod schemas
│   ├── server/               # Server-side exports
│   │   ├── index.ts
│   │   ├── route-handler.ts  # Next.js route handlers
│   │   └── file-handler.ts   # Catch-all handler
│   ├── client/               # Client-side exports
│   │   ├── index.ts
│   │   └── useFileUpload.tsx # React hooks
│   └── repositories/         # ORM adapters
│       ├── file.repository.interface.ts
│       ├── base.repository.ts
│       └── adapters/
│           ├── prisma.adapter.ts
│           └── drizzle.adapter.ts
├── examples/
│   └── nextjs-approuter/     # Complete example app
└── docs/                     # Documentation site

🔧 Development

Setup

# Install dependencies
bun install

# Build library
bun run build

# Watch mode
bun run dev

# Lint & format
bun run check:fix

# Type check
bun run typecheck

Run Example App

cd examples/nextjs-approuter
pnpm install
pnpm prisma migrate dev
pnpm dev

🧪 Tech Stack

🤝 Contributing

Contributions are welcome! Please check out the contributing guidelines.

📄 License

MIT License - see LICENSE file for details.

🙏 Acknowledgments

  • Built with inspiration from modern file upload libraries
  • Powered by Cloudflare R2 and AWS S3
  • Designed for the Next.js ecosystem

📞 Support


Made with ❤️ for the JS,TS community