@omi-io/errors-core
v1.0.1
Published
Error handling utilities for general-purpose software development.
Downloads
42
Maintainers
Readme
@omi-io/errors-core
Typed, JSON-serializable error hierarchy for general-purpose software development. Provides an abstract base class with safe serialization, ready-made domain errors (HTTP, env, data, auth, notification, service worker, third-party), and small utilities for working with unknown values caught in try/catch.
Features
- Abstract
ManagerErrorbase with a clean prototype chain (survives transpilation), V8 stack-trace cleanup, and a JSON-safetoJSON()that handles cycles,BigInt,Symboland nested errors. - Static
ManagerError.is(value, Ctor?)type guard. - Ready-made domain errors with rich metadata (
statusCode,code,property,variable,requiredPermission,timeoutMs, …). AggregateManagerErrorfor collecting multiple errors (Promise.allSettledpatterns).- Utilities for catch blocks:
isManagerError,getErrorMessage,toError,wrapError,serializeError. - Tree-shakable subpath exports (
@omi-io/errors-core/utils,/http,/auth, …).
Install
yarn add @omi-io/errors-coreUsage
Import from the root entry:
import {
ManagerError,
ValidationError,
AggregateManagerError,
TimeoutError,
OperationCancelledError,
isManagerError,
wrapError,
serializeError,
} from "@omi-io/errors-core";Or import from focused subpaths for better tree-shaking:
import { FetchError, HttpManagerError, NetworkError } from "@omi-io/errors-core/http";
import { PropertyRequiredError, FormatError } from "@omi-io/errors-core/data";
import { EnvNotFoundVariableError } from "@omi-io/errors-core/env";
import { UnauthorizedError, ForbiddenError } from "@omi-io/errors-core/auth";
import { TimeoutError } from "@omi-io/errors-core/timeout";
import { OperationCancelledError } from "@omi-io/errors-core/cancellation";
import { AggregateManagerError } from "@omi-io/errors-core/aggregate";
import { isManagerError, getErrorMessage } from "@omi-io/errors-core/utils";
import { FirebaseSubscribeError } from "@omi-io/errors-core/3dpart";API
Root
ManagerError(abstract) — base class for every error in the package.new ManagerError(message, cause?)— constructor (call from a subclass).error.name— set automatically from the constructor name.error.cause— the underlying value passed to the constructor.error.toString()→"Name: message".error.toJSON()→{ name, message, stack, cause }withcauserecursively serialized (cycles become"[Circular]",BigIntbecomes"42n", etc.).ManagerError.is(value, Ctor?)— static type guard.
ValidationError— generic validation failure.ISerializedManagerError— type of the object returned bytoJSON().
aggregate
AggregateManagerError(message, errors, cause?)— collects multiple underlying errors.errorsis exposed as a frozenReadonlyArray<unknown>and serialized recursively intoJSON().
auth
AuthManagerError(abstract) — base for authentication / authorization errors.UnauthorizedError(message?, cause?)— missing or invalid credentials (HTTP 401-style).ForbiddenError(message?, requiredPermission?, cause?)— insufficient permissions (HTTP 403-style). ExposesrequiredPermission.
cancellation
OperationCancelledError(message?, reason?, cause?)— operation cancelled (e.g. viaAbortSignal). Exposesreason.
data
FormatError(message, cause?)— value does not match the expected format.PropertyRequiredError(property, cause?)— missing required property; exposespropertyand serializes it intoJSON().
env
EnvManagerError(abstract) — base for environment-related errors.EnvNotFoundVariableError(message, variable, cause?)— required environment variable is not defined; exposesvariable.
http
HttpManagerError(abstract) — base for HTTP errors withstatusCodeandresponse.FetchError(message, statusCode, response, cause?)— request failed with a response.NetworkError(message, { url?, method? }?, cause?)— transport-level failure before any response is received (DNS / TLS /ECONNREFUSED/ aborted by network); has nostatusCode.
notification
NotificationManagerError(abstract) — base for push-notification errors.PushNotificationUnsubscribeError(message, cause?)— failed to unsubscribe from push notifications.
server
ServerRunError(message, cause?)— failure during server runtime.
text
InvalidTextError(message, cause?)— text content does not satisfy expectations.
timeout
TimeoutError(message, timeoutMs?, cause?)— operation exceeded its deadline; exposestimeoutMs.
url
URLDomainError(message, cause?)— invalid or unsupported URL domain.
utils
isManagerError(value, Ctor?)— type guard that narrows toManagerError(or a specific subclass).getErrorMessage(value, fallback?)— best-effort extraction of a human-readable message from any thrown value.toError(value)— coerces an unknown value into anError, preserving the original ascausefor non-Errorvalues.wrapError(value, ErrorClass, message?)— wraps an unknown value into the givenManagerErrorsubclass; returns the value unchanged if it is already an instance ofErrorClass.serializeError(value)— universal JSON-safe serializer for any thrown value (handles cycles,BigInt,Symbol,Function, plain objects,Error,ManagerError).SerializedError/ISerializedError— types describing the result ofserializeError.
worker
ServiceWorkerManagerError(abstract) — base for service-worker errors.ServiceWorkerRegistrationNotFoundError(message, cause?)— service worker registration is missing.
3dpart
ThirdPartyManagerError(abstract) — base for third-party integration errors.ThirdPartManagerErroris a deprecated alias.FirebaseAdminManagerError(abstract) — Firebase Admin errors, exposescode.FirebaseSubscribeError(message, code, cause?)— failed to subscribe in Firebase Messaging.FirebaseUnsubscribeError(message, code, cause?)— failed to unsubscribe in Firebase Messaging.
Examples
Defining your own error
ManagerError is abstract — subclass it for any domain error you need:
import { ManagerError } from "@omi-io/errors-core";
class MyDomainError extends ManagerError {
constructor(public readonly entityId: string, cause?: unknown) {
super(`Entity not found: ${entityId}`, cause);
this.name = "MyDomainError";
}
public toJSON() {
return { ...super.toJSON(), entityId: this.entityId };
}
}Catching unknown values safely
import { getErrorMessage, isManagerError, wrapError } from "@omi-io/errors-core/utils";
import { FetchError } from "@omi-io/errors-core/http";
try {
await api.call();
} catch (e) {
if (isManagerError(e, FetchError)) {
console.warn(`HTTP ${e.statusCode}: ${e.message}`);
return;
}
throw wrapError(e, FetchError, "Unexpected API failure");
}Aggregating parallel failures
import { AggregateManagerError } from "@omi-io/errors-core/aggregate";
const results = await Promise.allSettled(tasks);
const errors = results.flatMap(r => (r.status === "rejected" ? [r.reason] : []));
if (errors.length > 0) {
throw new AggregateManagerError("Batch import failed", errors);
}Timeouts and cancellation
import { TimeoutError } from "@omi-io/errors-core/timeout";
import { OperationCancelledError } from "@omi-io/errors-core/cancellation";
const withTimeout = <T>(promise: Promise<T>, ms: number) =>
Promise.race<T>([
promise,
new Promise<T>((_, reject) =>
setTimeout(() => reject(new TimeoutError("Operation timed out", ms)), ms)
),
]);
const onAbort = (signal: AbortSignal) => {
signal.addEventListener("abort", () => {
throw new OperationCancelledError(undefined, signal.reason);
});
};JSON-safe logging
import { serializeError } from "@omi-io/errors-core/utils";
try {
await job.run();
} catch (e) {
logger.error(JSON.stringify(serializeError(e)));
throw e;
}serializeError (and ManagerError#toJSON) safely handle cyclic causes, BigInt, Symbol and Function values, so JSON.stringify will never throw on them.
