wellcrafted 0.35.0 → 0.36.0
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/error/index.d.ts +4 -74
- package/dist/error/index.js +3 -106
- package/dist/error-Dy9wXt5_.js +107 -0
- package/dist/error-Dy9wXt5_.js.map +1 -0
- package/dist/index-B9PnZCTt.d.ts +73 -0
- package/dist/index-B9PnZCTt.d.ts.map +1 -0
- package/dist/{index-mb9iYu0a.d.ts → index-DnoV2ZDO.d.ts} +2 -2
- package/dist/{index-mb9iYu0a.d.ts.map → index-DnoV2ZDO.d.ts.map} +1 -1
- package/dist/json.d.ts +57 -1
- package/dist/json.d.ts.map +1 -1
- package/dist/json.js +51 -0
- package/dist/json.js.map +1 -0
- package/dist/logger/index.d.ts +3 -3
- package/dist/logger/index.js +2 -2
- package/dist/query/index.d.ts +3 -3
- package/dist/query/index.js +3 -3
- package/dist/result/index.d.ts +3 -3
- package/dist/result/index.js +3 -3
- package/dist/{result-DzL3K2yA.js → result-C5cJ1_WU.js} +9 -4
- package/dist/result-C5cJ1_WU.js.map +1 -0
- package/dist/{result-corfYKOe.js → result-C9V2Knvt.js} +2 -2
- package/dist/{result-corfYKOe.js.map → result-C9V2Knvt.js.map} +1 -1
- package/dist/{result-BongGO2O.d.ts → result-DKwq9BCr.d.ts} +9 -4
- package/dist/result-DKwq9BCr.d.ts.map +1 -0
- package/dist/{tap-err-Bqs9aQpZ.d.ts → tap-err-CFhHBPfH.d.ts} +2 -2
- package/dist/{tap-err-Bqs9aQpZ.d.ts.map → tap-err-CFhHBPfH.d.ts.map} +1 -1
- package/dist/{tap-err-Bf6rQ4Cw.js → tap-err-CP-re1HT.js} +2 -2
- package/dist/{tap-err-Bf6rQ4Cw.js.map → tap-err-CP-re1HT.js.map} +1 -1
- package/dist/testing.d.ts +53 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +59 -0
- package/dist/testing.js.map +1 -0
- package/dist/{types-cY80Bw6u.d.ts → types-tXXk7K9Q.d.ts} +2 -2
- package/dist/{types-cY80Bw6u.d.ts.map → types-tXXk7K9Q.d.ts.map} +1 -1
- package/package.json +5 -1
- package/dist/error/index.d.ts.map +0 -1
- package/dist/error/index.js.map +0 -1
- package/dist/result-BongGO2O.d.ts.map +0 -1
- package/dist/result-DzL3K2yA.js.map +0 -1
package/dist/error/index.d.ts
CHANGED
|
@@ -1,74 +1,4 @@
|
|
|
1
|
-
import "../result-
|
|
2
|
-
import { AnyTaggedError, DefineErrorsReturn, ErrorBody, ErrorsConfig, InferError, InferErrors, ValidatedConfig } from "../types-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Defines a set of typed error factories using Rust-style namespaced variants.
|
|
8
|
-
*
|
|
9
|
-
* Each key is a short variant name (the namespace provides context). Every
|
|
10
|
-
* factory returns `Err<...>` directly — ready for `trySync`/`tryAsync` catch
|
|
11
|
-
* handlers. The variant name is stamped as `name` on the error object.
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```ts
|
|
15
|
-
* const HttpError = defineErrors({
|
|
16
|
-
* Connection: ({ cause }: { cause: unknown }) => ({
|
|
17
|
-
* message: `Failed to connect: ${extractErrorMessage(cause)}`,
|
|
18
|
-
* cause,
|
|
19
|
-
* }),
|
|
20
|
-
* Response: ({ status }: { status: number; bodyMessage?: string }) => ({
|
|
21
|
-
* message: `HTTP ${status}`,
|
|
22
|
-
* status,
|
|
23
|
-
* }),
|
|
24
|
-
* Parse: ({ cause }: { cause: unknown }) => ({
|
|
25
|
-
* message: `Failed to parse response body: ${extractErrorMessage(cause)}`,
|
|
26
|
-
* cause,
|
|
27
|
-
* }),
|
|
28
|
-
* });
|
|
29
|
-
*
|
|
30
|
-
* type HttpError = InferErrors<typeof HttpError>;
|
|
31
|
-
*
|
|
32
|
-
* const result = HttpError.Connection({ cause: 'timeout' }); // Err<...>
|
|
33
|
-
* ```
|
|
34
|
-
*
|
|
35
|
-
* Inspired by Rust's {@link https://docs.rs/thiserror | thiserror} crate. The
|
|
36
|
-
* mapping is nearly 1:1:
|
|
37
|
-
*
|
|
38
|
-
* - `enum HttpError` → `const HttpError = defineErrors(...)`
|
|
39
|
-
* - Variant `Connection { cause: String }` → key `Connection: ({ cause }: { cause: unknown }) => (...)`
|
|
40
|
-
* - `#[error("Failed: {cause}")]` → `` message: `Failed: ${extractErrorMessage(cause)}` ``
|
|
41
|
-
* - `HttpError::Connection { ... }` → `HttpError.Connection({ ... })`
|
|
42
|
-
* - `match error { Connection { .. } => }` → `switch (error.name) { case 'Connection': }`
|
|
43
|
-
*
|
|
44
|
-
* The equivalent Rust `thiserror` enum:
|
|
45
|
-
* ```rust
|
|
46
|
-
* #[derive(Error, Debug)]
|
|
47
|
-
* enum HttpError {
|
|
48
|
-
* #[error("Failed to connect: {cause}")]
|
|
49
|
-
* Connection { cause: String },
|
|
50
|
-
*
|
|
51
|
-
* #[error("HTTP {status}")]
|
|
52
|
-
* Response { status: u16, body_message: Option<String> },
|
|
53
|
-
*
|
|
54
|
-
* #[error("Failed to parse response body: {cause}")]
|
|
55
|
-
* Parse { cause: String },
|
|
56
|
-
* }
|
|
57
|
-
* ```
|
|
58
|
-
*/
|
|
59
|
-
declare function defineErrors<const TConfig extends ErrorsConfig>(config: TConfig & ValidatedConfig<TConfig>): DefineErrorsReturn<TConfig>;
|
|
60
|
-
//# sourceMappingURL=defineErrors.d.ts.map
|
|
61
|
-
//#endregion
|
|
62
|
-
//#region src/error/extractErrorMessage.d.ts
|
|
63
|
-
/**
|
|
64
|
-
* Extracts a readable error message from an unknown error value
|
|
65
|
-
*
|
|
66
|
-
* @param error - The unknown error to extract a message from
|
|
67
|
-
* @returns A string representation of the error
|
|
68
|
-
*/
|
|
69
|
-
declare function extractErrorMessage(error: unknown): string;
|
|
70
|
-
//# sourceMappingURL=extractErrorMessage.d.ts.map
|
|
71
|
-
|
|
72
|
-
//#endregion
|
|
73
|
-
export { AnyTaggedError, DefineErrorsReturn, ErrorBody, ErrorsConfig, InferError, InferErrors, ValidatedConfig, defineErrors, extractErrorMessage };
|
|
74
|
-
//# sourceMappingURL=index.d.ts.map
|
|
1
|
+
import "../result-DKwq9BCr.js";
|
|
2
|
+
import { AnyTaggedError, DefineErrorsReturn, ErrorBody, ErrorsConfig, InferError, InferErrors, ValidatedConfig } from "../types-tXXk7K9Q.js";
|
|
3
|
+
import { defineErrors, extractErrorMessage } from "../index-B9PnZCTt.js";
|
|
4
|
+
export { AnyTaggedError, DefineErrorsReturn, ErrorBody, ErrorsConfig, InferError, InferErrors, ValidatedConfig, defineErrors, extractErrorMessage };
|
package/dist/error/index.js
CHANGED
|
@@ -1,107 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "../result-C5cJ1_WU.js";
|
|
2
|
+
import { defineErrors, extractErrorMessage } from "../error-Dy9wXt5_.js";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Defines a set of typed error factories using Rust-style namespaced variants.
|
|
6
|
-
*
|
|
7
|
-
* Each key is a short variant name (the namespace provides context). Every
|
|
8
|
-
* factory returns `Err<...>` directly — ready for `trySync`/`tryAsync` catch
|
|
9
|
-
* handlers. The variant name is stamped as `name` on the error object.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```ts
|
|
13
|
-
* const HttpError = defineErrors({
|
|
14
|
-
* Connection: ({ cause }: { cause: unknown }) => ({
|
|
15
|
-
* message: `Failed to connect: ${extractErrorMessage(cause)}`,
|
|
16
|
-
* cause,
|
|
17
|
-
* }),
|
|
18
|
-
* Response: ({ status }: { status: number; bodyMessage?: string }) => ({
|
|
19
|
-
* message: `HTTP ${status}`,
|
|
20
|
-
* status,
|
|
21
|
-
* }),
|
|
22
|
-
* Parse: ({ cause }: { cause: unknown }) => ({
|
|
23
|
-
* message: `Failed to parse response body: ${extractErrorMessage(cause)}`,
|
|
24
|
-
* cause,
|
|
25
|
-
* }),
|
|
26
|
-
* });
|
|
27
|
-
*
|
|
28
|
-
* type HttpError = InferErrors<typeof HttpError>;
|
|
29
|
-
*
|
|
30
|
-
* const result = HttpError.Connection({ cause: 'timeout' }); // Err<...>
|
|
31
|
-
* ```
|
|
32
|
-
*
|
|
33
|
-
* Inspired by Rust's {@link https://docs.rs/thiserror | thiserror} crate. The
|
|
34
|
-
* mapping is nearly 1:1:
|
|
35
|
-
*
|
|
36
|
-
* - `enum HttpError` → `const HttpError = defineErrors(...)`
|
|
37
|
-
* - Variant `Connection { cause: String }` → key `Connection: ({ cause }: { cause: unknown }) => (...)`
|
|
38
|
-
* - `#[error("Failed: {cause}")]` → `` message: `Failed: ${extractErrorMessage(cause)}` ``
|
|
39
|
-
* - `HttpError::Connection { ... }` → `HttpError.Connection({ ... })`
|
|
40
|
-
* - `match error { Connection { .. } => }` → `switch (error.name) { case 'Connection': }`
|
|
41
|
-
*
|
|
42
|
-
* The equivalent Rust `thiserror` enum:
|
|
43
|
-
* ```rust
|
|
44
|
-
* #[derive(Error, Debug)]
|
|
45
|
-
* enum HttpError {
|
|
46
|
-
* #[error("Failed to connect: {cause}")]
|
|
47
|
-
* Connection { cause: String },
|
|
48
|
-
*
|
|
49
|
-
* #[error("HTTP {status}")]
|
|
50
|
-
* Response { status: u16, body_message: Option<String> },
|
|
51
|
-
*
|
|
52
|
-
* #[error("Failed to parse response body: {cause}")]
|
|
53
|
-
* Parse { cause: String },
|
|
54
|
-
* }
|
|
55
|
-
* ```
|
|
56
|
-
*/
|
|
57
|
-
function defineErrors(config) {
|
|
58
|
-
const result = {};
|
|
59
|
-
for (const [name, ctor] of Object.entries(config)) result[name] = (...args) => {
|
|
60
|
-
const body = ctor(...args);
|
|
61
|
-
return Err(Object.freeze({
|
|
62
|
-
...body,
|
|
63
|
-
name
|
|
64
|
-
}));
|
|
65
|
-
};
|
|
66
|
-
return result;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
//#endregion
|
|
70
|
-
//#region src/error/extractErrorMessage.ts
|
|
71
|
-
/**
|
|
72
|
-
* Extracts a readable error message from an unknown error value
|
|
73
|
-
*
|
|
74
|
-
* @param error - The unknown error to extract a message from
|
|
75
|
-
* @returns A string representation of the error
|
|
76
|
-
*/
|
|
77
|
-
function extractErrorMessage(error) {
|
|
78
|
-
if (error instanceof Error) return error.message;
|
|
79
|
-
if (typeof error === "string") return error;
|
|
80
|
-
if (typeof error === "number" || typeof error === "boolean" || typeof error === "bigint") return String(error);
|
|
81
|
-
if (typeof error === "symbol") return error.toString();
|
|
82
|
-
if (error === null) return "null";
|
|
83
|
-
if (error === void 0) return "undefined";
|
|
84
|
-
if (Array.isArray(error)) return JSON.stringify(error);
|
|
85
|
-
if (typeof error === "object") {
|
|
86
|
-
const errorObj = error;
|
|
87
|
-
const messageProps = [
|
|
88
|
-
"message",
|
|
89
|
-
"error",
|
|
90
|
-
"description",
|
|
91
|
-
"title",
|
|
92
|
-
"reason",
|
|
93
|
-
"details"
|
|
94
|
-
];
|
|
95
|
-
for (const prop of messageProps) if (prop in errorObj && typeof errorObj[prop] === "string") return errorObj[prop];
|
|
96
|
-
try {
|
|
97
|
-
return JSON.stringify(error);
|
|
98
|
-
} catch {
|
|
99
|
-
return String(error);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return String(error);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
//#endregion
|
|
106
|
-
export { defineErrors, extractErrorMessage };
|
|
107
|
-
//# sourceMappingURL=index.js.map
|
|
4
|
+
export { defineErrors, extractErrorMessage };
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { Err } from "./result-C5cJ1_WU.js";
|
|
2
|
+
|
|
3
|
+
//#region src/error/defineErrors.ts
|
|
4
|
+
/**
|
|
5
|
+
* Defines a set of typed error factories using Rust-style namespaced variants.
|
|
6
|
+
*
|
|
7
|
+
* Each key is a short variant name (the namespace provides context). Every
|
|
8
|
+
* factory returns `Err<...>` directly — ready for `trySync`/`tryAsync` catch
|
|
9
|
+
* handlers. The variant name is stamped as `name` on the error object.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const HttpError = defineErrors({
|
|
14
|
+
* Connection: ({ cause }: { cause: unknown }) => ({
|
|
15
|
+
* message: `Failed to connect: ${extractErrorMessage(cause)}`,
|
|
16
|
+
* cause,
|
|
17
|
+
* }),
|
|
18
|
+
* Response: ({ status }: { status: number; bodyMessage?: string }) => ({
|
|
19
|
+
* message: `HTTP ${status}`,
|
|
20
|
+
* status,
|
|
21
|
+
* }),
|
|
22
|
+
* Parse: ({ cause }: { cause: unknown }) => ({
|
|
23
|
+
* message: `Failed to parse response body: ${extractErrorMessage(cause)}`,
|
|
24
|
+
* cause,
|
|
25
|
+
* }),
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* type HttpError = InferErrors<typeof HttpError>;
|
|
29
|
+
*
|
|
30
|
+
* const result = HttpError.Connection({ cause: 'timeout' }); // Err<...>
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* Inspired by Rust's {@link https://docs.rs/thiserror | thiserror} crate. The
|
|
34
|
+
* mapping is nearly 1:1:
|
|
35
|
+
*
|
|
36
|
+
* - `enum HttpError` → `const HttpError = defineErrors(...)`
|
|
37
|
+
* - Variant `Connection { cause: String }` → key `Connection: ({ cause }: { cause: unknown }) => (...)`
|
|
38
|
+
* - `#[error("Failed: {cause}")]` → `` message: `Failed: ${extractErrorMessage(cause)}` ``
|
|
39
|
+
* - `HttpError::Connection { ... }` → `HttpError.Connection({ ... })`
|
|
40
|
+
* - `match error { Connection { .. } => }` → `switch (error.name) { case 'Connection': }`
|
|
41
|
+
*
|
|
42
|
+
* The equivalent Rust `thiserror` enum:
|
|
43
|
+
* ```rust
|
|
44
|
+
* #[derive(Error, Debug)]
|
|
45
|
+
* enum HttpError {
|
|
46
|
+
* #[error("Failed to connect: {cause}")]
|
|
47
|
+
* Connection { cause: String },
|
|
48
|
+
*
|
|
49
|
+
* #[error("HTTP {status}")]
|
|
50
|
+
* Response { status: u16, body_message: Option<String> },
|
|
51
|
+
*
|
|
52
|
+
* #[error("Failed to parse response body: {cause}")]
|
|
53
|
+
* Parse { cause: String },
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
function defineErrors(config) {
|
|
58
|
+
const result = {};
|
|
59
|
+
for (const [name, ctor] of Object.entries(config)) result[name] = (...args) => {
|
|
60
|
+
const body = ctor(...args);
|
|
61
|
+
return Err(Object.freeze({
|
|
62
|
+
...body,
|
|
63
|
+
name
|
|
64
|
+
}));
|
|
65
|
+
};
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region src/error/extractErrorMessage.ts
|
|
71
|
+
/**
|
|
72
|
+
* Extracts a readable error message from an unknown error value
|
|
73
|
+
*
|
|
74
|
+
* @param error - The unknown error to extract a message from
|
|
75
|
+
* @returns A string representation of the error
|
|
76
|
+
*/
|
|
77
|
+
function extractErrorMessage(error) {
|
|
78
|
+
if (error instanceof Error) return error.message;
|
|
79
|
+
if (typeof error === "string") return error;
|
|
80
|
+
if (typeof error === "number" || typeof error === "boolean" || typeof error === "bigint") return String(error);
|
|
81
|
+
if (typeof error === "symbol") return error.toString();
|
|
82
|
+
if (error === null) return "null";
|
|
83
|
+
if (error === void 0) return "undefined";
|
|
84
|
+
if (Array.isArray(error)) return JSON.stringify(error);
|
|
85
|
+
if (typeof error === "object") {
|
|
86
|
+
const errorObj = error;
|
|
87
|
+
const messageProps = [
|
|
88
|
+
"message",
|
|
89
|
+
"error",
|
|
90
|
+
"description",
|
|
91
|
+
"title",
|
|
92
|
+
"reason",
|
|
93
|
+
"details"
|
|
94
|
+
];
|
|
95
|
+
for (const prop of messageProps) if (prop in errorObj && typeof errorObj[prop] === "string") return errorObj[prop];
|
|
96
|
+
try {
|
|
97
|
+
return JSON.stringify(error);
|
|
98
|
+
} catch {
|
|
99
|
+
return String(error);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return String(error);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
//#endregion
|
|
106
|
+
export { defineErrors, extractErrorMessage };
|
|
107
|
+
//# sourceMappingURL=error-Dy9wXt5_.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-Dy9wXt5_.js","names":["config: TConfig & ValidatedConfig<TConfig>","result: Record<string, unknown>","error: unknown"],"sources":["../src/error/defineErrors.ts","../src/error/extractErrorMessage.ts"],"sourcesContent":["import { Err } from \"../result/result.js\";\nimport type {\n\tDefineErrorsReturn,\n\tErrorsConfig,\n\tValidatedConfig,\n} from \"./types.js\";\n\n/**\n * Defines a set of typed error factories using Rust-style namespaced variants.\n *\n * Each key is a short variant name (the namespace provides context). Every\n * factory returns `Err<...>` directly — ready for `trySync`/`tryAsync` catch\n * handlers. The variant name is stamped as `name` on the error object.\n *\n * @example\n * ```ts\n * const HttpError = defineErrors({\n * Connection: ({ cause }: { cause: unknown }) => ({\n * message: `Failed to connect: ${extractErrorMessage(cause)}`,\n * cause,\n * }),\n * Response: ({ status }: { status: number; bodyMessage?: string }) => ({\n * message: `HTTP ${status}`,\n * status,\n * }),\n * Parse: ({ cause }: { cause: unknown }) => ({\n * message: `Failed to parse response body: ${extractErrorMessage(cause)}`,\n * cause,\n * }),\n * });\n *\n * type HttpError = InferErrors<typeof HttpError>;\n *\n * const result = HttpError.Connection({ cause: 'timeout' }); // Err<...>\n * ```\n *\n * Inspired by Rust's {@link https://docs.rs/thiserror | thiserror} crate. The\n * mapping is nearly 1:1:\n *\n * - `enum HttpError` → `const HttpError = defineErrors(...)`\n * - Variant `Connection { cause: String }` → key `Connection: ({ cause }: { cause: unknown }) => (...)`\n * - `#[error(\"Failed: {cause}\")]` → `` message: `Failed: ${extractErrorMessage(cause)}` ``\n * - `HttpError::Connection { ... }` → `HttpError.Connection({ ... })`\n * - `match error { Connection { .. } => }` → `switch (error.name) { case 'Connection': }`\n *\n * The equivalent Rust `thiserror` enum:\n * ```rust\n * #[derive(Error, Debug)]\n * enum HttpError {\n * #[error(\"Failed to connect: {cause}\")]\n * Connection { cause: String },\n *\n * #[error(\"HTTP {status}\")]\n * Response { status: u16, body_message: Option<String> },\n *\n * #[error(\"Failed to parse response body: {cause}\")]\n * Parse { cause: String },\n * }\n * ```\n */\nexport function defineErrors<const TConfig extends ErrorsConfig>(\n\tconfig: TConfig & ValidatedConfig<TConfig>,\n): DefineErrorsReturn<TConfig> {\n\tconst result: Record<string, unknown> = {};\n\n\tfor (const [name, ctor] of Object.entries(config)) {\n\t\tresult[name] = (...args: unknown[]) => {\n\t\t\tconst body = (ctor as (...a: unknown[]) => Record<string, unknown>)(\n\t\t\t\t...args,\n\t\t\t);\n\t\t\treturn Err(Object.freeze({ ...body, name }));\n\t\t};\n\t}\n\n\treturn result as DefineErrorsReturn<TConfig>;\n}\n","/**\n * Extracts a readable error message from an unknown error value\n *\n * @param error - The unknown error to extract a message from\n * @returns A string representation of the error\n */\nexport function extractErrorMessage(error: unknown): string {\n\t// Handle Error instances\n\tif (error instanceof Error) {\n\t\treturn error.message;\n\t}\n\n\t// Handle primitives\n\tif (typeof error === \"string\") return error;\n\tif (\n\t\ttypeof error === \"number\" ||\n\t\ttypeof error === \"boolean\" ||\n\t\ttypeof error === \"bigint\"\n\t)\n\t\treturn String(error);\n\tif (typeof error === \"symbol\") return error.toString();\n\tif (error === null) return \"null\";\n\tif (error === undefined) return \"undefined\";\n\n\t// Handle arrays\n\tif (Array.isArray(error)) return JSON.stringify(error);\n\n\t// Handle plain objects\n\tif (typeof error === \"object\") {\n\t\tconst errorObj = error as Record<string, unknown>;\n\n\t\t// Check common error properties\n\t\tconst messageProps = [\n\t\t\t\"message\",\n\t\t\t\"error\",\n\t\t\t\"description\",\n\t\t\t\"title\",\n\t\t\t\"reason\",\n\t\t\t\"details\",\n\t\t] as const;\n\t\tfor (const prop of messageProps) {\n\t\t\tif (prop in errorObj && typeof errorObj[prop] === \"string\") {\n\t\t\t\treturn errorObj[prop];\n\t\t\t}\n\t\t}\n\n\t\t// Fallback to JSON stringification\n\t\ttry {\n\t\t\treturn JSON.stringify(error);\n\t\t} catch {\n\t\t\treturn String(error);\n\t\t}\n\t}\n\n\t// Final fallback\n\treturn String(error);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4DA,SAAgB,aACfA,QAC8B;CAC9B,MAAMC,SAAkC,CAAE;AAE1C,MAAK,MAAM,CAAC,MAAM,KAAK,IAAI,OAAO,QAAQ,OAAO,CAChD,QAAO,QAAQ,CAAC,GAAG,SAAoB;EACtC,MAAM,OAAO,AAAC,KACb,GAAG,KACH;AACD,SAAO,IAAI,OAAO,OAAO;GAAE,GAAG;GAAM;EAAM,EAAC,CAAC;CAC5C;AAGF,QAAO;AACP;;;;;;;;;;ACrED,SAAgB,oBAAoBC,OAAwB;AAE3D,KAAI,iBAAiB,MACpB,QAAO,MAAM;AAId,YAAW,UAAU,SAAU,QAAO;AACtC,YACQ,UAAU,mBACV,UAAU,oBACV,UAAU,SAEjB,QAAO,OAAO,MAAM;AACrB,YAAW,UAAU,SAAU,QAAO,MAAM,UAAU;AACtD,KAAI,UAAU,KAAM,QAAO;AAC3B,KAAI,iBAAqB,QAAO;AAGhC,KAAI,MAAM,QAAQ,MAAM,CAAE,QAAO,KAAK,UAAU,MAAM;AAGtD,YAAW,UAAU,UAAU;EAC9B,MAAM,WAAW;EAGjB,MAAM,eAAe;GACpB;GACA;GACA;GACA;GACA;GACA;EACA;AACD,OAAK,MAAM,QAAQ,aAClB,KAAI,QAAQ,mBAAmB,SAAS,UAAU,SACjD,QAAO,SAAS;AAKlB,MAAI;AACH,UAAO,KAAK,UAAU,MAAM;EAC5B,QAAO;AACP,UAAO,OAAO,MAAM;EACpB;CACD;AAGD,QAAO,OAAO,MAAM;AACpB"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { DefineErrorsReturn, ErrorsConfig, ValidatedConfig } from "./types-tXXk7K9Q.js";
|
|
2
|
+
|
|
3
|
+
//#region src/error/defineErrors.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Defines a set of typed error factories using Rust-style namespaced variants.
|
|
7
|
+
*
|
|
8
|
+
* Each key is a short variant name (the namespace provides context). Every
|
|
9
|
+
* factory returns `Err<...>` directly — ready for `trySync`/`tryAsync` catch
|
|
10
|
+
* handlers. The variant name is stamped as `name` on the error object.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const HttpError = defineErrors({
|
|
15
|
+
* Connection: ({ cause }: { cause: unknown }) => ({
|
|
16
|
+
* message: `Failed to connect: ${extractErrorMessage(cause)}`,
|
|
17
|
+
* cause,
|
|
18
|
+
* }),
|
|
19
|
+
* Response: ({ status }: { status: number; bodyMessage?: string }) => ({
|
|
20
|
+
* message: `HTTP ${status}`,
|
|
21
|
+
* status,
|
|
22
|
+
* }),
|
|
23
|
+
* Parse: ({ cause }: { cause: unknown }) => ({
|
|
24
|
+
* message: `Failed to parse response body: ${extractErrorMessage(cause)}`,
|
|
25
|
+
* cause,
|
|
26
|
+
* }),
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* type HttpError = InferErrors<typeof HttpError>;
|
|
30
|
+
*
|
|
31
|
+
* const result = HttpError.Connection({ cause: 'timeout' }); // Err<...>
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* Inspired by Rust's {@link https://docs.rs/thiserror | thiserror} crate. The
|
|
35
|
+
* mapping is nearly 1:1:
|
|
36
|
+
*
|
|
37
|
+
* - `enum HttpError` → `const HttpError = defineErrors(...)`
|
|
38
|
+
* - Variant `Connection { cause: String }` → key `Connection: ({ cause }: { cause: unknown }) => (...)`
|
|
39
|
+
* - `#[error("Failed: {cause}")]` → `` message: `Failed: ${extractErrorMessage(cause)}` ``
|
|
40
|
+
* - `HttpError::Connection { ... }` → `HttpError.Connection({ ... })`
|
|
41
|
+
* - `match error { Connection { .. } => }` → `switch (error.name) { case 'Connection': }`
|
|
42
|
+
*
|
|
43
|
+
* The equivalent Rust `thiserror` enum:
|
|
44
|
+
* ```rust
|
|
45
|
+
* #[derive(Error, Debug)]
|
|
46
|
+
* enum HttpError {
|
|
47
|
+
* #[error("Failed to connect: {cause}")]
|
|
48
|
+
* Connection { cause: String },
|
|
49
|
+
*
|
|
50
|
+
* #[error("HTTP {status}")]
|
|
51
|
+
* Response { status: u16, body_message: Option<String> },
|
|
52
|
+
*
|
|
53
|
+
* #[error("Failed to parse response body: {cause}")]
|
|
54
|
+
* Parse { cause: String },
|
|
55
|
+
* }
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
declare function defineErrors<const TConfig extends ErrorsConfig>(config: TConfig & ValidatedConfig<TConfig>): DefineErrorsReturn<TConfig>;
|
|
59
|
+
//# sourceMappingURL=defineErrors.d.ts.map
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/error/extractErrorMessage.d.ts
|
|
62
|
+
/**
|
|
63
|
+
* Extracts a readable error message from an unknown error value
|
|
64
|
+
*
|
|
65
|
+
* @param error - The unknown error to extract a message from
|
|
66
|
+
* @returns A string representation of the error
|
|
67
|
+
*/
|
|
68
|
+
declare function extractErrorMessage(error: unknown): string;
|
|
69
|
+
//# sourceMappingURL=extractErrorMessage.d.ts.map
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
export { defineErrors, extractErrorMessage };
|
|
73
|
+
//# sourceMappingURL=index-B9PnZCTt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-B9PnZCTt.d.ts","names":[],"sources":["../src/error/defineErrors.ts","../src/error/extractErrorMessage.ts"],"sourcesContent":[],"mappings":";;;;;;AA4DA;;;;;;;;AAEqB;;;;ACxDrB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBDsDgB,mCAAmC,sBAC1C,UAAU,gBAAgB,WAChC,mBAAmB;;;;;;;AAFtB;;;AACS,iBCvDO,mBAAA,CDuDP,KAAA,EAAA,OAAA,CAAA,EAAA,MAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Err, Ok, Result } from "./result-
|
|
1
|
+
import { Err, Ok, Result } from "./result-DKwq9BCr.js";
|
|
2
2
|
|
|
3
3
|
//#region src/result/utils.d.ts
|
|
4
4
|
|
|
@@ -25,4 +25,4 @@ declare function partitionResults<T, E>(results: Result<T, E>[]): {
|
|
|
25
25
|
//# sourceMappingURL=utils.d.ts.map
|
|
26
26
|
//#endregion
|
|
27
27
|
export { partitionResults };
|
|
28
|
-
//# sourceMappingURL=index-
|
|
28
|
+
//# sourceMappingURL=index-DnoV2ZDO.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-DnoV2ZDO.d.ts","names":[],"sources":["../src/result/utils.ts"],"sourcesContent":[],"mappings":";;;;;;AAmBA;;;;;;;;;AAK+B;;;;;iBALf,gCAAgC,OAAO,GAAG;OAK7C,GAAG;QAAY,IAAI"}
|
package/dist/json.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
+
import { Err, Result } from "./result-DKwq9BCr.js";
|
|
2
|
+
import { InferError } from "./types-tXXk7K9Q.js";
|
|
3
|
+
import "./index-B9PnZCTt.js";
|
|
4
|
+
import "./tap-err-CFhHBPfH.js";
|
|
5
|
+
import "./index-DnoV2ZDO.js";
|
|
6
|
+
|
|
1
7
|
//#region src/json.d.ts
|
|
8
|
+
|
|
2
9
|
/**
|
|
3
10
|
* JSON-serializable value types.
|
|
4
11
|
* Ensures data can be safely serialized via JSON.stringify.
|
|
@@ -19,7 +26,56 @@ type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
|
19
26
|
* A record where every value is a {@link JsonValue}.
|
|
20
27
|
*/
|
|
21
28
|
type JsonObject = Record<string, JsonValue>;
|
|
29
|
+
/**
|
|
30
|
+
* Constructs a {@link JsonParseError}. Returns `Err<JsonParseError>` directly,
|
|
31
|
+
* ready to return from a `trySync`/`tryAsync` catch handler.
|
|
32
|
+
*/
|
|
33
|
+
declare const JsonParseError: (args_0: {
|
|
34
|
+
cause: unknown;
|
|
35
|
+
}) => Err<Readonly<{
|
|
36
|
+
name: "JsonParseError";
|
|
37
|
+
} & {
|
|
38
|
+
message: string;
|
|
39
|
+
cause: unknown;
|
|
40
|
+
}>>;
|
|
41
|
+
/**
|
|
42
|
+
* The error {@link parseJson} produces when its input is not valid JSON.
|
|
43
|
+
*
|
|
44
|
+
* JSON parsing has exactly one failure mode (the engine throws a `SyntaxError`),
|
|
45
|
+
* so this is a single variant. A valid-JSON-but-wrong-shape value is not a
|
|
46
|
+
* parse failure: validate the returned {@link JsonValue} against a schema for
|
|
47
|
+
* that case.
|
|
48
|
+
*/
|
|
49
|
+
type JsonParseError = InferError<typeof JsonParseError>;
|
|
50
|
+
/**
|
|
51
|
+
* Parses a JSON string into a {@link JsonValue}, returning a `Result` instead
|
|
52
|
+
* of throwing.
|
|
53
|
+
*
|
|
54
|
+
* Unlike `JSON.parse`, which returns `any` and throws on malformed input, this:
|
|
55
|
+
* - types the success value as {@link JsonValue}, forcing you to narrow or
|
|
56
|
+
* validate before treating it as a known shape
|
|
57
|
+
* - reports failure as a tagged {@link JsonParseError} rather than an exception
|
|
58
|
+
*
|
|
59
|
+
* No reviver argument is accepted. A reviver can return arbitrary values, which
|
|
60
|
+
* would make the {@link JsonValue} success type a lie.
|
|
61
|
+
*
|
|
62
|
+
* @param text - The JSON string to parse.
|
|
63
|
+
* @returns `Ok<JsonValue>` on success, `Err<JsonParseError>` on malformed input.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* import { parseJson } from "wellcrafted/json";
|
|
68
|
+
*
|
|
69
|
+
* const { data, error } = parseJson('{"count":1}');
|
|
70
|
+
* if (error) {
|
|
71
|
+
* console.error(error.message); // "Failed to parse JSON: ..."
|
|
72
|
+
* } else {
|
|
73
|
+
* data; // JsonValue — narrow or validate before using
|
|
74
|
+
* }
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
declare function parseJson(text: string): Result<JsonValue, JsonParseError>;
|
|
22
78
|
//# sourceMappingURL=json.d.ts.map
|
|
23
79
|
//#endregion
|
|
24
|
-
export { JsonObject, JsonValue };
|
|
80
|
+
export { JsonObject, JsonParseError, JsonValue, parseJson };
|
|
25
81
|
//# sourceMappingURL=json.d.ts.map
|
package/dist/json.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json.d.ts","names":[],"sources":["../src/json.ts"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"json.d.ts","names":[],"sources":["../src/json.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;AAmBA;;;;AAM6B;AAM7B;;AAAwC,KAZ5B,SAAA,GAY4B,MAAA,GAAA,MAAA,GAAA,OAAA,GAAA,IAAA,GAPrC,SAOqC,EAAA,GAAA;EAAS,CAAA,GAAxB,EAAA,MAAA,CAAA,EANL,SAMK;AAAM,CAAA;AAU/B;;;;KAVY,UAAA,GAAa,eAAe;AAyBxC;;;;AAAuC,cAfxB,cAewB,EAAA,CAAA,MAAA,EAAA;EA6BvB,KAAA,EAAA,OAAS;CAAA,EAAA,MAAA,CAvCvB,QAuCuB,CAAA;EAAA,IAAuB,EAAA,gBAAA;CAAS,GAAA;EAAgB,OAAhC,EAAA,MAAA;EAAM,KAAA,EAAA,OAAA;;;;;;;;;;KA7BnC,cAAA,GAAiB,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6B/B,SAAA,gBAAyB,OAAO,WAAW"}
|
package/dist/json.js
CHANGED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { trySync } from "./result-C5cJ1_WU.js";
|
|
2
|
+
import { defineErrors, extractErrorMessage } from "./error-Dy9wXt5_.js";
|
|
3
|
+
import "./tap-err-CP-re1HT.js";
|
|
4
|
+
import "./result-C9V2Knvt.js";
|
|
5
|
+
|
|
6
|
+
//#region src/json.ts
|
|
7
|
+
/**
|
|
8
|
+
* Constructs a {@link JsonParseError}. Returns `Err<JsonParseError>` directly,
|
|
9
|
+
* ready to return from a `trySync`/`tryAsync` catch handler.
|
|
10
|
+
*/
|
|
11
|
+
const { JsonParseError } = defineErrors({ JsonParseError: ({ cause }) => ({
|
|
12
|
+
message: `Failed to parse JSON: ${extractErrorMessage(cause)}`,
|
|
13
|
+
cause
|
|
14
|
+
}) });
|
|
15
|
+
/**
|
|
16
|
+
* Parses a JSON string into a {@link JsonValue}, returning a `Result` instead
|
|
17
|
+
* of throwing.
|
|
18
|
+
*
|
|
19
|
+
* Unlike `JSON.parse`, which returns `any` and throws on malformed input, this:
|
|
20
|
+
* - types the success value as {@link JsonValue}, forcing you to narrow or
|
|
21
|
+
* validate before treating it as a known shape
|
|
22
|
+
* - reports failure as a tagged {@link JsonParseError} rather than an exception
|
|
23
|
+
*
|
|
24
|
+
* No reviver argument is accepted. A reviver can return arbitrary values, which
|
|
25
|
+
* would make the {@link JsonValue} success type a lie.
|
|
26
|
+
*
|
|
27
|
+
* @param text - The JSON string to parse.
|
|
28
|
+
* @returns `Ok<JsonValue>` on success, `Err<JsonParseError>` on malformed input.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* import { parseJson } from "wellcrafted/json";
|
|
33
|
+
*
|
|
34
|
+
* const { data, error } = parseJson('{"count":1}');
|
|
35
|
+
* if (error) {
|
|
36
|
+
* console.error(error.message); // "Failed to parse JSON: ..."
|
|
37
|
+
* } else {
|
|
38
|
+
* data; // JsonValue — narrow or validate before using
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
function parseJson(text) {
|
|
43
|
+
return trySync({
|
|
44
|
+
try: () => JSON.parse(text),
|
|
45
|
+
catch: (cause) => JsonParseError({ cause })
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
//#endregion
|
|
50
|
+
export { JsonParseError, parseJson };
|
|
51
|
+
//# sourceMappingURL=json.js.map
|
package/dist/json.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","names":["text: string"],"sources":["../src/json.ts"],"sourcesContent":["import {\n\tdefineErrors,\n\textractErrorMessage,\n\ttype InferError,\n} from \"./error/index.js\";\nimport { type Result, trySync } from \"./result/index.js\";\n\n/**\n * JSON-serializable value types.\n * Ensures data can be safely serialized via JSON.stringify.\n *\n * @example\n * ```typescript\n * import type { JsonValue, JsonObject } from \"wellcrafted/json\";\n *\n * const value: JsonValue = { key: [1, \"two\", true, null] };\n * const obj: JsonObject = { name: \"Alice\", age: 30 };\n * ```\n */\nexport type JsonValue =\n\t| string\n\t| number\n\t| boolean\n\t| null\n\t| JsonValue[]\n\t| { [key: string]: JsonValue };\n\n/**\n * JSON-serializable object type.\n * A record where every value is a {@link JsonValue}.\n */\nexport type JsonObject = Record<string, JsonValue>;\n\n// =============================================================================\n// Parsing\n// =============================================================================\n\n/**\n * Constructs a {@link JsonParseError}. Returns `Err<JsonParseError>` directly,\n * ready to return from a `trySync`/`tryAsync` catch handler.\n */\nexport const { JsonParseError } = defineErrors({\n\tJsonParseError: ({ cause }: { cause: unknown }) => ({\n\t\tmessage: `Failed to parse JSON: ${extractErrorMessage(cause)}`,\n\t\tcause,\n\t}),\n});\n\n/**\n * The error {@link parseJson} produces when its input is not valid JSON.\n *\n * JSON parsing has exactly one failure mode (the engine throws a `SyntaxError`),\n * so this is a single variant. A valid-JSON-but-wrong-shape value is not a\n * parse failure: validate the returned {@link JsonValue} against a schema for\n * that case.\n */\nexport type JsonParseError = InferError<typeof JsonParseError>;\n\n/**\n * Parses a JSON string into a {@link JsonValue}, returning a `Result` instead\n * of throwing.\n *\n * Unlike `JSON.parse`, which returns `any` and throws on malformed input, this:\n * - types the success value as {@link JsonValue}, forcing you to narrow or\n * validate before treating it as a known shape\n * - reports failure as a tagged {@link JsonParseError} rather than an exception\n *\n * No reviver argument is accepted. A reviver can return arbitrary values, which\n * would make the {@link JsonValue} success type a lie.\n *\n * @param text - The JSON string to parse.\n * @returns `Ok<JsonValue>` on success, `Err<JsonParseError>` on malformed input.\n *\n * @example\n * ```ts\n * import { parseJson } from \"wellcrafted/json\";\n *\n * const { data, error } = parseJson('{\"count\":1}');\n * if (error) {\n * console.error(error.message); // \"Failed to parse JSON: ...\"\n * } else {\n * data; // JsonValue — narrow or validate before using\n * }\n * ```\n */\nexport function parseJson(text: string): Result<JsonValue, JsonParseError> {\n\treturn trySync({\n\t\ttry: () => JSON.parse(text) as JsonValue,\n\t\tcatch: (cause) => JsonParseError({ cause }),\n\t});\n}\n"],"mappings":";;;;;;;;;;AAyCA,MAAa,EAAE,gBAAgB,GAAG,aAAa,EAC9C,gBAAgB,CAAC,EAAE,OAA2B,MAAM;CACnD,SAAS,CAAC,sBAAsB,EAAE,oBAAoB,MAAM,EAAE;CAC9D;AACA,GACD,EAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCF,SAAgB,UAAUA,MAAiD;AAC1E,QAAO,QAAQ;EACd,KAAK,MAAM,KAAK,MAAM,KAAK;EAC3B,OAAO,CAAC,UAAU,eAAe,EAAE,MAAO,EAAC;CAC3C,EAAC;AACF"}
|
package/dist/logger/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Err } from "../result-
|
|
2
|
-
import { AnyTaggedError } from "../types-
|
|
3
|
-
import { tapErr } from "../tap-err-
|
|
1
|
+
import { Err } from "../result-DKwq9BCr.js";
|
|
2
|
+
import { AnyTaggedError } from "../types-tXXk7K9Q.js";
|
|
3
|
+
import { tapErr } from "../tap-err-CFhHBPfH.js";
|
|
4
4
|
|
|
5
5
|
//#region src/logger/types.d.ts
|
|
6
6
|
|
package/dist/logger/index.js
CHANGED
package/dist/query/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Result } from "../result-
|
|
2
|
-
import "../tap-err-
|
|
3
|
-
import "../index-
|
|
1
|
+
import { Result } from "../result-DKwq9BCr.js";
|
|
2
|
+
import "../tap-err-CFhHBPfH.js";
|
|
3
|
+
import "../index-DnoV2ZDO.js";
|
|
4
4
|
import { DefaultError, MutationFunction, MutationKey, MutationOptions, QueryClient, QueryFunction, QueryKey, QueryObserverOptions } from "@tanstack/query-core";
|
|
5
5
|
|
|
6
6
|
//#region src/query/utils.d.ts
|
package/dist/query/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Err, Ok, resolve } from "../result-
|
|
2
|
-
import "../tap-err-
|
|
3
|
-
import "../result-
|
|
1
|
+
import { Err, Ok, resolve } from "../result-C5cJ1_WU.js";
|
|
2
|
+
import "../tap-err-CP-re1HT.js";
|
|
3
|
+
import "../result-C9V2Knvt.js";
|
|
4
4
|
|
|
5
5
|
//#region src/query/utils.ts
|
|
6
6
|
/**
|
package/dist/result/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Err, Ok, Result, UnwrapErr, UnwrapOk, isErr, isOk, isResult, resolve, tryAsync, trySync, unwrap } from "../result-
|
|
2
|
-
import { tapErr } from "../tap-err-
|
|
3
|
-
import { partitionResults } from "../index-
|
|
1
|
+
import { Err, Ok, Result, UnwrapErr, UnwrapOk, isErr, isOk, isResult, resolve, tryAsync, trySync, unwrap } from "../result-DKwq9BCr.js";
|
|
2
|
+
import { tapErr } from "../tap-err-CFhHBPfH.js";
|
|
3
|
+
import { partitionResults } from "../index-DnoV2ZDO.js";
|
|
4
4
|
export { Err, Ok, Result, UnwrapErr, UnwrapOk, isErr, isOk, isResult, partitionResults, resolve, tapErr, tryAsync, trySync, unwrap };
|
package/dist/result/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Err, Ok, isErr, isOk, isResult, resolve, tryAsync, trySync, unwrap } from "../result-
|
|
2
|
-
import { tapErr } from "../tap-err-
|
|
3
|
-
import { partitionResults } from "../result-
|
|
1
|
+
import { Err, Ok, isErr, isOk, isResult, resolve, tryAsync, trySync, unwrap } from "../result-C5cJ1_WU.js";
|
|
2
|
+
import { tapErr } from "../tap-err-CP-re1HT.js";
|
|
3
|
+
import { partitionResults } from "../result-C9V2Knvt.js";
|
|
4
4
|
|
|
5
5
|
export { Err, Ok, isErr, isOk, isResult, partitionResults, resolve, tapErr, tryAsync, trySync, unwrap };
|
|
@@ -59,9 +59,13 @@ const Err = (error) => ({
|
|
|
59
59
|
* A value is considered a valid `Result` if:
|
|
60
60
|
* 1. It is a non-null object.
|
|
61
61
|
* 2. It has both `data` and `error` properties.
|
|
62
|
-
* 3. At least one of the `data` or `error` channels is `null`. Both being `null` represents `Ok(null)`.
|
|
63
62
|
*
|
|
64
|
-
*
|
|
63
|
+
* The `error` property is the runtime discriminant:
|
|
64
|
+
* - `error === null` represents `Ok<T>`, even when `data` is also `null` (`Ok(null)`).
|
|
65
|
+
* - `error !== null` represents `Err<E>`, even if external data also includes a non-null `data` value.
|
|
66
|
+
*
|
|
67
|
+
* This function checks only the Result shape. It does not validate the
|
|
68
|
+
* success or error payload types.
|
|
65
69
|
*
|
|
66
70
|
* @template T - The expected type of the success value if the value is an `Ok` variant (defaults to `unknown`).
|
|
67
71
|
* @template E - The expected type of the error value if the value is an `Err` variant (defaults to `unknown`).
|
|
@@ -118,7 +122,8 @@ function isOk(result) {
|
|
|
118
122
|
* Type guard to runtime check if a `Result<T, E>` is an `Err<E>` variant.
|
|
119
123
|
*
|
|
120
124
|
* This function narrows the type of a `Result` to `Err<E>` if it represents a failure outcome.
|
|
121
|
-
* An `Err<E>` variant is identified by its `error` property being non-`null
|
|
125
|
+
* An `Err<E>` variant is identified by its `error` property being non-`null`.
|
|
126
|
+
* The error side is the reliable discriminator because `Ok(null)` is valid.
|
|
122
127
|
*
|
|
123
128
|
* @template T - The success value type.
|
|
124
129
|
* @template E - The error value type.
|
|
@@ -356,4 +361,4 @@ function resolve(value) {
|
|
|
356
361
|
|
|
357
362
|
//#endregion
|
|
358
363
|
export { Err, Ok, isErr, isOk, isResult, resolve, tryAsync, trySync, unwrap };
|
|
359
|
-
//# sourceMappingURL=result-
|
|
364
|
+
//# sourceMappingURL=result-C5cJ1_WU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result-C5cJ1_WU.js","names":["data: T","error: E","value: unknown","result: Result<T, E>","value: T | Result<T, E>"],"sources":["../src/result/result.ts"],"sourcesContent":["/**\n * Represents the successful outcome of an operation, encapsulating the success value.\n *\n * This is the 'Ok' variant of the `Result` type. It holds a `data` property\n * of type `T` (the success value) and an `error` property explicitly set to `null`,\n * signifying no error occurred.\n *\n * Use this type in conjunction with `Err<E>` and `Result<T, E>`.\n *\n * @template T - The type of the success value contained within.\n */\nexport type Ok<T> = { data: T; error: null };\n\n/**\n * Represents the failure outcome of an operation, encapsulating the error value.\n *\n * This is the 'Err' variant of the `Result` type. It holds an `error` property\n * of type `E` (the error value) and a `data` property explicitly set to `null`,\n * signifying that no success value is present due to the failure.\n *\n * Use this type in conjunction with `Ok<T>` and `Result<T, E>`.\n *\n * @template E - The type of the error value contained within.\n */\nexport type Err<E> = { error: E; data: null };\n\n/**\n * A type that represents the outcome of an operation that can either succeed or fail.\n *\n * `Result<T, E>` is a discriminated union type with two possible variants:\n * - `Ok<T>`: Represents a successful outcome, containing a `data` field with the success value of type `T`.\n * In this case, the `error` field is `null`.\n * - `Err<E>`: Represents a failure outcome, containing an `error` field with the error value of type `E`.\n * In this case, the `data` field is `null`.\n *\n * This type promotes explicit error handling by requiring developers to check\n * the variant of the `Result` before accessing its potential value or error.\n * It helps avoid runtime errors often associated with implicit error handling (e.g., relying on `try-catch` for all errors).\n *\n * @template T - The type of the success value if the operation is successful (held in `Ok<T>`).\n * @template E - The type of the error value if the operation fails (held in `Err<E>`).\n * @example\n * ```ts\n * function divide(numerator: number, denominator: number): Result<number, string> {\n * if (denominator === 0) {\n * return Err(\"Cannot divide by zero\");\n * }\n * return Ok(numerator / denominator);\n * }\n *\n * const result1 = divide(10, 2);\n * if (isOk(result1)) {\n * console.log(\"Success:\", result1.data); // Output: Success: 5\n * }\n *\n * const result2 = divide(10, 0);\n * if (isErr(result2)) {\n * console.error(\"Failure:\", result2.error); // Output: Failure: Cannot divide by zero\n * }\n * ```\n */\nexport type Result<T, E> = Ok<T> | Err<E>;\n\n/**\n * Constructs an `Ok<T>` variant, representing a successful outcome.\n *\n * This factory function creates the success variant of a `Result`.\n * It wraps the provided `data` (the success value) and ensures the `error` property is `null`.\n *\n * @template T - The type of the success value.\n * @param data - The success value to be wrapped in the `Ok` variant.\n * @returns An `Ok<T>` object with the provided data and `error` set to `null`.\n * @example\n * ```ts\n * const successfulResult = Ok(\"Operation completed successfully\");\n * // successfulResult is { data: \"Operation completed successfully\", error: null }\n * ```\n */\nexport const Ok = <T>(data: T): Ok<T> => ({ data, error: null });\n\n/**\n * Constructs an `Err<E>` variant, representing a failure outcome.\n *\n * Wraps the provided `error` (the failure value) and sets `data` to `null`.\n *\n * **Don't call `Err(null)`.** It produces `{ data: null, error: null }` —\n * structurally identical to `Ok(null)`. The built-in `isErr` check\n * (`result.error !== null`) reads it as Ok, silently misclassifying your\n * failure as success. `Err(undefined)` is also discouraged: the discriminator\n * technically works (`undefined !== null`), but `undefined` is falsy, so\n * downstream `if (error)` checks trip and the error carries no information\n * anyway. Pass a meaningful error value (a string, a tagged error from\n * `defineErrors`, an `Error` instance), or use `Ok(null)`/`Ok(undefined)` if\n * what you meant was success-with-no-payload.\n *\n * At `catch (error: unknown)` boundaries, wrap the caught value in a tagged\n * error rather than passing it through — `TaggedError.X({ cause: error })`\n * is always non-null by construction, so the discriminator works regardless\n * of what was thrown.\n *\n * See `docs/philosophy/err-null-is-ok-null.md` for the full rationale.\n *\n * @template E - The type of the error value.\n * @param error - The error value to wrap. Don't pass `null` or `undefined`.\n * @returns An `Err<E>` object with the provided error and `data` set to `null`.\n * @example\n * ```ts\n * const failedResult = Err(new TypeError(\"Invalid input\"));\n * // failedResult is { error: TypeError(\"Invalid input\"), data: null }\n * ```\n */\nexport const Err = <E>(error: E): Err<E> => ({ error, data: null });\n\n/**\n * Utility type to extract the success value's type `T` from a `Result<T, E>` type.\n *\n * If `R` is an `Ok<T>` variant (or a `Result<T, E>` that could be an `Ok<T>`),\n * this type resolves to `T`. If `R` can only be an `Err<E>` variant, it resolves to `never`.\n * This is useful for obtaining the type of the `data` field when you know you have a success.\n *\n * @template R - The `Result<T, E>` type from which to extract the success value's type.\n * Must extend `Result<unknown, unknown>`.\n * @example\n * ```ts\n * type MyResult = Result<number, string>;\n * type SuccessValueType = UnwrapOk<MyResult>; // SuccessValueType is number\n *\n * type MyErrorResult = Err<string>;\n * type ErrorValueType = UnwrapOk<MyErrorResult>; // ErrorValueType is never\n * ```\n */\nexport type UnwrapOk<R extends Result<unknown, unknown>> = R extends Ok<infer U>\n\t? U\n\t: never;\n\n/**\n * Utility type to extract the error value's type `E` from a `Result<T, E>` type.\n *\n * If `R` is an `Err<E>` variant (or a `Result<T, E>` that could be an `Err<E>`),\n * this type resolves to `E`. If `R` can only be an `Ok<T>` variant, it resolves to `never`.\n * This is useful for obtaining the type of the `error` field when you know you have a failure.\n *\n * @template R - The `Result<T, E>` type from which to extract the error value's type.\n * Must extend `Result<unknown, unknown>`.\n * @example\n * ```ts\n * type MyResult = Result<number, string>;\n * type ErrorValueType = UnwrapErr<MyResult>; // ErrorValueType is string\n *\n * type MySuccessResult = Ok<number>;\n * type SuccessValueType = UnwrapErr<MySuccessResult>; // SuccessValueType is never\n * ```\n */\nexport type UnwrapErr<R extends Result<unknown, unknown>> = R extends Err<\n\tinfer E\n>\n\t? E\n\t: never;\n\n/**\n * Type guard to runtime check if an unknown value is a valid `Result<T, E>`.\n *\n * A value is considered a valid `Result` if:\n * 1. It is a non-null object.\n * 2. It has both `data` and `error` properties.\n *\n * The `error` property is the runtime discriminant:\n * - `error === null` represents `Ok<T>`, even when `data` is also `null` (`Ok(null)`).\n * - `error !== null` represents `Err<E>`, even if external data also includes a non-null `data` value.\n *\n * This function checks only the Result shape. It does not validate the\n * success or error payload types.\n *\n * @template T - The expected type of the success value if the value is an `Ok` variant (defaults to `unknown`).\n * @template E - The expected type of the error value if the value is an `Err` variant (defaults to `unknown`).\n * @param value - The value to check.\n * @returns `true` if the value conforms to the `Result` structure, `false` otherwise.\n * If `true`, TypeScript's type system will narrow `value` to `Result<T, E>`.\n * @example\n * ```ts\n * declare const someValue: unknown;\n *\n * if (isResult<string, Error>(someValue)) {\n * // someValue is now typed as Result<string, Error>\n * if (isOk(someValue)) {\n * console.log(someValue.data); // string\n * } else {\n * console.error(someValue.error); // Error\n * }\n * }\n * ```\n */\nexport function isResult<T = unknown, E = unknown>(\n\tvalue: unknown,\n): value is Result<T, E> {\n\tconst isNonNullObject = typeof value === \"object\" && value !== null;\n\tif (!isNonNullObject) return false;\n\n\tconst hasDataProperty = \"data\" in value;\n\tconst hasErrorProperty = \"error\" in value;\n\tif (!hasDataProperty || !hasErrorProperty) return false;\n\n\treturn true;\n}\n\n/**\n * Type guard to runtime check if a `Result<T, E>` is an `Ok<T>` variant.\n *\n * This function narrows the type of a `Result` to `Ok<T>` if it represents a successful outcome.\n * An `Ok<T>` variant is identified by its `error` property being `null`.\n *\n * @template T - The success value type.\n * @template E - The error value type.\n * @param result - The `Result<T, E>` to check.\n * @returns `true` if the `result` is an `Ok<T>` variant, `false` otherwise.\n * If `true`, TypeScript's type system will narrow `result` to `Ok<T>`.\n * @example\n * ```ts\n * declare const myResult: Result<number, string>;\n *\n * if (isOk(myResult)) {\n * // myResult is now typed as Ok<number>\n * console.log(\"Success value:\", myResult.data); // myResult.data is number\n * }\n * ```\n */\nexport function isOk<T, E>(result: Result<T, E>): result is Ok<T> {\n\treturn result.error === null;\n}\n\n/**\n * Type guard to runtime check if a `Result<T, E>` is an `Err<E>` variant.\n *\n * This function narrows the type of a `Result` to `Err<E>` if it represents a failure outcome.\n * An `Err<E>` variant is identified by its `error` property being non-`null`.\n * The error side is the reliable discriminator because `Ok(null)` is valid.\n *\n * @template T - The success value type.\n * @template E - The error value type.\n * @param result - The `Result<T, E>` to check.\n * @returns `true` if the `result` is an `Err<E>` variant, `false` otherwise.\n * If `true`, TypeScript's type system will narrow `result` to `Err<E>`.\n * @example\n * ```ts\n * declare const myResult: Result<number, string>;\n *\n * if (isErr(myResult)) {\n * // myResult is now typed as Err<string>\n * console.error(\"Error value:\", myResult.error); // myResult.error is string\n * }\n * ```\n */\nexport function isErr<T, E>(result: Result<T, E>): result is Err<E> {\n\treturn result.error !== null;\n}\n\n/**\n * Executes a synchronous operation and wraps its outcome in a Result type.\n *\n * This function attempts to execute the `try` operation:\n * - If the `try` operation completes successfully, its return value is wrapped in an `Ok<T>` variant.\n * - If the `try` operation throws an exception, the caught exception (of type `unknown`) is passed to\n * the `catch` function, which transforms it into either an `Ok<T>` (recovery) or `Err<E>` (propagation).\n *\n * The return type is automatically determined by what your catch function returns:\n * - If catch always returns `Ok<T>`, the return type collapses to `Ok<T>` (guaranteed success)\n * - If catch always returns `Err<E>`, the return type is `Ok<T> | Err<E>` (may succeed or fail)\n * - If catch returns a union like `Err<A> | Err<B>`, the return type is `Ok<T> | Err<A> | Err<B>` (union propagation)\n * - If catch can return either `Ok<T>` or `Err<E>`, the return type is `Ok<T> | Err<E>` (conditional recovery)\n *\n * @template T - The success value type\n * @template R - The return type of the catch handler (`Ok<T>` for recovery, `Err<E>` for propagation, or a union)\n * @param options - Configuration object\n * @param options.try - The operation to execute\n * @param options.catch - Error handler that transforms caught exceptions into either `Ok<T>` (recovery) or `Err<E>` (propagation)\n * @returns `Ok<T> | R` — the union of the success path and whatever the catch handler returns\n *\n * @example\n * ```ts\n * // Returns Ok<string> - guaranteed success since catch always returns Ok\n * const alwaysOk = trySync({\n * try: () => JSON.parse(input),\n * catch: () => Ok(\"fallback\") // Always Ok<T>\n * });\n *\n * // Returns Result<object, string> - may fail since catch always returns Err\n * const mayFail = trySync({\n * try: () => JSON.parse(input),\n * catch: (err) => Err(\"Parse failed\") // Returns Err<E>\n * });\n *\n * // Returns Result<void, MyError> - conditional recovery based on error type\n * const conditional = trySync({\n * try: () => riskyOperation(),\n * catch: (err) => {\n * if (isRecoverable(err)) return Ok(undefined);\n * return MyErr({ message: \"Unrecoverable\" });\n * }\n * });\n * ```\n */\n// biome-ignore lint/suspicious/noExplicitAny: required for union type inference in catch handlers\nexport function trySync<T, R extends Ok<T> | Err<any>>({\n\ttry: operation,\n\tcatch: catchFn,\n}: {\n\ttry: () => T;\n\tcatch: (error: unknown) => R;\n}): Ok<T> | R {\n\ttry {\n\t\tconst data = operation();\n\t\treturn Ok(data);\n\t} catch (error) {\n\t\treturn catchFn(error);\n\t}\n}\n\n/**\n * Executes an asynchronous operation and wraps its outcome in a Promise<Result>.\n *\n * This function attempts to execute the `try` operation:\n * - If the `try` operation resolves successfully, its resolved value is wrapped in an `Ok<T>` variant.\n * - If the `try` operation rejects or throws an exception, the caught error (of type `unknown`) is passed to\n * the `catch` function, which transforms it into either an `Ok<T>` (recovery) or `Err<E>` (propagation).\n *\n * The return type is automatically determined by what your catch function returns:\n * - If catch always returns `Ok<T>`, the return type collapses to `Promise<Ok<T>>` (guaranteed success)\n * - If catch always returns `Err<E>`, the return type is `Promise<Ok<T> | Err<E>>` (may succeed or fail)\n * - If catch returns a union like `Err<A> | Err<B>`, the return type is `Promise<Ok<T> | Err<A> | Err<B>>` (union propagation)\n * - If catch can return either `Ok<T>` or `Err<E>`, the return type is `Promise<Ok<T> | Err<E>>` (conditional recovery)\n *\n * @template T - The success value type\n * @template R - The return type of the catch handler (`Ok<T>` for recovery, `Err<E>` for propagation, or a union)\n * @param options - Configuration object\n * @param options.try - The async operation to execute\n * @param options.catch - Error handler that transforms caught exceptions/rejections into either `Ok<T>` (recovery) or `Err<E>` (propagation)\n * @returns `Promise<Ok<T> | R>` — the union of the success path and whatever the catch handler returns\n *\n * @example\n * ```ts\n * // Returns Promise<Ok<Response>> - guaranteed success since catch always returns Ok\n * const alwaysOk = tryAsync({\n * try: async () => fetch(url),\n * catch: () => Ok(new Response()) // Always Ok<T>\n * });\n *\n * // Returns Promise<Result<Response, Error>> - may fail since catch always returns Err\n * const mayFail = tryAsync({\n * try: async () => fetch(url),\n * catch: (err) => Err(new Error(\"Fetch failed\")) // Returns Err<E>\n * });\n *\n * // Returns Promise<Result<void, BlobError>> - conditional recovery based on error type\n * const conditional = await tryAsync({\n * try: async () => {\n * await deleteFile(filename);\n * },\n * catch: (err) => {\n * if ((err as { name?: string }).name === 'NotFoundError') {\n * return Ok(undefined); // Already deleted, that's fine\n * }\n * return BlobErr({ message: \"Delete failed\" });\n * }\n * });\n * ```\n */\n// biome-ignore lint/suspicious/noExplicitAny: required for union type inference in catch handlers\nexport async function tryAsync<T, R extends Ok<T> | Err<any>>({\n\ttry: operation,\n\tcatch: catchFn,\n}: {\n\ttry: () => Promise<T>;\n\tcatch: (error: unknown) => R;\n}): Promise<Ok<T> | R> {\n\ttry {\n\t\tconst data = await operation();\n\t\treturn Ok(data);\n\t} catch (error) {\n\t\treturn catchFn(error);\n\t}\n}\n\n/**\n * Resolves a value that may or may not be wrapped in a `Result`, returning the final value.\n *\n * This function handles the common pattern where a value might be a `Result<T, E>` or a plain `T`:\n * - If `value` is an `Ok<T>` variant, returns the contained success value.\n * - If `value` is an `Err<E>` variant, throws the contained error value.\n * - If `value` is not a `Result` (i.e., it's already a plain value of type `T`),\n * returns it as-is.\n *\n * This is useful when working with APIs that might return either direct values or Results,\n * allowing you to normalize them to the actual value or propagate errors via throwing.\n *\n * Use `resolve` when the input might or might not be a Result.\n * Use `unwrap` when you know the input is definitely a Result.\n *\n * @template T - The type of the success value (if `value` is `Ok<T>`) or the type of the plain value.\n * @template E - The type of the error value (if `value` is `Err<E>`).\n * @param value - The value to resolve. Can be a `Result<T, E>` or a plain value of type `T`.\n * @returns The final value of type `T` if `value` is `Ok<T>` or if `value` is already a plain `T`.\n * @throws The error value `E` if `value` is an `Err<E>` variant.\n *\n * @example\n * ```ts\n * // Example with an Ok variant\n * const okResult = Ok(\"success data\");\n * const resolved = resolve(okResult); // \"success data\"\n *\n * // Example with an Err variant\n * const errResult = Err(new Error(\"failure\"));\n * try {\n * resolve(errResult);\n * } catch (e) {\n * console.error(e.message); // \"failure\"\n * }\n *\n * // Example with a plain value\n * const plainValue = \"plain data\";\n * const resolved = resolve(plainValue); // \"plain data\"\n *\n * // Example with a function that might return Result or plain value\n * declare function mightReturnResult(): string | Result<string, Error>;\n * const outcome = mightReturnResult();\n * try {\n * const finalValue = resolve(outcome); // handles both cases\n * console.log(\"Final value:\", finalValue);\n * } catch (e) {\n * console.error(\"Operation failed:\", e);\n * }\n * ```\n */\n/**\n * Unwraps a `Result<T, E>`, returning the success value or throwing the error.\n *\n * This function extracts the data from a `Result`:\n * - If the `Result` is an `Ok<T>` variant, returns the contained success value of type `T`.\n * - If the `Result` is an `Err<E>` variant, throws the contained error value of type `E`.\n *\n * Unlike `resolve`, this function expects the input to always be a `Result` type,\n * making it more direct for cases where you know you're working with a `Result`.\n *\n * @template T - The type of the success value contained in the `Ok<T>` variant.\n * @template E - The type of the error value contained in the `Err<E>` variant.\n * @param result - The `Result<T, E>` to unwrap.\n * @returns The success value of type `T` if the `Result` is `Ok<T>`.\n * @throws The error value of type `E` if the `Result` is `Err<E>`.\n *\n * @example\n * ```ts\n * // Example with an Ok variant\n * const okResult = Ok(\"success data\");\n * const value = unwrap(okResult); // \"success data\"\n *\n * // Example with an Err variant\n * const errResult = Err(new Error(\"something went wrong\"));\n * try {\n * unwrap(errResult);\n * } catch (error) {\n * console.error(error.message); // \"something went wrong\"\n * }\n *\n * // Usage in a function that returns Result\n * function divide(a: number, b: number): Result<number, string> {\n * if (b === 0) return Err(\"Division by zero\");\n * return Ok(a / b);\n * }\n *\n * try {\n * const result = unwrap(divide(10, 2)); // 5\n * console.log(\"Result:\", result);\n * } catch (error) {\n * console.error(\"Division failed:\", error);\n * }\n * ```\n */\nexport function unwrap<T, E>(result: Result<T, E>): T {\n\tif (isOk(result)) {\n\t\treturn result.data;\n\t}\n\tthrow result.error;\n}\n\nexport function resolve<T, E>(value: T | Result<T, E>): T {\n\tif (isResult<T, E>(value)) {\n\t\tif (isOk(value)) {\n\t\t\treturn value.data;\n\t\t}\n\t\t// If it's a Result and not Ok, it must be Err.\n\t\t// The type guard isResult<T,E>(value) and isOk(value) already refine the type.\n\t\t// So, 'value' here is known to be Err<E>.\n\t\tthrow value.error;\n\t}\n\n\t// If it's not a Result type, return the value as-is.\n\t// 'value' here is known to be of type T.\n\treturn value;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA8EA,MAAa,KAAK,CAAIA,UAAoB;CAAE;CAAM,OAAO;AAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiC/D,MAAa,MAAM,CAAIC,WAAsB;CAAE;CAAO,MAAM;AAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiFlE,SAAgB,SACfC,OACwB;CACxB,MAAM,yBAAyB,UAAU,YAAY,UAAU;AAC/D,MAAK,gBAAiB,QAAO;CAE7B,MAAM,kBAAkB,UAAU;CAClC,MAAM,mBAAmB,WAAW;AACpC,MAAK,oBAAoB,iBAAkB,QAAO;AAElD,QAAO;AACP;;;;;;;;;;;;;;;;;;;;;;AAuBD,SAAgB,KAAWC,QAAuC;AACjE,QAAO,OAAO,UAAU;AACxB;;;;;;;;;;;;;;;;;;;;;;;AAwBD,SAAgB,MAAYA,QAAwC;AACnE,QAAO,OAAO,UAAU;AACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDD,SAAgB,QAAuC,EACtD,KAAK,WACL,OAAO,SAIP,EAAa;AACb,KAAI;EACH,MAAM,OAAO,WAAW;AACxB,SAAO,GAAG,KAAK;CACf,SAAQ,OAAO;AACf,SAAO,QAAQ,MAAM;CACrB;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDD,eAAsB,SAAwC,EAC7D,KAAK,WACL,OAAO,SAIP,EAAsB;AACtB,KAAI;EACH,MAAM,OAAO,MAAM,WAAW;AAC9B,SAAO,GAAG,KAAK;CACf,SAAQ,OAAO;AACf,SAAO,QAAQ,MAAM;CACrB;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgGD,SAAgB,OAAaA,QAAyB;AACrD,KAAI,KAAK,OAAO,CACf,QAAO,OAAO;AAEf,OAAM,OAAO;AACb;AAED,SAAgB,QAAcC,OAA4B;AACzD,KAAI,SAAe,MAAM,EAAE;AAC1B,MAAI,KAAK,MAAM,CACd,QAAO,MAAM;AAKd,QAAM,MAAM;CACZ;AAID,QAAO;AACP"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isOk } from "./result-
|
|
1
|
+
import { isOk } from "./result-C5cJ1_WU.js";
|
|
2
2
|
|
|
3
3
|
//#region src/result/utils.ts
|
|
4
4
|
/**
|
|
@@ -27,4 +27,4 @@ function partitionResults(results) {
|
|
|
27
27
|
|
|
28
28
|
//#endregion
|
|
29
29
|
export { partitionResults };
|
|
30
|
-
//# sourceMappingURL=result-
|
|
30
|
+
//# sourceMappingURL=result-C9V2Knvt.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"result-
|
|
1
|
+
{"version":3,"file":"result-C9V2Knvt.js","names":["results: Result<T, E>[]"],"sources":["../src/result/utils.ts"],"sourcesContent":["import type { Err, Ok, Result } from \"./result.js\";\nimport { isOk } from \"./result.js\";\n\n/**\n * Partitions an array of Result objects into two separate arrays based on their status.\n *\n * @template T - The success type\n * @template E - The error type\n * @param results - An array of Result objects to partition\n * @returns An object containing two arrays:\n * - `oks`: Array of successful Result objects (Ok<T>[])\n * - `errs`: Array of error Result objects (Err<E>[])\n *\n * @example\n * const results = [Ok(1), Err(\"error\"), Ok(2)];\n * const { oks, errs } = partitionResults(results);\n * // oks = [Ok(1), Ok(2)]\n * // errs = [Err(\"error\")]\n */\nexport function partitionResults<T, E>(results: Result<T, E>[]) {\n\treturn {\n\t\toks: [],\n\t\terrs: [],\n\t\t...Object.groupBy(results, (result) => (isOk(result) ? \"oks\" : \"errs\")),\n\t} as { oks: Ok<T>[]; errs: Err<E>[] };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,iBAAuBA,SAAyB;AAC/D,QAAO;EACN,KAAK,CAAE;EACP,MAAM,CAAE;EACR,GAAG,OAAO,QAAQ,SAAS,CAAC,WAAY,KAAK,OAAO,GAAG,QAAQ,OAAQ;CACvE;AACD"}
|
|
@@ -157,9 +157,13 @@ type UnwrapErr<R extends Result<unknown, unknown>> = R extends Err<infer E> ? E
|
|
|
157
157
|
* A value is considered a valid `Result` if:
|
|
158
158
|
* 1. It is a non-null object.
|
|
159
159
|
* 2. It has both `data` and `error` properties.
|
|
160
|
-
* 3. At least one of the `data` or `error` channels is `null`. Both being `null` represents `Ok(null)`.
|
|
161
160
|
*
|
|
162
|
-
*
|
|
161
|
+
* The `error` property is the runtime discriminant:
|
|
162
|
+
* - `error === null` represents `Ok<T>`, even when `data` is also `null` (`Ok(null)`).
|
|
163
|
+
* - `error !== null` represents `Err<E>`, even if external data also includes a non-null `data` value.
|
|
164
|
+
*
|
|
165
|
+
* This function checks only the Result shape. It does not validate the
|
|
166
|
+
* success or error payload types.
|
|
163
167
|
*
|
|
164
168
|
* @template T - The expected type of the success value if the value is an `Ok` variant (defaults to `unknown`).
|
|
165
169
|
* @template E - The expected type of the error value if the value is an `Err` variant (defaults to `unknown`).
|
|
@@ -207,7 +211,8 @@ declare function isOk<T, E>(result: Result<T, E>): result is Ok<T>;
|
|
|
207
211
|
* Type guard to runtime check if a `Result<T, E>` is an `Err<E>` variant.
|
|
208
212
|
*
|
|
209
213
|
* This function narrows the type of a `Result` to `Err<E>` if it represents a failure outcome.
|
|
210
|
-
* An `Err<E>` variant is identified by its `error` property being non-`null
|
|
214
|
+
* An `Err<E>` variant is identified by its `error` property being non-`null`.
|
|
215
|
+
* The error side is the reliable discriminator because `Ok(null)` is valid.
|
|
211
216
|
*
|
|
212
217
|
* @template T - The success value type.
|
|
213
218
|
* @template E - The error value type.
|
|
@@ -432,4 +437,4 @@ declare function resolve<T, E>(value: T | Result<T, E>): T;
|
|
|
432
437
|
//# sourceMappingURL=result.d.ts.map
|
|
433
438
|
//#endregion
|
|
434
439
|
export { Err, Ok, Result, UnwrapErr, UnwrapOk, isErr, isOk, isResult, resolve, tryAsync, trySync, unwrap };
|
|
435
|
-
//# sourceMappingURL=result-
|
|
440
|
+
//# sourceMappingURL=result-DKwq9BCr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result-DKwq9BCr.d.ts","names":[],"sources":["../src/result/result.ts"],"sourcesContent":[],"mappings":";;AAWA;AAaA;AAqCA;;;;;;AAAsC;AAiBtC;AAAgE,KAnEpD,EAmEoD,CAAA,CAAA,CAAA,GAAA;EAAA,IAApC,EAnEA,CAmEA;EAAC,KAAM,EAAA,IAAA;CAAC;AAAF;AAiClC;;;;;AAAqC;AAoBrC;;;;AAAqE,KA3GzD,GA2GyD,CAAA,CAAA,CAAA,GAAA;EAAE,KACpE,EA5G2B,CA4G3B;EAAC,IAAA,EAAA,IAAA;AAqBJ,CAAA;;;;;;AAGI;AAoCJ;;;;;AAEkB;AAgClB;;;;;;;AAA8D;AA0B9D;;;;;;;AAAgE;AAkDhE;;;;;;;AAIY,KArPA,MAqPA,CAAA,CAAA,EAAA,CAAA,CAAA,GArPe,EAqPf,CArPkB,CAqPlB,CAAA,GArPuB,GAqPvB,CArP2B,CAqP3B,CAAA;;;;;AAEC;AA2Db;;;;;;;;;;AAMe,cAvSF,EAuSE,EAAA,CAAA,CAAA,CAAA,CAAA,IAAA,EAvSa,CAuSb,EAAA,GAvSiB,EAuSjB,CAvSoB,CAuSpB,CAAA;;;;AAAJ;AAuGX;;;;;;AAAqD;AAOrD;;;;;;;AAAyD;;;;;;;;;;;;;cApX5C,gBAAiB,MAAI,IAAI;;;;;;;;;;;;;;;;;;;KAoB1B,mBAAmB,4BAA4B,UAAU,cAClE;;;;;;;;;;;;;;;;;;;KAqBS,oBAAoB,4BAA4B,UAAU,eAGnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoCa,6DAEJ,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;iBAgCN,mBAAmB,OAAO,GAAG,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;iBA0B/C,oBAAoB,OAAO,GAAG,eAAe,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkDjD,qBAAqB,GAAG,KAAK;OACvC;SACE;;aAEI;6BACgB;IACxB,GAAG,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA2DU,sBAAsB,GAAG,KAAK;OAC9C;SACE;;aAEI,QAAQ;6BACQ;IACxB,QAAQ,GAAG,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuGJ,qBAAqB,OAAO,GAAG,KAAK;iBAOpC,qBAAqB,IAAI,OAAO,GAAG,KAAK"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Result } from "./result-
|
|
1
|
+
import { Result } from "./result-DKwq9BCr.js";
|
|
2
2
|
|
|
3
3
|
//#region src/result/tap-err.d.ts
|
|
4
4
|
|
|
@@ -30,4 +30,4 @@ declare function tapErr<T, E>(logFn: (err: E) => void): (result: Result<T, E>) =
|
|
|
30
30
|
//# sourceMappingURL=tap-err.d.ts.map
|
|
31
31
|
//#endregion
|
|
32
32
|
export { tapErr };
|
|
33
|
-
//# sourceMappingURL=tap-err-
|
|
33
|
+
//# sourceMappingURL=tap-err-CFhHBPfH.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tap-err-
|
|
1
|
+
{"version":3,"file":"tap-err-CFhHBPfH.d.ts","names":[],"sources":["../src/result/tap-err.ts"],"sourcesContent":[],"mappings":";;;;;;AA2BA;;;;;;;;;AAEmC;;;;;;;;;;;;;iBAFnB,0BACF,sBACF,OAAO,GAAG,OAAO,OAAO,GAAG"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isErr } from "./result-
|
|
1
|
+
import { isErr } from "./result-C5cJ1_WU.js";
|
|
2
2
|
|
|
3
3
|
//#region src/result/tap-err.ts
|
|
4
4
|
/**
|
|
@@ -34,4 +34,4 @@ function tapErr(logFn) {
|
|
|
34
34
|
|
|
35
35
|
//#endregion
|
|
36
36
|
export { tapErr };
|
|
37
|
-
//# sourceMappingURL=tap-err-
|
|
37
|
+
//# sourceMappingURL=tap-err-CP-re1HT.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tap-err-
|
|
1
|
+
{"version":3,"file":"tap-err-CP-re1HT.js","names":["logFn: (err: E) => void"],"sources":["../src/result/tap-err.ts"],"sourcesContent":["import { isErr } from \"./result.js\";\nimport type { Result } from \"./result.js\";\n\n/**\n * Result-flow combinator. Logs on the `Err` branch and returns the `Result`\n * unchanged. Mirrors Rust's `Result::inspect_err` and Effect's\n * `tapErrorCause`.\n *\n * Takes a log **method**, not a whole logger. The caller picks the level at\n * the pipeline site — the same typed error can be logged as `warn` inside a\n * retry loop and as `error` on the last attempt, without the variant itself\n * carrying level. This is the `tracing::warn!(?err)` vs\n * `tracing::error!(?err)` idiom translated to Result-flow.\n *\n * No message argument. The typed error owns its message; a message\n * parameter here would drift away from the variant's template over time.\n *\n * @example\n * const result = await tryAsync({\n * try: () => writeTable(path),\n * catch: (cause) => MarkdownError.TableWrite({ path, cause }),\n * }).then(tapErr(log.warn));\n *\n * @example Level chosen at call site\n * await tryAttempt().then(tapErr(log.warn)); // inside retry\n * await tryFinal().then(tapErr(log.error)); // last try, giving up\n */\nexport function tapErr<T, E>(\n\tlogFn: (err: E) => void,\n): (result: Result<T, E>) => Result<T, E> {\n\treturn (result) => {\n\t\tif (isErr(result)) logFn(result.error);\n\t\treturn result;\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,SAAgB,OACfA,OACyC;AACzC,QAAO,CAAC,WAAW;AAClB,MAAI,MAAM,OAAO,CAAE,OAAM,OAAO,MAAM;AACtC,SAAO;CACP;AACD"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Result } from "./result-DKwq9BCr.js";
|
|
2
|
+
import "./tap-err-CFhHBPfH.js";
|
|
3
|
+
import "./index-DnoV2ZDO.js";
|
|
4
|
+
|
|
5
|
+
//#region src/testing.d.ts
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Test-only assertion helpers for `Result` values.
|
|
9
|
+
*
|
|
10
|
+
* These helpers intentionally **throw**. A failed expectation should abort the
|
|
11
|
+
* test, and every test runner reports a thrown error as a failure. Tests are
|
|
12
|
+
* the one place throwing is the correct control flow, so these are fenced into
|
|
13
|
+
* the `wellcrafted/testing` entry point and kept out of `wellcrafted/result`,
|
|
14
|
+
* which stays throw-free. Importing from `wellcrafted/testing` in production
|
|
15
|
+
* code is a smell worth linting against.
|
|
16
|
+
*
|
|
17
|
+
* They are framework-agnostic: they throw a plain `Error` rather than calling
|
|
18
|
+
* into a specific runner, so they work under bun, vitest, jest, or
|
|
19
|
+
* `node:test`.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Asserts that `result` is `Ok` and returns its `data`.
|
|
23
|
+
*
|
|
24
|
+
* Throws if `result` is `Err`. The returned value is narrowed to the success
|
|
25
|
+
* type, so no optional chaining or casting is needed at the call site.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { expectOk } from "wellcrafted/testing";
|
|
30
|
+
*
|
|
31
|
+
* const value = expectOk(parseConfig(raw)); // typed as the success value
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
declare function expectOk<T>(result: Result<T, unknown>): T;
|
|
35
|
+
/**
|
|
36
|
+
* Asserts that `result` is `Err` and returns its `error`.
|
|
37
|
+
*
|
|
38
|
+
* Throws if `result` is `Ok`. The returned value is narrowed to the error
|
|
39
|
+
* type, so no optional chaining or casting is needed at the call site.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* import { expectErr } from "wellcrafted/testing";
|
|
44
|
+
*
|
|
45
|
+
* const error = expectErr(parseConfig("not valid"));
|
|
46
|
+
* expect(error.name).toBe("ConfigParseError");
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
declare function expectErr<E>(result: Result<unknown, E>): E;
|
|
50
|
+
//# sourceMappingURL=testing.d.ts.map
|
|
51
|
+
//#endregion
|
|
52
|
+
export { expectErr, expectOk };
|
|
53
|
+
//# sourceMappingURL=testing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.d.ts","names":[],"sources":["../src/testing.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;AA+BA;;;;;AAA0D;AAuB1D;;;;;AAA2D;;;;;;;;;;;;iBAvB3C,oBAAoB,OAAO,cAAc;;;;;;;;;;;;;;;iBAuBzC,qBAAqB,gBAAgB,KAAK"}
|
package/dist/testing.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { isErr, isOk } from "./result-C5cJ1_WU.js";
|
|
2
|
+
import { extractErrorMessage } from "./error-Dy9wXt5_.js";
|
|
3
|
+
import "./tap-err-CP-re1HT.js";
|
|
4
|
+
import "./result-C9V2Knvt.js";
|
|
5
|
+
|
|
6
|
+
//#region src/testing.ts
|
|
7
|
+
/**
|
|
8
|
+
* Test-only assertion helpers for `Result` values.
|
|
9
|
+
*
|
|
10
|
+
* These helpers intentionally **throw**. A failed expectation should abort the
|
|
11
|
+
* test, and every test runner reports a thrown error as a failure. Tests are
|
|
12
|
+
* the one place throwing is the correct control flow, so these are fenced into
|
|
13
|
+
* the `wellcrafted/testing` entry point and kept out of `wellcrafted/result`,
|
|
14
|
+
* which stays throw-free. Importing from `wellcrafted/testing` in production
|
|
15
|
+
* code is a smell worth linting against.
|
|
16
|
+
*
|
|
17
|
+
* They are framework-agnostic: they throw a plain `Error` rather than calling
|
|
18
|
+
* into a specific runner, so they work under bun, vitest, jest, or
|
|
19
|
+
* `node:test`.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Asserts that `result` is `Ok` and returns its `data`.
|
|
23
|
+
*
|
|
24
|
+
* Throws if `result` is `Err`. The returned value is narrowed to the success
|
|
25
|
+
* type, so no optional chaining or casting is needed at the call site.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { expectOk } from "wellcrafted/testing";
|
|
30
|
+
*
|
|
31
|
+
* const value = expectOk(parseConfig(raw)); // typed as the success value
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
function expectOk(result) {
|
|
35
|
+
if (!isOk(result)) throw new Error(`Expected Ok, but got Err: ${extractErrorMessage(result.error)}`);
|
|
36
|
+
return result.data;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Asserts that `result` is `Err` and returns its `error`.
|
|
40
|
+
*
|
|
41
|
+
* Throws if `result` is `Ok`. The returned value is narrowed to the error
|
|
42
|
+
* type, so no optional chaining or casting is needed at the call site.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* import { expectErr } from "wellcrafted/testing";
|
|
47
|
+
*
|
|
48
|
+
* const error = expectErr(parseConfig("not valid"));
|
|
49
|
+
* expect(error.name).toBe("ConfigParseError");
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
function expectErr(result) {
|
|
53
|
+
if (!isErr(result)) throw new Error("Expected Err, but got Ok");
|
|
54
|
+
return result.error;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
export { expectErr, expectOk };
|
|
59
|
+
//# sourceMappingURL=testing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.js","names":["result: Result<T, unknown>","result: Result<unknown, E>"],"sources":["../src/testing.ts"],"sourcesContent":["import { extractErrorMessage } from \"./error/index.js\";\nimport { isErr, isOk, type Result } from \"./result/index.js\";\n\n/**\n * Test-only assertion helpers for `Result` values.\n *\n * These helpers intentionally **throw**. A failed expectation should abort the\n * test, and every test runner reports a thrown error as a failure. Tests are\n * the one place throwing is the correct control flow, so these are fenced into\n * the `wellcrafted/testing` entry point and kept out of `wellcrafted/result`,\n * which stays throw-free. Importing from `wellcrafted/testing` in production\n * code is a smell worth linting against.\n *\n * They are framework-agnostic: they throw a plain `Error` rather than calling\n * into a specific runner, so they work under bun, vitest, jest, or\n * `node:test`.\n */\n\n/**\n * Asserts that `result` is `Ok` and returns its `data`.\n *\n * Throws if `result` is `Err`. The returned value is narrowed to the success\n * type, so no optional chaining or casting is needed at the call site.\n *\n * @example\n * ```ts\n * import { expectOk } from \"wellcrafted/testing\";\n *\n * const value = expectOk(parseConfig(raw)); // typed as the success value\n * ```\n */\nexport function expectOk<T>(result: Result<T, unknown>): T {\n\tif (!isOk(result)) {\n\t\tthrow new Error(\n\t\t\t`Expected Ok, but got Err: ${extractErrorMessage(result.error)}`,\n\t\t);\n\t}\n\treturn result.data;\n}\n\n/**\n * Asserts that `result` is `Err` and returns its `error`.\n *\n * Throws if `result` is `Ok`. The returned value is narrowed to the error\n * type, so no optional chaining or casting is needed at the call site.\n *\n * @example\n * ```ts\n * import { expectErr } from \"wellcrafted/testing\";\n *\n * const error = expectErr(parseConfig(\"not valid\"));\n * expect(error.name).toBe(\"ConfigParseError\");\n * ```\n */\nexport function expectErr<E>(result: Result<unknown, E>): E {\n\tif (!isErr(result)) {\n\t\tthrow new Error(\"Expected Err, but got Ok\");\n\t}\n\treturn result.error;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,SAAgB,SAAYA,QAA+B;AAC1D,MAAK,KAAK,OAAO,CAChB,OAAM,IAAI,MACT,CAAC,0BAA0B,EAAE,oBAAoB,OAAO,MAAM,EAAE;AAGlE,QAAO,OAAO;AACd;;;;;;;;;;;;;;;AAgBD,SAAgB,UAAaC,QAA+B;AAC3D,MAAK,MAAM,OAAO,CACjB,OAAM,IAAI,MAAM;AAEjB,QAAO,OAAO;AACd"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Err } from "./result-
|
|
1
|
+
import { Err } from "./result-DKwq9BCr.js";
|
|
2
2
|
|
|
3
3
|
//#region src/error/types.d.ts
|
|
4
4
|
|
|
@@ -44,4 +44,4 @@ type InferError<T> = T extends ((...args: any[]) => Err<infer R>) ? R : never;
|
|
|
44
44
|
type InferErrors<T> = { [K in keyof T]: T[K] extends ((...args: any[]) => Err<infer R>) ? R : never }[keyof T];
|
|
45
45
|
//#endregion
|
|
46
46
|
export { AnyTaggedError, DefineErrorsReturn, ErrorBody, ErrorsConfig, InferError, InferErrors, ValidatedConfig };
|
|
47
|
-
//# sourceMappingURL=types-
|
|
47
|
+
//# sourceMappingURL=types-tXXk7K9Q.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types-
|
|
1
|
+
{"version":3,"file":"types-tXXk7K9Q.d.ts","names":[],"sources":["../src/error/types.ts"],"sourcesContent":[],"mappings":";;;;;;AAKA;AAWY,KAXA,cAAA,GAWS;EAQhB,IAAA,EAAA,MAAA;EAOO,OAAA,EAAA,MAAY;CAAA;;;AAAS;AAGjC;;AAAsC,KAlB1B,SAAA,GAkB0B;EAAY,OAErC,EAAA,MAAA;CAAC;;;;;;;KAZT,iBAcC,CAAA,UAAA,MAAA,CAAA,GAAA;EAAC,OAAA,EAAA,MAAA;EAIF,IAAA,CAAA,EAAA,kCAhBqC,CAgBzB,eAAA;CAAA;;AAKV,KAhBK,YAAA,GAAe,MAgBpB,CAAA,MAAA,EAAA,CAAA,GAAA,IAAA,EAAA,GAAA,EAAA,EAAA,GAhBuD,SAgBvD,CAAA;;AACI,KAdC,eAcD,CAAA,UAd2B,YAc3B,CAAA,GAAA,QACgB,MAbd,CAac,GAAA,MAAA,GAbD,CAaC,CAbC,CAaD,CAAA,UAAA,CAAA,GAAA,IAAA,EAAA,KAAA,EAAA,EAAA,GAAA,KAAA,EAAA,IAAA,CAAA,GAAA,IAAA,EAZb,CAYa,EAAA,GAZP,CAYO,GAZH,iBAYG,CAZe,CAYf,CAAA,GAXvB,CAWuB,CAXrB,CAWqB,CAAA,EAAK;;KAP3B,YAOK,CAAA,cAAA,MAAA,EAAA,YAAA,CAAA,GAAA,IAAA,EAAA,GAAA,EAAA,EAAA,GAJuB,SAIvB,CAAA,GAAA,QAFH,KAED,GAAA,CAAA,GAAA,IAAA,EADK,UACL,CADgB,GAChB,CAAA,EAAA,GAAA,GAAA,CAAI,QAAJ,CAAA;EAAG,IAAA,EAAkB,KAAlB;AAIJ,CAAA,GAJgC,UAIhC,CAJ2C,GAI3C,CAAA,CAAA,CAAA,EAAmB;KAAnB,mBAA0B,CAAA,CAAA,CAAA,GAAA,CAAA,CAAA,SAAA,GAAA,GAAA,CAAA,CAAA,EAAoB,CAApB,EAAA,GAAA,IAAA,GAAA,KAAA,CAAA,UAAA,CAAA,CAAA,EAAA,KAAA,EAAA,EAAA,GAAA,IAAA,IAG5B,CAH4B,GAAA,KAAA;;AAG5B,KAIS,kBAJT,CAAA,gBAI4C,YAJ5C,CAAA,GAKF,mBALE,CAAA,QAAC,MAOW,OAPX,GAAA,MAAA,GAO8B,YAP9B,CAO2C,CAP3C,EAO8C,OAP9C,CAOsD,CAPtD,CAAA,CAAA,EAIJ,CAAA,MAIU,OAJE,GAAA,MAAA,CAAkB,CAAA;;AAAiB,KAQnC,UARmC,CAAA,CAAA,CAAA,GAU9C,CAV8C,UAAA,CAAA,GAAA,IAAA,EAAA,GAAA,EAAA,EAAA,GAUhB,GAVgB,CAAA,KAAA,EAAA,CAAA,IAUD,CAVC,GAAA,KAAA;;AAGA,KAUnC,WAVmC,CAAA,CAAA,CAAA,GAAA,QAAG,MAYrC,CAZqC,GAYjC,CAZiC,CAY/B,CAZ+B,CAAA,UAAA,CAAA,GAAA,IAAA,EAAA,GAAA,EAAA,EAAA,GAYA,GAZA,CAAA,KAAA,EAAA,CAAA,IAYe,CAZf,GAAA,KAAA,EAAO,CAAA,MAajD,CAbkD,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wellcrafted",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.0",
|
|
4
4
|
"description": "Delightful TypeScript patterns for elegant, type-safe applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -36,6 +36,10 @@
|
|
|
36
36
|
"./standard-schema": {
|
|
37
37
|
"types": "./dist/standard-schema/index.d.ts",
|
|
38
38
|
"import": "./dist/standard-schema/index.js"
|
|
39
|
+
},
|
|
40
|
+
"./testing": {
|
|
41
|
+
"types": "./dist/testing.d.ts",
|
|
42
|
+
"import": "./dist/testing.js"
|
|
39
43
|
}
|
|
40
44
|
},
|
|
41
45
|
"scripts": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/error/defineErrors.ts","../../src/error/extractErrorMessage.ts"],"sourcesContent":[],"mappings":";;;;;;;;AA4DA;;;;;;;;AAEqB;;;;ACxDrB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBDsDgB,mCAAmC,sBAC1C,UAAU,gBAAgB,WAChC,mBAAmB;;;;;;;;AAFtB;;AAAmD,iBCtDnC,mBAAA,CDsDmC,KAAA,EAAA,OAAA,CAAA,EAAA,MAAA"}
|
package/dist/error/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["config: TConfig & ValidatedConfig<TConfig>","result: Record<string, unknown>","error: unknown"],"sources":["../../src/error/defineErrors.ts","../../src/error/extractErrorMessage.ts"],"sourcesContent":["import { Err } from \"../result/result.js\";\nimport type {\n\tDefineErrorsReturn,\n\tErrorsConfig,\n\tValidatedConfig,\n} from \"./types.js\";\n\n/**\n * Defines a set of typed error factories using Rust-style namespaced variants.\n *\n * Each key is a short variant name (the namespace provides context). Every\n * factory returns `Err<...>` directly — ready for `trySync`/`tryAsync` catch\n * handlers. The variant name is stamped as `name` on the error object.\n *\n * @example\n * ```ts\n * const HttpError = defineErrors({\n * Connection: ({ cause }: { cause: unknown }) => ({\n * message: `Failed to connect: ${extractErrorMessage(cause)}`,\n * cause,\n * }),\n * Response: ({ status }: { status: number; bodyMessage?: string }) => ({\n * message: `HTTP ${status}`,\n * status,\n * }),\n * Parse: ({ cause }: { cause: unknown }) => ({\n * message: `Failed to parse response body: ${extractErrorMessage(cause)}`,\n * cause,\n * }),\n * });\n *\n * type HttpError = InferErrors<typeof HttpError>;\n *\n * const result = HttpError.Connection({ cause: 'timeout' }); // Err<...>\n * ```\n *\n * Inspired by Rust's {@link https://docs.rs/thiserror | thiserror} crate. The\n * mapping is nearly 1:1:\n *\n * - `enum HttpError` → `const HttpError = defineErrors(...)`\n * - Variant `Connection { cause: String }` → key `Connection: ({ cause }: { cause: unknown }) => (...)`\n * - `#[error(\"Failed: {cause}\")]` → `` message: `Failed: ${extractErrorMessage(cause)}` ``\n * - `HttpError::Connection { ... }` → `HttpError.Connection({ ... })`\n * - `match error { Connection { .. } => }` → `switch (error.name) { case 'Connection': }`\n *\n * The equivalent Rust `thiserror` enum:\n * ```rust\n * #[derive(Error, Debug)]\n * enum HttpError {\n * #[error(\"Failed to connect: {cause}\")]\n * Connection { cause: String },\n *\n * #[error(\"HTTP {status}\")]\n * Response { status: u16, body_message: Option<String> },\n *\n * #[error(\"Failed to parse response body: {cause}\")]\n * Parse { cause: String },\n * }\n * ```\n */\nexport function defineErrors<const TConfig extends ErrorsConfig>(\n\tconfig: TConfig & ValidatedConfig<TConfig>,\n): DefineErrorsReturn<TConfig> {\n\tconst result: Record<string, unknown> = {};\n\n\tfor (const [name, ctor] of Object.entries(config)) {\n\t\tresult[name] = (...args: unknown[]) => {\n\t\t\tconst body = (ctor as (...a: unknown[]) => Record<string, unknown>)(\n\t\t\t\t...args,\n\t\t\t);\n\t\t\treturn Err(Object.freeze({ ...body, name }));\n\t\t};\n\t}\n\n\treturn result as DefineErrorsReturn<TConfig>;\n}\n","/**\n * Extracts a readable error message from an unknown error value\n *\n * @param error - The unknown error to extract a message from\n * @returns A string representation of the error\n */\nexport function extractErrorMessage(error: unknown): string {\n\t// Handle Error instances\n\tif (error instanceof Error) {\n\t\treturn error.message;\n\t}\n\n\t// Handle primitives\n\tif (typeof error === \"string\") return error;\n\tif (\n\t\ttypeof error === \"number\" ||\n\t\ttypeof error === \"boolean\" ||\n\t\ttypeof error === \"bigint\"\n\t)\n\t\treturn String(error);\n\tif (typeof error === \"symbol\") return error.toString();\n\tif (error === null) return \"null\";\n\tif (error === undefined) return \"undefined\";\n\n\t// Handle arrays\n\tif (Array.isArray(error)) return JSON.stringify(error);\n\n\t// Handle plain objects\n\tif (typeof error === \"object\") {\n\t\tconst errorObj = error as Record<string, unknown>;\n\n\t\t// Check common error properties\n\t\tconst messageProps = [\n\t\t\t\"message\",\n\t\t\t\"error\",\n\t\t\t\"description\",\n\t\t\t\"title\",\n\t\t\t\"reason\",\n\t\t\t\"details\",\n\t\t] as const;\n\t\tfor (const prop of messageProps) {\n\t\t\tif (prop in errorObj && typeof errorObj[prop] === \"string\") {\n\t\t\t\treturn errorObj[prop];\n\t\t\t}\n\t\t}\n\n\t\t// Fallback to JSON stringification\n\t\ttry {\n\t\t\treturn JSON.stringify(error);\n\t\t} catch {\n\t\t\treturn String(error);\n\t\t}\n\t}\n\n\t// Final fallback\n\treturn String(error);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4DA,SAAgB,aACfA,QAC8B;CAC9B,MAAMC,SAAkC,CAAE;AAE1C,MAAK,MAAM,CAAC,MAAM,KAAK,IAAI,OAAO,QAAQ,OAAO,CAChD,QAAO,QAAQ,CAAC,GAAG,SAAoB;EACtC,MAAM,OAAO,AAAC,KACb,GAAG,KACH;AACD,SAAO,IAAI,OAAO,OAAO;GAAE,GAAG;GAAM;EAAM,EAAC,CAAC;CAC5C;AAGF,QAAO;AACP;;;;;;;;;;ACrED,SAAgB,oBAAoBC,OAAwB;AAE3D,KAAI,iBAAiB,MACpB,QAAO,MAAM;AAId,YAAW,UAAU,SAAU,QAAO;AACtC,YACQ,UAAU,mBACV,UAAU,oBACV,UAAU,SAEjB,QAAO,OAAO,MAAM;AACrB,YAAW,UAAU,SAAU,QAAO,MAAM,UAAU;AACtD,KAAI,UAAU,KAAM,QAAO;AAC3B,KAAI,iBAAqB,QAAO;AAGhC,KAAI,MAAM,QAAQ,MAAM,CAAE,QAAO,KAAK,UAAU,MAAM;AAGtD,YAAW,UAAU,UAAU;EAC9B,MAAM,WAAW;EAGjB,MAAM,eAAe;GACpB;GACA;GACA;GACA;GACA;GACA;EACA;AACD,OAAK,MAAM,QAAQ,aAClB,KAAI,QAAQ,mBAAmB,SAAS,UAAU,SACjD,QAAO,SAAS;AAKlB,MAAI;AACH,UAAO,KAAK,UAAU,MAAM;EAC5B,QAAO;AACP,UAAO,OAAO,MAAM;EACpB;CACD;AAGD,QAAO,OAAO,MAAM;AACpB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"result-BongGO2O.d.ts","names":[],"sources":["../src/result/result.ts"],"sourcesContent":[],"mappings":";;AAWA;AAaA;AAqCA;;;;;;AAAsC;AAiBtC;AAAgE,KAnEpD,EAmEoD,CAAA,CAAA,CAAA,GAAA;EAAA,IAApC,EAnEA,CAmEA;EAAC,KAAM,EAAA,IAAA;CAAC;AAAF;AAiClC;;;;;AAAqC;AAoBrC;;;;AAAqE,KA3GzD,GA2GyD,CAAA,CAAA,CAAA,GAAA;EAAE,KACpE,EA5G2B,CA4G3B;EAAC,IAAA,EAAA,IAAA;AAqBJ,CAAA;;;;;;AAGI;AAgCJ;;;;;AAEkB;AAgClB;;;;;;;AAA8D;AAyB9D;;;;;;;AAAgE;AAkDhE;;;;;;;AAIY,KAhPA,MAgPA,CAAA,CAAA,EAAA,CAAA,CAAA,GAhPe,EAgPf,CAhPkB,CAgPlB,CAAA,GAhPuB,GAgPvB,CAhP2B,CAgP3B,CAAA;;;;;AAEC;AA2Db;;;;;;;;;;AAMe,cAlSF,EAkSE,EAAA,CAAA,CAAA,CAAA,CAAA,IAAA,EAlSa,CAkSb,EAAA,GAlSiB,EAkSjB,CAlSoB,CAkSpB,CAAA;;;;AAAJ;AAuGX;;;;;;AAAqD;AAOrD;;;;;;;AAAyD;;;;;;;;;;;;;cA/W5C,gBAAiB,MAAI,IAAI;;;;;;;;;;;;;;;;;;;KAoB1B,mBAAmB,4BAA4B,UAAU,cAClE;;;;;;;;;;;;;;;;;;;KAqBS,oBAAoB,4BAA4B,UAAU,eAGnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgCa,6DAEJ,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;iBAgCN,mBAAmB,OAAO,GAAG,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;iBAyB/C,oBAAoB,OAAO,GAAG,eAAe,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkDjD,qBAAqB,GAAG,KAAK;OACvC;SACE;;aAEI;6BACgB;IACxB,GAAG,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA2DU,sBAAsB,GAAG,KAAK;OAC9C;SACE;;aAEI,QAAQ;6BACQ;IACxB,QAAQ,GAAG,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuGJ,qBAAqB,OAAO,GAAG,KAAK;iBAOpC,qBAAqB,IAAI,OAAO,GAAG,KAAK"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"result-DzL3K2yA.js","names":["data: T","error: E","value: unknown","result: Result<T, E>","value: T | Result<T, E>"],"sources":["../src/result/result.ts"],"sourcesContent":["/**\n * Represents the successful outcome of an operation, encapsulating the success value.\n *\n * This is the 'Ok' variant of the `Result` type. It holds a `data` property\n * of type `T` (the success value) and an `error` property explicitly set to `null`,\n * signifying no error occurred.\n *\n * Use this type in conjunction with `Err<E>` and `Result<T, E>`.\n *\n * @template T - The type of the success value contained within.\n */\nexport type Ok<T> = { data: T; error: null };\n\n/**\n * Represents the failure outcome of an operation, encapsulating the error value.\n *\n * This is the 'Err' variant of the `Result` type. It holds an `error` property\n * of type `E` (the error value) and a `data` property explicitly set to `null`,\n * signifying that no success value is present due to the failure.\n *\n * Use this type in conjunction with `Ok<T>` and `Result<T, E>`.\n *\n * @template E - The type of the error value contained within.\n */\nexport type Err<E> = { error: E; data: null };\n\n/**\n * A type that represents the outcome of an operation that can either succeed or fail.\n *\n * `Result<T, E>` is a discriminated union type with two possible variants:\n * - `Ok<T>`: Represents a successful outcome, containing a `data` field with the success value of type `T`.\n * In this case, the `error` field is `null`.\n * - `Err<E>`: Represents a failure outcome, containing an `error` field with the error value of type `E`.\n * In this case, the `data` field is `null`.\n *\n * This type promotes explicit error handling by requiring developers to check\n * the variant of the `Result` before accessing its potential value or error.\n * It helps avoid runtime errors often associated with implicit error handling (e.g., relying on `try-catch` for all errors).\n *\n * @template T - The type of the success value if the operation is successful (held in `Ok<T>`).\n * @template E - The type of the error value if the operation fails (held in `Err<E>`).\n * @example\n * ```ts\n * function divide(numerator: number, denominator: number): Result<number, string> {\n * if (denominator === 0) {\n * return Err(\"Cannot divide by zero\");\n * }\n * return Ok(numerator / denominator);\n * }\n *\n * const result1 = divide(10, 2);\n * if (isOk(result1)) {\n * console.log(\"Success:\", result1.data); // Output: Success: 5\n * }\n *\n * const result2 = divide(10, 0);\n * if (isErr(result2)) {\n * console.error(\"Failure:\", result2.error); // Output: Failure: Cannot divide by zero\n * }\n * ```\n */\nexport type Result<T, E> = Ok<T> | Err<E>;\n\n/**\n * Constructs an `Ok<T>` variant, representing a successful outcome.\n *\n * This factory function creates the success variant of a `Result`.\n * It wraps the provided `data` (the success value) and ensures the `error` property is `null`.\n *\n * @template T - The type of the success value.\n * @param data - The success value to be wrapped in the `Ok` variant.\n * @returns An `Ok<T>` object with the provided data and `error` set to `null`.\n * @example\n * ```ts\n * const successfulResult = Ok(\"Operation completed successfully\");\n * // successfulResult is { data: \"Operation completed successfully\", error: null }\n * ```\n */\nexport const Ok = <T>(data: T): Ok<T> => ({ data, error: null });\n\n/**\n * Constructs an `Err<E>` variant, representing a failure outcome.\n *\n * Wraps the provided `error` (the failure value) and sets `data` to `null`.\n *\n * **Don't call `Err(null)`.** It produces `{ data: null, error: null }` —\n * structurally identical to `Ok(null)`. The built-in `isErr` check\n * (`result.error !== null`) reads it as Ok, silently misclassifying your\n * failure as success. `Err(undefined)` is also discouraged: the discriminator\n * technically works (`undefined !== null`), but `undefined` is falsy, so\n * downstream `if (error)` checks trip and the error carries no information\n * anyway. Pass a meaningful error value (a string, a tagged error from\n * `defineErrors`, an `Error` instance), or use `Ok(null)`/`Ok(undefined)` if\n * what you meant was success-with-no-payload.\n *\n * At `catch (error: unknown)` boundaries, wrap the caught value in a tagged\n * error rather than passing it through — `TaggedError.X({ cause: error })`\n * is always non-null by construction, so the discriminator works regardless\n * of what was thrown.\n *\n * See `docs/philosophy/err-null-is-ok-null.md` for the full rationale.\n *\n * @template E - The type of the error value.\n * @param error - The error value to wrap. Don't pass `null` or `undefined`.\n * @returns An `Err<E>` object with the provided error and `data` set to `null`.\n * @example\n * ```ts\n * const failedResult = Err(new TypeError(\"Invalid input\"));\n * // failedResult is { error: TypeError(\"Invalid input\"), data: null }\n * ```\n */\nexport const Err = <E>(error: E): Err<E> => ({ error, data: null });\n\n/**\n * Utility type to extract the success value's type `T` from a `Result<T, E>` type.\n *\n * If `R` is an `Ok<T>` variant (or a `Result<T, E>` that could be an `Ok<T>`),\n * this type resolves to `T`. If `R` can only be an `Err<E>` variant, it resolves to `never`.\n * This is useful for obtaining the type of the `data` field when you know you have a success.\n *\n * @template R - The `Result<T, E>` type from which to extract the success value's type.\n * Must extend `Result<unknown, unknown>`.\n * @example\n * ```ts\n * type MyResult = Result<number, string>;\n * type SuccessValueType = UnwrapOk<MyResult>; // SuccessValueType is number\n *\n * type MyErrorResult = Err<string>;\n * type ErrorValueType = UnwrapOk<MyErrorResult>; // ErrorValueType is never\n * ```\n */\nexport type UnwrapOk<R extends Result<unknown, unknown>> = R extends Ok<infer U>\n\t? U\n\t: never;\n\n/**\n * Utility type to extract the error value's type `E` from a `Result<T, E>` type.\n *\n * If `R` is an `Err<E>` variant (or a `Result<T, E>` that could be an `Err<E>`),\n * this type resolves to `E`. If `R` can only be an `Ok<T>` variant, it resolves to `never`.\n * This is useful for obtaining the type of the `error` field when you know you have a failure.\n *\n * @template R - The `Result<T, E>` type from which to extract the error value's type.\n * Must extend `Result<unknown, unknown>`.\n * @example\n * ```ts\n * type MyResult = Result<number, string>;\n * type ErrorValueType = UnwrapErr<MyResult>; // ErrorValueType is string\n *\n * type MySuccessResult = Ok<number>;\n * type SuccessValueType = UnwrapErr<MySuccessResult>; // SuccessValueType is never\n * ```\n */\nexport type UnwrapErr<R extends Result<unknown, unknown>> = R extends Err<\n\tinfer E\n>\n\t? E\n\t: never;\n\n/**\n * Type guard to runtime check if an unknown value is a valid `Result<T, E>`.\n *\n * A value is considered a valid `Result` if:\n * 1. It is a non-null object.\n * 2. It has both `data` and `error` properties.\n * 3. At least one of the `data` or `error` channels is `null`. Both being `null` represents `Ok(null)`.\n *\n * This function does not validate the types of `data` or `error` beyond `null` checks.\n *\n * @template T - The expected type of the success value if the value is an `Ok` variant (defaults to `unknown`).\n * @template E - The expected type of the error value if the value is an `Err` variant (defaults to `unknown`).\n * @param value - The value to check.\n * @returns `true` if the value conforms to the `Result` structure, `false` otherwise.\n * If `true`, TypeScript's type system will narrow `value` to `Result<T, E>`.\n * @example\n * ```ts\n * declare const someValue: unknown;\n *\n * if (isResult<string, Error>(someValue)) {\n * // someValue is now typed as Result<string, Error>\n * if (isOk(someValue)) {\n * console.log(someValue.data); // string\n * } else {\n * console.error(someValue.error); // Error\n * }\n * }\n * ```\n */\nexport function isResult<T = unknown, E = unknown>(\n\tvalue: unknown,\n): value is Result<T, E> {\n\tconst isNonNullObject = typeof value === \"object\" && value !== null;\n\tif (!isNonNullObject) return false;\n\n\tconst hasDataProperty = \"data\" in value;\n\tconst hasErrorProperty = \"error\" in value;\n\tif (!hasDataProperty || !hasErrorProperty) return false;\n\n\treturn true;\n}\n\n/**\n * Type guard to runtime check if a `Result<T, E>` is an `Ok<T>` variant.\n *\n * This function narrows the type of a `Result` to `Ok<T>` if it represents a successful outcome.\n * An `Ok<T>` variant is identified by its `error` property being `null`.\n *\n * @template T - The success value type.\n * @template E - The error value type.\n * @param result - The `Result<T, E>` to check.\n * @returns `true` if the `result` is an `Ok<T>` variant, `false` otherwise.\n * If `true`, TypeScript's type system will narrow `result` to `Ok<T>`.\n * @example\n * ```ts\n * declare const myResult: Result<number, string>;\n *\n * if (isOk(myResult)) {\n * // myResult is now typed as Ok<number>\n * console.log(\"Success value:\", myResult.data); // myResult.data is number\n * }\n * ```\n */\nexport function isOk<T, E>(result: Result<T, E>): result is Ok<T> {\n\treturn result.error === null;\n}\n\n/**\n * Type guard to runtime check if a `Result<T, E>` is an `Err<E>` variant.\n *\n * This function narrows the type of a `Result` to `Err<E>` if it represents a failure outcome.\n * An `Err<E>` variant is identified by its `error` property being non-`null` (and thus `data` being `null`).\n *\n * @template T - The success value type.\n * @template E - The error value type.\n * @param result - The `Result<T, E>` to check.\n * @returns `true` if the `result` is an `Err<E>` variant, `false` otherwise.\n * If `true`, TypeScript's type system will narrow `result` to `Err<E>`.\n * @example\n * ```ts\n * declare const myResult: Result<number, string>;\n *\n * if (isErr(myResult)) {\n * // myResult is now typed as Err<string>\n * console.error(\"Error value:\", myResult.error); // myResult.error is string\n * }\n * ```\n */\nexport function isErr<T, E>(result: Result<T, E>): result is Err<E> {\n\treturn result.error !== null; // Equivalent to result.data === null\n}\n\n/**\n * Executes a synchronous operation and wraps its outcome in a Result type.\n *\n * This function attempts to execute the `try` operation:\n * - If the `try` operation completes successfully, its return value is wrapped in an `Ok<T>` variant.\n * - If the `try` operation throws an exception, the caught exception (of type `unknown`) is passed to\n * the `catch` function, which transforms it into either an `Ok<T>` (recovery) or `Err<E>` (propagation).\n *\n * The return type is automatically determined by what your catch function returns:\n * - If catch always returns `Ok<T>`, the return type collapses to `Ok<T>` (guaranteed success)\n * - If catch always returns `Err<E>`, the return type is `Ok<T> | Err<E>` (may succeed or fail)\n * - If catch returns a union like `Err<A> | Err<B>`, the return type is `Ok<T> | Err<A> | Err<B>` (union propagation)\n * - If catch can return either `Ok<T>` or `Err<E>`, the return type is `Ok<T> | Err<E>` (conditional recovery)\n *\n * @template T - The success value type\n * @template R - The return type of the catch handler (`Ok<T>` for recovery, `Err<E>` for propagation, or a union)\n * @param options - Configuration object\n * @param options.try - The operation to execute\n * @param options.catch - Error handler that transforms caught exceptions into either `Ok<T>` (recovery) or `Err<E>` (propagation)\n * @returns `Ok<T> | R` — the union of the success path and whatever the catch handler returns\n *\n * @example\n * ```ts\n * // Returns Ok<string> - guaranteed success since catch always returns Ok\n * const alwaysOk = trySync({\n * try: () => JSON.parse(input),\n * catch: () => Ok(\"fallback\") // Always Ok<T>\n * });\n *\n * // Returns Result<object, string> - may fail since catch always returns Err\n * const mayFail = trySync({\n * try: () => JSON.parse(input),\n * catch: (err) => Err(\"Parse failed\") // Returns Err<E>\n * });\n *\n * // Returns Result<void, MyError> - conditional recovery based on error type\n * const conditional = trySync({\n * try: () => riskyOperation(),\n * catch: (err) => {\n * if (isRecoverable(err)) return Ok(undefined);\n * return MyErr({ message: \"Unrecoverable\" });\n * }\n * });\n * ```\n */\n// biome-ignore lint/suspicious/noExplicitAny: required for union type inference in catch handlers\nexport function trySync<T, R extends Ok<T> | Err<any>>({\n\ttry: operation,\n\tcatch: catchFn,\n}: {\n\ttry: () => T;\n\tcatch: (error: unknown) => R;\n}): Ok<T> | R {\n\ttry {\n\t\tconst data = operation();\n\t\treturn Ok(data);\n\t} catch (error) {\n\t\treturn catchFn(error);\n\t}\n}\n\n/**\n * Executes an asynchronous operation and wraps its outcome in a Promise<Result>.\n *\n * This function attempts to execute the `try` operation:\n * - If the `try` operation resolves successfully, its resolved value is wrapped in an `Ok<T>` variant.\n * - If the `try` operation rejects or throws an exception, the caught error (of type `unknown`) is passed to\n * the `catch` function, which transforms it into either an `Ok<T>` (recovery) or `Err<E>` (propagation).\n *\n * The return type is automatically determined by what your catch function returns:\n * - If catch always returns `Ok<T>`, the return type collapses to `Promise<Ok<T>>` (guaranteed success)\n * - If catch always returns `Err<E>`, the return type is `Promise<Ok<T> | Err<E>>` (may succeed or fail)\n * - If catch returns a union like `Err<A> | Err<B>`, the return type is `Promise<Ok<T> | Err<A> | Err<B>>` (union propagation)\n * - If catch can return either `Ok<T>` or `Err<E>`, the return type is `Promise<Ok<T> | Err<E>>` (conditional recovery)\n *\n * @template T - The success value type\n * @template R - The return type of the catch handler (`Ok<T>` for recovery, `Err<E>` for propagation, or a union)\n * @param options - Configuration object\n * @param options.try - The async operation to execute\n * @param options.catch - Error handler that transforms caught exceptions/rejections into either `Ok<T>` (recovery) or `Err<E>` (propagation)\n * @returns `Promise<Ok<T> | R>` — the union of the success path and whatever the catch handler returns\n *\n * @example\n * ```ts\n * // Returns Promise<Ok<Response>> - guaranteed success since catch always returns Ok\n * const alwaysOk = tryAsync({\n * try: async () => fetch(url),\n * catch: () => Ok(new Response()) // Always Ok<T>\n * });\n *\n * // Returns Promise<Result<Response, Error>> - may fail since catch always returns Err\n * const mayFail = tryAsync({\n * try: async () => fetch(url),\n * catch: (err) => Err(new Error(\"Fetch failed\")) // Returns Err<E>\n * });\n *\n * // Returns Promise<Result<void, BlobError>> - conditional recovery based on error type\n * const conditional = await tryAsync({\n * try: async () => {\n * await deleteFile(filename);\n * },\n * catch: (err) => {\n * if ((err as { name?: string }).name === 'NotFoundError') {\n * return Ok(undefined); // Already deleted, that's fine\n * }\n * return BlobErr({ message: \"Delete failed\" });\n * }\n * });\n * ```\n */\n// biome-ignore lint/suspicious/noExplicitAny: required for union type inference in catch handlers\nexport async function tryAsync<T, R extends Ok<T> | Err<any>>({\n\ttry: operation,\n\tcatch: catchFn,\n}: {\n\ttry: () => Promise<T>;\n\tcatch: (error: unknown) => R;\n}): Promise<Ok<T> | R> {\n\ttry {\n\t\tconst data = await operation();\n\t\treturn Ok(data);\n\t} catch (error) {\n\t\treturn catchFn(error);\n\t}\n}\n\n/**\n * Resolves a value that may or may not be wrapped in a `Result`, returning the final value.\n *\n * This function handles the common pattern where a value might be a `Result<T, E>` or a plain `T`:\n * - If `value` is an `Ok<T>` variant, returns the contained success value.\n * - If `value` is an `Err<E>` variant, throws the contained error value.\n * - If `value` is not a `Result` (i.e., it's already a plain value of type `T`),\n * returns it as-is.\n *\n * This is useful when working with APIs that might return either direct values or Results,\n * allowing you to normalize them to the actual value or propagate errors via throwing.\n *\n * Use `resolve` when the input might or might not be a Result.\n * Use `unwrap` when you know the input is definitely a Result.\n *\n * @template T - The type of the success value (if `value` is `Ok<T>`) or the type of the plain value.\n * @template E - The type of the error value (if `value` is `Err<E>`).\n * @param value - The value to resolve. Can be a `Result<T, E>` or a plain value of type `T`.\n * @returns The final value of type `T` if `value` is `Ok<T>` or if `value` is already a plain `T`.\n * @throws The error value `E` if `value` is an `Err<E>` variant.\n *\n * @example\n * ```ts\n * // Example with an Ok variant\n * const okResult = Ok(\"success data\");\n * const resolved = resolve(okResult); // \"success data\"\n *\n * // Example with an Err variant\n * const errResult = Err(new Error(\"failure\"));\n * try {\n * resolve(errResult);\n * } catch (e) {\n * console.error(e.message); // \"failure\"\n * }\n *\n * // Example with a plain value\n * const plainValue = \"plain data\";\n * const resolved = resolve(plainValue); // \"plain data\"\n *\n * // Example with a function that might return Result or plain value\n * declare function mightReturnResult(): string | Result<string, Error>;\n * const outcome = mightReturnResult();\n * try {\n * const finalValue = resolve(outcome); // handles both cases\n * console.log(\"Final value:\", finalValue);\n * } catch (e) {\n * console.error(\"Operation failed:\", e);\n * }\n * ```\n */\n/**\n * Unwraps a `Result<T, E>`, returning the success value or throwing the error.\n *\n * This function extracts the data from a `Result`:\n * - If the `Result` is an `Ok<T>` variant, returns the contained success value of type `T`.\n * - If the `Result` is an `Err<E>` variant, throws the contained error value of type `E`.\n *\n * Unlike `resolve`, this function expects the input to always be a `Result` type,\n * making it more direct for cases where you know you're working with a `Result`.\n *\n * @template T - The type of the success value contained in the `Ok<T>` variant.\n * @template E - The type of the error value contained in the `Err<E>` variant.\n * @param result - The `Result<T, E>` to unwrap.\n * @returns The success value of type `T` if the `Result` is `Ok<T>`.\n * @throws The error value of type `E` if the `Result` is `Err<E>`.\n *\n * @example\n * ```ts\n * // Example with an Ok variant\n * const okResult = Ok(\"success data\");\n * const value = unwrap(okResult); // \"success data\"\n *\n * // Example with an Err variant\n * const errResult = Err(new Error(\"something went wrong\"));\n * try {\n * unwrap(errResult);\n * } catch (error) {\n * console.error(error.message); // \"something went wrong\"\n * }\n *\n * // Usage in a function that returns Result\n * function divide(a: number, b: number): Result<number, string> {\n * if (b === 0) return Err(\"Division by zero\");\n * return Ok(a / b);\n * }\n *\n * try {\n * const result = unwrap(divide(10, 2)); // 5\n * console.log(\"Result:\", result);\n * } catch (error) {\n * console.error(\"Division failed:\", error);\n * }\n * ```\n */\nexport function unwrap<T, E>(result: Result<T, E>): T {\n\tif (isOk(result)) {\n\t\treturn result.data;\n\t}\n\tthrow result.error;\n}\n\nexport function resolve<T, E>(value: T | Result<T, E>): T {\n\tif (isResult<T, E>(value)) {\n\t\tif (isOk(value)) {\n\t\t\treturn value.data;\n\t\t}\n\t\t// If it's a Result and not Ok, it must be Err.\n\t\t// The type guard isResult<T,E>(value) and isOk(value) already refine the type.\n\t\t// So, 'value' here is known to be Err<E>.\n\t\tthrow value.error;\n\t}\n\n\t// If it's not a Result type, return the value as-is.\n\t// 'value' here is known to be of type T.\n\treturn value;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA8EA,MAAa,KAAK,CAAIA,UAAoB;CAAE;CAAM,OAAO;AAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiC/D,MAAa,MAAM,CAAIC,WAAsB;CAAE;CAAO,MAAM;AAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6ElE,SAAgB,SACfC,OACwB;CACxB,MAAM,yBAAyB,UAAU,YAAY,UAAU;AAC/D,MAAK,gBAAiB,QAAO;CAE7B,MAAM,kBAAkB,UAAU;CAClC,MAAM,mBAAmB,WAAW;AACpC,MAAK,oBAAoB,iBAAkB,QAAO;AAElD,QAAO;AACP;;;;;;;;;;;;;;;;;;;;;;AAuBD,SAAgB,KAAWC,QAAuC;AACjE,QAAO,OAAO,UAAU;AACxB;;;;;;;;;;;;;;;;;;;;;;AAuBD,SAAgB,MAAYA,QAAwC;AACnE,QAAO,OAAO,UAAU;AACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDD,SAAgB,QAAuC,EACtD,KAAK,WACL,OAAO,SAIP,EAAa;AACb,KAAI;EACH,MAAM,OAAO,WAAW;AACxB,SAAO,GAAG,KAAK;CACf,SAAQ,OAAO;AACf,SAAO,QAAQ,MAAM;CACrB;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDD,eAAsB,SAAwC,EAC7D,KAAK,WACL,OAAO,SAIP,EAAsB;AACtB,KAAI;EACH,MAAM,OAAO,MAAM,WAAW;AAC9B,SAAO,GAAG,KAAK;CACf,SAAQ,OAAO;AACf,SAAO,QAAQ,MAAM;CACrB;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgGD,SAAgB,OAAaA,QAAyB;AACrD,KAAI,KAAK,OAAO,CACf,QAAO,OAAO;AAEf,OAAM,OAAO;AACb;AAED,SAAgB,QAAcC,OAA4B;AACzD,KAAI,SAAe,MAAM,EAAE;AAC1B,MAAI,KAAK,MAAM,CACd,QAAO,MAAM;AAKd,QAAM,MAAM;CACZ;AAID,QAAO;AACP"}
|