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

@mtngtools/unstorage

v0.3.0

Published

Custom storage drivers for unstorage with AWS S3 support

Downloads

132

Readme

@mtngtools/unstorage

[!WARNING] This package is under active development and likely will have breaking changes.

A TypeScript library providing storage drivers for unstorage with support for various cloud storage backends, designed to extend the capabilities of unstorage with drivers not currently built in.

npm version TypeScript License: MIT

Current Drivers

Planned Driver Features

  • Auto-versioned writes - Store as current value, but also with copy as timestamped version (not to be overwritten)
  • Load version - Load prior version instead of current value

Features

  • TypeScript First: Built with TypeScript for better developer experience
  • Additional Features: Read-only mode, default clear protection, maxDepth filtering
  • Tested: Unit and E2E tests
  • Tree Shakeable: ESM and CJS builds with proper tree shaking, supports both convenience and granular imports
  • Type Safe: Full TypeScript support with detailed type definitions
  • Flexible Imports: Support both convenience imports (from root) and granular imports (from subpaths) for optimal tree-shaking

Quick Start

Installation

pnpm install @mtngtools/unstorage

Import Strategies

The package supports two import strategies:

1. Convenience imports (from root) - Everything available in one import:

import { awsS3Driver, awsSsmDriver, AwsS3DriverOptions, validateKey } from '@mtngtools/unstorage'

2. Granular imports (from subpaths) - Better tree-shaking, recommended for production:

import { awsS3Driver } from '@mtngtools/unstorage/drivers/aws-s3'
import { awsSsmDriver } from '@mtngtools/unstorage/drivers/aws-ssm'
import { validateKey } from '@mtngtools/unstorage/utils'
import type { MTBaseDriverOptions } from '@mtngtools/unstorage/types'

Both strategies work identically. Use subpath imports for production builds to optimize bundle size.

AWS S3 Driver

# Install required peer dependencies for S3 and unstorage if not already installed
pnpm install @aws-sdk/client-s3 unstorage

Convenience import (from root):

import { createStorage } from 'unstorage'
import { S3Client } from '@aws-sdk/client-s3'
import { awsS3Driver } from '@mtngtools/unstorage'

// Create storage instance
const storage = createStorage({
  driver: awsS3Driver({
    bucket: 'my-storage-bucket'
  })
})

// Use the storage
await storage.setItem('user:123', { name: 'John', email: '[email protected]' })
const user = await storage.getItem('user:123')
console.log(user) // { name: 'John', email: '[email protected]' }

Granular import (from subpath - recommended for production):

import { createStorage } from 'unstorage'
import { S3Client } from '@aws-sdk/client-s3'
import { awsS3Driver } from '@mtngtools/unstorage/drivers/aws-s3'

// Create storage instance
const storage = createStorage({
  driver: awsS3Driver({
    bucket: 'my-storage-bucket'
  })
})

// Use the storage
await storage.setItem('user:123', { name: 'John', email: '[email protected]' })
const user = await storage.getItem('user:123')
console.log(user) // { name: 'John', email: '[email protected]' }

Notes about recent driver changes:

  • Prefer storagePrefix (driver option) for S3 prefixing; the driver still accepts the legacy s3StoragePrefix but canonicalizes it to storagePrefix.
  • The driver validator computes and exposes fullBasePrefix (the joined storagePrefix + base) which the driver uses to build S3 keys. If you provide custom mapping functions, they now receive the validated options object as a second parameter so you can access fullBasePrefix.
  • You can pass a pre-constructed s3Client to reuse a client instance, or omit it and provide inline region/accessKeyId/secretAccessKey/sessionToken — the driver will construct an S3 client for you when needed.

AWS S3 Flex: custom key and value mapping

The flex variant lets you adapt keys and values to existing S3 layouts without forking the driver.

Convenience import (from root):

import { awsS3FlexDriver } from '@mtngtools/unstorage'

Granular import (from subpath - recommended for production):

import { awsS3FlexDriver } from '@mtngtools/unstorage/drivers/aws-s3'

Key mapping hooks allow you to translate between unstorage keys (':' separated) and S3 keys:

const storage = createStorage({
  driver: awsS3FlexDriver({
    s3Client,
    bucket: 'my-bucket',
    // Example: always store with .json suffix
    toStorageKey(key, opts) {
      return `${opts.fullBasePrefix ? opts.fullBasePrefix + '/' : ''}${key}.json`
    },
    fromStorageKey(s3Key, opts) {
      const withoutBase = opts.fullBasePrefix && s3Key.startsWith(opts.fullBasePrefix)
        ? s3Key.slice(opts.fullBasePrefix.length + 1)
        : s3Key
      return withoutBase.endsWith('.json') ? withoutBase.slice(0, -5) : withoutBase
    }
  })
})

Value mapping hooks let you transform raw strings read/written by the driver:

const storage = createStorage({
  driver: awsS3FlexDriver({
    s3Client,
    bucket: 'my-bucket',
    toStorageValue(value) {            // value is a string produced by unstorage serialization
      return value                     // transform if needed (e.g., compress, wrap, etc.)
    },
    fromStorageValue(value) {          // value is the raw string read from S3
      return JSON.parse(value)         // transform to your desired type
    }
  })
})

Type rules:

  • Mapping hooks are optional; both can be omitted.
  • If fromStorageKey is provided, either also provide toStorageKey or set readOnly: true.
  • If fromStorageValue is provided, either also provide toStorageValue or set readOnly: true.

AWS SSM Driver

AWS Systems Manager Parameter Store driver. Keys map to parameter paths (e.g. /my-app/key1).

pnpm install @mtngtools/unstorage @aws-sdk/client-ssm unstorage

Convenience import (from root):

import { createStorage } from 'unstorage'
import { awsSsmDriver } from '@mtngtools/unstorage'

const storage = createStorage({
  driver: awsSsmDriver({
    region: 'us-east-1',
    storagePrefix: 'my-app',
  })
})
await storage.setItem('config:feature-x', 'true')
const value = await storage.getItem('config:feature-x')

Granular import (from subpath - recommended for production):

import { awsSsmDriver } from '@mtngtools/unstorage/drivers/aws-ssm'

You can pass a pre-constructed ssmClient or omit it and provide region (and optionally credentials). Use withDecryption: true (default) to decrypt SecureString parameters when reading.

AWS SSM Flex: custom key and value mapping

The flex variant adds custom key and value mapping for Parameter Store, similar to S3 Flex.

Convenience import: import { awsSsmFlexDriver } from '@mtngtools/unstorage'
Granular import: import { awsSsmFlexDriver } from '@mtngtools/unstorage/drivers/aws-ssm'

See AWS SSM Driver for options and examples.

Documentation

Driver Documentation

Agent guidance

Testing

# Unit tests (standard)
pnpm test

# Additional modes
pnpm test:verbose      # Verbose reporter
pnpm test:min          # Dot/minimal reporter
pnpm test:ui           # Interactive UI mode
pnpm test:coverage     # Unit test coverage

# E2E tests (requires environment setup)
pnpm test:e2e

For E2E testing setup, see the specific driver documentation.

E2E Setup (S3)

E2E tests are gated and require:

  1. AWS credentials (CLI config, env vars, or credentials file)
  2. A test S3 bucket
  3. Environment config

Recommended (environment file):

cp .env.test.e2e .env.test.e2e.local
echo 'AWS_S3_E2E_ENABLED=true' >> .env.test.local
echo 'AWS_S3_TEST_BUCKET=your-bucket' >> .env.test.local
echo 'AWS_S3_TEST_PREFIX=your-test-prefix' >> .env.test.local
pnpm test:e2e

Or set variables directly:

export AWS_S3_E2E_ENABLED=true
export AWS_S3_TEST_BUCKET=your-bucket
export AWS_S3_TEST_PREFIX=test-mtng-unstorage-e2e/
# Optional if not in shared config
# export AWS_REGION=us-east-1
pnpm test:e2e

Environment file load order (highest wins):

  • .env.test.e2e.local
  • .env.test.e2e

Security:

  • Never commit credentials
  • Use a unique prefix (AWS_S3_TEST_PREFIX) to isolate and simplify cleanup

E2E Setup (SSM)

E2E tests for the SSM driver are gated. Enable and configure via environment:

# In .env.test.e2e.local or env vars
AWS_SSM_E2E_ENABLED=true
AWS_SSM_TEST_PREFIX=/test/mtng-unstorage/e2e
# AWS_REGION=us-east-1  # optional, uses default config

Use a dedicated test prefix to isolate and simplify cleanup. AWS credentials follow the same chain as S3 (CLI config, env vars, IAM roles).

License

MIT © Jason Bulson

Support

Related Projects