@effected/images 0.6.0 → 0.6.1
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/ImageBackendError.js +4 -6
- package/internal/causeMessage.js +39 -0
- package/package.json +1 -1
package/ImageBackendError.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
+
import { causeMessage } from "./internal/causeMessage.js";
|
|
1
2
|
import { Schema } from "effect";
|
|
2
3
|
|
|
3
4
|
// src/ImageBackendError.ts
|
|
4
|
-
const causeMessage = (cause) => {
|
|
5
|
-
let current = cause;
|
|
6
|
-
for (let depth = 0; depth < 8 && current instanceof Error && current.cause instanceof Error; depth++) current = current.cause;
|
|
7
|
-
return current instanceof Error ? current.message : String(current);
|
|
8
|
-
};
|
|
9
5
|
/**
|
|
10
6
|
* An image backend read or write failed.
|
|
11
7
|
*
|
|
@@ -33,7 +29,9 @@ var ImageBackendError = class extends Schema.TaggedError()("ImageBackendError",
|
|
|
33
29
|
cause: Schema.Defect()
|
|
34
30
|
}) {
|
|
35
31
|
get message() {
|
|
36
|
-
|
|
32
|
+
const summary = `Image backend ${this.operation} failed for key "${this.key}" (${this.reason})`;
|
|
33
|
+
const detail = causeMessage(this.cause);
|
|
34
|
+
return detail === void 0 ? summary : `${summary}: ${detail}`;
|
|
37
35
|
}
|
|
38
36
|
};
|
|
39
37
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Predicate } from "effect";
|
|
2
|
+
|
|
3
|
+
// src/internal/causeMessage.ts
|
|
4
|
+
/** How many nodes of a cause chain the walk reads before stopping, so a cyclic chain cannot spin. */
|
|
5
|
+
const CAUSE_DEPTH = 8;
|
|
6
|
+
/** The message a single node carries: a thrown string, or a non-empty string `message` property. */
|
|
7
|
+
const messageAt = (node) => {
|
|
8
|
+
const text = Predicate.isString(node) ? node : Predicate.hasProperty(node, "message") && Predicate.isString(node.message) ? node.message : void 0;
|
|
9
|
+
return text === void 0 || text.trim() === "" ? void 0 : text;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Every distinct non-empty message a preserved cause chain carries, nearest
|
|
13
|
+
* first and joined with `: `, or `undefined` when nothing along it has one.
|
|
14
|
+
*
|
|
15
|
+
* A `Schema.Defect()` field holds whatever was thrown, so the read is guarded
|
|
16
|
+
* rather than assumed: `Predicate.hasProperty` + `Predicate.isString` accepts
|
|
17
|
+
* an `Error`, a cross-realm `Error` that fails `instanceof`, a plain
|
|
18
|
+
* `{ message }` object and a thrown string alike. An empty or whitespace-only
|
|
19
|
+
* message counts as none. The walk follows `cause` links because a wrapper's
|
|
20
|
+
* text is often the generic summary and the driver's text underneath is the
|
|
21
|
+
* actionable detail, yet a wrapper that composes its own context must not
|
|
22
|
+
* lose it either; so nothing is dropped, and a deeper text the nearer one
|
|
23
|
+
* already contains is not repeated. The walk is bounded, so a cycle terminates.
|
|
24
|
+
*/
|
|
25
|
+
const causeMessage = (cause) => {
|
|
26
|
+
let message;
|
|
27
|
+
let node = cause;
|
|
28
|
+
for (let depth = 0; depth < CAUSE_DEPTH && node !== void 0 && node !== null; depth++) {
|
|
29
|
+
const text = messageAt(node);
|
|
30
|
+
if (text !== void 0) {
|
|
31
|
+
if (message === void 0 || text.includes(message)) message = text;
|
|
32
|
+
else if (!message.includes(text)) message = `${message}: ${text}`;
|
|
33
|
+
}
|
|
34
|
+
node = Predicate.hasProperty(node, "cause") ? node.cause : void 0;
|
|
35
|
+
}
|
|
36
|
+
return message;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export { causeMessage };
|