Releases: rxova/ts-extended-errors
Release list
ts-extended-errors@1.0.1
ts-extended-errors@1.0.0
Major Changes
-
#37
aa60b07Thanks @jonatankruszewski! - Require Node.js 22.12 or newer. Node 20 reached end of life in April 2026, and a major release is
the one moment the floor can move without surprising anyone. The code uses no Node.js APIs, so
browsers and other runtimes are unaffected; the build now uses the workspace's Node 22 target. -
#37
1a1eef0Thanks @jonatankruszewski! - Version 1.0.0. The API that shipped through the 0.x releases is now stable:ExtendedError,
defineError, the five cause-chain helpers,serializeError,deserializeError,toError,
isErrorLike,describeValueand the exported types. From here, a breaking change to any of them,
to the serialized shape, or to the defaults oftoJSONandserializeErrormeans a new major.What 1.0 settles on purpose:
JSON.stringify(error)includesstackby default and is meant for
logs, withincludeStack: falsefor anything client-facing; a thrown value that is not an error
serializes undername: typeof value; and cause chains are linear, followingcauseand never an
AggregateError'serrors.
Minor Changes
-
#37
9b8d427Thanks @jonatankruszewski! - Accept any object type as acontexttype, aninterfaceincluded. TheContexttype parameters of
ExtendedError,defineErrorand the exported constructor types were constrained to
Readonly<Record<string, unknown>>, which aninterfacefails for lack of an index signature, so
defineError<UserContext>(…)was a type error wheneverUserContextwas declared withinterface.
The constraint is nowobject;ErrorContextstays the default. -
#37
5e77158Thanks @jonatankruszewski! - Typecodeas the literal a class declares.defineError('NotFoundError', { code: 'HTTP_NOT_FOUND' })
now typescodeas'HTTP_NOT_FOUND'on the class and on its instances, and a class defined without
one is typed with its base's, so aswitchover a taxonomy's codes can be exhaustive and a
findCausepredicate can narrow on one.ExtendedErrorConstructor,MessageErrorConstructorand
DefineErrorOptionsgain aCodetype parameter after their existing ones, andErrorCode, its
constraint, is exported.Two consequences. Naming
Contextas a type argument leavescodeatstring | undefined, because
TypeScript infers all of a call's type arguments or none; nameCodeas well,
defineError<Context, 'X'>(…), to keep the literal. And a class-syntax subclass of adefineError
class can no longer declare a different staticcode, since its instance type already carries the
base's literal; define the leaf withdefineErrorand extend that. -
#37
51303b3Thanks @jonatankruszewski! - Keep a numericcodethroughserializeErroranddeserializeError. ADOMExceptionand many
driver errors carry a number there, and it was dropped, even underincludeOwnProperties, because
codeis a fixed field read only as a string.SerializedError.codeis nowstring | number; a
code that is neither a string nor a finite number is still left out. AnExtendedError's owncode
stays a string.
Patch Changes
-
#37
8b0633fThanks @jonatankruszewski! -describeValuenames a function,'[Function: loadUser]', instead of printing its source, and
describes an object whose JSON is{}by its string tag when that says more:'[object Map]'
rather than'{}'for aMap, aSetor aRegExp.toErrorandserializeErroruse it for a
thrown value that is not an error, so those messages change the same way. -
#37
6f75bdeThanks @jonatankruszewski! - Definecodeandcontexton an instance only when there is a value. Both were own enumerable
properties on every instance, so Node'sconsole.log(error)printed
code: undefined, context: undefinedafter the stack of every error that had neither. Reading an
absent one still givesundefined;Object.keys(error)no longer lists it.
ts-extended-errors@0.4.4
Patch Changes
- #28
eda94ccThanks @jonatankruszewski! - Treat getters, proxy traps and prototype checks that throw while inspecting an unknown value as
unavailable metadata. Serialization, normalization, cause traversal, type guards and
deserialization now keep handling the original failure; a value that refuses every form of
inspection is described as'<uninspectable object>'. Exceptions from caller-provided predicates
and error constructors still propagate.
ts-extended-errors@0.4.3
Patch Changes
- #25
1472f5eThanks @jonatankruszewski! - Describe the package as a zero-dependency error model for TypeScript applications that use native
exceptions but need typed context, cause-chain inspection, and reliable JSON round trips. Clarify
how that model differs from typed return values and effect systems, and document the trust,
redaction and class-name rules at a serialization boundary. The code does not change.
ts-extended-errors@0.4.2
Patch Changes
- #23
78935d7Thanks @jonatankruszewski! - Describe the package as a zero-dependency error model for TypeScript applications that use native exceptions but need typed context, cause-chain inspection, and reliable JSON round trips. The npm description, README andllms.txtsummary change; the code does not.
ts-extended-errors@0.4.1
Patch Changes
-
#21
1b358cfThanks @jonatankruszewski! - Publish to npm asts-extended-errors, in place of@rxova/ts-extended-errorson GitHub Packages.Install with
npm install ts-extended-errors; no.npmrcscope line or GitHub token is needed. Every
earlier version, 0.1.0 to 0.4.0, is on npm under the new name with the same code. A project on the
old name changes the dependency and its imports from@rxova/ts-extended-errorsto
ts-extended-errors; nothing else about the API changes. Releases now publish from CI through npm
trusted publishing, with provenance.
@rxova/ts-extended-errors@0.4.0
Minor Changes
-
#19
1c3cd65Thanks @jonatankruszewski! - Typecontextas present on the instances of a class defined withmessage, when the throw site has
to pass one. Fixes #17.messagemakescontexta required constructor argument as soon as its type has a required field,
but the instance type stayedContext | undefined— so every read went through a?.and a??
for a branch that cannot be taken, and the workaround was a hand-written class holding the value as
its own field, which is the boilerplatemessageexists to remove.const CorruptRecordError = defineError('CorruptRecordError', { message: ({ key }: { key: string }) => `unreadable record: ${key}`, }) const found = findCauseOf(error, CorruptRecordError) found?.context.key // string — was `'context' is possibly 'undefined'`
The narrowing uses the same condition the constructor already uses to decide whether
contextis
required, so a class whose context has no required fields is unchanged: there the options argument
really is optional and an instance really can have none.The
(message, options)constructor is the one path that could otherwise build an instance without
a context, anddeserializeErrorrebuilds through it. It cannot require the argument without the
class ceasing to be anErrorClass— which is what lets it be passed inclassesand be another
class'sbase— so it now defaultscontextto{}. A payload carrying nocontexttherefore
rebuilds ascontext: {}rather thanundefined, anderror.context.keyreadsundefinedinstead
of throwing.
Patch Changes
-
#18
540e69fThanks @jonatankruszewski! - Point the tarball'sllms.txtand README at the documentation site.The package now has docs at https://rxova.org/packages/ts-extended-errors/, built from
apps/docsin
this repository. Both files ship inside the tarball, so an agent that installed the package and read
node_modules/@rxova/ts-extended-errors/llms.txthad no way to find them.llms.txtgains the site, itsllms.txtindex and itsllms-full.txt; the README's "For coding
agents" section says the same for a reader. Nothing about the API or the published files changes.
@rxova/ts-extended-errors@0.3.0
Minor Changes
- #15
a65757eThanks @jonatankruszewski! -defineErrortakes amessageoption,(context) => string, that writes the message from the
context:new InvalidDateError({ context: { value } }). The type ofcontextcomes from its
parameter or from the type parameter, and is required when it has required fields. A class defined
on one without its ownmessagewrites the message the same way. Whenmessagethrows, the error
is still created, with the class name as its message. A string first argument still sets the
message, which is howdeserializeErrorrebuilds these classes. Classes defined withoutmessage
are unchanged.
@rxova/ts-extended-errors@0.2.1
Patch Changes
- #10
97a54deThanks @jonatankruszewski! - Rewrite the repository README: what the library does with a short example, install, the workspace
layout, development commands and hooks, contributing and releases.
@rxova/ts-extended-errors@0.2.0
Minor Changes
- #8
06c11b0Thanks @jonatankruszewski! -serializeErrorwrites anAggregateError'serrors, each serialized like acause, and
deserializeErrorrebuilds them as anAggregateError. The newmaxAggregatedErrorsoption
(default 10) caps how many are kept across the whole output, anderrorsOmittedcounts the rest.
Patch Changes
- #8
50d0330Thanks @jonatankruszewski! -serializeErrorcopiescontextfield by field through a JSON round trip instead of returning the
error's own object. A later change to the error's context no longer changes a serialized copy, a
redactor editing the output no longer edits the error, and aBigIntincontextor in an own
field is written as'10n'instead of makingJSON.stringifythrow.