Skip to Content
URNOverview

@evanion/urn

@evanion/urn 2.1.0 and its patch releases up to 2.1.1, the version on npm. Values on this page were produced by running the source at f9b1d93, a later commit than the 2.1.0 tag, and are not re-executed.

Eliminate identifier ambiguity with RFC-compliant Universal Resource Names.

A bare 42 in a message does not say whether it names a game or an order. @evanion/urn writes and reads Uniform Resource Names (URNs), identifiers that carry their own context: urn:game:42 is a game and urn:order:42 is an order.

The Problem: The “Ambiguous ID” Trap

In systems that integrate multiple data sources, simple IDs like 123 are a liability. You cannot tell if 123 refers to a user, a product, or a transaction without knowing the external context. This leads to “type confusion,” where a product ID is accidentally treated as a user ID, or “collision risks,” where two different entities share the same numeric identifier.

Uniform Resource Names solve this by embedding the context directly into the identifier. Instead of passing a raw ID and a separate “type” flag, you pass a single string like urn:game:brass-birmingham. This makes your identifiers self-describing and safe to pass across service boundaries.

How @evanion/urn works

@evanion/urn reads a URN with parse, which returns its three primary parts: urn (the scheme), nid (the namespace identifier), and nss (the namespace-specific string). stringify joins these parts back into a single URN.

To manage different namespaces, you create a namespace class—a subclass of URN that sets a static nid property. For example, in a board game shop, a GameURN class would set nid to 'game'.

.('urn:game:brass-birmingham'); // -> { urn: 'urn', nid: 'game', nss: 'brass-birmingham' }

The URN vocabulary

Every page in this section uses the following terms to describe the parts of a URN, such as urn:game:brass-birmingham?=edition=2018.

  • Scheme: The first part, always urn per RFC 8141 .
  • Namespace Identifier (NID): The second part (game), which defines the kind of resource being named.
  • Namespace-Specific String (NSS): The third part (brass-birmingham), which uniquely identifies the resource within that namespace.
  • Component: An optional tail after the NSS.
    • r-component (?+): Parameters for the service resolving the URN.
    • q-component (?=): Parameters for the resource itself (e.g., an edition).
    • f-component (#): A specific fragment or section within the resource.
  • Namespace Class: A subclass of URN (like GameURN) that defines the nid and optional separators.
  • Foreign URN: A URN whose scheme or NID differs from the class being used to parse it. If GameURN parses urn:order:42, the order:42 part remains together in the nss.

Core capabilities

GoalTool
Create a URN from an IDstringify (on a namespace class or URN)
Split a URN into its partsparse
Verify if a URN is in a specific namespacebelongsToNamespace or sameNamespace
Get the raw ID regardless of namespaceextractId
Screen a string without throwingisValidFormat
Handle malformed inputValidationError and InvalidError
Attach metadata (editions, sections)q- and f-components
Safe encoding for titlesencodeNss and decodeNss
Compare two URNsequals (RFC 8141 §3.1 equivalence)

Design constraints

To maintain technical rigor and prevent common bugs, @evanion/urn explicitly avoids four behaviors:

  • No automatic normalization: parse preserves the original case. Use equals for case-insensitive comparison.
  • No implicit encoding: stringify throws on literal spaces. You must use encodeNss explicitly before stringify will accept such an NSS.
  • No deduplication: If an ID already contains a :, it is preserved as part of the NSS to avoid losing data.
  • No resolution: The library names resources; it does not fetch them from a database.

Get started with your own namespace

To start minting URNs, you only need a namespace class and the basic parse/stringify model. Getting started shows you how to install the package and declare your first GameURN class.

Last updated on