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

@reharik/smart-enum

v0.10.0

Published

Type-safe smart enums for TypeScript with database and transport serialization support

Readme

@reharik/smart-enum

Type-safe, feature-rich enumerations for TypeScript. Every member is a frozen object that carries its own wire value, display label, ordering, and any custom fields you give it — with runtime lookup, iteration, serialization, and database revival built in.

📖 Full documentation: https://reharik.github.io/smart-enums/

The idea

Have you ever followed one value — an order status, say — through a codebase and counted how many places had to know about it? The database stores 'ACTIVE', the API ships 'ACTIVE', a <select> uses it, a labels map turns it into 'Active', an array lists every option, and a few ifs compare it. Add 'ARCHIVED' and there are five places to update. Miss one and it's not carelessness — those places were never connected. The language gave you a bare string, so the concept scattered.

A smart enum lets that concept be one object that knows everything about itself:

import { enumeration, type Enumeration } from '@reharik/smart-enum';

const Status = enumeration('Status', {
  input: ['pending', 'active', 'completed'] as const,
});
type Status = Enumeration<typeof Status>;

Status.active;               // { key: 'active', value: 'ACTIVE', display: 'Active', index: 1 }
Status.active.display;       // 'Active'        — the label lives with the value
Status.fromValue('ACTIVE');  // Status.active   — runtime lookup, type-narrowed
Status.items();              // every member, in order — your dropdown options
Status.values();             // ['PENDING','ACTIVE','COMPLETED'] — your validator set

The options list, wire value, label, valid-set, and ordering are all the same object, defined once. There's no fifth place to forget.

Why people reach for it

  • Metadata that travels with the value — attach status, retryable, column, anything, and read it off the member at runtime instead of from a parallel map.
  • Lookup without boilerplate — fromValue / fromKey (and try* variants), all type-narrowed to the enum's members.
  • Survives the boundary — members serialize to self-describing JSON and revive into the same instances across a network, a database, or a full GraphQL stack. A value that left as Status.active comes back knowing it is.
  • Tiny and lock-in-free — ~600 bytes full, ~149 for just enumeration via entry points; output is plain frozen objects and ordinary JSON.

Strict revival

Reading enums back out of a database means declaring which columns map to which enums. That mapping is the contract, and strict — on by default — enforces it in both directions:

reviveRowFromDatabase(row, {
  fieldEnumMapping: { operations: Operation },
});
  • The data side — a stored string that matches no member throws EnumRevivalError, instead of leaking a bare string into your domain logic.
  • The mapping side — a key naming a field the row doesn't have throws too. A typo like { operation: Operation } against an operations column used to be a silent no-op: nothing revived, no warning, and the column arrived as raw strings while still typed as members. That failure surfaces far from its cause — .value returning undefined, or every element collapsing into one key when used to build a map.

The error lists the row's actual fields, because the whole class of bug is near-miss names:

EnumRevivalError: Cannot revive field "operation": not present on the row.
Available fields: id, operations, status

With the Knex adapter, mapping keys are also constrained to the query's row type, so TypeScript catches the typo first — and suggests the field you meant. The runtime check backstops untyped queries and .select<T>() assertions that don't match the database.

Pass strict: false to disable both checks — when you're migrating and expect transitional values, or when one mapping is deliberately shared across queries that select different columns.

Install

npm install @reharik/smart-enum

Then read the five-minute quick start, or Coming from TypeScript enums if you're migrating.

The ecosystem

| Package | Purpose | | --- | --- | | @reharik/smart-enum-knex | Knex query-level enum revival via postProcessResponse | | @reharik/graphql-codegen-smart-enum | Generate smart-enum definitions from GraphQL schema enums | | @reharik/graphql-codegen-smart-enum-type-policies | Apollo typePolicies for client-side enum rehydration | | @reharik/graphql-codegen-smart-enum-preset | Codegen preset that wires the whole stack with zero per-enum config |

License

MIT