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 🙏

© 2025 – Pkg Stats / Ryan Hefner

pico-s3

v2.11.0

Published

A lightweght S3 client that doesn't require the aws sdk.

Downloads

3,797

Readme

Pico S3

npm version

A super lightweight S3 client that doesn't require the AWS SDK. Perfect for simple S3 operations without the overhead of the full AWS SDK. Be sure to 🌟 this repository for updates!

Features

  • 🪶 Lightweight - No AWS SDK dependency
  • 🚀 Simple API - Easy to use, minimal configuration
  • 🔐 Presigned URLs - Generate presigned URLs for uploads and downloads
  • 🌐 Multi-provider - Support for AWS, MinIO, Wasabi, DigitalOcean, GCP, Contabo, Cloudflare R2, and Supabase
  • 📦 TypeScript - Full TypeScript support with type definitions
  • 🔧 Flexible - Upload from Data URLs, Buffers, or files

Installation

npm i pico-s3

Quick Start

const { PicoS3 } = require('pico-s3');

const p3 = new PicoS3({
    provider: 'AWS', // or 'MINIO', 'WASABI', 'DO', 'GCP', 'CONTABO', 'R2', 'SUPABASE'
    region: 'us-east-1',
    bucket: 'my-bucket',
    accessKeyId: 'YOUR_ACCESS_KEY_ID',
    secretAccessKey: 'YOUR_SECRET_ACCESS_KEY'
});

// Upload a file
const url = await p3.upload({
    file: dataUrl, // Data URL or Buffer
    filename: "my-file.jpg"
});

console.log('File uploaded:', url);

Configuration

Basic Configuration

const p3 = new PicoS3({
    provider: 'AWS',              // Required: Cloud provider
    region: 'us-east-1',          // Required for most providers
    bucket: 'my-bucket',          // Required: Bucket name
    accessKeyId: 'YOUR_KEY',      // Required: Access key
    secretAccessKey: 'YOUR_SECRET' // Required: Secret key
});

MinIO Configuration

For MinIO or self-hosted S3-compatible services, include the host parameter:

const p3 = new PicoS3({
    provider: 'MINIO',
    bucket: 'my-bucket',
    host: 'http://192.168.1.100:9000', // MinIO host (IP or domain)
    accessKeyId: 'YOUR_KEY',
    secretAccessKey: 'YOUR_SECRET'
});

Environment Variables

You can also initialize with environment variables:

const p3 = new PicoS3(true);

Set these environment variables:

PICO_S3_CLOUD_PROVIDER=MINIO
PICO_S3_REGION=us-east-1
PICO_S3_BUCKET=my-bucket
PICO_S3_HOST=http://192.168.1.100:9000
PICO_S3_ACCESS_KEY_ID=YOUR_KEY
PICO_S3_SECRET_ACCESS_KEY=YOUR_SECRET

API Reference

Upload Methods

upload(options)

Upload a file from a Data URL or Buffer.

// Upload from Data URL
const url = await p3.upload({
    file: 'data:image/jpeg;base64,...',
    filename: 'photo.jpg',
    directory: '/photos', // Optional
    public: true          // Optional: Make file publicly accessible
});

// Upload from Buffer
const buffer = fs.readFileSync('file.pdf');
const url = await p3.upload({
    file: buffer,
    filename: 'document.pdf',
    directory: '/documents'
});

Download Methods

getObject(options)

Get the full Axios response object.

const response = await p3.getObject({
    filename: 'photo.jpg',
    directory: '/photos'
});

getObjectBuffer(options)

Download a file as a Buffer.

const buffer = await p3.getObjectBuffer({
    filename: 'photo.jpg',
    directory: '/photos'
});

getObjectDataUrl(options)

Download a file as a Data URL.

const dataUrl = await p3.getObjectDataUrl({
    filename: 'photo.jpg',
    directory: '/photos'
});

getTextFile(options)

Download a text file as a string.

const text = await p3.getTextFile({
    filename: 'data.json',
    directory: '/config'
});

Presigned URL Methods

getPresignedUrl(options)

Generate a presigned URL for downloading a file.

const downloadUrl = await p3.getPresignedUrl({
    filename: 'photo.jpg',
    directory: '/photos'
});

// Share this URL - it's valid for 24 hours by default
console.log('Download URL:', downloadUrl);

getPresignedUploadUrl(options)

Generate a presigned URL for uploading a file directly from the browser or client.

const uploadUrl = await p3.getPresignedUploadUrl({
    filename: 'document.pdf',
    directory: '/uploads',
    expiresIn: 3600,              // Optional: Expiration in seconds (default: 3600)
    contentType: 'application/pdf' // Optional: Content-Type for the upload
});

// Use this URL for direct uploads from browser
// Example with fetch:
const file = document.getElementById('fileInput').files[0];
await fetch(uploadUrl, {
    method: 'PUT',
    body: file,
    headers: {
        'Content-Type': 'application/pdf'
    }
});

Client-side upload example:

// Server-side: Generate presigned URL
app.post('/api/get-upload-url', async (req, res) => {
    const uploadUrl = await p3.getPresignedUploadUrl({
        filename: req.body.filename,
        directory: '/uploads',
        expiresIn: 3600,
        contentType: req.body.contentType
    });
    res.json({ uploadUrl });
});

// Client-side: Upload directly to S3/MinIO
const response = await fetch('/api/get-upload-url', {
    method: 'POST',
    body: JSON.stringify({
        filename: 'my-file.pdf',
        contentType: 'application/pdf'
    })
});

const { uploadUrl } = await response.json();

// Upload file directly to S3/MinIO
await fetch(uploadUrl, {
    method: 'PUT',
    body: fileBlob,
    headers: {
        'Content-Type': 'application/pdf'
    }
});

File Management Methods

deleteObject(options)

Delete a file.

const deleted = await p3.deleteObject({
    filename: 'old-file.jpg',
    directory: '/photos'
});
// Returns: true if successful

objectExists(options)

Check if a file exists.

const exists = await p3.objectExists({
    filename: 'photo.jpg',
    directory: '/photos'
});
// Returns: true or false

getObjectMetadata(options)

Get file metadata (headers).

const metadata = await p3.getObjectMetadata({
    filename: 'photo.jpg',
    directory: '/photos'
});
// Returns: { 'content-type': 'image/jpeg', 'content-length': '12345', ... }

getObjectEtag(options)

Get the ETag of a file.

const etag = await p3.getObjectEtag({
    filename: 'photo.jpg',
    directory: '/photos'
});
// Returns: "abc123def456..."

Utility Methods

getProvider()

Get the current provider name.

const provider = p3.getProvider();
// Returns: 'MINIO', 'AWS', etc.

getProviderConfig()

Get the provider configuration object.

const config = p3.getProviderConfig();
// Returns: { host: Function, url: Function, res: Function, ... }

Supported Providers

| Provider | Code | Notes | |----------|------|-------| | AWS S3 | AWS | Amazon Web Services S3 | | MinIO | MINIO | Requires host parameter | | Wasabi | WASABI | S3-compatible cloud storage | | DigitalOcean Spaces | DO | DigitalOcean's object storage | | Google Cloud Storage | GCP | Google Cloud Platform | | Contabo | CONTABO | Contabo object storage | | Cloudflare R2 | R2 or R2_ALT | Two configuration styles supported | | Supabase | SUPABASE | Requires host parameter |

Error Handling

const { FileNotFoundError } = require('pico-s3');

try {
    const file = await p3.getObject({
        filename: 'non-existent.jpg'
    });
} catch (error) {
    if (error instanceof FileNotFoundError) {
        console.log('File not found');
    } else {
        console.error('Other error:', error.message);
    }
}

Advanced Usage

Custom Headers

const url = await p3.upload({
    file: buffer,
    filename: 'file.pdf',
    headers: {
        'Cache-Control': 'max-age=3600',
        'x-amz-meta-custom': 'value'
    }
});

Directory Structure

// Upload to nested directories
await p3.upload({
    file: buffer,
    filename: 'report.pdf',
    directory: '/2024/january/reports'
});

// Directory slashes are normalized automatically
// These are equivalent:
directory: '/photos/'
directory: '/photos'
directory: 'photos/'
directory: 'photos'

TypeScript Support

Full TypeScript definitions are included:

import { PicoS3, CLOUD_PROVIDERS, S3RequestOptions } from 'pico-s3';

const options: S3RequestOptions = {
    provider: CLOUD_PROVIDERS.MINIO,
    bucket: 'my-bucket',
    host: 'http://localhost:9000',
    accessKeyId: 'key',
    secretAccessKey: 'secret'
};

const p3 = new PicoS3(options);

Debug Logging

Enable debug logging:

DEBUG=pico-s3 node your-script.js

For error logging only:

DEBUG=pico-s3:error node your-script.js

License

MIT

Contributing

Issues and pull requests are welcome! Please submit them at https://github.com/smashah/picoS3/issues