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

@cqrs-toolkit/hypermedia

v0.2.0

Published

CQRS-aware Hydra API documentation types, IRI templates, HAL rendering, content negotiation, and embed planning

Downloads

264

Readme

@cqrs-toolkit/hypermedia

CQRS-aware Hydra API documentation, HAL rendering, content negotiation, and embed planning for server-side hypermedia APIs.

Define versioned command and query surfaces with HydraDoc, render HAL+JSON responses with embedded resources and CURIEs, negotiate profiles via HTTP headers, plan command validation pipelines, and resolve ?include= tokens into parallel data loads.

Entry Points

The package has three entry points:

| Import | Purpose | | ---------------------------------- | ------------------------------------------------------------------------------------- | | @cqrs-toolkit/hypermedia | Core types: HydraDoc, HAL, HypermediaTypes, embed spec types | | @cqrs-toolkit/hypermedia/server | Server utilities: profile negotiation, command/embed planning, formatting, exceptions | | @cqrs-toolkit/hypermedia/builder | Build-time tooling: generate Hydra ApiDocumentation JSON-LD from class definitions |

Defining API Surfaces

HydraDoc is the core namespace for declaring what your API exposes — versioned representations, query surfaces, and command capabilities.

Representations

A Representation describes a versioned read model: its profile URN, media types, and surfaces for querying single items and collections.

import { HydraDoc } from '@cqrs-toolkit/hypermedia'

const taskRep = new HydraDoc.Representation({
  id: 'task-v1',
  version: '1.0.0',
  resourceSurface: {
    profileUrn: 'urn:profile:pms:Task',
    mediaTypes: ['application/json'],
    template: new HydraDoc.IriTemplate({
      template: '/api/tasks/{id}',
      mappings: [{ variable: 'id', property: 'id' }],
    }),
  },
  collectionSurface: {
    profileUrn: 'urn:profile:pms:Task',
    mediaTypes: ['application/json'],
    template: new HydraDoc.IriTemplate({
      template: '/api/tasks{?status,limit,cursor}',
      mappings: [
        { variable: 'status', property: 'status' },
        { variable: 'limit', property: 'limit' },
        { variable: 'cursor', property: 'cursor' },
      ],
    }),
  },
})

Command Capabilities

Commands are grouped into CommandsDef — a set of versioned capabilities with surfaces that describe how to invoke them.

const taskCommands = new HydraDoc.CommandsDef({
  surfaces: HydraDoc.standardCommandSurfaces(
    new HydraDoc.IriTemplate({
      template: '/api/tasks/{id}/commands/{commandType}',
      mappings: [
        { variable: 'id', property: 'id' },
        { variable: 'commandType', property: 'commandType' },
      ],
    }),
    new HydraDoc.IriTemplate({
      template: '/api/tasks',
      mappings: [],
    }),
  ),
  capabilities: [
    {
      id: 'RenameTask-1.0.0',
      stableId: 'RenameTask',
      version: '1.0.0',
      commandType: 'RenameTask',
      dispatch: 'command',
      schema: taskRenameSchema,
    },
  ],
})

HAL Rendering

The HAL namespace renders resource and collection descriptors into HAL+JSON, handling _links, _embedded, and CURIEs.

import { HAL } from '@cqrs-toolkit/hypermedia'

// Single resource
const hal = HAL.fromResource(resourceDescriptor, resourceDefinition, { idKey: 'id' })

// Collection with pagination
const halCollection = HAL.fromCollection(
  collectionDescriptor,
  resourceDefinition,
  collectionDefinition,
  { idKey: 'id' },
)

Server Utilities

Profile Negotiation

ProfileNegotiator handles Accept-Profile / Content-Profile header negotiation, selecting the best version from registered profiles.

import { ProfileNegotiator } from '@cqrs-toolkit/hypermedia/server'

const negotiator = new ProfileNegotiator([
  { urn: 'urn:profile:pms:Task', version: '1.0.0', representation: taskRepV1 },
  { urn: 'urn:profile:pms:Task', version: '2.0.0', representation: taskRepV2 },
])

const result = negotiator.negotiate(request, reply)
// result.kind: 'none' (no profile requested) | 'matched' | 'replied' (406)

ProfileHandler wraps the negotiator with Result<T, E> integration for query endpoints.

Command Planning

CommandPlanner negotiates command versions, validates payloads against JSON Schema, and chains adapters for backwards compatibility.

import { CommandPlanner } from '@cqrs-toolkit/hypermedia/server'

const planner = new CommandPlanner(taskCommands, extractDispatch, validate)

const negotiated = planner.negotiate(request, reply)
const validated = planner.validate(negotiated, requestBody)
const hydrated = planner.hydrate(validated)

Embed Planning

EmbedPlanner validates ?include= tokens, resolves parent dependencies, and executes resolvers in parallel.

import { EmbedPlanner } from '@cqrs-toolkit/hypermedia/server'

const planner = new EmbedPlanner(embeddableSpecs, { maxIncludes: 3 })

const result = await planner.resolve(
  request.query, // e.g. { include: 'pms:DataTag,pms:Category' }
  params,
  locals,
  context,
)
// result: EmbeddedOutput keyed by className

Response Formatting

Hypermedia provides helpers that combine descriptors with HAL rendering and pagination.

import { Hypermedia } from '@cqrs-toolkit/hypermedia/server'

// Build a collection descriptor from a cursor-paginated query result
const descriptor = Hypermedia.buildCollectionDescriptor(connection, toResourceDescriptor)

// Format as HAL with pagination links
const body = Hypermedia.formatCollection(descriptor, {
  resourceDefs,
  collectionDef,
  idKey: 'id',
})

Exceptions

Typed HTTP exceptions for common error responses:

  • 4xx: BadRequestException, ForbiddenException, NotFoundException, TooManyIncludesException
  • 5xx: InternalErrorException, BadGatewayException, GatewayTimeoutException
  • toUpstreamException(err) maps Node network errors (ETIMEDOUT, ECONNREFUSED, etc.) to the appropriate exception

Builder

Generate Hydra ApiDocumentation JSON-LD and JSON Schema files from your class definitions at build time.

import {
  buildHydraApiDocumentation,
  generateHydraDocumentation,
} from '@cqrs-toolkit/hypermedia/builder'

const result = buildHydraApiDocumentation({
  classes: [taskClassDef, projectClassDef],
  prefixes: ['pms'],
})

// Write JSON-LD and schemas to disk
await generateHydraDocumentation({
  buildResult: result,
  outDir: './hydra',
})

API Reference

Full API documentation is generated from source and available at docs/api.

Key entry points: