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

just-upload-it

v1.1.2

Published

Universal file/image uploader with pluggable drivers

Readme

just-upload-it

codecov CI npm version License: MIT TypeScript

Universal file upload abstraction for Node.js

Switch between local storage, Cloudinary, S3, and more with a single API.

⚠️ Under active development - Not recommended for production use yet.


🎯 Why just-upload-it?

  • 🔄 Provider-agnostic - Switch storage providers without changing your code
  • 📦 Normalized API - Consistent input/output across all drivers
  • 🎨 Auto-detection - Automatically detects file types and metadata
  • 📝 TypeScript - Fully typed with comprehensive interfaces
  • 🧩 Extensible - Easy to add custom drivers
  • 🪶 Lightweight - Minimal dependencies

Installation

npm install just-upload-it

🚀 Quick Start

import { Uploader } from 'just-upload-it';
import fs from 'fs';

const uploader = new Uploader({ provider: 'local' });

const fileBuffer = fs.readFileSync('./photo.jpg');
const result = await uploader.upload(fileBuffer, {
  rename: 'profile-pic',
  path: 'users-123',
});

await uploader.delete(result.publicId);

🎨 Supported Providers

| Provider | Status | Features | | ------------ | :-----: | ------------------------------- | | Local | Stable | File system storage | | Cloudinary | Stable | Cloud storage with CDN delivery | | AWS S3 | Stable | Scalable cloud storage | | Google Cloud | Planned | - | | Azure Blob | Planned | - |

📖 API Reference

new Uploader(config) Creates a new uploader instance.

const uploader = new Uploader({
  provider: 'local' | 'cloudinary' | 'aws-s3',
  config: <ProviderConfig>,
});

uploader.upload(buffer, options?) Uploads a file buffer.

Parameters:

  • buffer: Buffer - File content as Buffer
  • options?: UploadOptions - Upload configuration

Returns: Promise<UploadResult>

interface UploadOptions {
  rename?: string; // Custom filename (without extension)
  path?: string; // Subfolder path
  metadata?: {
    format?: string; // File extension (auto-detected if omitted)
    resourceType?: 'image' | 'video' | 'raw'; // Auto-detected
    [key: string]: any; // Custom metadata
  };
}

interface UploadResult {
  url: string; // Public URL of uploaded file
  publicId: string; // Unique identifier for deletion
  metadata?: {
    size: number; // File size in bytes
    format: string; // File extension
    resourceType: 'image' | 'video' | 'raw';
    [key: string]: any;
  };
}

uploader.delete(publicId, options?) Deletes an uploaded file.

Parameters:

  • publicId: string - File identifier from upload result
  • options?: DeleteOptions - Deletion configuration

Returns: Promise<DeleteResult>

interface DeleteOptions {
  resourceType?: 'image' | 'video' | 'raw'; // Required for some providers
}

interface DeleteResult {
  result: 'ok' | 'not found' | 'error';
}

🔧 Provider Configuration

Local Storage

import { Uploader, LocalConfig } from 'just-upload-it';

const config: LocalConfig = {
  baseDir: './uploads', // Upload directory (default: './uploads')
  baseUrl: 'http://localhost:3000/uploads', // Base URL for files
  overwrite: false, // Allow overwriting existing files
};

const uploader = new Uploader({ provider: 'local', config });

Cloudinary

import { Uploader, CloudinaryConfig } from 'just-upload-it';

const config: CloudinaryConfig = {
  cloudName: 'your-cloud-name',
  apiKey: 'your-api-key',
  apiSecret: 'your-api-secret',
};

const uploader = new Uploader({ provider: 'cloudinary', config });

const result = await uploader.upload(fileBuffer, {
  rename: 'my-file',
  path: 'test-folder',
  metadata: { description: 'Example file' },
});

await uploader.delete(result.publicId);

⚠️ Important: For non-image files (video, raw), always set resourceType in options.
This ensures correct deletion of the file.

await uploader.delete(publicId, { resourceType: 'raw' });

AWS S3

import { Uploader, S3Config } from 'just-upload-it';

const config: S3Config = {
  region: 'your-bucket-region',
  bucket: 'your-bucket-name',
  accessKeyId: 'your-access-key-id',
  secretAccessKey: 'your-secret-access-key',
};

const uploader = new Uploader({ provider: 'aws-s3', config });

const result = await uploader.upload(fileBuffer, {
  rename: 'document',
  path: 'uploads',
  metadata: {
    format: 'pdf',
    resourceType: 'raw',
  },
});

💡 Examples

Upload with auto-detection

File type, format, and resource type are automatically detected:

const result = await uploader.upload(imageBuffer);
// No need to specify format or resourceType

Upload with custom metadata

const result = await uploader.upload(fileBuffer, {
  rename: 'user-avatar',
  path: 'users',
  metadata: {
    userId: '12345',
    uploadedBy: '[email protected]',
  },
});

Upload to organized folders

const today = new Date().toISOString().split('T')[0];

const result = await uploader.upload(buffer, {
  path: `uploads-${today}`,
  rename: 'document',
});

Switch providers without code changes

// Development: local storage
const uploader = new Uploader({
  provider: process.env.NODE_ENV === 'production' ? 'cloudinary' : 'local',
  config: process.env.NODE_ENV === 'production' ? cloudinaryConfig : localConfig,
});

// Same code works for both!
await uploader.upload(buffer);

Testing

Unit Tests (always run)

npm test

Integration Tests

Integration tests for Cloudinary and AWS S3 are optional. If credentials are not provided:

  • Tests will be skipped gracefully
  • Coverage threshold is adjusted automatically (65% instead of 80%)
  • Local driver tests still run and provide good coverage

To run full integration tests, create a .env file:

cp .env.example .env
# Edit .env with your credentials

Then run: npm test

License

MIT License © 2025 EstebanSD