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.3.0

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)

  GoneError,              // GONE                — existed, permanently retired
  PreconditionFailedError,// PRECONDITION_FAILED — caller's precondition no longer holds
  PaymentRequiredError,   // PAYMENT_REQUIRED    — billing / quota gate
  RateLimitError,         // RATE_LIMIT          — caller is going too fast
  NotImplementedError,    // NOT_IMPLEMENTED     — recognized operation, no implementation
  UnavailableError,       // UNAVAILABLE         — dependency down or shedding load
  TimeoutError,           // TIMEOUT             — operation exceeded its deadline
} from '@quilla-be-kit/errors';

Every category is transport-neutral: each means something to a queue consumer, a CLI, or an RPC service, not only to an HTTP handler. Pick the one that describes what went wrong, then subclass it when you need a narrower code:

export class ResourceRetiredError extends GoneError {
  override readonly code: string = 'RESOURCE_RETIRED';
}

Consumers that serve HTTP get a status for free — see Classification.

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 isRetriable(e: unknown): boolean {
  if (!QuillaError.is(e)) return false;
  if (e instanceof TimeoutError)     return true;   // deadline, not a verdict
  if (e instanceof UnavailableError) return true;   // dependency may come back
  if (e instanceof RateLimitError)   return true;   // after a backoff
  if (e instanceof ExternalError)    return true;   // upstream may recover
  return false;                                     // Validation, NotFound,
                                                    // Gone, Forbidden, … are
                                                    // terminal for this caller
}

Do not hand-roll an HTTP status table from these categories. @quilla-be-kit/http already maps every category to a status in its DefaultErrorResolver, and exposes an HttpStatusAware brand for errors that need a status no category covers. Status codes live in the HTTP layer on purpose — this package stays transport-agnostic so messaging and persistence can depend on it without inheriting a transport vocabulary.

  • 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.