Yieldless
Reference

yieldless/router

Tuple-returning route handlers with HTTP error mapping.

yieldless/router turns tuple-native handlers into Hono-style JSON handlers.

Exports

  • honoHandler(handler, options)

Error classes

  • HttpError
  • BadRequestError
  • UnauthorizedError
  • ForbiddenError
  • NotFoundError
  • ConflictError
  • ValidationError

Handler shape

  • type TupleRouteHandler<Context, Data, ErrorType = Error> = (context: Context) => PromiseLike<SafeResult<Data, ErrorType>> | SafeResult<Data, ErrorType>

Example

import { honoHandler, NotFoundError } from "yieldless/router";

export const getRepository = honoHandler(async (c) => {
  const repo = await findRepository(c.req.param("id"));

  if (repo === null) {
    return [new NotFoundError("Repository not found"), null];
  }

  return [null, repo];
});

What the adapter does

InputOutput
Success tuplecontext.json(data, status)
HttpError instanceConfigured status code
Unknown errorGeneric 500
options.mapError()Normalize custom domain errors into HttpError

When this module is enough

If your framework only needs a json() method on the context, this adapter is usually enough.

Good

Return domain or HTTP errors as tuples and let the adapter serialize them.

export const getUser = honoHandler(async (c) => {
  const [error, user] = await loadUser(c.req.param("id"));
  if (error) return [error, null];

  if (user === null) {
    return [new NotFoundError("User not found"), null];
  }

  return [null, user];
});

Use mapError() when your domain errors are not already HttpError instances.

honoHandler(handler, {
  mapError: (error) =>
    error instanceof DomainValidationError
      ? new BadRequestError(error.message)
      : error,
});

Avoid

Do not throw routine route failures just to let a global error handler find them later.

if (user === null) {
  throw new Error("User not found");
}

For expected misses, return a tuple error with an explicit HTTP shape.

On this page