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

ipfs-storage

v2.0.0

Published

IPFS storage API providers.

Readme

IPFS STORAGE API PROVIDERS

This library provides a unified interface for uploading files to and deleting files from various IPFS storage providers.

Supported Providers:

  • [x] Filebase [filebase.com]
  • [x] Storacha [storacha.network] (formerly web3.storage)
  • [x] Pinata [pinata.cloud]
  • [x] Lighthouse [lighthouse.storage]
  • [ ] Fleek [fleek.xyz] (Temporarily Disabled)

Prerequisites

  • Node.js: Version 18 or higher.
  • Credentials: You will need API credentials for each service you intend to use. Store these securely, for example, using environment variables (see examples).
  • Storacha Setup: Storacha requires a one-time setup using their CLI (w3) to log in your agent (w3 login <email>) and create/select a space (w3 space create, w3 space use). This library assumes the agent is already configured in the environment where the code runs.

Installation

npm install ipfs-storage
# or
yarn add ipfs-storage

Breaking Changes (v1.x -> v2.x)

  • Pinata: uploadFile.pinata now returns an object { url: string, providerId: string }. The providerId is required for deleteFile.pinata.
  • Fleek: Authentication changed (requires PAT/ProjectID), but the provider is temporarily disabled due to module resolution issues with @fleek-platform/sdk in ESM projects.
  • Storacha (web3.storage): Authentication requires a pre-configured agent (via w3 login) instead of an API token.
  • Dependencies: Underlying SDKs for all providers have been updated.

Examples

First, set up your environment variables (e.g., in a .env file and load with dotenv):

# Filebase
FILEBASE_KEY=YOUR_FILEBASE_ACCESS_KEY
FILEBASE_SECRET=YOUR_FILEBASE_SECRET_KEY
FILEBASE_BUCKET=your-filebase-bucket-name

# Pinata
PINATA_JWT=YOUR_PINATA_JWT

# Storacha (No key needed here, login via w3 cli)

Then, use the library in your code:

const fs = require("fs");
const { join } = require("path");
const { uploadFile, deleteFile } = require("ipfs-storage");
const { create } = require('@web3-storage/w3up-client'); // Needed for pre-configured client example
require("dotenv").config(); // Load .env variables

// Helper function to extract CID v1 from common IPFS gateway URLs
const extractCidFromUrl = (url) => {
  try {
    const urlObject = new URL(url);
    const hostnameParts = urlObject.hostname.split(".");
    // Assuming format like https://{cid}.ipfs.{gateway}/
    if (hostnameParts.length > 2 && hostnameParts[1] === "ipfs") {
      return hostnameParts[0];
    }
  } catch (e) { /* ignore */ }
  return null;
};

// Example usage (run within an async function or use .then())
async function runExamples() {
  let fileBuffer;
  try {
    fileBuffer = fs.readFileSync(join(__dirname, "banner.png"));
  } catch (err) {
    console.error("Error reading file:", err);
    return;
  }

  const fileData = { hash: "banner-test", ext: ".png", buffer: fileBuffer };

  // --- Filebase Example ---
  if (process.env.FILEBASE_KEY) {
    try {
      const filebaseConnect = {
        key: process.env.FILEBASE_KEY,
        secret: process.env.FILEBASE_SECRET,
        bucket: process.env.FILEBASE_BUCKET,
      };
      const url = await uploadFile.filebase(filebaseConnect, fileData);
      console.log("✅ FILEBASE Upload:", url);

      await deleteFile.filebase(filebaseConnect, { hash: fileData.hash, ext: fileData.ext });
      console.log("✅ FILEBASE Delete: OK");
    } catch (err) {
      console.error("🆘 FILEBASE:", err.message || err);
    }
  }

  // --- Pinata Example ---
  if (process.env.PINATA_JWT) {
    try {
      const pinataConnect = { jwt: process.env.PINATA_JWT };
      // Pinata upload now returns { url, providerId }
      const result = await uploadFile.pinata(pinataConnect, fileData);
      console.log("✅ PINATA Upload:", result.url);

      // Pinata delete now requires the providerId
      await deleteFile.pinata(pinataConnect, { providerId: result.providerId });
      console.log("✅ PINATA Delete: OK");
    } catch (err) {
      console.error("🆘 PINATA:", err.message || err);
    }
  }

  // --- Fleek Example ---
  /* // Temporarily disabled due to SDK compatibility issues
  if (process.env.FLEEK_PAT && process.env.FLEEK_PROJECT_ID) {
  // ... (Fleek example code commented out) ...
  }
  */

  // --- Storacha Example (formerly Web3.storage) ---
  console.log("\n--- Storacha ---");

  // Storacha requires a one-time EXTERNAL setup using `w3 login <email>`
  // and `w3 space use <did>` before this library can use the ambient state.
  // The library CANNOT perform the interactive email login.
  console.log("Attempting Storacha using ambient agent state...");
  try {
    // If agent is logged in and space is set externally, this will work:
    const url = await uploadFile.storacha({}, fileData);
    console.log("✅ STORACHA Upload (Ambient):", url);
    const cid = extractCidFromUrl(url);
    if (cid) {
      await deleteFile.storacha({}, { cid });
      console.log("✅ STORACHA Delete (Ambient): OK");
    } else {
      console.error("🆘 STORACHA Delete (Ambient): Could not extract CID from URL", url);
    }
  } catch (err) {
    console.warn("🆘 STORACHA (Ambient State):", err.message || err, "(FAILED: Ensure agent is logged in and space is selected externally via w3 commands)");
  }

  // Option for applications: Pass a pre-configured client & space DID
  // (Application must handle client creation, login flow, and space selection itself)
  console.log("\nExample: Using Storacha with a pre-configured client (if available)... ");
  let preConfiguredClient;
  let spaceDidToUse; // Replace with your actual Space DID
  try {
    // Example: Initialize client (in a real app, handle login flow properly)
    preConfiguredClient = await create();
    const accounts = await preConfiguredClient.accounts();
    if (!accounts || Object.keys(accounts).length === 0) {
      console.warn("  -> Storacha Pre-config: Agent not logged in. Skipping pre-configured client test.");
      // In a real app: initiate login -> await client.login('email'); ... wait for link click ...
    } else {
      const spaces = await preConfiguredClient.spaces();
      if (!spaces || spaces.length === 0) {
         console.warn("  -> Storacha Pre-config: Agent has no spaces. Skipping pre-configured client test.");
      } else {
         spaceDidToUse = spaces[0].did(); // Using the first space for the example
         console.log(`  -> Storacha Pre-config: Using space DID: ${spaceDidToUse}`);

         const storachaConnect = { client: preConfiguredClient, spaceDid: spaceDidToUse };
         const url = await uploadFile.storacha(storachaConnect, fileData);
         console.log("✅ STORACHA Upload (Pre-config):", url);
         const cid = extractCidFromUrl(url);
         if (cid) {
           await deleteFile.storacha(storachaConnect, { cid });
           console.log("✅ STORACHA Delete (Pre-config): OK");
         } else {
           console.error("🆘 STORACHA Delete (Pre-config): Could not extract CID from URL", url);
         }
      }
    }
  } catch (err) {
     console.error("🆘 STORACHA (Pre-configured Client Example):", err.message || err);
  }

  // --- Lighthouse Example ---
  if (process.env.LIGHTHOUSE_TOKEN) {
    try {
      const lighthouseConnect = { token: process.env.LIGHTHOUSE_TOKEN };
      const url = await uploadFile.lighthouse(lighthouseConnect, fileData);
      console.log("✅ LIGHTHOUSE Upload:", url);

      // Note: deleteFile.lighthouse is currently not implemented (pending SDK docs)
      const cid = extractCidFromUrl(url);
      if (cid) {
        try {
          await deleteFile.lighthouse(lighthouseConnect, { cid });
          console.log("✅ LIGHTHOUSE Delete: OK (Unimplemented function did not throw?)");
        } catch (deleteErr) {
          if (deleteErr.message && deleteErr.message.includes("not implemented")) {
            console.log("✅ LIGHTHOUSE Delete: OK (Not implemented as expected)");
          } else {
            console.error("🆘 LIGHTHOUSE Delete Error:", deleteErr.message || deleteErr);
          }
        }
      } else {
        console.error("🆘 LIGHTHOUSE Delete: Could not extract CID from URL", url);
      }
    } catch (err) {
      console.error("🆘 LIGHTHOUSE:", err.message || err);
    }
  }
}

runExamples();

---

`(c)` Alex Baker