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

@wgtechlabs/secrets-engine

v2.0.0

Published

Bun-first TypeScript SDK for securely storing and managing secrets with zero-friction, machine-bound AES-256-GCM encryption.

Readme

@wgtechlabs/secrets-engine

GitHub Repo Banner

Keep your secrets truly secret. With encrypted names and values, zero friction, and strict security by default, secrets‑engine gives developers defense‑in‑depth without the hassle. It’s a TypeScript SDK for secure secret storage, powered by machine‑bound AES‑256‑GCM and hardened SQLite.

Features

  • Zero friction — No passphrase, no setup wizard. Works out of the box.
  • Maximum privacy — Both key names and values are encrypted. No metadata leakage.
  • Machine-bound — Encryption keys are derived from machine identity + random keyfile via scrypt.
  • Defense in depth — Filesystem permission verification, HMAC integrity checks, per-entry unique IVs.
  • Bun-native — Built on bun:sqlite and Node crypto. Zero external runtime dependencies.

Installation

bun add @wgtechlabs/secrets-engine

Quick Start

import { SecretsEngine } from "@wgtechlabs/secrets-engine";

// Open or create a store (defaults to ~/.secrets-engine/)
const secrets = await SecretsEngine.open();

// Store secrets with dot-notation namespacing
await secrets.set("openai.apiKey", "sk-...");
await secrets.set("anthropic.apiKey", "sk-ant-...");

// Retrieve
const key = await secrets.get("openai.apiKey"); // "sk-..."

// Check existence (no decryption needed — HMAC lookup)
await secrets.has("openai.apiKey"); // true

// List keys with glob patterns
await secrets.keys("openai.*"); // ["openai.apiKey"]

// Delete
await secrets.delete("openai.apiKey");

// Clean up
await secrets.close();

Storage Location

The SDK resolves the storage directory using this priority order:

| Priority | Option | Path | |----------|--------|------| | 1 (highest) | { path: "/custom/path" } | Explicit path | | 2 | { location: "xdg" } | ~/.config/secrets-engine/ | | 3 (default) | (none) | ~/.secrets-engine/ |

// XDG-aware
const secrets = await SecretsEngine.open({ location: "xdg" });

// Custom path
const secrets = await SecretsEngine.open({ path: "/opt/myapp/secrets" });

API Reference

SecretsEngine.open(options?)

Open or create a secrets store. Returns a Promise<SecretsEngine>.

secrets.get(key)

Retrieve a decrypted secret value. Returns string | null.

secrets.getOrThrow(key)

Retrieve a decrypted secret, throwing KeyNotFoundError if missing.

secrets.set(key, value)

Store an encrypted secret.

secrets.has(key)

Check if a key exists via HMAC hash lookup (no decryption).

secrets.delete(key)

Remove a secret. Returns true if deleted, false if not found.

secrets.keys(pattern?)

List all key names, optionally filtered by glob pattern (e.g., "openai.*").

secrets.destroy()

Irreversibly delete the entire store, keyfile, and directory.

secrets.close()

Close the database connection and release resources. This method is async and must be awaited.

Returns a Promise<void> that resolves when the database is closed and integrity is finalized.

Breaking Change (v2.0.0): This method is now async. Update your code to await secrets.close().

secrets.size

Number of secrets currently stored.

secrets.storagePath

Absolute path to the storage directory.

Security Model

| Layer | Protection | |-------|-----------| | Encryption | AES-256-GCM with unique IV per entry | | Key derivation | scrypt (N=2¹⁷, r=8, p=1) from machine ID + random keyfile | | Key name privacy | Both names and values encrypted; HMAC-SHA256 index | | File permissions | Strict verification on open (700/600/400) | | Integrity | HMAC-SHA256 of database contents in meta.json | | Machine binding | Hostname + MAC + username + random keyfile |

Error Types

| Error | When | |-------|------| | SecurityError | File permissions too permissive | | IntegrityError | Database HMAC verification fails | | KeyNotFoundError | getOrThrow() for missing key | | DecryptionError | Corrupted entry or wrong key | | InitializationError | Cannot create store directory |

All errors extend SecretsEngineError with a .code property.

Development

bun install
bun test
bun run typecheck
bun run lint

License

MIT — WG Tech Labs