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

@onderwijsin/nuxt-storage-admin

v0.2.4

Published

Admin-protected CRUD endpoints for explicitly configured Nitro storage mounts.

Readme

@onderwijsin/nuxt-storage-admin

@onderwijsin/nuxt-storage-admin provides administrator-only CRUD endpoints for explicitly allowed Nitro storage mounts. It is intended for operational tooling, debugging, and controlled maintenance—not as a general application data API.

Requires Nuxt 4 and Node.js 22 or later.

The module is disabled by default. It never exposes every useStorage() mount implicitly.

Installation

pnpm add @onderwijsin/nuxt-storage-admin
export default defineNuxtConfig({
  modules: ["@onderwijsin/nuxt-storage-admin"],
  storageAdmin: {
    enabled: true,
    adminToken: process.env.STORAGE_ADMIN_TOKEN,
    internalKeyPrefixes: ["__cache_meta:"],
    internalKeySuffixes: ["$"],
    mounts: {
      cache: {
        permissions: ["read", "write", "delete"],
        prefixes: ["pages", "kennisbank:articles"]
      }
    }
  }
});

Import the module stylesheet from the consuming application's main CSS file:

@import "@onderwijsin/nuxt-storage-admin";

It imports Tailwind CSS and Nuxt UI, then sources the storage browser components so their utility classes are included. Nuxt UI is registered automatically while the development browser is enabled.

Concepts

  • A mount is the first argument to Nitro useStorage(), such as cache, sessions, or uploads.
  • A prefix is a boundary inside a mount. For example, kennisbank:articles is a cache base and prefix inside the cache mount.
  • A configured prefix permits that exact key and descendants separated by :. Configuring pages permits pages and pages:home, but not pages-private.

Internal records are never listed, read, written, or deleted through this API. The default patterns hide the cache metadata index (__cache_meta:) and legacy cache sidecars ($); configure these patterns to match the storage conventions in the consuming application.

Configuration reference

export default defineNuxtConfig({
  storageAdmin: {
    enabled: true,
    adminToken: process.env.STORAGE_ADMIN_TOKEN,
    adminHeaderName: "x-admin-token",
    devAuthBypass: false,
    internalKeyPrefixes: ["__cache_meta:"],
    internalKeySuffixes: ["$"],
    mounts: {
      cache: {
        permissions: ["read", "write", "delete"],
        prefixes: ["pages", "kennisbank:articles"],
        allowRoot: false
      },
      operations: {
        permissions: ["read"],
        allowRoot: true
      }
    },
    ui: {
      enabled: true,
      path: "/_storage"
    },
    defaultLimit: 100,
    maxLimit: 500,
    maxListedKeys: 10_000
  }
});

Authentication

In production, each API request must include either:

x-admin-token: <adminToken>

or:

Authorization: Bearer <adminToken>

The custom header name is configurable through adminHeaderName. Missing or invalid credentials produce 401.

Development requests require the same token by default. Set devAuthBypass: true only for a trusted local server when using the browser without client-side credentials. Nuxt logs a prominent warning when this explicit bypass is enabled; it is ignored in production builds.

API reference

All successful responses have a { "data": ... } envelope. All paths below are relative to the application origin.

List entries

GET /api/_storage/:mount/items?prefix=<prefix>&limit=<limit>&cursor=<cursor>

| Query parameter | Required | Description | | --------------- | -------- | -------------------------------------------------------------------------------------------------------------------- | | prefix | No | Allowed key prefix to list. Omit it to aggregate every configured prefix. A mount with no prefixes cannot be listed. | | limit | No | Positive page size, limited by maxLimit. | | cursor | No | Cursor returned as nextCursor from a prior request. | | page | No | Positive page number. Intended for the development UI; when present, it takes precedence over cursor. | | metadata | No | Set true to additionally retrieve raw driver metadata. path is always returned. | | search | No | Case-insensitive search across storage keys and path. Metadata is read automatically for this query. |

Example:

GET /api/_storage/cache/items?prefix=kennisbank:articles&search=example
{
  "data": {
    "items": [
      {
        "key": "kennisbank:articles:example:abc123",
        "path": "/kennisbank/artikelen/example"
      }
    ],
    "nextCursor": null,
    "page": 1,
    "total": 1
  }
}

path is available only when the selected storage driver writes metadata. The cache module will provide it; ordinary Unstorage drivers may return null. Raw driver metadata is omitted by default; request it explicitly with metadata=true only when it is needed.

nextCursor is a storage key string, not an entry object. Use it unchanged as cursor in the next request. Cursors are valid only for the same mount, prefix, search query, and ordering; writes between requests can change the result set.

Read an entry

GET /api/_storage/:mount/items/:key
{
  "data": {
    "key": "kennisbank:articles:example:abc123",
    "value": { "title": "Example" }
  }
}

Create or replace an entry

PUT /api/_storage/:mount/items/:key
Content-Type: application/json
{ "value": { "title": "Example", "published": true } }
{ "data": { "key": "kennisbank:articles:example:abc123", "updated": true } }

Delete one entry

DELETE /api/_storage/:mount/items/:key
{ "data": { "key": "kennisbank:articles:example:abc123", "deleted": true } }

Clear a prefix

POST /api/_storage/:mount/actions/delete-by-prefix
Content-Type: application/json
{ "prefix": "kennisbank:articles", "confirm": true }

The request is rejected when confirm is not literally true or the prefix is not permitted. It uses Unstorage's native clear(prefix) operation, allowing the active driver to clear the base efficiently and remove related internal cache records.

{ "data": { "prefix": "kennisbank:articles", "cleared": true } }

Clear a mount

POST /api/_storage/:mount/actions/clear
Content-Type: application/json
{ "confirm": true }

This removes every key in the selected mount through storage.clear(). It requires delete permission and allowRoot: true on the mount; an ordinary prefix allowlist is not enough.

{ "data": { "mount": "operations", "cleared": true } }

Development browser

When storageAdmin.enabled and storageAdmin.ui.enabled are true, nuxt dev registers a Nuxt UI page at ui.path (default /_storage). Page registration is independent of authentication: development requests still require the configured token unless devAuthBypass is also true. The browser provides:

  • a selector containing only configured mount/prefix pairs;
  • key and cached-path search;
  • selectable page sizes; and
  • server-backed pagination; and
  • per-entry and selected-entry deletion with a confirmation prompt.

The browser is not registered in production. Set ui.enabled: false to exclude the UI and avoid registering @nuxt/ui as a module dependency.

The host application's root component must render Nuxt UI's <UApp> so the browser can open its confirmation dialog and action menus.

Avoid configuring application pages at ui.path (default /_storage) or API handlers below /api/_storage/**; those locations are reserved by this module while it is enabled.

Listing limits and provider behavior

Unstorage exposes key enumeration through getKeys(), and not every driver can paginate or cancel that call. Listing refuses a mount without configured prefixes and only enumerates configured bases. maxListedKeys is a post-enumeration response guard: generic drivers have already materialized the key array before a larger result can return 413, so it does not cap provider or process memory. Configure narrow prefixes and do not use this endpoint to inspect large mounts.

| Option | Default | Contract | | --------------- | -------: | ---------------------------------------------------------------------------------- | | maxListedKeys | 10_000 | Maximum non-internal keys accepted after enumeration; larger results return 413. |

Searches by path necessarily inspect metadata for every accepted key. Driver listing failures return 503; a fixed 10-second response deadline returns 504. The deadline does not cancel an underlying driver operation. A failed or late metadata lookup on an otherwise listable entry is represented as path: null.

Error behavior

| Status | Meaning | | ------ | -------------------------------------------------------------------------------------------- | | 400 | Invalid route parameter, query, or body. | | 401 | Missing or invalid administrator token in production. | | 403 | The configured mount, permission, prefix, or metadata key is not allowed. | | 404 | Storage administration is disabled, the mount is not configured, or an entry does not exist. | | 413 | The selected storage base contains more than maxListedKeys entries after enumeration. | | 503 | The storage provider failed while listing keys. | | 504 | The storage provider timed out while listing keys. |

Compatibility

Developed and tested against Node.js 24 and Nuxt 4.5.x. The package declares Node.js >=22 and may work with other Nuxt versions permitted by its package metadata, but versions outside the current CI matrix are not continuously tested. Nuxt 3 is not guaranteed.