effect-errors
v1.3.10
Published
A POC for errors reporting in Effect
Downloads
856
Readme
effect-errors
Some sort of POC to improve the way Effect reports errors in a dev env 🤔
⚡ So how does it work?
Had to re-export runSync
and runPromise
to apply prettyPrint
function on the cause returned by a catchAll
.
So using it would look like this :
import { runPromise } from 'effect-errors';
await runPromise(
Effect.gen(function* () {
// ...
}),
);
You can also directly import the prettyPrint
function to do whatever with it if you want 🤷
import { prettyPrint } from 'effect-errors';
await Effect.runPromise(
pipe(
Effect.gen(function* () {
// ...
}),
Effect.sandbox,
Effect.catchAll((e) => {
console.error(prettyPrint(e));
return Effect.fail('❌ runPromise failure') as never;
}),
),
);
Signature is the following:
const prettyPrint: <E>(cause: Cause<E>, options?: PrettyPrintOptions) => string;
PrettyPrintOptions
allows you to tweak the following:
enabled
- Whether pretty printing is enabled or not
default:
true
stripCwd
- Whether spans and stacktrace should contain absolute or relative paths
default:
false
(absolute paths)
reverseSpans
- Whether spans order should reversed (entry point first instead of inner callee first)
default:
true
(entry point first)
⚡ How should I raise errors?
The best way is to use either SchemaError
or TaggedError
.
🔶 SchemaError
Declaring the error could look like this:
import * as Schema from '@effect/schema/Schema';
export class FileNotFoundError extends Schema.TaggedError<SchemaError>()(
'FileNotFound',
{
cause: Schema.optional(Schema.unknown),
},
) {}
You would then raise a FileNotFoundError
to the error channel like this:
Effect.tryPromise({
try: () => ...,
catch: (e) => new FileNotFoundError({ cause: e }),
});
// or raising directly
Effect.fail(new FileNotFoundError({ cause: "Oh no!" }));
🔶 TaggedError
export class UserNotFoundError extends TaggedError('UserNotFound')<{
cause?: unknown;
}> {}
You would then raise a UserNotFoundError
to the error channel like this:
Effect.tryPromise({
try: () => ...,
catch: (e) => new UserNotFoundError({ cause: e }),
});
// or raising directly
Effect.fail(new UserNotFoundError({ cause: "User does not exist" }));
🔶 Plain object
Alternatively, you can use a plain object with a _tag
and message
attribute, but you won't get any stacktrace if you use this method:
Effect.fail({ _tag: 'SucksToBeMe', message: 'Yeah...' });
⚡ Capturing errors data
You might want to apply your own logic to reported errors data; for example if you want to display errors in html. You can do so using captureErrors
. The function has the following signature:
export interface ErrorSpan {
name: string;
attributes: ReadonlyMap<string, unknown>;
status: SpanStatus;
}
export interface ErrorData {
errorType: unknown;
message: unknown;
stack?: string;
spans?: ErrorSpan[];
isPlainString: boolean;
}
export interface CapturedErrors {
interrupted: boolean;
errors: ErrorData[];
}
export interface CaptureErrorsOptions {
reverseSpans?: boolean;
stripCwd?: boolean;
}
type captureErrorsFunction: <E>(cause: Cause<E>, options: CaptureErrorsOptions) => CapturedErrors
You can use captureErrors
like so:
import { captureErrors } from 'effect-errors';
await Effect.runPromise(
pipe(
effect,
Effect.catchAll((e) => {
const data = captureErrors(e);
// ...
}),
),
);
⚡ examples
🔶 error logging - runPromise
/ runSync
I wrote some examples for fun and giggles. You can run them using:
bun run-examples
🔶 Custom display for errors - captureErrors
You can check this example using remix error boundaries.