@minerouter/normid
v1.0.3
Published
Deterministic ID from string — NFKC + SHA-256 → base62. Zero dependencies. One name, one ID, everywhere.
Maintainers
Readme
normid — Deterministic ID from String
One name, one ID, everywhere.
Zero-dependency library for deterministic ID generation. Same input produces the same ID on any platform, in any language, without network or database.
Algorithm: NFKC normalize → locale-fixed uppercase → trim
→ SHA-256(SHA-256(ns) || SHA-256(input))
→ truncate 20 bytes → base62 → id_<28 chars>Why normid?
A username takes different forms across platforms:
Username, username, USERNAME.
Without a shared database, these cannot be linked. normid solves this —
case, Unicode, whitespace, locale — none of it matters.
import { normid } from '@minerouter/normid'
const id = await normid('Username')
await normid('username') === id // true
await normid('USERNAME') === id // trueInstallation
npm install @minerouter/normidDependencies: 0 — uses Web Crypto API (crypto.subtle), built into Node ≥18 and all browsers.
API
normid(input: string, namespace?: string): Promise<string>
| Param | Type | Default | Description |
|-------|------|---------|-------------|
| input | string | — | String to generate ID from (username, nickname, etc.) |
| namespace | string | 'user' | Domain isolation prefix |
Returns: id_ + 28 base62 chars = 31 total.
Throws: If input is empty or whitespace-only after normalization.
Proof
For username WooonderkinG33 (12 letters), all 4,096 case permutations
produce the exact same ID in under a second:
Combinations: 4,096
Unique IDs: 1
Time: ~1.1s
Throughput: ~3,500 IDs/secWhat normid is NOT for
- ❌ Passwords / secrets — no salt, unsafe
- ❌ PII anonymization — small input → brute-forceable
- ❌ Authentication — identifies, doesn't prove ownership
Full specification
GitHub: WooonderkinG33/MineRouter-NORMID
License
MIT
