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

@zamatica/secrets

v0.1.0

Published

Pluggable secrets-provider interface + reference obfuscated-file impl + NestJS adapter. Core types are framework-agnostic; ship your own provider for real secret stores (systemd-creds, CyberArk, Broadcom PAM, k8s Secrets, etc.).

Readme

@zamatica/secrets

Pluggable SecretsProvider interface, a reference obfuscated-file implementation, and a NestJS adapter. Drop in your real provider (systemd-creds, CyberArk, Broadcom PAM, k8s mounted Secret, etc.) by satisfying the same interface.

Subpaths

  • @zamatica/secrets — the SecretsProvider interface + the SECRETS_PROVIDER DI token string. No framework deps.
  • @zamatica/secrets/filecreateFileSecretsProvider({ baseDir }) and the scrambleNotEncrypt / unscramble primitives. Disk-only.
  • @zamatica/secrets/nestjsSecretsModule.forRoot({ provider }).

Interface

export interface SecretsProvider {
  get(key: string): Promise<string | undefined>;
  set?(key: string, value: string): Promise<void>;
  list?(prefix?: string): Promise<readonly string[]>;
  readonly capabilities: { writable: boolean; enumerable: boolean };
}

set and list are optional — read-only providers (CyberArk-style) leave them off and advertise capabilities.writable = false / capabilities.enumerable = false. Consumers check capabilities before invoking.

The file impl is OBFUSCATION, not encryption

Per the template's "super simple obfuscated file store" decision: secrets are XOR-scrambled with a constant key (no per-install secret) and stored as Base64 files under baseDir. The function is deliberately named scrambleNotEncrypt. Anyone with disk access can recover. Suitable as a deterrent against casual eyeballing and as a development default. Production deployments swap providers.

Per-file layout (vs a single secrets.json bag):

  • Concurrent writes from daemon + admin CLI need no lock.
  • list() is readdir — no parsing.
  • Per-secret delete is rm $baseDir/$key — no rewrite that could corrupt other secrets on crash.
  • Per-file mode is 0600; baseDir is 0700. Writes are atomic via sibling .tmp + rename.

Keys are validated: no path separators, no . / .. / empty / dotfile names. A daemon's secrets.get(userInput) cannot traverse out of baseDir.

NestJS wiring

import { SecretsModule } from '@zamatica/secrets/nestjs';
import { createFileSecretsProvider } from '@zamatica/secrets/file';

@Module({
  imports: [
    SecretsModule.forRoot({
      provider: createFileSecretsProvider({ baseDir: '/etc/mtz/secrets' }),
    }),
  ],
})
export class AppModule {}

Consumers @Inject(SECRETS_PROVIDER) private secrets: SecretsProvider. The module is global: true so feature modules don't need to re-import.

Swapping in a real provider

// e.g. systemd-creds via CREDENTIALS_DIRECTORY (systemd v250+)
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';

function createSystemdCredsProvider(): SecretsProvider {
  const dir = process.env['CREDENTIALS_DIRECTORY'];
  if (dir === undefined) throw new Error('not running under systemd LoadCredential');
  return {
    capabilities: { writable: false, enumerable: true },
    async get(key) {
      try {
        return (await readFile(join(dir, key), 'utf8')).trim();
      } catch { return undefined; }
    },
    async list(prefix) {
      const fs = await import('node:fs/promises');
      const entries = await fs.readdir(dir);
      return prefix ? entries.filter(e => e.startsWith(prefix)) : entries;
    },
  };
}

The consumer's SecretsModule.forRoot doesn't care which provider you pass — same DI token, same call sites.

Status

v0.x. The interface is stable; the file impl is intentionally simple. If a second descendant needs a real provider, harvest the implementation back into this lib as @zamatica/secrets/<provider-name> for reuse.