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

@masters-union/union-stack

v1.1.0

Published

UnionStack — file upload SDK. Direct-to-R2 multipart uploads with a small client surface.

Readme

Union Stack

File upload SDK — direct-to-bucket multipart uploads with a small client surface.

| Environment | Import from | | --- | --- | | Browser (vanilla / any framework) | @masters-union/union-stack | | React | @masters-union/union-stack/react | | Node.js (server-to-server) | @masters-union/union-stack/node |

Each entry is independent — importing /node pulls in none of the React, picker, or DOM code, and vice versa.

API domain

By default the SDK calls the standard UnionStack API host. If your key has an API domain set in the dashboard, pass that hostname to init:

const client = UnionStack.init({
  apiKey: process.env.UNION_STACK_API_KEY,
  apiDomain: 'uploads.example.com',
});

You need this only when some of your users cannot reach the standard host at all. Corporate and campus DNS filters, ad-blocking resolvers, and newly-registered-domain blocklists return NXDOMAIN for it, which the browser reports as ERR_NAME_NOT_RESOLVED before a request is ever sent. Nothing reaches the API, so there is no server-side record of the failure. The symptom is uploads that fail for one specific group of users while working for everyone else, with a NETWORK error reading "Couldn't reach the upload service".

Safe to get wrong: the standard hosts stay in place behind whatever you set, so a malformed value, or a domain whose DNS or certificate breaks later, falls back instead of failing. Bad values are logged and ignored, never thrown.

Pass a bare hostname, not a URL. It has to be set at init and cannot be delivered through the API, since fetching it would require resolving the host that is failing. Changing the setting in the dashboard does nothing until your integration is updated and redeployed.

Server-side uploads (Node.js)

Run uploads from your backend — no browser, no picker. Import from the /node subpath and upload a path, Buffer, Uint8Array, ArrayBuffer, Blob/File, or a Node Readable stream.

One-time setup: create a key with its allowed origins left empty. A key with no origins is server-only — it accepts your backend's requests (which carry no Origin header) and rejects browser use. Don't reuse a key that lists browser origins here; it will reject server calls with ORIGIN_REQUIRED. Keep the key in an environment variable.

const { UnionStack } = require('@masters-union/union-stack/node');

const client = UnionStack.init({ apiKey: process.env.UNION_STACK_API_KEY });

// Filename + content type are inferred from the path; large files stream from disk.
const file = await client.upload('./invoice.pdf');
console.log(file.url);
// → https://files.unionstack.in/f/V1StGXR8_Z5jdHi6B-myT

Example: re-host remote files into UnionStack

A migration script that fetches files by URL and uploads the bytes — note there's no Origin header to spoof anymore; a server-only key (empty allowed origins) accepts backend calls directly.

const { UnionStack } = require('@masters-union/union-stack/node');

const client = UnionStack.init({ apiKey: process.env.UNION_STACK_API_KEY });

const MIME_TO_EXT = {
  'application/pdf': 'pdf',
  'image/jpeg': 'jpg',
  'image/png': 'png',
  'image/avif': 'avif',
  'image/webp': 'webp',
  'video/mp4': 'mp4',
  'text/csv': 'csv',
  'application/xml': 'xml',
  'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'pptx',
  'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'xlsx',
  'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'docx',

  // ... expand this based on your analysis first based on the files present in the database
};


function resolveExtension(mime, rowId) {
  if (MIME_TO_EXT[mime]) return MIME_TO_EXT[mime];

  console.error(`unknown mime: ${mime} for row ${rowId}`);

  fs.appendFileSync('./unknown-mimes.log', JSON.stringify({ rowId, mime }) + '\n')

  throw new Error(`couldn't resolve file type`);
}

async function withRetry(fn, retries = 3) {
  let lastErr;
  for(let i = 0; i < retries; i++) {
    try {
      return await fn();
    } catch(error) {
      lastErr = error;
    }
  }
  throw lastErr;
}

async function getFinalUrl(row) {
  try {
    const response = await withRetry(() => fetch(row.url, {
      method: 'GET'
    }));

    if(!response.ok) {
      throw new Error("Failed to fetch the resource");
    }

    const mime = response.headers
      .get('content-type')
      ?.split(';')[0]
      ?.trim() || 'application/octet-stream';

    const ext = resolveExtension(mime, row.id);

    // if (contentEncoding === 'br') {
    //   // decompression logic, before enabling this block, check for a single filetype to figure out if brotliCompression was ever done in the first place on files, on FileStack from my experience, there isn't any brotliCompression even if the tag is br.
    //   finalStrema = nodeStream.pipe(createBrotliDecompress());
    // }
    // const filepath = `./temp/file_${row.id}.${ext}`;

    // await pipeline(
    //   nodeStream,
    //   fs.createWriteStream(filepath)
    // );

    // const buffer = fs.readFileSync(filepath);

    const contentLength = response.headers.get('content-length');
    
    const buffer = Buffer.from(await response.arrayBuffer());

    if(contentLength && buffer.length !== Number(contentLength)) {
      throw new Error(`size mismatch: exp=> ${contentLength}, got=> ${buffer.length}`);
    }

    const blob = new Blob([buffer], {
      fileName: `file_${row.id}.${ext}`,
      type: mime
    });

    console.log(blob);
    const uploadResponse = await withRetry(() => client.upload(blob, {
      filename: `file_${row.id}.${ext}`,
      mimeType: mime
    }));

    if(uploadResponse.status !== 'Stored') {
      throw new Error("Failed to store uploaded file to UnionStack");
    }

    return uploadResponse.url;
  } catch (error) {
    throw new Error(error.message);
  }
}