@firtoz/maybe-error 1.5.2 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,7 +4,10 @@
4
4
  [![npm downloads](https://img.shields.io/npm/dm/%40firtoz%2Fmaybe-error.svg)](https://www.npmjs.com/package/@firtoz/maybe-error)
5
5
  [![license](https://img.shields.io/npm/l/%40firtoz%2Fmaybe-error.svg)](https://github.com/firtoz/fullstack-toolkit/blob/main/LICENSE)
6
6
 
7
- Type-safe result handling with the MaybeError pattern for TypeScript. Perfect for elegant error handling without exceptions.
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
8
+ [![zero dependencies](https://img.shields.io/badge/deps-zero-22c55e)](https://github.com/firtoz/fullstack-toolkit/tree/main/packages/maybe-error)
9
+
10
+ **`MaybeError` results without exceptions** — discriminated unions, tree-shakeable, zero runtime dependencies.
8
11
 
9
12
  > **⚠️ Early WIP Notice:** This package is in very early development and is **not production-ready**. It is TypeScript-only and may have breaking changes. While I (the maintainer) have limited time, I'm open to PRs for features, bug fixes, or additional support (like JS builds). Please feel free to try it out and contribute! See [CONTRIBUTING.md](../../CONTRIBUTING.md) for details.
10
13
 
@@ -0,0 +1,135 @@
1
+ /**
2
+ * @fileoverview Type-safe error handling utilities using discriminated unions
3
+ *
4
+ * This module provides a Result-like pattern for handling operations that may fail,
5
+ * inspired by Rust's Result type and functional programming error handling patterns.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // Basic usage
10
+ * const result = success(42);
11
+ * const error = fail("Something went wrong");
12
+ *
13
+ * // Type-safe error handling
14
+ * function divide(a: number, b: number): MaybeError<number> {
15
+ * if (b === 0) return fail("Division by zero");
16
+ * return success(a / b);
17
+ * }
18
+ *
19
+ * const result = divide(10, 2);
20
+ * if (result.success) {
21
+ * console.log(result.result); // 5
22
+ * } else {
23
+ * console.error(result.error); // "Division by zero"
24
+ * }
25
+ * ```
26
+ */
27
+ /**
28
+ * Represents a failed operation with an error value.
29
+ *
30
+ * @template TError - The type of the error value (defaults to string)
31
+ * @example
32
+ * ```typescript
33
+ * const error: DefiniteError<string> = { success: false, error: "Not found" };
34
+ * const customError: DefiniteError<{code: number, message: string}> = {
35
+ * success: false,
36
+ * error: { code: 404, message: "Resource not found" }
37
+ * };
38
+ * ```
39
+ */
40
+ type DefiniteError<TError = string> = {
41
+ success: false;
42
+ error: TError;
43
+ };
44
+ /**
45
+ * Represents a successful operation with an optional result value.
46
+ *
47
+ * Uses conditional types to make the result field optional when T is undefined,
48
+ * but required when T has a concrete type.
49
+ *
50
+ * @template T - The type of the success value (defaults to undefined)
51
+ * @example
52
+ * ```typescript
53
+ * const voidSuccess: DefiniteSuccess = { success: true };
54
+ * const valueSuccess: DefiniteSuccess<number> = { success: true, result: 42 };
55
+ * ```
56
+ */
57
+ type DefiniteSuccess<T = undefined> = {
58
+ success: true;
59
+ } & (T extends undefined ? {
60
+ result?: T;
61
+ } : {
62
+ result: T;
63
+ });
64
+ /**
65
+ * A discriminated union representing either a successful result or an error.
66
+ *
67
+ * This is the main type for operations that may fail. The `success` field
68
+ * acts as a discriminant, allowing TypeScript to narrow the type in conditionals.
69
+ *
70
+ * @template T - The type of the success value (defaults to undefined)
71
+ * @template TError - The type of the error value (defaults to string)
72
+ * @example
73
+ * ```typescript
74
+ * function fetchUser(id: string): MaybeError<User, ApiError> {
75
+ * // Implementation that returns either success(user) or fail(apiError)
76
+ * }
77
+ *
78
+ * const result = fetchUser("123");
79
+ * if (result.success) {
80
+ * // TypeScript knows result.result is User
81
+ * console.log(result.result.name);
82
+ * } else {
83
+ * // TypeScript knows result.error is ApiError
84
+ * console.error(result.error.message);
85
+ * }
86
+ * ```
87
+ */
88
+ type MaybeError<T = undefined, TError = string> = DefiniteSuccess<T> | DefiniteError<TError>;
89
+ /**
90
+ * Utility type to extract the success value type from a MaybeError type.
91
+ *
92
+ * Useful for type manipulation when you need to work with the success type
93
+ * without the error handling wrapper.
94
+ *
95
+ * @template T - A MaybeError type
96
+ * @example
97
+ * ```typescript
98
+ * type UserResult = MaybeError<User, string>;
99
+ * type UserType = AssumeSuccess<UserResult>; // User
100
+ * ```
101
+ */
102
+ type AssumeSuccess<T extends MaybeError<unknown>> = Exclude<T, undefined> extends MaybeError<infer U> ? U : never;
103
+ /**
104
+ * Creates a successful result with an optional value.
105
+ *
106
+ * Uses function overloading to provide different signatures based on whether
107
+ * a value is provided or not.
108
+ *
109
+ * @template T - The type of the success value
110
+ * @param params - The success value (optional for void operations)
111
+ * @returns A DefiniteSuccess instance
112
+ * @example
113
+ * ```typescript
114
+ * const voidResult = success(); // DefiniteSuccess<undefined>
115
+ * const valueResult = success(42); // DefiniteSuccess<number>
116
+ * const stringResult = success("hello"); // DefiniteSuccess<string>
117
+ * ```
118
+ */
119
+ declare const success: <T = undefined>(...params: T extends undefined ? [] : [T]) => DefiniteSuccess<T>;
120
+ /**
121
+ * Creates a failed result with an error value.
122
+ *
123
+ * @template TError - The type of the error value
124
+ * @param error - The error value
125
+ * @returns A DefiniteError instance
126
+ * @example
127
+ * ```typescript
128
+ * const stringError = fail("Something went wrong");
129
+ * const objectError = fail({ code: 500, message: "Internal server error" });
130
+ * const customError = fail(new Error("Custom error"));
131
+ * ```
132
+ */
133
+ declare const fail: <TError = string>(error: TError) => DefiniteError<TError>;
134
+
135
+ export { type AssumeSuccess, type DefiniteError, type DefiniteSuccess, type MaybeError, fail, success };
@@ -0,0 +1,3 @@
1
+ export { fail, success } from './chunk-FAVWW3FP.js';
2
+ //# sourceMappingURL=MaybeError.js.map
3
+ //# sourceMappingURL=MaybeError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"MaybeError.js"}
@@ -0,0 +1,20 @@
1
+ // src/MaybeError.ts
2
+ var success = (...params) => {
3
+ if (params.length === 0) {
4
+ return { success: true };
5
+ }
6
+ return {
7
+ success: true,
8
+ result: params[0]
9
+ };
10
+ };
11
+ var fail = (error) => {
12
+ return {
13
+ success: false,
14
+ error
15
+ };
16
+ };
17
+
18
+ export { fail, success };
19
+ //# sourceMappingURL=chunk-FAVWW3FP.js.map
20
+ //# sourceMappingURL=chunk-FAVWW3FP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/MaybeError.ts"],"names":[],"mappings":";AAgIO,IAAM,OAAA,GAAU,IACnB,MAAA,KACqB;AACxB,EAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACxB,IAAA,OAAO,EAAE,SAAS,IAAA,EAAK;AAAA,EACxB;AAEA,EAAA,OAAO;AAAA,IACN,OAAA,EAAS,IAAA;AAAA,IACT,MAAA,EAAQ,OAAO,CAAC;AAAA,GACjB;AACD;AAeO,IAAM,IAAA,GAAO,CAAkB,KAAA,KAAyC;AAC9E,EAAA,OAAO;AAAA,IACN,OAAA,EAAS,KAAA;AAAA,IACT;AAAA,GACD;AACD","file":"chunk-FAVWW3FP.js","sourcesContent":["/**\n * @fileoverview Type-safe error handling utilities using discriminated unions\n *\n * This module provides a Result-like pattern for handling operations that may fail,\n * inspired by Rust's Result type and functional programming error handling patterns.\n *\n * @example\n * ```typescript\n * // Basic usage\n * const result = success(42);\n * const error = fail(\"Something went wrong\");\n *\n * // Type-safe error handling\n * function divide(a: number, b: number): MaybeError<number> {\n * if (b === 0) return fail(\"Division by zero\");\n * return success(a / b);\n * }\n *\n * const result = divide(10, 2);\n * if (result.success) {\n * console.log(result.result); // 5\n * } else {\n * console.error(result.error); // \"Division by zero\"\n * }\n * ```\n */\n\n/**\n * Represents a failed operation with an error value.\n *\n * @template TError - The type of the error value (defaults to string)\n * @example\n * ```typescript\n * const error: DefiniteError<string> = { success: false, error: \"Not found\" };\n * const customError: DefiniteError<{code: number, message: string}> = {\n * success: false,\n * error: { code: 404, message: \"Resource not found\" }\n * };\n * ```\n */\nexport type DefiniteError<TError = string> = {\n\tsuccess: false;\n\terror: TError;\n};\n\n/**\n * Represents a successful operation with an optional result value.\n *\n * Uses conditional types to make the result field optional when T is undefined,\n * but required when T has a concrete type.\n *\n * @template T - The type of the success value (defaults to undefined)\n * @example\n * ```typescript\n * const voidSuccess: DefiniteSuccess = { success: true };\n * const valueSuccess: DefiniteSuccess<number> = { success: true, result: 42 };\n * ```\n */\nexport type DefiniteSuccess<T = undefined> = {\n\tsuccess: true;\n} & (T extends undefined\n\t? {\n\t\t\tresult?: T;\n\t\t}\n\t: {\n\t\t\tresult: T;\n\t\t});\n\n/**\n * A discriminated union representing either a successful result or an error.\n *\n * This is the main type for operations that may fail. The `success` field\n * acts as a discriminant, allowing TypeScript to narrow the type in conditionals.\n *\n * @template T - The type of the success value (defaults to undefined)\n * @template TError - The type of the error value (defaults to string)\n * @example\n * ```typescript\n * function fetchUser(id: string): MaybeError<User, ApiError> {\n * // Implementation that returns either success(user) or fail(apiError)\n * }\n *\n * const result = fetchUser(\"123\");\n * if (result.success) {\n * // TypeScript knows result.result is User\n * console.log(result.result.name);\n * } else {\n * // TypeScript knows result.error is ApiError\n * console.error(result.error.message);\n * }\n * ```\n */\nexport type MaybeError<T = undefined, TError = string> =\n\t| DefiniteSuccess<T>\n\t| DefiniteError<TError>;\n\n/**\n * Utility type to extract the success value type from a MaybeError type.\n *\n * Useful for type manipulation when you need to work with the success type\n * without the error handling wrapper.\n *\n * @template T - A MaybeError type\n * @example\n * ```typescript\n * type UserResult = MaybeError<User, string>;\n * type UserType = AssumeSuccess<UserResult>; // User\n * ```\n */\nexport type AssumeSuccess<T extends MaybeError<unknown>> =\n\tExclude<T, undefined> extends MaybeError<infer U> ? U : never;\n\n/**\n * Creates a successful result with an optional value.\n *\n * Uses function overloading to provide different signatures based on whether\n * a value is provided or not.\n *\n * @template T - The type of the success value\n * @param params - The success value (optional for void operations)\n * @returns A DefiniteSuccess instance\n * @example\n * ```typescript\n * const voidResult = success(); // DefiniteSuccess<undefined>\n * const valueResult = success(42); // DefiniteSuccess<number>\n * const stringResult = success(\"hello\"); // DefiniteSuccess<string>\n * ```\n */\nexport const success = <T = undefined>(\n\t...params: T extends undefined ? [] : [T]\n): DefiniteSuccess<T> => {\n\tif (params.length === 0) {\n\t\treturn { success: true } as unknown as DefiniteSuccess<T>;\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tresult: params[0],\n\t} as unknown as DefiniteSuccess<T>;\n};\n\n/**\n * Creates a failed result with an error value.\n *\n * @template TError - The type of the error value\n * @param error - The error value\n * @returns A DefiniteError instance\n * @example\n * ```typescript\n * const stringError = fail(\"Something went wrong\");\n * const objectError = fail({ code: 500, message: \"Internal server error\" });\n * const customError = fail(new Error(\"Custom error\"));\n * ```\n */\nexport const fail = <TError = string>(error: TError): DefiniteError<TError> => {\n\treturn {\n\t\tsuccess: false,\n\t\terror,\n\t};\n};\n"]}
@@ -0,0 +1,8 @@
1
+ // src/exhaustiveGuard.ts
2
+ function exhaustiveGuard(value) {
3
+ throw new Error(`Exhaustive guard triggered with value: ${value}`);
4
+ }
5
+
6
+ export { exhaustiveGuard };
7
+ //# sourceMappingURL=chunk-Z5JSMWNM.js.map
8
+ //# sourceMappingURL=chunk-Z5JSMWNM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/exhaustiveGuard.ts"],"names":[],"mappings":";AAAO,SAAS,gBAAgB,KAAA,EAAqB;AACpD,EAAA,MAAM,IAAI,KAAA,CAAM,CAAA,uCAAA,EAA0C,KAAK,CAAA,CAAE,CAAA;AAClE","file":"chunk-Z5JSMWNM.js","sourcesContent":["export function exhaustiveGuard(value: never): never {\n\tthrow new Error(`Exhaustive guard triggered with value: ${value}`);\n}\n"]}
@@ -0,0 +1,3 @@
1
+ declare function exhaustiveGuard(value: never): never;
2
+
3
+ export { exhaustiveGuard };
@@ -0,0 +1,3 @@
1
+ export { exhaustiveGuard } from './chunk-Z5JSMWNM.js';
2
+ //# sourceMappingURL=exhaustiveGuard.js.map
3
+ //# sourceMappingURL=exhaustiveGuard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"exhaustiveGuard.js"}
@@ -0,0 +1,2 @@
1
+ export { AssumeSuccess, DefiniteError, DefiniteSuccess, MaybeError, fail, success } from './MaybeError.js';
2
+ export { exhaustiveGuard } from './exhaustiveGuard.js';
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { fail, success } from './chunk-FAVWW3FP.js';
2
+ export { exhaustiveGuard } from './chunk-Z5JSMWNM.js';
3
+ //# sourceMappingURL=index.js.map
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
package/package.json CHANGED
@@ -1,24 +1,31 @@
1
1
  {
2
2
  "name": "@firtoz/maybe-error",
3
- "version": "1.5.2",
3
+ "version": "1.6.1",
4
4
  "description": "Type-safe result handling with MaybeError pattern",
5
- "main": "./src/index.ts",
6
- "module": "./src/index.ts",
7
- "types": "./src/index.ts",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
8
9
  "exports": {
9
10
  ".": {
10
- "types": "./src/index.ts",
11
- "import": "./src/index.ts",
12
- "require": "./src/index.ts"
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.js",
14
+ "default": "./dist/index.js"
13
15
  }
14
16
  },
15
17
  "files": [
18
+ "dist/**/*.js",
19
+ "dist/**/*.js.map",
20
+ "dist/**/*.d.ts",
16
21
  "src/**/*.ts",
17
22
  "!src/**/*.test.ts",
18
23
  "README.md"
19
24
  ],
20
25
  "scripts": {
21
- "typecheck": "tsc --noEmit -p ./tsconfig.json",
26
+ "build": "tsup",
27
+ "prepack": "bun run build",
28
+ "typecheck": "tsgo --noEmit -p ./tsconfig.json",
22
29
  "lint": "biome check --write src",
23
30
  "lint:ci": "biome ci src",
24
31
  "format": "biome format src --write",
@@ -50,6 +57,6 @@
50
57
  "access": "public"
51
58
  },
52
59
  "devDependencies": {
53
- "bun-types": "^1.3.5"
60
+ "bun-types": "^1.3.12"
54
61
  }
55
62
  }