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

@agglabs-one/object

v0.1.5

Published

Node SDK for AGG One Object Storage — upload, list, link and delete files.

Readme

@agglabs-one/object

Node SDK for AGG One Object Storage. Upload, list, link and delete files over the API with a scoped key. Zero runtime dependencies; Node 18+.

Install

npm install @agglabs-one/object

Quick start

import { randomUUID } from 'node:crypto';
import { ObjectStorage } from '@agglabs-one/object';

const store = new ObjectStorage({ key: process.env.AGG_STORAGE_KEY! });

// Upload a local file — name and content-type are inferred from the path.
const obj = await store.upload('./contract.pdf', {
  path: `/contracts/${randomUUID()}`,
  visibility: 'private',
});

// Download it back (a fresh signed link is fetched automatically).
await store.download(obj.id, './downloaded.pdf');

Create a key in your account under Object Storage → Preferences → API Access. A key is scoped to the project it's created in, and shown only once.

API

new ObjectStorage(options)

| Option | Default | | | --- | --- | --- | | key | — | Required. agk_<prefix>_<secret>. | | baseUrl | https://object.one.agglabs.com | Override the API host. | | timeoutMs | 120000 | Per-request timeout. | | encryptionKey | — | Base64 of a 32-byte key for locking uploads. See Encryption. |

upload(input, options?) → Promise<StorageObject>

input is a file path, a Buffer/Uint8Array, or a Readable stream — streamed to the server, never buffered whole. Needs storage:write.

await store.upload('./logo.png', { path: '/assets', visibility: 'public' });
await store.upload(buffer, { name: 'report.json' });
await store.upload(fs.createReadStream('./big.zip'), { name: 'big.zip' });

Options: name (required unless uploading a path), path (default /), visibility (public | private, default = bucket setting), contentType (guessed from name), overwrite (replace a same-named file), lock (encrypt this object with your encryptionKey — see Encryption).

list(options?) → Promise<Listing>

Lists one folder. { path } defaults to /. Needs storage:read.

const { folders, objects, usage, maxBytes } = await store.list({ path: '/contracts' });

link(id) → Promise<StorageObject>

A fresh object record — a private object's url is newly signed. Needs storage:read.

download(idOrObject, destPath) → Promise<StorageObject>

Streams an object to a local file, fetching a fresh link first so an expired signature never bites.

remove(id) → Promise<void>

Deletes an object. Needs storage:delete.

Encryption (locked objects)

Lock a file with a customer key the server never stores. A locked object is encrypted at rest (AES-256-GCM), can't be opened via any public or signed link, and decrypts only through download() with the same key.

// Generate a key ONCE and store it somewhere durable (a secret manager).
const encryptionKey = ObjectStorage.generateKey(); // base64 of 32 random bytes

const store = new ObjectStorage({ key: process.env.AGG_STORAGE_KEY!, encryptionKey });

// Lock on upload — the object is forced private and cannot be served publicly.
const obj = await store.upload('./contract.pdf', { path: '/contracts', lock: true });
console.log(obj.locked); // true — `obj.url` is empty for a locked object

// download() and remove() send the key automatically when it's configured.
await store.download(obj, './contract.pdf');
await store.remove(obj.id);
  • lock: true requires encryptionKey in the client options, or upload throws.
  • Reading or deleting a locked object without the right key returns 403.
  • storage:read alone is not enough for a locked object — the key authorizes reading the bytes, the API key only authorizes the call.

⚠️ Lost key = unrecoverable file. The server never stores your key and cannot reset or recover it. If you lose it, every file locked with it is gone for good. Rotating a key means re-uploading the file with the new key.

Errors

Every non-2xx response throws a typed error you can branch on:

import { InsufficientScopeError, ConflictError } from '@agglabs-one/object';

try {
  await store.upload('./x.pdf', { name: 'x.pdf' });
} catch (err) {
  if (err instanceof ConflictError) { /* already exists — pass { overwrite: true } */ }
  if (err instanceof InsufficientScopeError) { /* key lacks storage:write */ }
}

StorageError (base) · InvalidKeyError (401) · InsufficientScopeError (403) · NotFoundError (404) · ConflictError (409). Each carries .status and .code.

Types

StorageObject, Listing, Visibility, ClientOptions, UploadOptions, ListOptions, and UploadInput are all exported.