wellcrafted 0.15.0 → 0.17.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/README.md CHANGED
@@ -539,11 +539,14 @@ const userResult = await fetchUser(1);
539
539
 
540
540
  When using `trySync` and `tryAsync`, you have two approaches to ensure your `mapError` function returns the correct TaggedError type:
541
541
 
542
- #### Approach 1: Explicit Generics (Recommended)
542
+ #### Approach 1: Explicit Generics
543
+
544
+ Pass the success type and error type as generic parameters. This approach is clear and explicit about the expected types:
543
545
 
544
546
  ```ts
547
+ // For tryAsync
545
548
  async function readConfig(path: string) {
546
- return tryAsync<string, FileError>({ // 👈 Explicitly specify generics
549
+ return tryAsync<string, FileError>({ // 👈 <SuccessType, ErrorType>
547
550
  try: async () => {
548
551
  const content = await fs.readFile(path, 'utf-8');
549
552
  return content;
@@ -556,21 +559,59 @@ async function readConfig(path: string) {
556
559
  })
557
560
  });
558
561
  }
562
+
563
+ // For trySync
564
+ function parseConfig(content: string) {
565
+ return trySync<Config, ParseError>({ // 👈 <SuccessType, ErrorType>
566
+ try: () => {
567
+ const parsed = JSON.parse(content);
568
+ validateConfig(parsed); // throws if invalid
569
+ return parsed as Config;
570
+ },
571
+ mapError: (error) => ({
572
+ name: "ParseError",
573
+ message: "Invalid configuration format",
574
+ context: { contentLength: content.length },
575
+ cause: error
576
+ })
577
+ });
578
+ }
559
579
  ```
560
580
 
561
- #### Approach 2: Return Type Annotation
581
+ #### Approach 2: Return Type Annotation on mapError
582
+
583
+ Annotate the return type of the `mapError` function. This approach can be cleaner when generics would format awkwardly:
562
584
 
563
585
  ```ts
564
- async function readConfig(path: string) {
586
+ // For tryAsync
587
+ async function saveUser(user: User) {
565
588
  return tryAsync({
566
589
  try: async () => {
567
- const content = await fs.readFile(path, 'utf-8');
568
- return content;
590
+ const result = await db.users.insert(user);
591
+ return result.id;
569
592
  },
570
- mapError: (error): FileError => ({ // 👈 Annotate return type
571
- name: "FileError",
572
- message: "Failed to read configuration file",
573
- context: { path },
593
+ mapError: (error): DatabaseError => ({ // 👈 Annotate return type
594
+ name: "DatabaseError",
595
+ message: "Failed to save user to database",
596
+ context: { userId: user.id },
597
+ cause: error
598
+ })
599
+ });
600
+ }
601
+
602
+ // For trySync
603
+ function validateEmail(email: string) {
604
+ return trySync({
605
+ try: () => {
606
+ if (!email.includes('@')) {
607
+ throw new Error('Invalid email format');
608
+ }
609
+ return email.toLowerCase();
610
+ },
611
+ mapError: (error): ValidationError => ({ // 👈 Annotate return type
612
+ name: "ValidationError",
613
+ message: "Email validation failed",
614
+ context: { email },
574
615
  cause: error
575
616
  })
576
617
  });
@@ -585,6 +626,107 @@ async function readConfig(path: string) {
585
626
 
586
627
  ---
587
628
 
629
+ ## Partitioning Results
630
+
631
+ When working with multiple asynchronous operations that return `Result` objects, you'll often need to separate the successful results from the failed ones. The `partitionResults` utility function makes this easy by splitting an array of Results into two separate arrays.
632
+
633
+ ### When to Use `partitionResults`
634
+
635
+ Use `partitionResults` when you have:
636
+ - Multiple async operations that might fail independently
637
+ - A need to handle all errors collectively
638
+ - Successful results that should be processed together
639
+
640
+ ### Common Pattern: Map → Filter → Partition
641
+
642
+ This is a typical workflow when processing multiple commands or operations:
643
+
644
+ ```ts
645
+ import { partitionResults } from "wellcrafted/result";
646
+
647
+ // Example: Processing multiple commands that might fail
648
+ const results = await Promise.all(
649
+ commands
650
+ .map((command) => {
651
+ const config = getCommandConfig(command.id);
652
+ if (!config) return; // Early return if config missing
653
+ return executeCommand({ command, config });
654
+ })
655
+ .filter((result) => result !== undefined) // Remove undefined values
656
+ );
657
+
658
+ const { oks, errs } = partitionResults(results);
659
+
660
+ // Handle all errors at once
661
+ if (errs.length > 0) {
662
+ const errorMessages = errs.map(({ error }) => error.message).join(', ');
663
+ showNotification(`${errs.length} operations failed: ${errorMessages}`);
664
+ return;
665
+ }
666
+
667
+ return oks.map(ok => ok.data); // Return processed content
668
+ ```
669
+
670
+ ### Real-World Example: Batch File Processing
671
+
672
+ ```ts
673
+ import { tryAsync, partitionResults } from "wellcrafted/result";
674
+ import { type TaggedError } from "wellcrafted/error";
675
+ import * as fs from 'fs/promises';
676
+
677
+ type FileError = TaggedError<"FileError">;
678
+
679
+ async function processFiles(filePaths: string[]) {
680
+ // Map each file path to a Result-returning operation
681
+ const results = await Promise.all(
682
+ filePaths
683
+ .map((path) => {
684
+ if (!path.endsWith('.txt')) return; // Skip non-text files
685
+ return tryAsync<string, FileError>({
686
+ try: async () => {
687
+ const content = await fs.readFile(path, 'utf-8');
688
+ return content.toUpperCase(); // Process the content
689
+ },
690
+ mapError: (error) => ({
691
+ name: "FileError",
692
+ message: "Failed to process file",
693
+ context: { path },
694
+ cause: error
695
+ })
696
+ });
697
+ })
698
+ .filter((result) => result !== undefined)
699
+ );
700
+
701
+ const { oks, errs } = partitionResults(results);
702
+
703
+ // Report all errors together
704
+ if (errs.length > 0) {
705
+ console.error(`Failed to process ${errs.length} files:`);
706
+ errs.forEach(err => {
707
+ console.error(`- ${err.error.context.path}: ${err.error.message}`);
708
+ });
709
+ }
710
+
711
+ // Process successful results
712
+ if (oks.length > 0) {
713
+ console.log(`Successfully processed ${oks.length} files`);
714
+ return oks.map(ok => ok.data); // Return processed content
715
+ }
716
+
717
+ return [];
718
+ }
719
+ ```
720
+
721
+ ### Key Benefits
722
+
723
+ 1. **Batch Error Handling**: Instead of stopping at the first error, you can collect all failures and present them together
724
+ 2. **Type Safety**: The returned `oks` and `errs` arrays are properly typed as `Ok<T>[]` and `Err<E>[]` respectively
725
+ 3. **Clean Separation**: Successful and failed operations are cleanly separated for different handling logic
726
+ 4. **Composability**: Works seamlessly with the map → filter → partition pattern for complex data processing
727
+
728
+ ---
729
+
588
730
  ## API Reference
589
731
 
590
732
  ### Quick Reference Table
@@ -597,6 +739,7 @@ async function readConfig(path: string) {
597
739
  | `isErr(result)` | Check if failure | `if (isErr(res)) { ... }` |
598
740
  | `trySync()` | Wrap throwing function | `trySync({ try: () => JSON.parse(str) })` |
599
741
  | `tryAsync()` | Wrap async throwing function | `tryAsync({ try: () => fetch(url) })` |
742
+ | `partitionResults()` | Split Results into oks/errs | `const { oks, errs } = partitionResults(results)` |
600
743
 
601
744
  ### Detailed API
602
745
 
@@ -681,12 +824,14 @@ That said, the influence of Effect is clear. Functions like `trySync` and `tryAs
681
824
 
682
825
  ### Why `{ data, error }` instead of a boolean flag like `{ ok: boolean, ... }`?
683
826
 
684
- Some libraries use a discriminated union with a boolean flag, like `{ ok: true, data: T } | { ok: false, error: E }`. While a valid pattern, we chose the `{ data, error }` shape for two main reasons:
827
+ Some libraries use a boolean flag for their discriminated union, like `{ ok: true, data: T } | { ok: false, error: E }`. While a valid pattern, we chose the `{ data, error }` shape for two main reasons:
685
828
 
686
829
  1. **Ergonomics and Familiarity**: The destructuring pattern `const { data, error } = operation()` is clean and will feel familiar to developers using modern libraries like Supabase and Astro Actions. It provides immediate access to the inner values without an extra layer of property access. Checking a boolean flag first (`if (result.ok)`) and then accessing the value (`result.data`) is slightly more verbose.
687
830
 
688
831
  2. **Lack of Standardization**: The boolean flag approach isn't standardized. Zod's `.safeParse`, for example, returns `{ success: boolean, ... }`. By adopting the `{ data, error }` pattern, we align with a simple, common, and intuitive structure for handling success and failure states in modern JavaScript.
689
832
 
833
+ **Note**: The `{ data, error }` pattern is also a discriminated union—you can use either `data` or `error` as the discriminant key and check if either of them is null. This creates the same type-narrowing benefits as a boolean flag while maintaining cleaner destructuring ergonomics.
834
+
690
835
  ### What's the difference between an `Err` variant and an `error` value?
691
836
 
692
837
  This is a key distinction in the library's terminology:
@@ -0,0 +1,41 @@
1
+ //#region src/brand.d.ts
2
+ /**
3
+ * Internal symbol used to create nominal typing for branded types.
4
+ */
5
+ declare const brand: unique symbol;
6
+ /**
7
+ * Creates a brand type for nominal typing in TypeScript.
8
+ *
9
+ * Branded types help create distinct types from primitive types, preventing
10
+ * accidental mixing of values that should be semantically different.
11
+ *
12
+ * @template T - A string literal type that serves as the brand identifier
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * // Create a branded ID type
17
+ * type ID = string & Brand<"ID">;
18
+ *
19
+ * // Create functions that work with branded types
20
+ * function createID(value: string): ID {
21
+ * return value as ID;
22
+ * }
23
+ *
24
+ * function processID(id: ID): void {
25
+ * console.log(`Processing ID: ${id}`);
26
+ * }
27
+ *
28
+ * // Usage
29
+ * const userID = createID("user-123");
30
+ * const productID = createID("product-456");
31
+ *
32
+ * processID(userID); // ✅ Works
33
+ * processID("raw-string"); // ❌ TypeScript error - string is not assignable to ID
34
+ * ```
35
+ */
36
+ type Brand<T extends string> = {
37
+ [brand]: T;
38
+ };
39
+ //#endregion
40
+ export { Brand };
41
+ //# sourceMappingURL=brand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brand.d.ts","names":[],"sources":["../src/brand.ts"],"sourcesContent":[],"mappings":";;;AAmCA;cAhCc,KAgCG,EAAA,OAAA,MAAA;;;AAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAAlC;GAA6B,KAAA,GAAQ"}
package/dist/brand.js ADDED
File without changes
@@ -0,0 +1,116 @@
1
+ //#region src/error/types.d.ts
2
+ /**
3
+ * Base error structure for all errors in the Result system.
4
+ *
5
+ * Provides a consistent structure for error objects that are JSON-serializable
6
+ * and contain comprehensive debugging information.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * const error: BaseError = {
11
+ * name: "DatabaseError",
12
+ * message: "Connection failed",
13
+ * context: { host: "localhost", port: 5432 },
14
+ * cause: originalError
15
+ * };
16
+ * ```
17
+ */
18
+ type BaseError = Readonly<{
19
+ name: string;
20
+ message: string;
21
+ context?: Record<string, unknown>;
22
+ cause: unknown;
23
+ }>;
24
+ /**
25
+ * Creates a tagged error type for type-safe error handling.
26
+ * Uses the `name` property as a discriminator for tagged unions.
27
+ *
28
+ * Error types should follow the convention of ending with "Error" suffix.
29
+ * The Err data structure wraps these error types in the Result system.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * type ValidationError = TaggedError<"ValidationError">
34
+ * type NetworkError = TaggedError<"NetworkError">
35
+ *
36
+ * function handleError(error: ValidationError | NetworkError) {
37
+ * switch (error.name) {
38
+ * case "ValidationError": // TypeScript knows this is ValidationError
39
+ * break;
40
+ * case "NetworkError": // TypeScript knows this is NetworkError
41
+ * break;
42
+ * }
43
+ * }
44
+ *
45
+ * // Used in Result types:
46
+ * function validate(input: string): Result<string, ValidationError> {
47
+ * if (!input) {
48
+ * return Err({
49
+ * name: "ValidationError",
50
+ * message: "Input is required",
51
+ * context: { input },
52
+ * cause: null,
53
+ * });
54
+ * }
55
+ * return Ok(input);
56
+ * }
57
+ *
58
+ * // Context is optional - omit when not needed:
59
+ * function checkAuth(): Result<User, AuthError> {
60
+ * if (!isAuthenticated) {
61
+ * return Err({
62
+ * name: "AuthError",
63
+ * message: "User not authenticated",
64
+ * cause: null,
65
+ * });
66
+ * }
67
+ * return Ok(currentUser);
68
+ * }
69
+ * ```
70
+ */
71
+ type TaggedError<T extends string> = BaseError & {
72
+ readonly name: T;
73
+ };
74
+ //# sourceMappingURL=types.d.ts.map
75
+ //#endregion
76
+ //#region src/error/utils.d.ts
77
+ /**
78
+ * Extracts a readable error message from an unknown error value
79
+ *
80
+ * This utility is commonly used in mapError functions when converting
81
+ * unknown errors to typed error objects in the Result system.
82
+ *
83
+ * @param error - The unknown error to extract a message from
84
+ * @returns A string representation of the error
85
+ *
86
+ * @example
87
+ * ```ts
88
+ * // With native Error
89
+ * const error = new Error("Something went wrong");
90
+ * const message = extractErrorMessage(error); // "Something went wrong"
91
+ *
92
+ * // With string error
93
+ * const stringError = "String error";
94
+ * const message2 = extractErrorMessage(stringError); // "String error"
95
+ *
96
+ * // With object error
97
+ * const unknownError = { code: 500, details: "Server error" };
98
+ * const message3 = extractErrorMessage(unknownError); // '{"code":500,"details":"Server error"}'
99
+ *
100
+ * // Used in mapError function
101
+ * const result = await tryAsync({
102
+ * try: () => riskyOperation(),
103
+ * mapError: (error): NetworkError => ({
104
+ * name: "NetworkError",
105
+ * message: extractErrorMessage(error),
106
+ * context: { operation: "riskyOperation" },
107
+ * cause: error,
108
+ * }),
109
+ * });
110
+ * ```
111
+ */
112
+ declare function extractErrorMessage(error: unknown): string;
113
+ //# sourceMappingURL=utils.d.ts.map
114
+ //#endregion
115
+ export { BaseError, TaggedError, extractErrorMessage };
116
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/error/types.ts","../../src/error/utils.ts"],"sourcesContent":[],"mappings":";;AAgBA;;;;AAAgC;AAsDhC;;;;AACiB;;;;ACpCjB;;KDnBY,SAAA,GAAY;;;YAGb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAmDC,gCAAgC;iBAC5B;;;;;;AAvDhB;;;;AAAgC;AAsDhC;;;;AACiB;;;;ACpCjB;;;;;;;;;;;;;;;;;;;;;iBAAgB,mBAAA"}
@@ -0,0 +1,56 @@
1
+ //#region src/error/utils.ts
2
+ /**
3
+ * Extracts a readable error message from an unknown error value
4
+ *
5
+ * This utility is commonly used in mapError functions when converting
6
+ * unknown errors to typed error objects in the Result system.
7
+ *
8
+ * @param error - The unknown error to extract a message from
9
+ * @returns A string representation of the error
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * // With native Error
14
+ * const error = new Error("Something went wrong");
15
+ * const message = extractErrorMessage(error); // "Something went wrong"
16
+ *
17
+ * // With string error
18
+ * const stringError = "String error";
19
+ * const message2 = extractErrorMessage(stringError); // "String error"
20
+ *
21
+ * // With object error
22
+ * const unknownError = { code: 500, details: "Server error" };
23
+ * const message3 = extractErrorMessage(unknownError); // '{"code":500,"details":"Server error"}'
24
+ *
25
+ * // Used in mapError function
26
+ * const result = await tryAsync({
27
+ * try: () => riskyOperation(),
28
+ * mapError: (error): NetworkError => ({
29
+ * name: "NetworkError",
30
+ * message: extractErrorMessage(error),
31
+ * context: { operation: "riskyOperation" },
32
+ * cause: error,
33
+ * }),
34
+ * });
35
+ * ```
36
+ */
37
+ function extractErrorMessage(error) {
38
+ if (error instanceof Error) return error.message;
39
+ if (typeof error === "string") return error;
40
+ if (typeof error === "object" && error !== null) {
41
+ const errorObj = error;
42
+ if (typeof errorObj.message === "string") return errorObj.message;
43
+ if (typeof errorObj.error === "string") return errorObj.error;
44
+ if (typeof errorObj.description === "string") return errorObj.description;
45
+ try {
46
+ return JSON.stringify(error);
47
+ } catch {
48
+ return String(error);
49
+ }
50
+ }
51
+ return String(error);
52
+ }
53
+
54
+ //#endregion
55
+ export { extractErrorMessage };
56
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["error: unknown"],"sources":["../../src/error/utils.ts"],"sourcesContent":["/**\n * Extracts a readable error message from an unknown error value\n *\n * This utility is commonly used in mapError functions when converting\n * unknown errors to typed error objects in the Result system.\n *\n * @param error - The unknown error to extract a message from\n * @returns A string representation of the error\n *\n * @example\n * ```ts\n * // With native Error\n * const error = new Error(\"Something went wrong\");\n * const message = extractErrorMessage(error); // \"Something went wrong\"\n *\n * // With string error\n * const stringError = \"String error\";\n * const message2 = extractErrorMessage(stringError); // \"String error\"\n *\n * // With object error\n * const unknownError = { code: 500, details: \"Server error\" };\n * const message3 = extractErrorMessage(unknownError); // '{\"code\":500,\"details\":\"Server error\"}'\n *\n * // Used in mapError function\n * const result = await tryAsync({\n * try: () => riskyOperation(),\n * mapError: (error): NetworkError => ({\n * name: \"NetworkError\",\n * message: extractErrorMessage(error),\n * context: { operation: \"riskyOperation\" },\n * cause: error,\n * }),\n * });\n * ```\n */\nexport function extractErrorMessage(error: unknown): string {\n\tif (error instanceof Error) {\n\t\treturn error.message;\n\t}\n\n\tif (typeof error === \"string\") {\n\t\treturn error;\n\t}\n\n\tif (typeof error === \"object\" && error !== null) {\n\t\t// Check for common error properties\n\t\tconst errorObj = error as Record<string, unknown>;\n\t\tif (typeof errorObj.message === \"string\") {\n\t\t\treturn errorObj.message;\n\t\t}\n\t\tif (typeof errorObj.error === \"string\") {\n\t\t\treturn errorObj.error;\n\t\t}\n\t\tif (typeof errorObj.description === \"string\") {\n\t\t\treturn errorObj.description;\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\treturn String(error);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,SAAgB,oBAAoBA,OAAwB;AAC3D,KAAI,iBAAiB,MACpB,QAAO,MAAM;AAGd,YAAW,UAAU,SACpB,QAAO;AAGR,YAAW,UAAU,YAAY,UAAU,MAAM;EAEhD,MAAM,WAAW;AACjB,aAAW,SAAS,YAAY,SAC/B,QAAO,SAAS;AAEjB,aAAW,SAAS,UAAU,SAC7B,QAAO,SAAS;AAEjB,aAAW,SAAS,gBAAgB,SACnC,QAAO,SAAS;AAIjB,MAAI;AACH,UAAO,KAAK,UAAU,MAAM;EAC5B,QAAO;AACP,UAAO,OAAO,MAAM;EACpB;CACD;AAED,QAAO,OAAO,MAAM;AACpB"}
@@ -1,4 +1,4 @@
1
- //#region src/result.d.ts
1
+ //#region src/result/result.d.ts
2
2
  /**
3
3
  * Represents the successful outcome of an operation, encapsulating the success value.
4
4
  *
@@ -330,56 +330,104 @@ declare function tryAsync<T, E>({
330
330
  mapError: (error: unknown) => E;
331
331
  }): Promise<Result<T, E>>;
332
332
  /**
333
- * Unwraps a value if it is a `Result`, otherwise returns the value itself.
333
+ * Resolves a value that may or may not be wrapped in a `Result`, returning the final value.
334
334
  *
335
- * - If `value` is an `Ok<T>` variant, its `data` (the success value) is returned.
336
- * - If `value` is an `Err<E>` variant, its `error` (the error value) is thrown.
335
+ * This function handles the common pattern where a value might be a `Result<T, E>` or a plain `T`:
336
+ * - If `value` is an `Ok<T>` variant, returns the contained success value.
337
+ * - If `value` is an `Err<E>` variant, throws the contained error value.
337
338
  * - If `value` is not a `Result` (i.e., it's already a plain value of type `T`),
338
- * it is returned as-is.
339
+ * returns it as-is.
339
340
  *
340
- * This function is useful for situations where an operation might return either a
341
- * direct value or a `Result` wrapping a value/error, and you want to
342
- * uniformly access the value or propagate the error via throwing.
341
+ * This is useful when working with APIs that might return either direct values or Results,
342
+ * allowing you to normalize them to the actual value or propagate errors via throwing.
343
+ *
344
+ * Use `resolve` when the input might or might not be a Result.
345
+ * Use `unwrap` when you know the input is definitely a Result.
343
346
  *
344
347
  * @template T - The type of the success value (if `value` is `Ok<T>`) or the type of the plain value.
345
348
  * @template E - The type of the error value (if `value` is `Err<E>`).
346
- * @param value - The value to unwrap. It can be a `Result<T, E>` or a plain value of type `T`.
347
- * @returns The success value of type `T` if `value` is `Ok<T>` or if `value` is a plain `T`.
349
+ * @param value - The value to resolve. Can be a `Result<T, E>` or a plain value of type `T`.
350
+ * @returns The final value of type `T` if `value` is `Ok<T>` or if `value` is already a plain `T`.
348
351
  * @throws The error value `E` if `value` is an `Err<E>` variant.
349
352
  *
350
353
  * @example
351
354
  * ```ts
352
355
  * // Example with an Ok variant
353
356
  * const okResult = Ok("success data");
354
- * const unwrappedOk = unwrapIfResult(okResult); // "success data"
357
+ * const resolved = resolve(okResult); // "success data"
355
358
  *
356
359
  * // Example with an Err variant
357
360
  * const errResult = Err(new Error("failure"));
358
361
  * try {
359
- * unwrapIfResult(errResult);
362
+ * resolve(errResult);
360
363
  * } catch (e) {
361
364
  * console.error(e.message); // "failure"
362
365
  * }
363
366
  *
364
367
  * // Example with a plain value
365
368
  * const plainValue = "plain data";
366
- * const unwrappedPlain = unwrapIfResult(plainValue); // "plain data"
369
+ * const resolved = resolve(plainValue); // "plain data"
367
370
  *
368
371
  * // Example with a function that might return Result or plain value
369
372
  * declare function mightReturnResult(): string | Result<string, Error>;
370
373
  * const outcome = mightReturnResult();
371
374
  * try {
372
- * const finalValue = unwrapIfResult(outcome); // handles both cases
375
+ * const finalValue = resolve(outcome); // handles both cases
373
376
  * console.log("Final value:", finalValue);
374
377
  * } catch (e) {
375
378
  * console.error("Operation failed:", e);
376
379
  * }
377
380
  * ```
378
381
  */
379
- declare function unwrapIfResult<T, E>(value: T | Result<T, E>): T;
382
+ /**
383
+ * Unwraps a `Result<T, E>`, returning the success value or throwing the error.
384
+ *
385
+ * This function extracts the data from a `Result`:
386
+ * - If the `Result` is an `Ok<T>` variant, returns the contained success value of type `T`.
387
+ * - If the `Result` is an `Err<E>` variant, throws the contained error value of type `E`.
388
+ *
389
+ * Unlike `resolve`, this function expects the input to always be a `Result` type,
390
+ * making it more direct for cases where you know you're working with a `Result`.
391
+ *
392
+ * @template T - The type of the success value contained in the `Ok<T>` variant.
393
+ * @template E - The type of the error value contained in the `Err<E>` variant.
394
+ * @param result - The `Result<T, E>` to unwrap.
395
+ * @returns The success value of type `T` if the `Result` is `Ok<T>`.
396
+ * @throws The error value of type `E` if the `Result` is `Err<E>`.
397
+ *
398
+ * @example
399
+ * ```ts
400
+ * // Example with an Ok variant
401
+ * const okResult = Ok("success data");
402
+ * const value = unwrap(okResult); // "success data"
403
+ *
404
+ * // Example with an Err variant
405
+ * const errResult = Err(new Error("something went wrong"));
406
+ * try {
407
+ * unwrap(errResult);
408
+ * } catch (error) {
409
+ * console.error(error.message); // "something went wrong"
410
+ * }
411
+ *
412
+ * // Usage in a function that returns Result
413
+ * function divide(a: number, b: number): Result<number, string> {
414
+ * if (b === 0) return Err("Division by zero");
415
+ * return Ok(a / b);
416
+ * }
417
+ *
418
+ * try {
419
+ * const result = unwrap(divide(10, 2)); // 5
420
+ * console.log("Result:", result);
421
+ * } catch (error) {
422
+ * console.error("Division failed:", error);
423
+ * }
424
+ * ```
425
+ */
426
+ declare function unwrap<T, E>(result: Result<T, E>): T;
427
+ declare function resolve<T, E>(value: T | Result<T, E>): T;
380
428
  //# sourceMappingURL=result.d.ts.map
381
429
  //#endregion
382
- //#region src/utils.d.ts
430
+ //#region src/result/utils.d.ts
383
431
  /**
384
432
  * Partitions an array of Result objects into two separate arrays based on their status.
385
433
  *
@@ -401,109 +449,7 @@ declare function partitionResults<T, E>(results: Result<T, E>[]): {
401
449
  errs: Err<E>[];
402
450
  };
403
451
  //# sourceMappingURL=utils.d.ts.map
404
- //#endregion
405
- //#region src/error/types.d.ts
406
- type BaseError = Readonly<{
407
- name: string;
408
- message: string;
409
- context: Record<string, unknown>;
410
- cause: unknown;
411
- }>;
412
- /**
413
- * Creates a tagged error type for type-safe error handling.
414
- * Uses the `name` property as a discriminator for tagged unions.
415
- *
416
- * Error types should follow the convention of ending with "Error" suffix.
417
- * The Err data structure wraps these error types in the Result system.
418
- *
419
- * @example
420
- * ```ts
421
- * type ValidationError = TaggedError<"ValidationError">
422
- * type NetworkError = TaggedError<"NetworkError">
423
- *
424
- * function handleError(error: ValidationError | NetworkError) {
425
- * switch (error.name) {
426
- * case "ValidationError": // TypeScript knows this is ValidationError
427
- * break;
428
- * case "NetworkError": // TypeScript knows this is NetworkError
429
- * break;
430
- * }
431
- * }
432
- *
433
- * // Used in Result types:
434
- * function validate(input: string): Result<string, ValidationError> {
435
- * if (!input) {
436
- * return Err({
437
- * name: "ValidationError",
438
- * message: "Input is required",
439
- * context: { input },
440
- * cause: null,
441
- * });
442
- * }
443
- * return Ok(input);
444
- * }
445
- * ```
446
- */
447
- type TaggedError<T extends string> = BaseError & {
448
- readonly name: T;
449
- };
450
- declare function createTryFns<TName extends string>(name: TName): {
451
- trySync: <T>({
452
- try: operation,
453
- mapErr
454
- }: {
455
- try: () => T;
456
- mapErr: (error: unknown) => Omit<TaggedError<TName>, "name">;
457
- }) => Result<T, TaggedError<TName>>;
458
- tryAsync: <T>({
459
- try: operation,
460
- mapErr
461
- }: {
462
- try: () => Promise<T>;
463
- mapErr: (error: unknown) => Omit<TaggedError<TName>, "name">;
464
- }) => Promise<Result<T, TaggedError<TName>>>;
465
- };
466
- //# sourceMappingURL=types.d.ts.map
467
- //#endregion
468
- //#region src/error/utils.d.ts
469
- /**
470
- * Extracts a readable error message from an unknown error value
471
- *
472
- * This utility is commonly used in mapError functions when converting
473
- * unknown errors to typed error objects in the Result system.
474
- *
475
- * @param error - The unknown error to extract a message from
476
- * @returns A string representation of the error
477
- *
478
- * @example
479
- * ```ts
480
- * // With native Error
481
- * const error = new Error("Something went wrong");
482
- * const message = extractErrorMessage(error); // "Something went wrong"
483
- *
484
- * // With string error
485
- * const stringError = "String error";
486
- * const message2 = extractErrorMessage(stringError); // "String error"
487
- *
488
- * // With object error
489
- * const unknownError = { code: 500, details: "Server error" };
490
- * const message3 = extractErrorMessage(unknownError); // '{"code":500,"details":"Server error"}'
491
- *
492
- * // Used in mapError function
493
- * const result = await tryAsync({
494
- * try: () => riskyOperation(),
495
- * mapError: (error): NetworkError => ({
496
- * name: "NetworkError",
497
- * message: extractErrorMessage(error),
498
- * context: { operation: "riskyOperation" },
499
- * cause: error,
500
- * }),
501
- * });
502
- * ```
503
- */
504
- declare function extractErrorMessage(error: unknown): string;
505
- //# sourceMappingURL=utils.d.ts.map
506
452
 
507
453
  //#endregion
508
- export { BaseError, Err, ExtractErrFromResult, ExtractOkFromResult, Ok, Result, TaggedError, UnwrapErr, UnwrapOk, createTryFns, extractErrorMessage, isErr, isOk, isResult, partitionResults, tryAsync, trySync, unwrapIfResult };
454
+ export { Err, ExtractErrFromResult, ExtractOkFromResult, Ok, Result, UnwrapErr, UnwrapOk, isErr, isOk, isResult, partitionResults, resolve, tryAsync, trySync, unwrap };
509
455
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/result/result.ts","../../src/result/utils.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;AAiBlC;;;;;AAAqC;AAWrC;;;;AAAsE,KAlF1D,GAkF0D,CAAA,CAAA,CAAA,GAAA;EAAO,KAAA,EAlF/C,CAkF+C;EAcjE,IAAA,EAAA,IAAA;CAAoB;;;;AAA8C;AAuB9E;;;;;;AACI;AAqBJ;;;;;;AAGI;AAgCJ;;;;;AAEkB;AAuClB;;;;;;;AAA8D;AAyB9D;;;AAA8C,KA7MlC,MA6MkC,CAAA,CAAA,EAAA,CAAA,CAAA,GA7MnB,EA6MmB,CA7MhB,CA6MgB,CAAA,GA7MX,GA6MW,CA7MP,CA6MO,CAAA;;;;AAAkB;AAyChE;;;;;;;;;AAMU;AAsDV;AAA8B,cAjSjB,EAiSiB,EAAA,CAAA,CAAA,CAAA,CAAA,IAAA,EAjSF,CAiSE,EAAA,GAjSE,EAiSF,CAjSK,CAiSL,CAAA;;;;;;;;;;AAMnB;AAuGX;;;;;AAAoD,cA7XvC,GA6XuC,EAAA,CAAA,CAAA,CAAA,CAAA,KAAA,EA7XtB,CA6XsB,EAAA,GA7XlB,GA6XkB,CA7Xd,CA6Xc,CAAA;AAAC;AAOrD;;;;;;;AAAyD;KAzX7C,8BAA8B,4BAA4B,QACrE;;;ACxFD;;;;;;;;;AAK+B,KDgGnB,oBChGmB,CAAA,UDgGY,MChGZ,CAAA,OAAA,EAAA,OAAA,CAAA,CAAA,GDgGwC,OChGxC,CDiG9B,CCjG8B,EAAA;;;;;;;;;;;;;;;;;;;;;KDuHnB,mBAAmB,4BAA4B,UAAU,cAClE;;;;;;;;;;;;;;;;;;;KAqBS,oBAAoB,4BAA4B,UAAU,eAGnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgCa,6DAEJ,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;iBAuCN,mBAAmB,OAAO,GAAG,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;iBAyB/C,oBAAoB,OAAO,GAAG,eAAe,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyCjD;OACV;;;aAGM;gCACmB;IAC3B,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsDQ;OAChB;;;aAGM,QAAQ;gCACW;IAC3B,QAAQ,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuGN,qBAAqB,OAAO,GAAG,KAAK;iBAOpC,qBAAqB,IAAI,OAAO,GAAG,KAAK;;;;AAxdxD;AAaA;AAqCA;;;;;;AAAsC;AAiBtC;;;;;AAAkC;AAiBlC;AAAmE,iBC5EnD,gBD4EmD,CAAA,CAAA,EAAA,CAAA,CAAA,CAAA,OAAA,EC5EnB,MD4EmB,CC5EZ,CD4EY,EC5ET,CD4ES,CAAA,EAAA,CAAA,EAAA;EAAA,GAArC,ECvEjB,EDuEiB,CCvEd,CDuEc,CAAA,EAAA;EAAC,IAAO,ECvEV,GDuEU,CCvEN,CDuEM,CAAA,EAAA;CAAC;AAAF"}
@@ -1,4 +1,4 @@
1
- //#region src/result.ts
1
+ //#region src/result/result.ts
2
2
  /**
3
3
  * Constructs an `Ok<T>` variant, representing a successful outcome.
4
4
  *
@@ -225,53 +225,104 @@ async function tryAsync({ try: operation, mapError }) {
225
225
  }
226
226
  }
227
227
  /**
228
- * Unwraps a value if it is a `Result`, otherwise returns the value itself.
228
+ * Resolves a value that may or may not be wrapped in a `Result`, returning the final value.
229
229
  *
230
- * - If `value` is an `Ok<T>` variant, its `data` (the success value) is returned.
231
- * - If `value` is an `Err<E>` variant, its `error` (the error value) is thrown.
230
+ * This function handles the common pattern where a value might be a `Result<T, E>` or a plain `T`:
231
+ * - If `value` is an `Ok<T>` variant, returns the contained success value.
232
+ * - If `value` is an `Err<E>` variant, throws the contained error value.
232
233
  * - If `value` is not a `Result` (i.e., it's already a plain value of type `T`),
233
- * it is returned as-is.
234
+ * returns it as-is.
234
235
  *
235
- * This function is useful for situations where an operation might return either a
236
- * direct value or a `Result` wrapping a value/error, and you want to
237
- * uniformly access the value or propagate the error via throwing.
236
+ * This is useful when working with APIs that might return either direct values or Results,
237
+ * allowing you to normalize them to the actual value or propagate errors via throwing.
238
+ *
239
+ * Use `resolve` when the input might or might not be a Result.
240
+ * Use `unwrap` when you know the input is definitely a Result.
238
241
  *
239
242
  * @template T - The type of the success value (if `value` is `Ok<T>`) or the type of the plain value.
240
243
  * @template E - The type of the error value (if `value` is `Err<E>`).
241
- * @param value - The value to unwrap. It can be a `Result<T, E>` or a plain value of type `T`.
242
- * @returns The success value of type `T` if `value` is `Ok<T>` or if `value` is a plain `T`.
244
+ * @param value - The value to resolve. Can be a `Result<T, E>` or a plain value of type `T`.
245
+ * @returns The final value of type `T` if `value` is `Ok<T>` or if `value` is already a plain `T`.
243
246
  * @throws The error value `E` if `value` is an `Err<E>` variant.
244
247
  *
245
248
  * @example
246
249
  * ```ts
247
250
  * // Example with an Ok variant
248
251
  * const okResult = Ok("success data");
249
- * const unwrappedOk = unwrapIfResult(okResult); // "success data"
252
+ * const resolved = resolve(okResult); // "success data"
250
253
  *
251
254
  * // Example with an Err variant
252
255
  * const errResult = Err(new Error("failure"));
253
256
  * try {
254
- * unwrapIfResult(errResult);
257
+ * resolve(errResult);
255
258
  * } catch (e) {
256
259
  * console.error(e.message); // "failure"
257
260
  * }
258
261
  *
259
262
  * // Example with a plain value
260
263
  * const plainValue = "plain data";
261
- * const unwrappedPlain = unwrapIfResult(plainValue); // "plain data"
264
+ * const resolved = resolve(plainValue); // "plain data"
262
265
  *
263
266
  * // Example with a function that might return Result or plain value
264
267
  * declare function mightReturnResult(): string | Result<string, Error>;
265
268
  * const outcome = mightReturnResult();
266
269
  * try {
267
- * const finalValue = unwrapIfResult(outcome); // handles both cases
270
+ * const finalValue = resolve(outcome); // handles both cases
268
271
  * console.log("Final value:", finalValue);
269
272
  * } catch (e) {
270
273
  * console.error("Operation failed:", e);
271
274
  * }
272
275
  * ```
273
276
  */
274
- function unwrapIfResult(value) {
277
+ /**
278
+ * Unwraps a `Result<T, E>`, returning the success value or throwing the error.
279
+ *
280
+ * This function extracts the data from a `Result`:
281
+ * - If the `Result` is an `Ok<T>` variant, returns the contained success value of type `T`.
282
+ * - If the `Result` is an `Err<E>` variant, throws the contained error value of type `E`.
283
+ *
284
+ * Unlike `resolve`, this function expects the input to always be a `Result` type,
285
+ * making it more direct for cases where you know you're working with a `Result`.
286
+ *
287
+ * @template T - The type of the success value contained in the `Ok<T>` variant.
288
+ * @template E - The type of the error value contained in the `Err<E>` variant.
289
+ * @param result - The `Result<T, E>` to unwrap.
290
+ * @returns The success value of type `T` if the `Result` is `Ok<T>`.
291
+ * @throws The error value of type `E` if the `Result` is `Err<E>`.
292
+ *
293
+ * @example
294
+ * ```ts
295
+ * // Example with an Ok variant
296
+ * const okResult = Ok("success data");
297
+ * const value = unwrap(okResult); // "success data"
298
+ *
299
+ * // Example with an Err variant
300
+ * const errResult = Err(new Error("something went wrong"));
301
+ * try {
302
+ * unwrap(errResult);
303
+ * } catch (error) {
304
+ * console.error(error.message); // "something went wrong"
305
+ * }
306
+ *
307
+ * // Usage in a function that returns Result
308
+ * function divide(a: number, b: number): Result<number, string> {
309
+ * if (b === 0) return Err("Division by zero");
310
+ * return Ok(a / b);
311
+ * }
312
+ *
313
+ * try {
314
+ * const result = unwrap(divide(10, 2)); // 5
315
+ * console.log("Result:", result);
316
+ * } catch (error) {
317
+ * console.error("Division failed:", error);
318
+ * }
319
+ * ```
320
+ */
321
+ function unwrap(result) {
322
+ if (isOk(result)) return result.data;
323
+ throw result.error;
324
+ }
325
+ function resolve(value) {
275
326
  if (isResult(value)) {
276
327
  if (isOk(value)) return value.data;
277
328
  throw value.error;
@@ -280,7 +331,7 @@ function unwrapIfResult(value) {
280
331
  }
281
332
 
282
333
  //#endregion
283
- //#region src/utils.ts
334
+ //#region src/result/utils.ts
284
335
  /**
285
336
  * Partitions an array of Result objects into two separate arrays based on their status.
286
337
  *
@@ -306,80 +357,5 @@ function partitionResults(results) {
306
357
  }
307
358
 
308
359
  //#endregion
309
- //#region src/error/utils.ts
310
- /**
311
- * Extracts a readable error message from an unknown error value
312
- *
313
- * This utility is commonly used in mapError functions when converting
314
- * unknown errors to typed error objects in the Result system.
315
- *
316
- * @param error - The unknown error to extract a message from
317
- * @returns A string representation of the error
318
- *
319
- * @example
320
- * ```ts
321
- * // With native Error
322
- * const error = new Error("Something went wrong");
323
- * const message = extractErrorMessage(error); // "Something went wrong"
324
- *
325
- * // With string error
326
- * const stringError = "String error";
327
- * const message2 = extractErrorMessage(stringError); // "String error"
328
- *
329
- * // With object error
330
- * const unknownError = { code: 500, details: "Server error" };
331
- * const message3 = extractErrorMessage(unknownError); // '{"code":500,"details":"Server error"}'
332
- *
333
- * // Used in mapError function
334
- * const result = await tryAsync({
335
- * try: () => riskyOperation(),
336
- * mapError: (error): NetworkError => ({
337
- * name: "NetworkError",
338
- * message: extractErrorMessage(error),
339
- * context: { operation: "riskyOperation" },
340
- * cause: error,
341
- * }),
342
- * });
343
- * ```
344
- */
345
- function extractErrorMessage(error) {
346
- if (error instanceof Error) return error.message;
347
- if (typeof error === "string") return error;
348
- if (typeof error === "object" && error !== null) {
349
- const errorObj = error;
350
- if (typeof errorObj.message === "string") return errorObj.message;
351
- if (typeof errorObj.error === "string") return errorObj.error;
352
- if (typeof errorObj.description === "string") return errorObj.description;
353
- try {
354
- return JSON.stringify(error);
355
- } catch {
356
- return String(error);
357
- }
358
- }
359
- return String(error);
360
- }
361
-
362
- //#endregion
363
- //#region src/error/types.ts
364
- function createTryFns(name) {
365
- return {
366
- trySync: ({ try: operation, mapErr }) => trySync({
367
- try: operation,
368
- mapErr: (error) => ({
369
- ...mapErr(error),
370
- name
371
- })
372
- }),
373
- tryAsync: ({ try: operation, mapErr }) => tryAsync({
374
- try: operation,
375
- mapErr: (error) => ({
376
- ...mapErr(error),
377
- name
378
- })
379
- })
380
- };
381
- }
382
-
383
- //#endregion
384
- export { Err, Ok, createTryFns, extractErrorMessage, isErr, isOk, isResult, partitionResults, tryAsync, trySync, unwrapIfResult };
360
+ export { Err, Ok, isErr, isOk, isResult, partitionResults, resolve, tryAsync, trySync, unwrap };
385
361
  //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["data: T","error: E","value: unknown","result: Result<T, E>","value: T | Result<T, E>","results: Result<T, E>[]"],"sources":["../../src/result/result.ts","../../src/result/utils.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 * This factory function creates the error variant of a `Result`.\n * It wraps the provided `error` (the error value) and ensures the `data` property is `null`.\n *\n * @template E - The type of the error value.\n * @param error - The error value to be wrapped in the `Err` variant. This value represents the specific error that occurred.\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 `Ok<T>` variant from a `Result<T, E>` union type.\n *\n * If `R` is a `Result` type (e.g., `Result<string, Error>`), this type will resolve\n * to `Ok<string>`. This can be useful in generic contexts or for type narrowing.\n *\n * @template R - The `Result<T, E>` union type from which to extract the `Ok<T>` variant.\n * Must extend `Result<unknown, unknown>`.\n */\nexport type ExtractOkFromResult<R extends Result<unknown, unknown>> = Extract<\n\tR,\n\t{ error: null }\n>;\n\n/**\n * Utility type to extract the `Err<E>` variant from a `Result<T, E>` union type.\n *\n * If `R` is a `Result` type (e.g., `Result<string, Error>`), this type will resolve\n * to `Err<Error>`. This can be useful in generic contexts or for type narrowing.\n *\n * @template R - The `Result<T, E>` union type from which to extract the `Err<E>` variant.\n * Must extend `Result<unknown, unknown>`.\n */\nexport type ExtractErrFromResult<R extends Result<unknown, unknown>> = Extract<\n\tR,\n\t{ data: null }\n>;\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. Exactly one of `data` or `error` is `null`. The other must be non-`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\tconst isBothNull = value.data === null && value.error === null;\n\tif (isBothNull) return false;\n\n\tconst isNeitherNull = value.data !== null && value.error !== null;\n\tif (isNeitherNull) return false;\n\n\t// Exactly one property is null\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 (success or failure) in a `Result<T, E>`.\n *\n * This function attempts to execute the `operation`.\n * - If `operation` completes successfully, its return value is wrapped in an `Ok<T>` variant.\n * - If `operation` throws an exception, the caught exception (of type `unknown`) is passed to\n * the `mapError` function. `mapError` is responsible for transforming this `unknown`\n * exception into a well-typed error value of type `E`. This error value is then wrapped\n * in an `Err<E>` variant.\n *\n * @template T - The type of the success value returned by the `operation` if it succeeds.\n * @template E - The type of the error value produced by `mapError` if the `operation` fails.\n * @param options - An object containing the operation and error mapping function.\n * @param options.try - The synchronous operation to execute. This function is expected to return a value of type `T`.\n * @param options.mapError - A function that takes the `unknown` exception caught from `options.try`\n * and transforms it into a specific error value of type `E`. This function\n * is crucial for creating a well-typed error for the `Err<E>` variant.\n * @returns A `Result<T, E>`: `Ok<T>` if `options.try` succeeds, or `Err<E>` if it throws and `options.mapError` provides an error value.\n * @example\n * ```ts\n * function parseJson(jsonString: string): Result<object, SyntaxError> {\n * return trySync({\n * try: () => JSON.parse(jsonString),\n * mapError: (err: unknown) => {\n * if (err instanceof SyntaxError) return err;\n * return new SyntaxError(\"Unknown parsing error\");\n * }\n * });\n * }\n *\n * const validResult = parseJson('{\"name\":\"Result\"}'); // Ok<{name: string}>\n * const invalidResult = parseJson('invalid json'); // Err<SyntaxError>\n *\n * if (isOk(validResult)) console.log(validResult.data);\n * if (isErr(invalidResult)) console.error(invalidResult.error.message);\n * ```\n */\nexport function trySync<T, E>({\n\ttry: operation,\n\tmapError,\n}: {\n\ttry: () => T;\n\tmapError: (error: unknown) => E;\n}): Result<T, E> {\n\ttry {\n\t\tconst data = operation();\n\t\treturn Ok(data);\n\t} catch (error) {\n\t\treturn Err(mapError(error));\n\t}\n}\n\n/**\n * Executes an asynchronous operation (returning a `Promise`) and wraps its outcome in a `Promise<Result<T, E>>`.\n *\n * This function attempts to execute the asynchronous `operation`.\n * - If the `Promise` returned by `operation` resolves successfully, its resolved value is wrapped in an `Ok<T>` variant.\n * - If the `Promise` returned by `operation` rejects, or if `operation` itself throws an exception synchronously,\n * the caught exception/rejection reason (of type `unknown`) is passed to the `mapError` function.\n * `mapError` is responsible for transforming this `unknown` error into a well-typed error value of type `E`.\n * This error value is then wrapped in an `Err<E>` variant.\n *\n * The entire outcome (`Ok<T>` or `Err<E>`) is wrapped in a `Promise`.\n *\n * @template T - The type of the success value the `Promise` from `operation` resolves to.\n * @template E - The type of the error value produced by `mapError` if the `operation` fails or rejects.\n * @param options - An object containing the asynchronous operation and error mapping function.\n * @param options.try - The asynchronous operation to execute. This function must return a `Promise<T>`.\n * @param options.mapError - A function that takes the `unknown` exception/rejection reason caught from `options.try`\n * and transforms it into a specific error value of type `E`. This function\n * is crucial for creating a well-typed error for the `Err<E>` variant.\n * @returns A `Promise` that resolves to a `Result<T, E>`: `Ok<T>` if `options.try`'s `Promise` resolves,\n * or `Err<E>` if it rejects/throws and `options.mapError` provides an error value.\n * @example\n * ```ts\n * async function fetchData(url: string): Promise<Result<Response, Error>> {\n * return tryAsync({\n * try: async () => fetch(url),\n * mapError: (err: unknown) => {\n * if (err instanceof Error) return err;\n * return new Error(\"Network request failed\");\n * }\n * });\n * }\n *\n * async function processData() {\n * const result = await fetchData(\"/api/data\");\n * if (isOk(result)) {\n * const response = result.data;\n * console.log(\"Data fetched:\", await response.json());\n * } else {\n * console.error(\"Fetch error:\", result.error.message);\n * }\n * }\n * processData();\n * ```\n */\nexport async function tryAsync<T, E>({\n\ttry: operation,\n\tmapError,\n}: {\n\ttry: () => Promise<T>;\n\tmapError: (error: unknown) => E;\n}): Promise<Result<T, E>> {\n\ttry {\n\t\tconst data = await operation();\n\t\treturn Ok(data);\n\t} catch (error) {\n\t\treturn Err(mapError(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","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":";;;;;;;;;;;;;;;;AA8EA,MAAa,KAAK,CAAIA,UAAoB;CAAE;CAAM,OAAO;AAAM;;;;;;;;;;;;;;;;AAiB/D,MAAa,MAAM,CAAIC,WAAsB;CAAE;CAAO,MAAM;AAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyGlE,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;CAElD,MAAM,aAAa,MAAM,SAAS,QAAQ,MAAM,UAAU;AAC1D,KAAI,WAAY,QAAO;CAEvB,MAAM,gBAAgB,MAAM,SAAS,QAAQ,MAAM,UAAU;AAC7D,KAAI,cAAe,QAAO;AAG1B,QAAO;AACP;;;;;;;;;;;;;;;;;;;;;;AAuBD,SAAgB,KAAWC,QAAuC;AACjE,QAAO,OAAO,UAAU;AACxB;;;;;;;;;;;;;;;;;;;;;;AAuBD,SAAgB,MAAYA,QAAwC;AACnE,QAAO,OAAO,UAAU;AACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCD,SAAgB,QAAc,EAC7B,KAAK,WACL,UAIA,EAAgB;AAChB,KAAI;EACH,MAAM,OAAO,WAAW;AACxB,SAAO,GAAG,KAAK;CACf,SAAQ,OAAO;AACf,SAAO,IAAI,SAAS,MAAM,CAAC;CAC3B;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CD,eAAsB,SAAe,EACpC,KAAK,WACL,UAIA,EAAyB;AACzB,KAAI;EACH,MAAM,OAAO,MAAM,WAAW;AAC9B,SAAO,GAAG,KAAK;CACf,SAAQ,OAAO;AACf,SAAO,IAAI,SAAS,MAAM,CAAC;CAC3B;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;;;;;;;;;;;;;;;;;;;;AC9dD,SAAgB,iBAAuBC,SAAyB;AAC/D,QAAO;EACN,KAAK,CAAE;EACP,MAAM,CAAE;EACR,GAAG,OAAO,QAAQ,SAAS,CAAC,WAAY,KAAK,OAAO,GAAG,QAAQ,OAAQ;CACvE;AACD"}
package/package.json CHANGED
@@ -1,47 +1,51 @@
1
1
  {
2
- "name": "wellcrafted",
3
- "version": "0.15.0",
4
- "description": "Delightful TypeScript patterns for elegant, type-safe applications",
5
- "type": "module",
6
- "files": ["dist", "README.md", "LICENSE"],
7
- "exports": {
8
- "./result": {
9
- "types": "./dist/result.d.ts",
10
- "import": "./dist/result.js"
11
- },
12
- "./error": {
13
- "types": "./dist/error/index.d.ts",
14
- "import": "./dist/error/index.js"
15
- },
16
- "./brand": {
17
- "types": "./dist/brand.d.ts",
18
- "import": "./dist/brand.js"
19
- }
20
- },
21
- "scripts": {
22
- "build": "tsdown",
23
- "format": "biome format --write .",
24
- "lint": "biome lint --write .",
25
- "release": "pnpm run build && changeset version && changeset publish"
26
- },
27
- "keywords": [
28
- "typescript",
29
- "delightful",
30
- "elegant",
31
- "type-safe",
32
- "well-crafted",
33
- "polished",
34
- "utilities",
35
- "result",
36
- "error-handling",
37
- "brand-types"
38
- ],
39
- "author": "",
40
- "license": "MIT",
41
- "devDependencies": {
42
- "@biomejs/biome": "^1.9.4",
43
- "@changesets/cli": "^2.27.10",
44
- "tsdown": "^0.12.5",
45
- "typescript": "^5.7.2"
46
- }
47
- }
2
+ "name": "wellcrafted",
3
+ "version": "0.17.0",
4
+ "description": "Delightful TypeScript patterns for elegant, type-safe applications",
5
+ "type": "module",
6
+ "files": [
7
+ "dist",
8
+ "README.md",
9
+ "LICENSE"
10
+ ],
11
+ "exports": {
12
+ "./result": {
13
+ "types": "./dist/result/index.d.ts",
14
+ "import": "./dist/result/index.js"
15
+ },
16
+ "./error": {
17
+ "types": "./dist/error/index.d.ts",
18
+ "import": "./dist/error/index.js"
19
+ },
20
+ "./brand": {
21
+ "types": "./dist/brand.d.ts",
22
+ "import": "./dist/brand.js"
23
+ }
24
+ },
25
+ "keywords": [
26
+ "typescript",
27
+ "delightful",
28
+ "elegant",
29
+ "type-safe",
30
+ "well-crafted",
31
+ "polished",
32
+ "utilities",
33
+ "result",
34
+ "error-handling",
35
+ "brand-types"
36
+ ],
37
+ "author": "",
38
+ "license": "MIT",
39
+ "devDependencies": {
40
+ "@biomejs/biome": "^1.9.4",
41
+ "@changesets/cli": "^2.27.10",
42
+ "tsdown": "^0.12.5",
43
+ "typescript": "^5.7.2"
44
+ },
45
+ "scripts": {
46
+ "build": "tsdown",
47
+ "format": "biome format --write .",
48
+ "lint": "biome lint --write .",
49
+ "release": "pnpm run build && changeset version && changeset publish"
50
+ }
51
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/result.ts","../src/utils.ts","../src/error/types.ts","../src/error/utils.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;AAiBlC;;;;;AAAqC;AAWrC;;;;AAAsE,KAlF1D,GAkF0D,CAAA,CAAA,CAAA,GAAA;EAAO,KAAA,EAlF/C,CAkF+C;EAcjE,IAAA,EAAA,IAAA;CAAoB;;;;AAA8C;AAuB9E;;;;;;AACI;AAqBJ;;;;;;AAGI;AAgCJ;;;;;AAEkB;AAuClB;;;;;;;AAA8D;AAyB9D;;;AAA8C,KA7MlC,MA6MkC,CAAA,CAAA,EAAA,CAAA,CAAA,GA7MnB,EA6MmB,CA7MhB,CA6MgB,CAAA,GA7MX,GA6MW,CA7MP,CA6MO,CAAA;;;;AAAkB;AAyChE;;;;;;;;;AAMU;AAsDV;AAA8B,cAjSjB,EAiSiB,EAAA,CAAA,CAAA,CAAA,CAAA,IAAA,EAjSF,CAiSE,EAAA,GAjSE,EAiSF,CAjSK,CAiSL,CAAA;;;;;;;;;;AAMnB;AAwDX;;;;;AAAgD,cA9UnC,GA8UmC,EAAA,CAAA,CAAA,CAAA,CAAA,KAAA,EA9UlB,CA8UkB,EAAA,GA9Ud,GA8Uc,CA9UV,CA8UU,CAAA;;AAAgB;;;;AC1ZhE;;;;AAAgD,KDuFpC,mBCvFoC,CAAA,UDuFN,MCvFM,CAAA,OAAA,EAAA,OAAA,CAAA,CAAA,GDuFsB,OCvFtB,CDwF/C,CCxF+C,EAAA;EAAM,KAKtC,EAAA,IAAA;CAAC,CAAA;;;AAAc;;;;ACrB/B;;;AAAwB,KFqHZ,oBErHY,CAAA,UFqHmB,MErHnB,CAAA,OAAA,EAAA,OAAA,CAAA,CAAA,GFqH+C,OErH/C,CFsHvB,CEtHuB,EAAA;EAAQ,IAAA,EAAA,IAAA;AA0ChC,CAAA,CAAA;;;;AACiB;AAGjB;;;;;;;;;;;;;;AAiBc,KF6EF,QE7EE,CAAA,UF6EiB,ME7EjB,CAAA,OAAA,EAAA,OAAA,CAAA,CAAA,GF6E6C,CE7E7C,SF6EuD,EE7EvD,CAAA,KAAA,EAAA,CAAA,GF8EX,CE9EW,GAAA,KAAA;;;;;;;;;;;AAMX;;;;ACrCH;;;;KHkIY,oBAAoB,4BAA4B,UAAU,eAGnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgCa,6DAEJ,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;iBAuCN,mBAAmB,OAAO,GAAG,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;iBAyB/C,oBAAoB,OAAO,GAAG,eAAe,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyCjD;OACV;;;aAGM;gCACmB;IAC3B,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsDQ;OAChB;;;aAGM,QAAQ;gCACW;IAC3B,QAAQ,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwDN,4BAA4B,IAAI,OAAO,GAAG,KAAK;;;;AAla/D;AAaA;AAqCA;;;;;;AAAsC;AAiBtC;;;;;AAAkC;AAiBlC;AAAmE,iBC5EnD,gBD4EmD,CAAA,CAAA,EAAA,CAAA,CAAA,CAAA,OAAA,EC5EnB,MD4EmB,CC5EZ,CD4EY,EC5ET,CD4ES,CAAA,EAAA,CAAA,EAAA;EAAA,GAArC,ECvEjB,EDuEiB,CCvEd,CDuEc,CAAA,EAAA;EAAC,IAAO,ECvEV,GDuEU,CCvEN,CDuEM,CAAA,EAAA;CAAC;AAAF;;;KE5FzB,SAAA,GAAY;EFQZ,IAAA,EAAE,MAAA;EAaF,OAAG,EAAA,MAAA;EAqCH,OAAA,EEvDF,MFuDQ,CAAA,MAAA,EAAA,OAAA,CAAA;EAAA,KAAA,EAAA,OAAA;CAAA,CAAA;;;;AAAoB;AAiBtC;;;;;AAAkC;AAiBlC;;;;;AAAqC;AAWrC;;;;;AAA6E;AAc7E;;;;;AAA8E;AAuB9E;;;;;;AACI;AAqBQ,KExHA,WFwHS,CAAA,UAAA,MAAA,CAAA,GExHuB,SFwHvB,GAAA;EAAA,SAAA,IAAA,EEvHL,CFuHK;CAAA;AAAuC,iBEpH5C,YFoH4C,CAAA,cAAA,MAAA,CAAA,CAAA,IAAA,EEpHH,KFoHG,CAAA,EAAA;EAAC,OAAS,EAAA,CAAA,CAAA,CAAA,CAAA;IAAA,GAAA,EEjHzD,SFiHyD;IAAA;EAmCtD,CAnCsD,EAAA;IAGnE,GAAA,EAAA,GAAA,GEhHW,CFgHX;IAAC,MAAA,EAAA,CAAA,KAAA,EAAA,OAAA,EAAA,GE/G2B,IF+G3B,CE/G+B,WF+G/B,CE/G+B,KF+G/B,CAAA,EAAA,MAAA,CAAA;EAgCY,CAAA,EAAA,GE9Ib,MF8IqB,CE9IrB,CF8IqB,EE9IrB,WF8IqB,CE9IrB,KF8IqB,CAAA,CAAA;EAAA,QAAA,EAAA,CAAA,CAAA,CAAA,CAAA;IAAA,GAAA,EEtIV,SFsIU;IAAA;EAED,CAFC,EAAA;IAEL,GAAA,EAAA,GAAA,GEpIL,OFoIK,CEpIG,CFoIH,CAAA;IAAG,MAAA,EAAA,CAAA,KAAA,EAAA,OAAA,EAAA,GEnIS,IFmIT,CEnIa,WFmIb,CEnIa,KFmIb,CAAA,EAAA,MAAA,CAAA;EAAC,CAAA,EAAX,GElIT,OFkIS,CElIT,MFkIS,CElIT,CFkIS,EElIT,WFkIS,CElIT,KFkIS,CAAA,CAAA,CAAA;AAAM,CAAA;AAuClB;;;;AAtOA;AAaA;AAqCA;;;;;;AAAsC;AAiBtC;;;;;AAAkC;AAiBlC;;;;;AAAqC;AAWrC;;;;;AAA6E;AAc7E;;;;;AAA8E;AAuB9E;AAAoB,iBG5GJ,mBAAA,CH4GI,KAAA,EAAA,OAAA,CAAA,EAAA,MAAA"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":["data: T","error: E","value: unknown","result: Result<T, E>","value: T | Result<T, E>","results: Result<T, E>[]","error: unknown","name: TName"],"sources":["../src/result.ts","../src/utils.ts","../src/error/utils.ts","../src/error/types.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 * This factory function creates the error variant of a `Result`.\n * It wraps the provided `error` (the error value) and ensures the `data` property is `null`.\n *\n * @template E - The type of the error value.\n * @param error - The error value to be wrapped in the `Err` variant. This value represents the specific error that occurred.\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 `Ok<T>` variant from a `Result<T, E>` union type.\n *\n * If `R` is a `Result` type (e.g., `Result<string, Error>`), this type will resolve\n * to `Ok<string>`. This can be useful in generic contexts or for type narrowing.\n *\n * @template R - The `Result<T, E>` union type from which to extract the `Ok<T>` variant.\n * Must extend `Result<unknown, unknown>`.\n */\nexport type ExtractOkFromResult<R extends Result<unknown, unknown>> = Extract<\n\tR,\n\t{ error: null }\n>;\n\n/**\n * Utility type to extract the `Err<E>` variant from a `Result<T, E>` union type.\n *\n * If `R` is a `Result` type (e.g., `Result<string, Error>`), this type will resolve\n * to `Err<Error>`. This can be useful in generic contexts or for type narrowing.\n *\n * @template R - The `Result<T, E>` union type from which to extract the `Err<E>` variant.\n * Must extend `Result<unknown, unknown>`.\n */\nexport type ExtractErrFromResult<R extends Result<unknown, unknown>> = Extract<\n\tR,\n\t{ data: null }\n>;\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. Exactly one of `data` or `error` is `null`. The other must be non-`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\tconst isBothNull = value.data === null && value.error === null;\n\tif (isBothNull) return false;\n\n\tconst isNeitherNull = value.data !== null && value.error !== null;\n\tif (isNeitherNull) return false;\n\n\t// Exactly one property is null\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 (success or failure) in a `Result<T, E>`.\n *\n * This function attempts to execute the `operation`.\n * - If `operation` completes successfully, its return value is wrapped in an `Ok<T>` variant.\n * - If `operation` throws an exception, the caught exception (of type `unknown`) is passed to\n * the `mapError` function. `mapError` is responsible for transforming this `unknown`\n * exception into a well-typed error value of type `E`. This error value is then wrapped\n * in an `Err<E>` variant.\n *\n * @template T - The type of the success value returned by the `operation` if it succeeds.\n * @template E - The type of the error value produced by `mapError` if the `operation` fails.\n * @param options - An object containing the operation and error mapping function.\n * @param options.try - The synchronous operation to execute. This function is expected to return a value of type `T`.\n * @param options.mapError - A function that takes the `unknown` exception caught from `options.try`\n * and transforms it into a specific error value of type `E`. This function\n * is crucial for creating a well-typed error for the `Err<E>` variant.\n * @returns A `Result<T, E>`: `Ok<T>` if `options.try` succeeds, or `Err<E>` if it throws and `options.mapError` provides an error value.\n * @example\n * ```ts\n * function parseJson(jsonString: string): Result<object, SyntaxError> {\n * return trySync({\n * try: () => JSON.parse(jsonString),\n * mapError: (err: unknown) => {\n * if (err instanceof SyntaxError) return err;\n * return new SyntaxError(\"Unknown parsing error\");\n * }\n * });\n * }\n *\n * const validResult = parseJson('{\"name\":\"Result\"}'); // Ok<{name: string}>\n * const invalidResult = parseJson('invalid json'); // Err<SyntaxError>\n *\n * if (isOk(validResult)) console.log(validResult.data);\n * if (isErr(invalidResult)) console.error(invalidResult.error.message);\n * ```\n */\nexport function trySync<T, E>({\n\ttry: operation,\n\tmapError,\n}: {\n\ttry: () => T;\n\tmapError: (error: unknown) => E;\n}): Result<T, E> {\n\ttry {\n\t\tconst data = operation();\n\t\treturn Ok(data);\n\t} catch (error) {\n\t\treturn Err(mapError(error));\n\t}\n}\n\n/**\n * Executes an asynchronous operation (returning a `Promise`) and wraps its outcome in a `Promise<Result<T, E>>`.\n *\n * This function attempts to execute the asynchronous `operation`.\n * - If the `Promise` returned by `operation` resolves successfully, its resolved value is wrapped in an `Ok<T>` variant.\n * - If the `Promise` returned by `operation` rejects, or if `operation` itself throws an exception synchronously,\n * the caught exception/rejection reason (of type `unknown`) is passed to the `mapError` function.\n * `mapError` is responsible for transforming this `unknown` error into a well-typed error value of type `E`.\n * This error value is then wrapped in an `Err<E>` variant.\n *\n * The entire outcome (`Ok<T>` or `Err<E>`) is wrapped in a `Promise`.\n *\n * @template T - The type of the success value the `Promise` from `operation` resolves to.\n * @template E - The type of the error value produced by `mapError` if the `operation` fails or rejects.\n * @param options - An object containing the asynchronous operation and error mapping function.\n * @param options.try - The asynchronous operation to execute. This function must return a `Promise<T>`.\n * @param options.mapError - A function that takes the `unknown` exception/rejection reason caught from `options.try`\n * and transforms it into a specific error value of type `E`. This function\n * is crucial for creating a well-typed error for the `Err<E>` variant.\n * @returns A `Promise` that resolves to a `Result<T, E>`: `Ok<T>` if `options.try`'s `Promise` resolves,\n * or `Err<E>` if it rejects/throws and `options.mapError` provides an error value.\n * @example\n * ```ts\n * async function fetchData(url: string): Promise<Result<Response, Error>> {\n * return tryAsync({\n * try: async () => fetch(url),\n * mapError: (err: unknown) => {\n * if (err instanceof Error) return err;\n * return new Error(\"Network request failed\");\n * }\n * });\n * }\n *\n * async function processData() {\n * const result = await fetchData(\"/api/data\");\n * if (isOk(result)) {\n * const response = result.data;\n * console.log(\"Data fetched:\", await response.json());\n * } else {\n * console.error(\"Fetch error:\", result.error.message);\n * }\n * }\n * processData();\n * ```\n */\nexport async function tryAsync<T, E>({\n\ttry: operation,\n\tmapError,\n}: {\n\ttry: () => Promise<T>;\n\tmapError: (error: unknown) => E;\n}): Promise<Result<T, E>> {\n\ttry {\n\t\tconst data = await operation();\n\t\treturn Ok(data);\n\t} catch (error) {\n\t\treturn Err(mapError(error));\n\t}\n}\n\n/**\n * Unwraps a value if it is a `Result`, otherwise returns the value itself.\n *\n * - If `value` is an `Ok<T>` variant, its `data` (the success value) is returned.\n * - If `value` is an `Err<E>` variant, its `error` (the error value) is thrown.\n * - If `value` is not a `Result` (i.e., it's already a plain value of type `T`),\n * it is returned as-is.\n *\n * This function is useful for situations where an operation might return either a\n * direct value or a `Result` wrapping a value/error, and you want to\n * uniformly access the value or propagate the error via throwing.\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 unwrap. It can be a `Result<T, E>` or a plain value of type `T`.\n * @returns The success value of type `T` if `value` is `Ok<T>` or if `value` is 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 unwrappedOk = unwrapIfResult(okResult); // \"success data\"\n *\n * // Example with an Err variant\n * const errResult = Err(new Error(\"failure\"));\n * try {\n * unwrapIfResult(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 unwrappedPlain = unwrapIfResult(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 = unwrapIfResult(outcome); // handles both cases\n * console.log(\"Final value:\", finalValue);\n * } catch (e) {\n * console.error(\"Operation failed:\", e);\n * }\n * ```\n */\nexport function unwrapIfResult<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","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","/**\n * Extracts a readable error message from an unknown error value\n *\n * This utility is commonly used in mapError functions when converting\n * unknown errors to typed error objects in the Result system.\n *\n * @param error - The unknown error to extract a message from\n * @returns A string representation of the error\n *\n * @example\n * ```ts\n * // With native Error\n * const error = new Error(\"Something went wrong\");\n * const message = extractErrorMessage(error); // \"Something went wrong\"\n *\n * // With string error\n * const stringError = \"String error\";\n * const message2 = extractErrorMessage(stringError); // \"String error\"\n *\n * // With object error\n * const unknownError = { code: 500, details: \"Server error\" };\n * const message3 = extractErrorMessage(unknownError); // '{\"code\":500,\"details\":\"Server error\"}'\n *\n * // Used in mapError function\n * const result = await tryAsync({\n * try: () => riskyOperation(),\n * mapError: (error): NetworkError => ({\n * name: \"NetworkError\",\n * message: extractErrorMessage(error),\n * context: { operation: \"riskyOperation\" },\n * cause: error,\n * }),\n * });\n * ```\n */\nexport function extractErrorMessage(error: unknown): string {\n\tif (error instanceof Error) {\n\t\treturn error.message;\n\t}\n\n\tif (typeof error === \"string\") {\n\t\treturn error;\n\t}\n\n\tif (typeof error === \"object\" && error !== null) {\n\t\t// Check for common error properties\n\t\tconst errorObj = error as Record<string, unknown>;\n\t\tif (typeof errorObj.message === \"string\") {\n\t\t\treturn errorObj.message;\n\t\t}\n\t\tif (typeof errorObj.error === \"string\") {\n\t\t\treturn errorObj.error;\n\t\t}\n\t\tif (typeof errorObj.description === \"string\") {\n\t\t\treturn errorObj.description;\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\treturn String(error);\n}\n","import { tryAsync, trySync } from \"../result.js\";\nimport { extractErrorMessage } from \"./utils.js\";\n\nexport type BaseError = Readonly<{\n\tname: string;\n\tmessage: string;\n\tcontext: Record<string, unknown>;\n\tcause: unknown;\n}>;\n\n/**\n * Creates a tagged error type for type-safe error handling.\n * Uses the `name` property as a discriminator for tagged unions.\n *\n * Error types should follow the convention of ending with \"Error\" suffix.\n * The Err data structure wraps these error types in the Result system.\n *\n * @example\n * ```ts\n * type ValidationError = TaggedError<\"ValidationError\">\n * type NetworkError = TaggedError<\"NetworkError\">\n *\n * function handleError(error: ValidationError | NetworkError) {\n * switch (error.name) {\n * case \"ValidationError\": // TypeScript knows this is ValidationError\n * break;\n * case \"NetworkError\": // TypeScript knows this is NetworkError\n * break;\n * }\n * }\n *\n * // Used in Result types:\n * function validate(input: string): Result<string, ValidationError> {\n * if (!input) {\n * return Err({\n * name: \"ValidationError\",\n * message: \"Input is required\",\n * context: { input },\n * cause: null,\n * });\n * }\n * return Ok(input);\n * }\n * ```\n */\nexport type TaggedError<T extends string> = BaseError & {\n\treadonly name: T;\n};\n\nexport function createTryFns<TName extends string>(name: TName) {\n\ttype TError = TaggedError<TName>;\n\treturn {\n\t\ttrySync: <T>({\n\t\t\ttry: operation,\n\t\t\tmapErr,\n\t\t}: {\n\t\t\ttry: () => T;\n\t\t\tmapErr: (error: unknown) => Omit<TError, \"name\">;\n\t\t}) =>\n\t\t\ttrySync<T, TError>({\n\t\t\t\ttry: operation,\n\t\t\t\tmapErr: (error) => ({\n\t\t\t\t\t...mapErr(error),\n\t\t\t\t\tname,\n\t\t\t\t}),\n\t\t\t}),\n\t\ttryAsync: <T>({\n\t\t\ttry: operation,\n\t\t\tmapErr,\n\t\t}: {\n\t\t\ttry: () => Promise<T>;\n\t\t\tmapErr: (error: unknown) => Omit<TError, \"name\">;\n\t\t}) =>\n\t\t\ttryAsync<T, TError>({\n\t\t\t\ttry: operation,\n\t\t\t\tmapErr: (error) => ({ ...mapErr(error), name }),\n\t\t\t}),\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA8EA,MAAa,KAAK,CAAIA,UAAoB;CAAE;CAAM,OAAO;AAAM;;;;;;;;;;;;;;;;AAiB/D,MAAa,MAAM,CAAIC,WAAsB;CAAE;CAAO,MAAM;AAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyGlE,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;CAElD,MAAM,aAAa,MAAM,SAAS,QAAQ,MAAM,UAAU;AAC1D,KAAI,WAAY,QAAO;CAEvB,MAAM,gBAAgB,MAAM,SAAS,QAAQ,MAAM,UAAU;AAC7D,KAAI,cAAe,QAAO;AAG1B,QAAO;AACP;;;;;;;;;;;;;;;;;;;;;;AAuBD,SAAgB,KAAWC,QAAuC;AACjE,QAAO,OAAO,UAAU;AACxB;;;;;;;;;;;;;;;;;;;;;;AAuBD,SAAgB,MAAYA,QAAwC;AACnE,QAAO,OAAO,UAAU;AACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCD,SAAgB,QAAc,EAC7B,KAAK,WACL,UAIA,EAAgB;AAChB,KAAI;EACH,MAAM,OAAO,WAAW;AACxB,SAAO,GAAG,KAAK;CACf,SAAQ,OAAO;AACf,SAAO,IAAI,SAAS,MAAM,CAAC;CAC3B;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CD,eAAsB,SAAe,EACpC,KAAK,WACL,UAIA,EAAyB;AACzB,KAAI;EACH,MAAM,OAAO,MAAM,WAAW;AAC9B,SAAO,GAAG,KAAK;CACf,SAAQ,OAAO;AACf,SAAO,IAAI,SAAS,MAAM,CAAC;CAC3B;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDD,SAAgB,eAAqBC,OAA4B;AAChE,KAAI,SAAe,MAAM,EAAE;AAC1B,MAAI,KAAK,MAAM,CACd,QAAO,MAAM;AAKd,QAAM,MAAM;CACZ;AAID,QAAO;AACP;;;;;;;;;;;;;;;;;;;;ACxaD,SAAgB,iBAAuBC,SAAyB;AAC/D,QAAO;EACN,KAAK,CAAE;EACP,MAAM,CAAE;EACR,GAAG,OAAO,QAAQ,SAAS,CAAC,WAAY,KAAK,OAAO,GAAG,QAAQ,OAAQ;CACvE;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACUD,SAAgB,oBAAoBC,OAAwB;AAC3D,KAAI,iBAAiB,MACpB,QAAO,MAAM;AAGd,YAAW,UAAU,SACpB,QAAO;AAGR,YAAW,UAAU,YAAY,UAAU,MAAM;EAEhD,MAAM,WAAW;AACjB,aAAW,SAAS,YAAY,SAC/B,QAAO,SAAS;AAEjB,aAAW,SAAS,UAAU,SAC7B,QAAO,SAAS;AAEjB,aAAW,SAAS,gBAAgB,SACnC,QAAO,SAAS;AAIjB,MAAI;AACH,UAAO,KAAK,UAAU,MAAM;EAC5B,QAAO;AACP,UAAO,OAAO,MAAM;EACpB;CACD;AAED,QAAO,OAAO,MAAM;AACpB;;;;ACjBD,SAAgB,aAAmCC,MAAa;AAE/D,QAAO;EACN,SAAS,CAAI,EACZ,KAAK,WACL,QAIA,KACA,QAAmB;GAClB,KAAK;GACL,QAAQ,CAAC,WAAW;IACnB,GAAG,OAAO,MAAM;IAChB;GACA;EACD,EAAC;EACH,UAAU,CAAI,EACb,KAAK,WACL,QAIA,KACA,SAAoB;GACnB,KAAK;GACL,QAAQ,CAAC,WAAW;IAAE,GAAG,OAAO,MAAM;IAAE;GAAM;EAC9C,EAAC;CACH;AACD"}