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

@quilla-be-kit/errors

v0.2.1

Published

Transport-agnostic error primitives: QuillaError base with cross-realm-safe brand, and category classes (Validation, NotFound, Conflict, Unauthorized, Forbidden, Internal, External, Unknown).

Readme

@quilla-be-kit/errors

Transport-agnostic error primitives: QuillaError abstract base with a cross-realm-safe brand, plus concrete category classes consumers extend or throw directly.

Zero runtime dependencies.

Install

pnpm add @quilla-be-kit/errors

Categories

import {
  QuillaError,      // abstract base — brand carrier + toJSON
  ValidationError,  // VALIDATION   — bad input
  NotFoundError,    // NOT_FOUND    — resource missing
  ConflictError,    // CONFLICT     — duplicate, optimistic lock, state clash
  UnauthorizedError,// UNAUTHORIZED — no / bad credentials
  ForbiddenError,   // FORBIDDEN    — authorized but not allowed
  InternalError,    // INTERNAL     — known internal failure
  ExternalError,    // EXTERNAL     — downstream service failed
  UnknownError,     // UNKNOWN      — unrecognized thrown value (extends InternalError)
} from '@quilla-be-kit/errors';

Usage

Throw a category class directly, or extend it for a specific leaf:

// Ad-hoc:
throw new NotFoundError({ message: 'User not found', context: { id } });

// Domain-specific leaf — code is immutable per class:
class CrossScopeAccessError extends NotFoundError {
  override readonly code = 'CROSS_SCOPE_ACCESS';
  constructor(opts: { entity: string; id: string; scopeId: string }) {
    super({
      message: `${opts.entity} with id ${opts.id} not found in scope`,
      context: opts,
    });
  }
}

Why code is immutable

Each concrete class assigns a readonly code at class level and subclasses override it. The category+code pair is what the classification pattern below keys on — runtime mutation would break instanceof guarantees and the serialized toJSON() shape. Always use override readonly code = '...' for domain-specific leaves.

Chaining causes (ES2022)

Use the native cause property to preserve the underlying failure when wrapping low-level errors into a domain category:

try {
  await dependency.call();
} catch (err) {
  throw new ExternalError({
    message: 'Payment provider unreachable',
    context: { providerId },
    cause: err,  // serialized into toJSON().cause as a string
  });
}

cause flows through to toJSON() for structured logs. Log aggregators see the wrapped category (with the user-safe message) and the underlying cause string in one record.

Classification

Use QuillaError.is(e) as the cross-realm-safe boundary check, then instanceof for category matching:

function toHttpStatus(e: unknown): number {
  if (!QuillaError.is(e)) return 500;
  if (e instanceof ValidationError)   return 400;
  if (e instanceof UnauthorizedError) return 401;
  if (e instanceof ForbiddenError)    return 403;
  if (e instanceof NotFoundError)     return 404;
  if (e instanceof ConflictError)     return 409;
  if (e instanceof ExternalError)     return 502;
  return 500;
}
  • QuillaError.is() uses Symbol.for('quilla-be-kit.error') — works across module-system realms (e.g. duplicate package copies).
  • instanceof works within a single realm and is inheritance-aware (CrossScopeAccessError matches instanceof NotFoundError).
  • To keep instanceof reliable, downstream packages should declare @quilla-be-kit/errors as a peerDependency.

Serialization

err.toJSON();
// { name: 'NotFoundError', code: 'NOT_FOUND', message: '…', context?: {…}, cause?: … }

Safe for structured logging. message is the public, end-user-safe string; internal debug detail goes in context.

Logger integration

QuillaErrorSerializer bridges @quilla-be-kit/errors into @quilla-be-kit/observability's LogErrorSerializer contract. Wire it once at the factory level and every logger.error(msg, err) call will surface code and context in the log entry:

import { createLoggerFactory } from '@quilla-be-kit/observability';
import { QuillaErrorSerializer } from '@quilla-be-kit/errors';

const factory = createLoggerFactory({
  config: { service: 'my-backend', level: 'info', mode: 'pretty' },
  errorSerializer: new QuillaErrorSerializer(),
});

const logger = factory.create('OrderService');

try {
  await placeOrder(id);
} catch (err) {
  logger.error('Order placement failed', err);
  // pretty output:
  //   ConflictError [CONFLICT]: Order already exists
  //   context: {"orderId":"ord-99"}
  //     at OrderService.place (…)
}

Non-QuillaError values (plain Error, strings, etc.) return undefined from serialize() so the logger falls back to its default serialization — nothing breaks if both error types coexist in the same process.