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

@ekaone/shielded

v0.1.2

Published

A super lightweight, zero-dependency TypeScript library for TypeScript primitive that prevents sensitive state from leaking through logging, devtools, and serialization.

Readme

@ekaone/shielded

Typescript data safety primitive that prevents sensitive state from leaking through logging, devtools, and serialization.


The Problem Space

Modern JavaScript applications handle sensitive data constantly — auth tokens, payment details, PII, session credentials. The risk isn't always a malicious attacker. Most leaks happen from your own team, during normal development and operations.

Console logging during debugging

// Developer debugging an auth issue
console.log("current store:", store)
// → { user: "Eka", token: "eyJhbGciOiJIUzI1NiIsInR..." } ❌

A single console.log in a code review, a debug session, or a staging environment can expose tokens that were never meant to be visible.

Error tracking capturing full state

Sentry.captureException(err, { extra: store })
// → token, cardToken, ssn all appear in your Sentry dashboard ❌

Tools like Sentry, Datadog, and LogRocket serialize everything they receive. If your store is in scope when an error occurs, every key goes to the cloud.

JSON serialization leaking to the client

// Server-side rendering — state serialized into HTML
const html = `<script>window.__STATE__ = ${JSON.stringify(store)}</script>`
// → sensitive fields visible in page source ❌

SSR hydration is a common vector for leaking server-side secrets to the browser.

Devtools broadcasting everything

Redux DevTools, Zustand devtools, and React Query devtools display the full store in real time. Any sensitive value in state is immediately visible to anyone with devtools open — including in production if devtools extensions are installed.

The core issue

No existing state manager addresses this at the primitive level. The safe path requires manually sanitizing every log call, every error boundary, every analytics event, and every serialization point. @ekaone/shielded makes the safe path the default.


How It Works

sealed() wraps a value in an opaque container that is invisible to all standard serialization and logging mechanisms. The value is stored in a native private class field (#value) — unreachable via Object.keys, Object.entries, or property enumeration. It only surfaces when you explicitly call .unwrap().

const token = sealed("eyJhbG...")

console.log(token)              // [Sealed]
JSON.stringify({ token })       // '{}'
`${token}`                      // "[Sealed]"
Object.keys({ token })          // []  (no enumerable properties)

token.unwrap()                  // "eyJhbG..."  ← explicit opt-in only

Installation

npm install @ekaone/shielded
pnpm install @ekaone/shielded
yarn install @ekaone/shielded

API

sealed(value)

Wraps any value so it is hidden from serialization and logging. Use .unwrap() to explicitly read it.

import { sealed } from "@ekaone/shielded"

const token = sealed("eyJhbG...")

// All of these hide the value
console.log(token)                    // [Sealed]
JSON.stringify({ token })             // '{}'
String(token)                         // "[Sealed]"
`Bearer ${token}`                     // "Bearer [Sealed]"

// Explicit read
token.unwrap()                        // "eyJhbG..."
token.isSealed                        // true
token.isExpired                       // false

Works with any type:

sealed(42).unwrap()           // 42
sealed({ a: 1 }).unwrap()     // { a: 1 }
sealed(true).unwrap()         // true
sealed(null).unwrap()         // null

createStore(state)

Creates a store with full sealed value awareness. Plain values behave normally. Sealed values stay sealed until explicitly unwrapped.

import { createStore, sealed } from "@ekaone/shielded"

const store = createStore({
  user: "Eka",
  token: sealed("eyJhbG..."),
  cardToken: sealed("tok_visa_..."),
})

// Read plain value
store.get("user")                     // "Eka"

// Read sealed value — still sealed
store.get("token")                    // SealedValue<string>
store.get("token").unwrap()           // "eyJhbG..."

// Write
store.set("user", "John")
store.set("token", sealed("newToken..."))

// Snapshot — sealed keys omitted entirely
store.snapshot()                      // { user: "Eka" }

// Safe to log or send to error tracking
console.log(store.snapshot())         // { user: "Eka" } ✅
Sentry.captureException(err, {
  extra: store.snapshot()             // token and cardToken never appear ✅
})

store.subscribe(fn)

Subscribe to state changes. Returns an unsubscribe function. Sealed values remain sealed inside the subscriber.

const unsubscribe = store.subscribe((state) => {
  console.log(state.user)             // "Eka"
  console.log(state.token)            // [Sealed]  ← never leaks
})

store.set("user", "John")             // subscriber fires

// Stop listening
unsubscribe()

withTTL(value, ms)

Wraps a sealed value with a time-to-live in milliseconds. After expiry, .unwrap() throws. Useful for session tokens, OTP values, and temporary credentials.

import { sealed, withTTL } from "@ekaone/shielded"

const token = withTTL(sealed("eyJhbG..."), 5 * 60 * 1000) // 5 minutes

token.unwrap()       // "eyJhbG..."  (within TTL)
token.isExpired      // false

// After 5 minutes:
token.unwrap()       // throws "[shielded] sealed value has expired"
token.isExpired      // true

isSealedValue(value)

Type guard — returns true if a value is a SealedValue. Useful for conditional unwrapping.

import { isSealedValue } from "@ekaone/shielded"

const val = store.get("token")

if (isSealedValue(val)) {
  const raw = val.unwrap()  // TypeScript knows this is safe
}

isSealedValue(sealed("x"))  // true
isSealedValue("x")          // false
isSealedValue({ isSealed: true })  // false  ← spoofed objects rejected

Real World Use Cases

Auth tokens

const authStore = createStore({
  user: { name: "Eka", role: "admin" },
  accessToken: sealed("eyJhbG..."),
  refreshToken: sealed("dGhpcyBp..."),
})

// Use in API calls
await fetch("/api/data", {
  headers: {
    Authorization: `Bearer ${authStore.get("accessToken").unwrap()}`
  }
})

// Safe to log the store state
console.log(authStore.snapshot())
// { user: { name: "Eka", role: "admin" } }  ← tokens never appear

Payment flow

const checkoutStore = createStore({
  cartTotal: 9900,
  currency: "USD",
  cardLast4: "4242",
  stripeToken: sealed("tok_visa_..."),
})

// Sentry captures a crash during checkout
Sentry.captureException(err, {
  extra: checkoutStore.snapshot()
  // { cartTotal: 9900, currency: "USD", cardLast4: "4242" }
  // stripeToken is never in the report ✅
})

Healthcare / PII

const patientStore = createStore({
  name: "John Doe",
  dob: sealed("1985-03-12"),
  ssn: sealed("***-**-1234"),
  appointmentDate: "2026-04-01",
})

// Safe analytics event
analytics.track("appointment_viewed", patientStore.snapshot())
// { name: "John Doe", appointmentDate: "2026-04-01" }  ← no PII ✅

Session with expiry

const sessionStore = createStore({
  userId: "usr_abc123",
  sessionToken: withTTL(sealed("sess_xyz..."), 30 * 60 * 1000), // 30 min
})

// Works within session window
sessionStore.get("sessionToken").unwrap()   // "sess_xyz..."

// After 30 minutes — automatic protection
sessionStore.get("sessionToken").unwrap()   // throws: sealed value has expired

Composing with Existing State Managers

sealed() works as a standalone primitive. You can drop it into Zustand, Jotai, or any other state manager without replacing anything.

With Zustand

import { create } from "zustand"
import { sealed, isSealedValue } from "@ekaone/shielded"

const useStore = create(() => ({
  user: "Eka",
  token: sealed("eyJhbG..."),
}))

// In a component
const token = useStore((s) => s.token)
token.unwrap()   // "eyJhbG..."

// Safe devtools snapshot
const safeState = Object.fromEntries(
  Object.entries(useStore.getState()).filter(([, v]) => !isSealedValue(v))
)

With Jotai

import { atom } from "jotai"
import { sealed } from "@ekaone/shielded"

const tokenAtom = atom(sealed("eyJhbG..."))

// In a component
const [token] = useAtom(tokenAtom)
token.unwrap()   // "eyJhbG..."

TypeScript

Fully typed. sealed() preserves the inner type through unwrap().

import type { SealedValue, Store } from "@ekaone/shielded"

const token: SealedValue<string> = sealed("eyJhbG...")
const num: SealedValue<number> = sealed(42)

token.unwrap()   // string
num.unwrap()     // number

Performance

sealed() adds no asymptotic overhead. All operations remain O(1).

| Operation | Complexity | vs baseline | |---|---|---| | sealed(value) | O(1) | same | | .unwrap() | O(1) | +1 function call | | JSON.stringify | O(k) | same or faster — sealed keys skipped | | snapshot() | O(k) | O(k) key scan | | subscribe notify | O(n) | same — n subscribers |

The constant overhead of .unwrap() is a single property access — nanoseconds in practice, unmeasurable in any real application.


License

MIT © Eka Prasetia

Links


⭐ If this library helps you, please consider giving it a star on GitHub!