effect 4.0.0-beta.10 → 4.0.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Channel.d.ts +7 -7
- package/dist/Config.d.ts +157 -0
- package/dist/Config.d.ts.map +1 -1
- package/dist/Config.js +56 -1
- package/dist/Config.js.map +1 -1
- package/dist/Effect.d.ts +296 -8
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js +72 -0
- package/dist/Effect.js.map +1 -1
- package/dist/ErrorReporter.d.ts +376 -0
- package/dist/ErrorReporter.d.ts.map +1 -0
- package/dist/ErrorReporter.js +246 -0
- package/dist/ErrorReporter.js.map +1 -0
- package/dist/Fiber.d.ts +2 -2
- package/dist/Fiber.d.ts.map +1 -1
- package/dist/Fiber.js.map +1 -1
- package/dist/Graph.d.ts.map +1 -1
- package/dist/Graph.js +3 -6
- package/dist/Graph.js.map +1 -1
- package/dist/LogLevel.d.ts +5 -0
- package/dist/LogLevel.d.ts.map +1 -1
- package/dist/LogLevel.js.map +1 -1
- package/dist/Logger.d.ts +25 -91
- package/dist/Logger.d.ts.map +1 -1
- package/dist/Logger.js +2 -3
- package/dist/Logger.js.map +1 -1
- package/dist/Queue.d.ts.map +1 -1
- package/dist/Queue.js +0 -1
- package/dist/Queue.js.map +1 -1
- package/dist/Random.d.ts +17 -0
- package/dist/Random.d.ts.map +1 -1
- package/dist/Random.js +17 -0
- package/dist/Random.js.map +1 -1
- package/dist/References.d.ts +3 -3
- package/dist/References.d.ts.map +1 -1
- package/dist/Schema.d.ts +3 -1
- package/dist/Schema.d.ts.map +1 -1
- package/dist/SchemaAST.d.ts.map +1 -1
- package/dist/SchemaAST.js +2 -1
- package/dist/SchemaAST.js.map +1 -1
- package/dist/Stream.d.ts +5 -5
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/effect.js +98 -33
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/hashMap.js +2 -2
- package/dist/internal/hashMap.js.map +1 -1
- package/dist/unstable/ai/LanguageModel.d.ts.map +1 -1
- package/dist/unstable/ai/LanguageModel.js +86 -14
- package/dist/unstable/ai/LanguageModel.js.map +1 -1
- package/dist/unstable/ai/McpSchema.d.ts +112 -36
- package/dist/unstable/ai/McpSchema.d.ts.map +1 -1
- package/dist/unstable/ai/McpSchema.js +47 -10
- package/dist/unstable/ai/McpSchema.js.map +1 -1
- package/dist/unstable/ai/McpServer.d.ts.map +1 -1
- package/dist/unstable/ai/McpServer.js +33 -6
- package/dist/unstable/ai/McpServer.js.map +1 -1
- package/dist/unstable/ai/Tool.d.ts +16 -0
- package/dist/unstable/ai/Tool.d.ts.map +1 -1
- package/dist/unstable/ai/Tool.js +14 -0
- package/dist/unstable/ai/Tool.js.map +1 -1
- package/dist/unstable/cli/CliOutput.js +37 -6
- package/dist/unstable/cli/CliOutput.js.map +1 -1
- package/dist/unstable/cli/Command.d.ts +199 -7
- package/dist/unstable/cli/Command.d.ts.map +1 -1
- package/dist/unstable/cli/Command.js +116 -6
- package/dist/unstable/cli/Command.js.map +1 -1
- package/dist/unstable/cli/HelpDoc.d.ts +60 -2
- package/dist/unstable/cli/HelpDoc.d.ts.map +1 -1
- package/dist/unstable/cli/internal/command.d.ts +11 -1
- package/dist/unstable/cli/internal/command.d.ts.map +1 -1
- package/dist/unstable/cli/internal/command.js +33 -8
- package/dist/unstable/cli/internal/command.js.map +1 -1
- package/dist/unstable/cli/internal/completions/CommandDescriptor.js +7 -2
- package/dist/unstable/cli/internal/completions/CommandDescriptor.js.map +1 -1
- package/dist/unstable/cli/internal/parser.js +10 -2
- package/dist/unstable/cli/internal/parser.js.map +1 -1
- package/dist/unstable/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
- package/dist/unstable/cluster/ClusterWorkflowEngine.js +2 -2
- package/dist/unstable/cluster/ClusterWorkflowEngine.js.map +1 -1
- package/dist/unstable/http/Headers.d.ts.map +1 -1
- package/dist/unstable/http/Headers.js +27 -10
- package/dist/unstable/http/Headers.js.map +1 -1
- package/dist/unstable/http/HttpClient.d.ts +28 -4
- package/dist/unstable/http/HttpClient.d.ts.map +1 -1
- package/dist/unstable/http/HttpClient.js.map +1 -1
- package/dist/unstable/http/HttpEffect.d.ts +3 -8
- package/dist/unstable/http/HttpEffect.d.ts.map +1 -1
- package/dist/unstable/http/HttpEffect.js +25 -31
- package/dist/unstable/http/HttpEffect.js.map +1 -1
- package/dist/unstable/http/HttpMiddleware.d.ts.map +1 -1
- package/dist/unstable/http/HttpMiddleware.js +4 -8
- package/dist/unstable/http/HttpMiddleware.js.map +1 -1
- package/dist/unstable/http/HttpServerError.d.ts +14 -27
- package/dist/unstable/http/HttpServerError.d.ts.map +1 -1
- package/dist/unstable/http/HttpServerError.js +37 -44
- package/dist/unstable/http/HttpServerError.js.map +1 -1
- package/dist/unstable/http/HttpServerRespondable.d.ts +2 -2
- package/dist/unstable/http/HttpServerRespondable.d.ts.map +1 -1
- package/dist/unstable/http/HttpServerRespondable.js +5 -5
- package/dist/unstable/http/HttpServerRespondable.js.map +1 -1
- package/dist/unstable/http/HttpServerResponse.d.ts +2 -1
- package/dist/unstable/http/HttpServerResponse.d.ts.map +1 -1
- package/dist/unstable/http/HttpServerResponse.js +2 -0
- package/dist/unstable/http/HttpServerResponse.js.map +1 -1
- package/dist/unstable/http/internal/preResponseHandler.d.ts +2 -0
- package/dist/unstable/http/internal/preResponseHandler.d.ts.map +1 -0
- package/dist/unstable/http/internal/preResponseHandler.js +10 -0
- package/dist/unstable/http/internal/preResponseHandler.js.map +1 -0
- package/dist/unstable/httpapi/HttpApiBuilder.d.ts +1 -1
- package/dist/unstable/httpapi/HttpApiBuilder.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApiBuilder.js +1 -1
- package/dist/unstable/httpapi/HttpApiBuilder.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiError.d.ts +11 -0
- package/dist/unstable/httpapi/HttpApiError.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApiError.js +29 -9
- package/dist/unstable/httpapi/HttpApiError.js.map +1 -1
- package/dist/unstable/observability/OtlpLogger.d.ts.map +1 -1
- package/dist/unstable/observability/OtlpLogger.js +7 -4
- package/dist/unstable/observability/OtlpLogger.js.map +1 -1
- package/dist/unstable/reactivity/Atom.js +1 -1
- package/dist/unstable/reactivity/Atom.js.map +1 -1
- package/dist/unstable/reactivity/AtomRegistry.d.ts +6 -0
- package/dist/unstable/reactivity/AtomRegistry.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomRegistry.js +22 -1
- package/dist/unstable/reactivity/AtomRegistry.js.map +1 -1
- package/dist/unstable/rpc/RpcSchema.d.ts +13 -0
- package/dist/unstable/rpc/RpcSchema.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcSchema.js +14 -0
- package/dist/unstable/rpc/RpcSchema.js.map +1 -1
- package/dist/unstable/rpc/RpcSerialization.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcSerialization.js +34 -9
- package/dist/unstable/rpc/RpcSerialization.js.map +1 -1
- package/dist/unstable/rpc/RpcServer.d.ts +0 -7
- package/dist/unstable/rpc/RpcServer.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcServer.js +9 -10
- package/dist/unstable/rpc/RpcServer.js.map +1 -1
- package/dist/unstable/workflow/WorkflowEngine.d.ts +6 -0
- package/dist/unstable/workflow/WorkflowEngine.d.ts.map +1 -1
- package/dist/unstable/workflow/WorkflowEngine.js +131 -0
- package/dist/unstable/workflow/WorkflowEngine.js.map +1 -1
- package/package.json +1 -1
- package/src/Channel.ts +9 -9
- package/src/Config.ts +171 -9
- package/src/Effect.ts +315 -8
- package/src/ErrorReporter.ts +459 -0
- package/src/Fiber.ts +9 -2
- package/src/Graph.ts +16 -6
- package/src/LogLevel.ts +6 -0
- package/src/Logger.ts +28 -95
- package/src/Queue.ts +0 -1
- package/src/Random.ts +18 -0
- package/src/References.ts +4 -4
- package/src/Schema.ts +1 -1
- package/src/SchemaAST.ts +2 -1
- package/src/Stream.ts +7 -7
- package/src/index.ts +5 -0
- package/src/internal/effect.ts +205 -49
- package/src/internal/hashMap.ts +2 -2
- package/src/unstable/ai/LanguageModel.ts +117 -16
- package/src/unstable/ai/McpSchema.ts +57 -11
- package/src/unstable/ai/McpServer.ts +44 -6
- package/src/unstable/ai/Tool.ts +15 -0
- package/src/unstable/cli/CliOutput.ts +45 -6
- package/src/unstable/cli/Command.ts +298 -11
- package/src/unstable/cli/HelpDoc.ts +68 -2
- package/src/unstable/cli/internal/command.ts +47 -11
- package/src/unstable/cli/internal/completions/CommandDescriptor.ts +7 -2
- package/src/unstable/cli/internal/parser.ts +11 -3
- package/src/unstable/cluster/ClusterWorkflowEngine.ts +2 -2
- package/src/unstable/http/Headers.ts +28 -13
- package/src/unstable/http/HttpClient.ts +45 -10
- package/src/unstable/http/HttpEffect.ts +30 -44
- package/src/unstable/http/HttpMiddleware.ts +4 -14
- package/src/unstable/http/HttpServerError.ts +42 -45
- package/src/unstable/http/HttpServerRespondable.ts +6 -6
- package/src/unstable/http/HttpServerResponse.ts +3 -1
- package/src/unstable/http/internal/preResponseHandler.ts +15 -0
- package/src/unstable/httpapi/HttpApiBuilder.ts +2 -1
- package/src/unstable/httpapi/HttpApiError.ts +30 -9
- package/src/unstable/observability/OtlpLogger.ts +9 -5
- package/src/unstable/reactivity/Atom.ts +1 -1
- package/src/unstable/reactivity/AtomRegistry.ts +29 -1
- package/src/unstable/rpc/RpcSchema.ts +17 -0
- package/src/unstable/rpc/RpcSerialization.ts +44 -9
- package/src/unstable/rpc/RpcServer.ts +14 -19
- package/src/unstable/workflow/WorkflowEngine.ts +178 -0
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pluggable error reporting for Effect programs.
|
|
3
|
+
*
|
|
4
|
+
* Reporting is triggered by `Effect.withErrorReporting`,
|
|
5
|
+
* `ErrorReporter.report`, or built-in reporting boundaries in the HTTP and
|
|
6
|
+
* RPC server modules.
|
|
7
|
+
*
|
|
8
|
+
* Each reporter receives a structured callback with the failing `Cause`, a
|
|
9
|
+
* pretty-printed `Error`, severity, and any extra attributes attached to the
|
|
10
|
+
* original error — making it straightforward to forward failures to Sentry,
|
|
11
|
+
* Datadog, or a custom logging backend.
|
|
12
|
+
*
|
|
13
|
+
* Use the annotation symbols (`ignore`, `severity`, `attributes`) on your
|
|
14
|
+
* error classes to control reporting behavior per-error.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { Data, Effect, ErrorReporter } from "effect"
|
|
19
|
+
*
|
|
20
|
+
* // A reporter that logs to the console
|
|
21
|
+
* const consoleReporter = ErrorReporter.make(({ error, severity }) => {
|
|
22
|
+
* console.error(`[${severity}]`, error.message)
|
|
23
|
+
* })
|
|
24
|
+
*
|
|
25
|
+
* // An error that should be ignored by reporters
|
|
26
|
+
* class NotFoundError extends Data.TaggedError("NotFoundError")<{}> {
|
|
27
|
+
* readonly [ErrorReporter.ignore] = true
|
|
28
|
+
* }
|
|
29
|
+
*
|
|
30
|
+
* // An error with custom severity and attributes
|
|
31
|
+
* class RateLimitError extends Data.TaggedError("RateLimitError")<{
|
|
32
|
+
* readonly retryAfter: number
|
|
33
|
+
* }> {
|
|
34
|
+
* readonly [ErrorReporter.severity] = "Warn" as const
|
|
35
|
+
* readonly [ErrorReporter.attributes] = {
|
|
36
|
+
* retryAfter: this.retryAfter
|
|
37
|
+
* }
|
|
38
|
+
* }
|
|
39
|
+
*
|
|
40
|
+
* // Opt in to error reporting with Effect.withErrorReporting
|
|
41
|
+
* const program = Effect.gen(function*() {
|
|
42
|
+
* yield* new RateLimitError({ retryAfter: 60 })
|
|
43
|
+
* }).pipe(
|
|
44
|
+
* Effect.withErrorReporting,
|
|
45
|
+
* Effect.provide(ErrorReporter.layer([consoleReporter]))
|
|
46
|
+
* )
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @since 4.0.0
|
|
50
|
+
*/
|
|
51
|
+
import type * as Cause from "./Cause.ts"
|
|
52
|
+
import * as Effect from "./Effect.ts"
|
|
53
|
+
import type * as Fiber from "./Fiber.ts"
|
|
54
|
+
import * as effect from "./internal/effect.ts"
|
|
55
|
+
import * as Layer from "./Layer.ts"
|
|
56
|
+
import * as LogLevel from "./LogLevel.ts"
|
|
57
|
+
import type { Severity } from "./LogLevel.ts"
|
|
58
|
+
import type { ReadonlyRecord } from "./Record.ts"
|
|
59
|
+
import type * as Scope from "./Scope.ts"
|
|
60
|
+
import type * as ServiceMap from "./ServiceMap.ts"
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @since 4.0.0
|
|
64
|
+
* @category Type Identifiers
|
|
65
|
+
*/
|
|
66
|
+
export type TypeId = "~effect/ErrorReporter"
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @since 4.0.0
|
|
70
|
+
* @category Type Identifiers
|
|
71
|
+
*/
|
|
72
|
+
export const TypeId: TypeId = "~effect/ErrorReporter"
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* An `ErrorReporter` receives reported failures and forwards them to an
|
|
76
|
+
* external system (logging service, error tracker, etc.).
|
|
77
|
+
*
|
|
78
|
+
* Reporting is triggered by `Effect.withErrorReporting`,
|
|
79
|
+
* `ErrorReporter.report`, or built-in boundaries in the HTTP and RPC server
|
|
80
|
+
* modules. Use {@link make} to create a reporter — it handles deduplication
|
|
81
|
+
* and per-error annotation extraction automatically.
|
|
82
|
+
*
|
|
83
|
+
* @since 4.0.0
|
|
84
|
+
* @category Models
|
|
85
|
+
*/
|
|
86
|
+
export interface ErrorReporter {
|
|
87
|
+
readonly [TypeId]: TypeId
|
|
88
|
+
report(options: {
|
|
89
|
+
readonly cause: Cause.Cause<unknown>
|
|
90
|
+
readonly fiber: Fiber.Fiber<unknown, unknown>
|
|
91
|
+
readonly timestamp: bigint
|
|
92
|
+
}): void
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Creates an `ErrorReporter` from a callback.
|
|
97
|
+
*
|
|
98
|
+
* The returned reporter automatically deduplicates causes and individual
|
|
99
|
+
* errors (the same object is never reported twice), skips interruptions,
|
|
100
|
+
* and resolves the `ignore`, `severity`, and `attributes` annotations on
|
|
101
|
+
* each error before invoking your callback.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```ts
|
|
105
|
+
* import { ErrorReporter } from "effect"
|
|
106
|
+
*
|
|
107
|
+
* // Forward every failure to the console
|
|
108
|
+
* const consoleReporter = ErrorReporter.make(
|
|
109
|
+
* ({ error, severity, attributes }) => {
|
|
110
|
+
* console.error(`[${severity}]`, error.message, attributes)
|
|
111
|
+
* }
|
|
112
|
+
* )
|
|
113
|
+
* ```
|
|
114
|
+
*
|
|
115
|
+
* @since 4.0.0
|
|
116
|
+
* @category Constructors
|
|
117
|
+
*/
|
|
118
|
+
export const make = (
|
|
119
|
+
report: (options: {
|
|
120
|
+
readonly cause: Cause.Cause<unknown>
|
|
121
|
+
readonly error: Error
|
|
122
|
+
readonly attributes: ReadonlyRecord<string, unknown>
|
|
123
|
+
readonly severity: Severity
|
|
124
|
+
readonly fiber: Fiber.Fiber<unknown, unknown>
|
|
125
|
+
readonly timestamp: bigint
|
|
126
|
+
}) => void
|
|
127
|
+
): ErrorReporter => {
|
|
128
|
+
const reported = new WeakSet<Cause.Cause<unknown> | object>()
|
|
129
|
+
return {
|
|
130
|
+
[TypeId]: TypeId,
|
|
131
|
+
report(options) {
|
|
132
|
+
if (reported.has(options.cause)) return
|
|
133
|
+
reported.add(options.cause)
|
|
134
|
+
for (let i = 0; i < options.cause.reasons.length; i++) {
|
|
135
|
+
const reason = options.cause.reasons[i]
|
|
136
|
+
if (reason._tag === "Interrupt") continue
|
|
137
|
+
const original = reason._tag === "Fail" ? reason.error : reason.defect
|
|
138
|
+
const isObject = typeof original === "object" && original !== null
|
|
139
|
+
if (isObject) {
|
|
140
|
+
if (reported.has(original)) continue
|
|
141
|
+
reported.add(original)
|
|
142
|
+
}
|
|
143
|
+
if (isIgnored(original)) continue
|
|
144
|
+
const pretty = effect.causePrettyError(original as any, reason.annotations)
|
|
145
|
+
report({
|
|
146
|
+
...options,
|
|
147
|
+
error: pretty,
|
|
148
|
+
severity: isObject ? getSeverity(original) : "Error",
|
|
149
|
+
attributes: isObject ? getAttributes(original) : emptyAttributes
|
|
150
|
+
})
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* A `ServiceMap.Reference` holding the set of active `ErrorReporter`s for the
|
|
158
|
+
* current fiber. Defaults to an empty set (no reporting).
|
|
159
|
+
*
|
|
160
|
+
* Prefer {@link layer} to configure reporters via the `Layer` API. Use this
|
|
161
|
+
* reference directly only when you need low-level control (e.g. reading the
|
|
162
|
+
* current reporters or swapping them inside a `FiberRef`).
|
|
163
|
+
*
|
|
164
|
+
* @since 4.0.0
|
|
165
|
+
* @category References
|
|
166
|
+
*/
|
|
167
|
+
export const CurrentErrorReporters: ServiceMap.Reference<ReadonlySet<ErrorReporter>> = effect.CurrentErrorReporters
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Creates a `Layer` that registers one or more `ErrorReporter`s.
|
|
171
|
+
*
|
|
172
|
+
* Reporters can be plain `ErrorReporter` values or effectful
|
|
173
|
+
* `Effect<ErrorReporter>` values that are resolved when the layer is built.
|
|
174
|
+
*
|
|
175
|
+
* By default the provided reporters **replace** any previously registered
|
|
176
|
+
* reporters. Set `mergeWithExisting: true` to add them alongside existing
|
|
177
|
+
* ones.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```ts
|
|
181
|
+
* import { Effect, ErrorReporter } from "effect"
|
|
182
|
+
*
|
|
183
|
+
* const consoleReporter = ErrorReporter.make(({ error, severity }) => {
|
|
184
|
+
* console.error(`[${severity}]`, error.message)
|
|
185
|
+
* })
|
|
186
|
+
*
|
|
187
|
+
* const metricsReporter = ErrorReporter.make(({ severity }) => {
|
|
188
|
+
* // increment an error counter by severity
|
|
189
|
+
* })
|
|
190
|
+
*
|
|
191
|
+
* // Replace all existing reporters
|
|
192
|
+
* const ReporterLive = ErrorReporter.layer([
|
|
193
|
+
* consoleReporter,
|
|
194
|
+
* metricsReporter
|
|
195
|
+
* ])
|
|
196
|
+
*
|
|
197
|
+
* // Add to existing reporters instead of replacing
|
|
198
|
+
* const ReporterMerged = ErrorReporter.layer(
|
|
199
|
+
* [metricsReporter],
|
|
200
|
+
* { mergeWithExisting: true }
|
|
201
|
+
* )
|
|
202
|
+
*
|
|
203
|
+
* const program = Effect.gen(function*() {
|
|
204
|
+
* yield* Effect.fail("boom")
|
|
205
|
+
* }).pipe(
|
|
206
|
+
* Effect.withErrorReporting,
|
|
207
|
+
* Effect.provide(ReporterLive)
|
|
208
|
+
* )
|
|
209
|
+
* ```
|
|
210
|
+
*
|
|
211
|
+
* @since 4.0.0
|
|
212
|
+
* @category Layers
|
|
213
|
+
*/
|
|
214
|
+
export const layer = <
|
|
215
|
+
const Reporters extends ReadonlyArray<ErrorReporter | Effect.Effect<ErrorReporter, any, any>>
|
|
216
|
+
>(
|
|
217
|
+
reporters: Reporters,
|
|
218
|
+
options?: { readonly mergeWithExisting?: boolean | undefined } | undefined
|
|
219
|
+
): Layer.Layer<
|
|
220
|
+
never,
|
|
221
|
+
Reporters extends readonly [] ? never : Effect.Error<Reporters[number]>,
|
|
222
|
+
Exclude<
|
|
223
|
+
Reporters extends readonly [] ? never : Effect.Services<Reporters[number]>,
|
|
224
|
+
Scope.Scope
|
|
225
|
+
>
|
|
226
|
+
> =>
|
|
227
|
+
Layer.effect(
|
|
228
|
+
CurrentErrorReporters,
|
|
229
|
+
Effect.withFiber(Effect.fnUntraced(function*(fiber) {
|
|
230
|
+
const currentReporters = new Set(
|
|
231
|
+
options?.mergeWithExisting === true ? fiber.getRef(effect.CurrentErrorReporters) : []
|
|
232
|
+
)
|
|
233
|
+
for (const reporter of reporters) {
|
|
234
|
+
currentReporters.add(Effect.isEffect(reporter) ? yield* reporter : reporter)
|
|
235
|
+
}
|
|
236
|
+
return currentReporters
|
|
237
|
+
}))
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Manually report a `Cause` to all registered `ErrorReporter`s on the
|
|
242
|
+
* current fiber.
|
|
243
|
+
*
|
|
244
|
+
* This is useful when you want to report an error for observability without
|
|
245
|
+
* actually failing the fiber.
|
|
246
|
+
*
|
|
247
|
+
* @example
|
|
248
|
+
* ```ts
|
|
249
|
+
* import { Cause, Effect, ErrorReporter } from "effect"
|
|
250
|
+
*
|
|
251
|
+
* // Log the cause for monitoring, then continue with a fallback
|
|
252
|
+
* const program = Effect.gen(function*() {
|
|
253
|
+
* const cause = Cause.fail("something went wrong")
|
|
254
|
+
* yield* ErrorReporter.report(cause)
|
|
255
|
+
* return "fallback value"
|
|
256
|
+
* })
|
|
257
|
+
* ```
|
|
258
|
+
*
|
|
259
|
+
* @since 4.0.0
|
|
260
|
+
* @category Reporting
|
|
261
|
+
*/
|
|
262
|
+
export const report = <E>(cause: Cause.Cause<E>): Effect.Effect<void> =>
|
|
263
|
+
Effect.withFiber((fiber) => {
|
|
264
|
+
effect.reportCauseUnsafe(fiber, cause)
|
|
265
|
+
return Effect.void
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Interface that errors can implement to control reporting behavior.
|
|
270
|
+
*
|
|
271
|
+
* All three annotation properties are optional:
|
|
272
|
+
* - `[ErrorReporter.ignore]` — when `true`, the error is never reported
|
|
273
|
+
* - `[ErrorReporter.severity]` — overrides the default `"Error"` severity
|
|
274
|
+
* - `[ErrorReporter.attributes]` — extra key/value pairs forwarded to reporters
|
|
275
|
+
*
|
|
276
|
+
* The global `Error` interface is augmented with `Reportable`, so these
|
|
277
|
+
* properties are available on all `Error` instances.
|
|
278
|
+
*
|
|
279
|
+
* @since 4.0.0
|
|
280
|
+
* @category Annotations
|
|
281
|
+
*/
|
|
282
|
+
export interface Reportable {
|
|
283
|
+
readonly [ignore]?: boolean
|
|
284
|
+
readonly [severity]?: Severity
|
|
285
|
+
readonly [attributes]?: ReadonlyRecord<string, unknown>
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
declare global {
|
|
289
|
+
interface Error extends Reportable {}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Symbol key used to mark an error as unreportable.
|
|
294
|
+
*
|
|
295
|
+
* Set this property to `true` on any error class to prevent it from being
|
|
296
|
+
* forwarded to reporters. Useful for expected errors such as HTTP 404s.
|
|
297
|
+
*
|
|
298
|
+
* @example
|
|
299
|
+
* ```ts
|
|
300
|
+
* import { Data, ErrorReporter } from "effect"
|
|
301
|
+
*
|
|
302
|
+
* class NotFoundError extends Data.TaggedError("NotFoundError")<{}> {
|
|
303
|
+
* readonly [ErrorReporter.ignore] = true
|
|
304
|
+
* }
|
|
305
|
+
* ```
|
|
306
|
+
*
|
|
307
|
+
* @since 4.0.0
|
|
308
|
+
* @category Annotations
|
|
309
|
+
*/
|
|
310
|
+
export type ignore = "~effect/ErrorReporter/ignore"
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Symbol key used to mark an error as unreportable.
|
|
314
|
+
*
|
|
315
|
+
* Set this property to `true` on any error class to prevent it from being
|
|
316
|
+
* forwarded to reporters. Useful for expected errors such as HTTP 404s.
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* ```ts
|
|
320
|
+
* import { Data, ErrorReporter } from "effect"
|
|
321
|
+
*
|
|
322
|
+
* class NotFoundError extends Data.TaggedError("NotFoundError")<{}> {
|
|
323
|
+
* readonly [ErrorReporter.ignore] = true
|
|
324
|
+
* }
|
|
325
|
+
* ```
|
|
326
|
+
*
|
|
327
|
+
* @since 4.0.0
|
|
328
|
+
* @category Annotations
|
|
329
|
+
*/
|
|
330
|
+
export const ignore: ignore = "~effect/ErrorReporter/ignore"
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Returns `true` if the given value has the `ErrorReporter.ignore` annotation
|
|
334
|
+
* set to `true`.
|
|
335
|
+
*
|
|
336
|
+
* @since 4.0.0
|
|
337
|
+
* @category Annotations
|
|
338
|
+
*/
|
|
339
|
+
export const isIgnored = (u: unknown): boolean =>
|
|
340
|
+
typeof u === "object" && u !== null && ignore in u && u[ignore] === true
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Symbol key used to override the severity level of an error.
|
|
344
|
+
*
|
|
345
|
+
* When set, the reporter callback receives this value as `severity` instead
|
|
346
|
+
* of the default `"Error"`. Accepted values are the `LogLevel.Severity`
|
|
347
|
+
* literals: `"Trace"`, `"Debug"`, `"Info"`, `"Warn"`, `"Error"`, `"Fatal"`.
|
|
348
|
+
*
|
|
349
|
+
* @example
|
|
350
|
+
* ```ts
|
|
351
|
+
* import { Data, ErrorReporter } from "effect"
|
|
352
|
+
*
|
|
353
|
+
* class DeprecationWarning extends Data.TaggedError("DeprecationWarning")<{}> {
|
|
354
|
+
* readonly [ErrorReporter.severity] = "Warn" as const
|
|
355
|
+
* }
|
|
356
|
+
* ```
|
|
357
|
+
*
|
|
358
|
+
* @since 4.0.0
|
|
359
|
+
* @category Annotations
|
|
360
|
+
*/
|
|
361
|
+
export type severity = "~effect/ErrorReporter/severity"
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Symbol key used to override the severity level of an error.
|
|
365
|
+
*
|
|
366
|
+
* When set, the reporter callback receives this value as `severity` instead
|
|
367
|
+
* of the default `"Error"`. Accepted values are the `LogLevel.Severity`
|
|
368
|
+
* literals: `"Trace"`, `"Debug"`, `"Info"`, `"Warn"`, `"Error"`, `"Fatal"`.
|
|
369
|
+
*
|
|
370
|
+
* @example
|
|
371
|
+
* ```ts
|
|
372
|
+
* import { Data, ErrorReporter } from "effect"
|
|
373
|
+
*
|
|
374
|
+
* class DeprecationWarning extends Data.TaggedError("DeprecationWarning")<{}> {
|
|
375
|
+
* readonly [ErrorReporter.severity] = "Warn" as const
|
|
376
|
+
* }
|
|
377
|
+
* ```
|
|
378
|
+
*
|
|
379
|
+
* @since 4.0.0
|
|
380
|
+
* @category Annotations
|
|
381
|
+
*/
|
|
382
|
+
export const severity: severity = "~effect/ErrorReporter/severity"
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Reads the `ErrorReporter.severity` annotation from an error object,
|
|
386
|
+
* falling back to `"Error"` when unset or invalid.
|
|
387
|
+
*
|
|
388
|
+
* @since 4.0.0
|
|
389
|
+
* @category Annotations
|
|
390
|
+
*/
|
|
391
|
+
export const getSeverity = (error: object): Severity => {
|
|
392
|
+
if (severity in error && LogLevel.values.includes(error[severity] as Severity)) {
|
|
393
|
+
return error[severity] as Severity
|
|
394
|
+
}
|
|
395
|
+
return "Error"
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Symbol key used to attach extra key/value metadata to an error report.
|
|
400
|
+
*
|
|
401
|
+
* Reporters receive these attributes alongside the error, making it easy to
|
|
402
|
+
* include contextual information such as user IDs, request IDs, or any
|
|
403
|
+
* domain-specific data useful for debugging.
|
|
404
|
+
*
|
|
405
|
+
* @example
|
|
406
|
+
* ```ts
|
|
407
|
+
* import { Data, ErrorReporter } from "effect"
|
|
408
|
+
*
|
|
409
|
+
* class PaymentError extends Data.TaggedError("PaymentError")<{
|
|
410
|
+
* readonly orderId: string
|
|
411
|
+
* }> {
|
|
412
|
+
* readonly [ErrorReporter.attributes] = {
|
|
413
|
+
* orderId: this.orderId
|
|
414
|
+
* }
|
|
415
|
+
* }
|
|
416
|
+
* ```
|
|
417
|
+
*
|
|
418
|
+
* @since 4.0.0
|
|
419
|
+
* @category Annotations
|
|
420
|
+
*/
|
|
421
|
+
export type attributes = "~effect/ErrorReporter/attributes"
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Symbol key used to attach extra key/value metadata to an error report.
|
|
425
|
+
*
|
|
426
|
+
* Reporters receive these attributes alongside the error, making it easy to
|
|
427
|
+
* include contextual information such as user IDs, request IDs, or any
|
|
428
|
+
* domain-specific data useful for debugging.
|
|
429
|
+
*
|
|
430
|
+
* @example
|
|
431
|
+
* ```ts
|
|
432
|
+
* import { Data, ErrorReporter } from "effect"
|
|
433
|
+
*
|
|
434
|
+
* class PaymentError extends Data.TaggedError("PaymentError")<{
|
|
435
|
+
* readonly orderId: string
|
|
436
|
+
* }> {
|
|
437
|
+
* readonly [ErrorReporter.attributes] = {
|
|
438
|
+
* orderId: this.orderId
|
|
439
|
+
* }
|
|
440
|
+
* }
|
|
441
|
+
* ```
|
|
442
|
+
*
|
|
443
|
+
* @since 4.0.0
|
|
444
|
+
* @category Annotations
|
|
445
|
+
*/
|
|
446
|
+
export const attributes: attributes = "~effect/ErrorReporter/attributes"
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Reads the `ErrorReporter.attributes` annotation from an error object,
|
|
450
|
+
* returning an empty record when unset.
|
|
451
|
+
*
|
|
452
|
+
* @since 4.0.0
|
|
453
|
+
* @category Annotations
|
|
454
|
+
*/
|
|
455
|
+
export const getAttributes = (error: object): ReadonlyRecord<string, unknown> => {
|
|
456
|
+
return attributes in error ? error[attributes] as any : emptyAttributes
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
const emptyAttributes: ReadonlyRecord<string, unknown> = {}
|
package/src/Fiber.ts
CHANGED
|
@@ -338,7 +338,10 @@ export const interruptAs: {
|
|
|
338
338
|
* @since 2.0.0
|
|
339
339
|
* @category interruption
|
|
340
340
|
*/
|
|
341
|
-
(
|
|
341
|
+
(
|
|
342
|
+
fiberId: number | undefined,
|
|
343
|
+
annotations?: ServiceMap.ServiceMap<never> | undefined
|
|
344
|
+
): <A, E>(self: Fiber<A, E>) => Effect<void>
|
|
342
345
|
/**
|
|
343
346
|
* Interrupts a fiber with a specific fiber ID as the interruptor. This allows
|
|
344
347
|
* tracking which fiber initiated the interruption.
|
|
@@ -361,7 +364,11 @@ export const interruptAs: {
|
|
|
361
364
|
* @since 2.0.0
|
|
362
365
|
* @category interruption
|
|
363
366
|
*/
|
|
364
|
-
<A, E>(
|
|
367
|
+
<A, E>(
|
|
368
|
+
self: Fiber<A, E>,
|
|
369
|
+
fiberId: number | undefined,
|
|
370
|
+
annotations?: ServiceMap.ServiceMap<never> | undefined
|
|
371
|
+
): Effect<void>
|
|
365
372
|
} = effect.fiberInterruptAs
|
|
366
373
|
|
|
367
374
|
/**
|
package/src/Graph.ts
CHANGED
|
@@ -2529,13 +2529,23 @@ export interface MermaidOptions<N, E> {
|
|
|
2529
2529
|
* Escapes special characters in labels for Mermaid syntax compatibility.
|
|
2530
2530
|
*/
|
|
2531
2531
|
const escapeMermaidLabel = (label: string): string => {
|
|
2532
|
+
// Escape special characters for Mermaid using HTML entity codes
|
|
2533
|
+
// According to: https://mermaid.js.org/syntax/flowchart.html#special-characters-that-break-syntax
|
|
2532
2534
|
return label
|
|
2533
|
-
.replace(
|
|
2534
|
-
.replace(/"/g, "
|
|
2535
|
-
.replace(
|
|
2536
|
-
.replace(
|
|
2537
|
-
.replace(
|
|
2538
|
-
.replace(/\
|
|
2535
|
+
.replace(/#/g, "#35;")
|
|
2536
|
+
.replace(/"/g, "#quot;")
|
|
2537
|
+
.replace(/</g, "#lt;")
|
|
2538
|
+
.replace(/>/g, "#gt;")
|
|
2539
|
+
.replace(/&/g, "#amp;")
|
|
2540
|
+
.replace(/\[/g, "#91;")
|
|
2541
|
+
.replace(/\]/g, "#93;")
|
|
2542
|
+
.replace(/\{/g, "#123;")
|
|
2543
|
+
.replace(/\}/g, "#125;")
|
|
2544
|
+
.replace(/\(/g, "#40;")
|
|
2545
|
+
.replace(/\)/g, "#41;")
|
|
2546
|
+
.replace(/\|/g, "#124;")
|
|
2547
|
+
.replace(/\\/g, "#92;")
|
|
2548
|
+
.replace(/\n/g, "<br/>");
|
|
2539
2549
|
}
|
|
2540
2550
|
|
|
2541
2551
|
/**
|
package/src/LogLevel.ts
CHANGED
|
@@ -142,6 +142,12 @@ import * as References from "./References.ts"
|
|
|
142
142
|
*/
|
|
143
143
|
export type LogLevel = "All" | "Fatal" | "Error" | "Warn" | "Info" | "Debug" | "Trace" | "None"
|
|
144
144
|
|
|
145
|
+
/**
|
|
146
|
+
* @since 4.0.0
|
|
147
|
+
* @category models
|
|
148
|
+
*/
|
|
149
|
+
export type Severity = "Fatal" | "Error" | "Warn" | "Info" | "Debug" | "Trace"
|
|
150
|
+
|
|
145
151
|
/**
|
|
146
152
|
* @since 4.0.0
|
|
147
153
|
* @category models
|