@satoshibits/functional 1.0.2

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.
Files changed (46) hide show
  1. package/README.md +242 -0
  2. package/dist/array-utils.d.mts +317 -0
  3. package/dist/array-utils.d.mts.map +1 -0
  4. package/dist/array-utils.mjs +370 -0
  5. package/dist/array-utils.mjs.map +1 -0
  6. package/dist/composition.d.mts +603 -0
  7. package/dist/composition.d.mts.map +1 -0
  8. package/dist/composition.mjs +516 -0
  9. package/dist/composition.mjs.map +1 -0
  10. package/dist/object-utils.d.mts +267 -0
  11. package/dist/object-utils.d.mts.map +1 -0
  12. package/dist/object-utils.mjs +258 -0
  13. package/dist/object-utils.mjs.map +1 -0
  14. package/dist/option.d.mts +622 -0
  15. package/dist/option.d.mts.map +1 -0
  16. package/dist/option.mjs +637 -0
  17. package/dist/option.mjs.map +1 -0
  18. package/dist/performance.d.mts +265 -0
  19. package/dist/performance.d.mts.map +1 -0
  20. package/dist/performance.mjs +453 -0
  21. package/dist/performance.mjs.map +1 -0
  22. package/dist/pipeline.d.mts +431 -0
  23. package/dist/pipeline.d.mts.map +1 -0
  24. package/dist/pipeline.mjs +460 -0
  25. package/dist/pipeline.mjs.map +1 -0
  26. package/dist/predicates.d.mts +722 -0
  27. package/dist/predicates.d.mts.map +1 -0
  28. package/dist/predicates.mjs +802 -0
  29. package/dist/predicates.mjs.map +1 -0
  30. package/dist/reader-result.d.mts +422 -0
  31. package/dist/reader-result.d.mts.map +1 -0
  32. package/dist/reader-result.mjs +758 -0
  33. package/dist/reader-result.mjs.map +1 -0
  34. package/dist/result.d.mts +684 -0
  35. package/dist/result.d.mts.map +1 -0
  36. package/dist/result.mjs +814 -0
  37. package/dist/result.mjs.map +1 -0
  38. package/dist/types.d.mts +439 -0
  39. package/dist/types.d.mts.map +1 -0
  40. package/dist/types.mjs +191 -0
  41. package/dist/types.mjs.map +1 -0
  42. package/dist/validation.d.mts +622 -0
  43. package/dist/validation.d.mts.map +1 -0
  44. package/dist/validation.mjs +852 -0
  45. package/dist/validation.mjs.map +1 -0
  46. package/package.json +46 -0
@@ -0,0 +1,814 @@
1
+ "use strict";
2
+ /**
3
+ * @module result
4
+ * @description Type-safe error handling without exceptions using the Result pattern.
5
+ * Result types represent operations that can either succeed with a value or fail
6
+ * with an error. This provides a functional alternative to try-catch blocks,
7
+ * making error handling explicit and composable. Similar to Rust's Result type
8
+ * or fp-ts's Either, but with a simpler API focused on practical use cases.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { Result, unwrap, safe } from './result.mts';
13
+ *
14
+ * // basic usage
15
+ * function divide(a: number, b: number): Result<number, string> {
16
+ * if (b === 0) {
17
+ * return Result.err('Division by zero');
18
+ * }
19
+ * return Result.ok(a / b);
20
+ * }
21
+ *
22
+ * // composing operations
23
+ * const result = Result.flatMap((x: number) => divide(x, 2))(
24
+ * Result.map((x: number) => x * 10)(
25
+ * divide(20, 4)
26
+ * )
27
+ * );
28
+ * // => { success: true, data: 25 }
29
+ *
30
+ * // error handling
31
+ * const safeOperation = Result.orElse(
32
+ * (error: string) => Result.ok(0) // default value on error
33
+ * )(divide(10, 0));
34
+ * // => { success: true, data: 0 }
35
+ * ```
36
+ *
37
+ * @category Core
38
+ * @since 2025-07-03
39
+ */
40
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
41
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
42
+ return new (P || (P = Promise))(function (resolve, reject) {
43
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
44
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
45
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
46
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
47
+ });
48
+ };
49
+ var __generator = (this && this.__generator) || function (thisArg, body) {
50
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
51
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
52
+ function verb(n) { return function (v) { return step([n, v]); }; }
53
+ function step(op) {
54
+ if (f) throw new TypeError("Generator is already executing.");
55
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
56
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
57
+ if (y = 0, t) op = [op[0] & 2, t.value];
58
+ switch (op[0]) {
59
+ case 0: case 1: t = op; break;
60
+ case 4: _.label++; return { value: op[1], done: false };
61
+ case 5: _.label++; y = op[1]; op = [0]; continue;
62
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
63
+ default:
64
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
65
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
66
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
67
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
68
+ if (t[2]) _.ops.pop();
69
+ _.trys.pop(); continue;
70
+ }
71
+ op = body.call(thisArg, _);
72
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
73
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
74
+ }
75
+ };
76
+ /**
77
+ * Result utility functions for working with Result types.
78
+ * @description Provides a functional API for creating, transforming, and composing Results.
79
+ * All functions are curried to support functional composition and partial application.
80
+ *
81
+ * @category Utilities
82
+ * @since 2025-07-03
83
+ */
84
+ export var Result = {
85
+ /**
86
+ * Creates a successful Result containing the given data.
87
+ * @description Factory function for creating success cases. The error type
88
+ * can be inferred from context or explicitly specified.
89
+ *
90
+ * @template T - The type of the success value
91
+ * @template E - The type of the error (defaults to never for success cases)
92
+ * @param {T} data - The success value to wrap
93
+ * @returns {Result<T, E>} A successful Result containing the data
94
+ *
95
+ * @category Constructors
96
+ * @example
97
+ * // Basic usage
98
+ * const result = Result.ok(42);
99
+ * // => { success: true, data: 42 }
100
+ *
101
+ * @example
102
+ * // With explicit types
103
+ * const typed: Result<number, string> = Result.ok(42);
104
+ *
105
+ * @example
106
+ * // In a function
107
+ * function getUser(id: string): Result<User, string> {
108
+ * const user = database.find(id);
109
+ * return user ? Result.ok(user) : Result.err('User not found');
110
+ * }
111
+ *
112
+ * @since 2025-07-03
113
+ */
114
+ ok: function (data) { return ({ success: true, data: data }); },
115
+ /**
116
+ * Creates a failed Result containing the given error.
117
+ * @description Factory function for creating failure cases. The success type
118
+ * can be inferred from context or explicitly specified.
119
+ *
120
+ * @template T - The type of the success value (defaults to never for error cases)
121
+ * @template E - The type of the error (defaults to string)
122
+ * @param {E} error - The error value to wrap
123
+ * @returns {Result<T, E>} A failed Result containing the error
124
+ *
125
+ * @category Constructors
126
+ * @example
127
+ * // Basic usage
128
+ * const result = Result.err('Something went wrong');
129
+ * // => { success: false, error: 'Something went wrong' }
130
+ *
131
+ * @example
132
+ * // With custom error type
133
+ * interface ValidationError {
134
+ * field: string;
135
+ * message: string;
136
+ * }
137
+ *
138
+ * const error: Result<number, ValidationError> = Result.err({
139
+ * field: 'age',
140
+ * message: 'Must be positive'
141
+ * });
142
+ *
143
+ * @since 2025-07-03
144
+ */
145
+ err: function (error) { return ({
146
+ success: false,
147
+ error: error,
148
+ }); },
149
+ /**
150
+ * Transforms the data inside a successful Result using the given function.
151
+ * @description If the Result is a failure, returns the failure unchanged.
152
+ * This is the functor map operation for Result types.
153
+ *
154
+ * @template T - The input success type
155
+ * @template U - The output success type
156
+ * @template E - The error type
157
+ * @param {function(T): U} f - Function to transform the success value
158
+ * @returns {function(Result<T, E>): Result<U, E>} A function that transforms Results
159
+ *
160
+ * @category Transformations
161
+ * @example
162
+ * // Basic transformation
163
+ * const double = Result.map((x: number) => x * 2);
164
+ * double(Result.ok(21)); // => { success: true, data: 42 }
165
+ * double(Result.err('error')); // => { success: false, error: 'error' }
166
+ *
167
+ * @example
168
+ * // Chaining transformations
169
+ * const result = Result.map((s: string) => s.toUpperCase())(
170
+ * Result.map((n: number) => n.toString())(
171
+ * Result.ok(42)
172
+ * )
173
+ * );
174
+ * // => { success: true, data: '42' }
175
+ *
176
+ * @since 2025-07-03
177
+ */
178
+ map: function (f) {
179
+ return function (result) {
180
+ return result.success ? Result.ok(f(result.data)) : result;
181
+ };
182
+ },
183
+ /**
184
+ * Chains Result-returning operations.
185
+ * @description If the first Result is successful, applies the function to its data.
186
+ * If it's a failure, returns the failure. This is the monadic bind operation
187
+ * for Result types, enabling sequential composition of fallible operations.
188
+ *
189
+ * @template T - The input success type
190
+ * @template U - The output success type
191
+ * @template E - The error type
192
+ * @param {function(T): Result<U, E>} f - Function that returns a new Result
193
+ * @returns {function(Result<T, E>): Result<U, E>} A function that chains Results
194
+ *
195
+ * @category Combinators
196
+ * @example
197
+ * // Chaining fallible operations
198
+ * function parseNumber(s: string): Result<number, string> {
199
+ * const n = Number(s);
200
+ * return isNaN(n) ? Result.err('Not a number') : Result.ok(n);
201
+ * }
202
+ *
203
+ * function safeDivide(n: number): Result<number, string> {
204
+ * return n === 0 ? Result.err('Division by zero') : Result.ok(100 / n);
205
+ * }
206
+ *
207
+ * const result = Result.flatMap(safeDivide)(
208
+ * parseNumber('5')
209
+ * );
210
+ * // => { success: true, data: 20 }
211
+ *
212
+ * @since 2025-07-03
213
+ */
214
+ flatMap: function (f) {
215
+ return function (result) {
216
+ return result.success ? f(result.data) : result;
217
+ };
218
+ },
219
+ /**
220
+ * Transforms the error inside a failed Result using the given function.
221
+ * @description If the Result is successful, returns the success unchanged.
222
+ * Useful for normalizing errors or adding context to error messages.
223
+ *
224
+ * @template T - The success type
225
+ * @template E - The input error type
226
+ * @template F - The output error type
227
+ * @param {function(E): F} f - Function to transform the error
228
+ * @returns {function(Result<T, E>): Result<T, F>} A function that transforms error types
229
+ *
230
+ * @category Transformations
231
+ * @example
232
+ * // Adding context to errors
233
+ * const withContext = Result.mapError(
234
+ * (e: string) => `Database error: ${e}`
235
+ * );
236
+ *
237
+ * @example
238
+ * // Converting error types
239
+ * interface AppError {
240
+ * code: string;
241
+ * message: string;
242
+ * }
243
+ *
244
+ * const toAppError = Result.mapError(
245
+ * (e: Error): AppError => ({
246
+ * code: 'INTERNAL_ERROR',
247
+ * message: e.message
248
+ * })
249
+ * );
250
+ *
251
+ * @since 2025-07-03
252
+ */
253
+ mapError: function (f) {
254
+ return function (result) {
255
+ return result.success ? result : Result.err(f(result.error));
256
+ };
257
+ },
258
+ /**
259
+ * Returns the data from a successful Result, or the provided default value if failed.
260
+ * @description Extracts the value from a Result, providing a fallback for the error case.
261
+ * Useful when you want to handle errors by substituting a default value.
262
+ *
263
+ * @template T - The success type
264
+ * @template E - The error type
265
+ * @param {T} defaultValue - The value to return if the Result is an error
266
+ * @returns {function(Result<T, E>): T} A function that extracts values with a default
267
+ *
268
+ * @category Extraction
269
+ * @example
270
+ * // Providing defaults
271
+ * const getWithDefault = Result.getOrElse(0);
272
+ * getWithDefault(Result.ok(42)); // => 42
273
+ * getWithDefault(Result.err('error')); // => 0
274
+ *
275
+ * @example
276
+ * // Configuration with fallback
277
+ * const port = Result.getOrElse(3000)(
278
+ * parsePort(process.env.PORT)
279
+ * );
280
+ *
281
+ * @since 2025-07-03
282
+ */
283
+ getOrElse: function (defaultValue) {
284
+ return function (result) {
285
+ return result.success ? result.data : defaultValue;
286
+ };
287
+ },
288
+ /**
289
+ * Returns the data from a successful Result, or calls the provided function with the error.
290
+ * @description Pattern matches on the Result, applying one of two functions based on
291
+ * success or failure. Both functions must return the same type. This is similar
292
+ * to the fold operation in functional programming.
293
+ *
294
+ * @template T - The success type
295
+ * @template U - The return type
296
+ * @template E - The error type
297
+ * @param {function(T): U} onSuccess - Function to apply to success value
298
+ * @param {function(E): U} onFailure - Function to apply to error value
299
+ * @returns {function(Result<T, E>): U} A function that folds Results into a value
300
+ *
301
+ * @category Extraction
302
+ * @example
303
+ * // Converting to a message
304
+ * const toMessage = Result.fold(
305
+ * (user: User) => `Welcome, ${user.name}!`,
306
+ * (error: string) => `Error: ${error}`
307
+ * );
308
+ *
309
+ * @example
310
+ * // Converting to React component
311
+ * const renderResult = Result.fold(
312
+ * (data: Data) => <SuccessView data={data} />,
313
+ * (error: Error) => <ErrorView error={error} />
314
+ * );
315
+ *
316
+ * @since 2025-07-03
317
+ */
318
+ fold: function (onSuccess, onFailure) {
319
+ return function (result) {
320
+ return result.success ? onSuccess(result.data) : onFailure(result.error);
321
+ };
322
+ },
323
+ /**
324
+ * Combines two Results. If both are successful, applies the function to both data values.
325
+ * @description If either is a failure, returns the first failure encountered.
326
+ * This implements applicative-style composition for Result types.
327
+ *
328
+ * @template T - The first success type
329
+ * @template U - The second success type
330
+ * @template V - The combined success type
331
+ * @template E - The error type
332
+ * @param {function(T, U): V} f - Function to combine the success values
333
+ * @returns {function(Result<T, E>, Result<U, E>): Result<V, E>} A function that combines Results
334
+ *
335
+ * @category Combinations
336
+ * @example
337
+ * // Combining two results
338
+ * const add = Result.combine((a: number, b: number) => a + b);
339
+ * add(Result.ok(2), Result.ok(3)); // => { success: true, data: 5 }
340
+ * add(Result.ok(2), Result.err('error')); // => { success: false, error: 'error' }
341
+ *
342
+ * @example
343
+ * // Building objects from multiple Results
344
+ * const createUser = Result.combine(
345
+ * (name: string, age: number): User => ({ name, age })
346
+ * );
347
+ *
348
+ * const user = createUser(
349
+ * validateName(input.name),
350
+ * validateAge(input.age)
351
+ * );
352
+ *
353
+ * @since 2025-07-03
354
+ */
355
+ combine: function (f) {
356
+ return function (resultA, resultB) {
357
+ if (!resultA.success) {
358
+ return Result.err(resultA.error);
359
+ }
360
+ if (!resultB.success) {
361
+ return Result.err(resultB.error);
362
+ }
363
+ return Result.ok(f(resultA.data, resultB.data));
364
+ };
365
+ },
366
+ /**
367
+ * Sequences an array of Results.
368
+ * @description If all are successful, returns an array of all data values.
369
+ * If any are failures, returns the first failure encountered. This is
370
+ * useful for validating multiple values where all must succeed.
371
+ *
372
+ * @template T - The success type of each Result
373
+ * @template E - The error type
374
+ * @param {Result<T, E>[]} results - Array of Results to sequence
375
+ * @returns {Result<T[], E>} A Result containing an array of values or the first error
376
+ *
377
+ * @category Combinations
378
+ * @example
379
+ * // Validating multiple inputs
380
+ * const results = [
381
+ * validateEmail('user@example.com'),
382
+ * validateEmail('admin@example.com'),
383
+ * validateEmail('test@example.com')
384
+ * ];
385
+ *
386
+ * const allEmails = Result.sequence(results);
387
+ * // If all valid: { success: true, data: ['user@...', 'admin@...', 'test@...'] }
388
+ * // If any invalid: { success: false, error: 'Invalid email format' }
389
+ *
390
+ * @see combineWithAllErrors - Collects all errors instead of short-circuiting
391
+ * @since 2025-07-03
392
+ */
393
+ sequence: function (results) {
394
+ var data = [];
395
+ for (var _i = 0, results_1 = results; _i < results_1.length; _i++) {
396
+ var result = results_1[_i];
397
+ if (!result.success) {
398
+ return result;
399
+ }
400
+ data.push(result.data);
401
+ }
402
+ return Result.ok(data);
403
+ },
404
+ /**
405
+ * Filters a successful Result based on a predicate.
406
+ * @description If the predicate fails, returns a failure with the provided error.
407
+ * If the Result is already a failure, returns it unchanged. This allows
408
+ * adding validation to existing Results.
409
+ *
410
+ * @template T - The success type
411
+ * @template E - The error type
412
+ * @param {function(T): boolean} predicate - Function to test the success value
413
+ * @param {E} error - Error to return if the predicate fails
414
+ * @returns {function(Result<T, E>): Result<T, E>} A function that filters Results
415
+ *
416
+ * @category Validations
417
+ * @example
418
+ * // Adding validation
419
+ * const mustBePositive = Result.filter(
420
+ * (n: number) => n > 0,
421
+ * 'Number must be positive'
422
+ * );
423
+ *
424
+ * mustBePositive(Result.ok(42)); // => { success: true, data: 42 }
425
+ * mustBePositive(Result.ok(-1)); // => { success: false, error: 'Number must be positive' }
426
+ *
427
+ * @example
428
+ * // Chaining validations
429
+ * const validateAge = (age: number) => Result.ok(age)
430
+ * |> Result.filter(n => n >= 0, 'Age cannot be negative')
431
+ * |> Result.filter(n => n <= 150, 'Age seems unrealistic');
432
+ *
433
+ * @since 2025-07-03
434
+ */
435
+ filter: function (predicate, error) {
436
+ return function (result) {
437
+ return !result.success ? result : predicate(result.data) ? result : Result.err(error);
438
+ };
439
+ },
440
+ /**
441
+ * Provides a fallback Result if the original fails.
442
+ * @description The fallback function receives the error and returns a new Result.
443
+ * This allows error recovery and chaining of alternative operations.
444
+ *
445
+ * @template T - The success type
446
+ * @template E - The input error type
447
+ * @template F - The output error type
448
+ * @param {function(E): Result<T, F>} fallbackFn - Function to create a fallback Result
449
+ * @returns {function(Result<T, E>): Result<T, F>} A function that adds fallback logic
450
+ *
451
+ * @category Error Handling
452
+ * @example
453
+ * // Fallback to cache
454
+ * const getUser = Result.orElse(
455
+ * (error: string) => getCachedUser()
456
+ * )(fetchUserFromAPI());
457
+ *
458
+ * @example
459
+ * // Try multiple sources
460
+ * const config = Result.orElse(
461
+ * () => loadFromFile('./config.json')
462
+ * )(Result.orElse(
463
+ * () => loadFromEnv()
464
+ * )(loadFromDatabase()));
465
+ *
466
+ * @since 2025-07-03
467
+ */
468
+ orElse: function (fallbackFn) {
469
+ return function (result) {
470
+ return result.success ? result : fallbackFn(result.error);
471
+ };
472
+ },
473
+ /**
474
+ * Combines an array of Results, collecting ALL errors instead of short-circuiting.
475
+ * @description If all succeed, returns an array of values. If any fail, returns
476
+ * an array of all errors. This is useful for validation scenarios where you
477
+ * want to report all errors at once rather than stopping at the first one.
478
+ *
479
+ * @template T - The success type of each Result
480
+ * @template E - The error type of each Result
481
+ * @param {Result<T, E>[]} results - Array of Results to combine
482
+ * @returns {Result<T[], E[]>} Success with all values or failure with all errors
483
+ *
484
+ * @category Combinations
485
+ * @example
486
+ * // Form validation with all errors
487
+ * const validations = [
488
+ * validateName(form.name),
489
+ * validateEmail(form.email),
490
+ * validateAge(form.age)
491
+ * ];
492
+ *
493
+ * const result = Result.combineWithAllErrors(validations);
494
+ * // If any fail: { success: false, error: ['Invalid name', 'Invalid email'] }
495
+ * // If all succeed: { success: true, data: ['John', 'john@example.com', 25] }
496
+ *
497
+ * @see sequence - Short-circuits on first error
498
+ * @since 2025-07-03
499
+ */
500
+ combineWithAllErrors: function (results) {
501
+ var successes = [];
502
+ var errors = [];
503
+ for (var _i = 0, results_2 = results; _i < results_2.length; _i++) {
504
+ var result = results_2[_i];
505
+ if (result.success) {
506
+ successes.push(result.data);
507
+ }
508
+ else {
509
+ errors.push(result.error);
510
+ }
511
+ }
512
+ return errors.length > 0 ? Result.err(errors) : Result.ok(successes);
513
+ },
514
+ /**
515
+ * Checks if a Result is successful.
516
+ * @description Type guard that narrows a Result to its success case.
517
+ * Useful in conditional statements and array filtering.
518
+ *
519
+ * @template T - The success type
520
+ * @template E - The error type
521
+ * @param {Result<T, E>} result - The Result to check
522
+ * @returns {result is { success: true; data: T }} True if the Result is successful
523
+ *
524
+ * @category Type Guards
525
+ * @example
526
+ * // Type narrowing
527
+ * const result = divide(10, 2);
528
+ * if (Result.isOk(result)) {
529
+ * console.log(result.data); // TypeScript knows data exists
530
+ * }
531
+ *
532
+ * @example
533
+ * // Filtering arrays
534
+ * const results = [Result.ok(1), Result.err('error'), Result.ok(2)];
535
+ * const successes = results.filter(Result.isOk);
536
+ * // => [{ success: true, data: 1 }, { success: true, data: 2 }]
537
+ *
538
+ * @see isErr - Check if Result is a failure
539
+ * @since 2025-07-03
540
+ */
541
+ isOk: function (result) {
542
+ return result.success;
543
+ },
544
+ /**
545
+ * Checks if a Result is a failure.
546
+ * @description Type guard that narrows a Result to its failure case.
547
+ * Useful in conditional statements and error handling.
548
+ *
549
+ * @template T - The success type
550
+ * @template E - The error type
551
+ * @param {Result<T, E>} result - The Result to check
552
+ * @returns {result is { success: false; error: E }} True if the Result is a failure
553
+ *
554
+ * @category Type Guards
555
+ * @example
556
+ * // Error handling
557
+ * const result = parseJSON(input);
558
+ * if (Result.isErr(result)) {
559
+ * logger.error(result.error); // TypeScript knows error exists
560
+ * }
561
+ *
562
+ * @example
563
+ * // Collecting errors
564
+ * const results = processItems(items);
565
+ * const errors = results.filter(Result.isErr).map(r => r.error);
566
+ *
567
+ * @see isOk - Check if Result is successful
568
+ * @since 2025-07-03
569
+ */
570
+ isErr: function (result) {
571
+ return !result.success;
572
+ },
573
+ /**
574
+ * Converts a promise that might throw into a Result.
575
+ * @description Catches exceptions and converts them to error Results.
576
+ * This bridges the gap between exception-based and Result-based error handling.
577
+ *
578
+ * @template T - The type of the resolved value
579
+ * @param {Promise<T>} promise - The promise that might reject
580
+ * @returns {Promise<Result<T, Error>>} A promise of a Result
581
+ *
582
+ * @category Interop
583
+ * @example
584
+ * // Converting async operations
585
+ * const result = await Result.fromPromise(
586
+ * fetch('/api/user').then(r => r.json())
587
+ * );
588
+ *
589
+ * if (Result.isOk(result)) {
590
+ * console.log('User:', result.data);
591
+ * } else {
592
+ * console.error('Failed:', result.error.message);
593
+ * }
594
+ *
595
+ * @example
596
+ * // With async/await
597
+ * async function safeReadFile(path: string): Promise<Result<string, Error>> {
598
+ * return Result.fromPromise(
599
+ * fs.promises.readFile(path, 'utf-8')
600
+ * );
601
+ * }
602
+ *
603
+ * @since 2025-07-03
604
+ */
605
+ fromPromise: function (promise) { return __awaiter(void 0, void 0, void 0, function () {
606
+ var data, error_1;
607
+ return __generator(this, function (_a) {
608
+ switch (_a.label) {
609
+ case 0:
610
+ _a.trys.push([0, 2, , 3]);
611
+ return [4 /*yield*/, promise];
612
+ case 1:
613
+ data = _a.sent();
614
+ return [2 /*return*/, Result.ok(data)];
615
+ case 2:
616
+ error_1 = _a.sent();
617
+ return [2 /*return*/, Result.err(error_1 instanceof Error ? error_1 : new Error(String(error_1)))];
618
+ case 3: return [2 /*return*/];
619
+ }
620
+ });
621
+ }); },
622
+ /**
623
+ * Converts a function that might throw into a Result-returning function.
624
+ * @description Wraps a function to catch any thrown exceptions and convert
625
+ * them to Result errors. This allows using exception-based APIs in a
626
+ * Result-based codebase.
627
+ *
628
+ * @template T - The tuple type of function arguments
629
+ * @template U - The return type of the function
630
+ * @param {function(...T): U} fn - Function that might throw
631
+ * @returns {function(...T): Result<U, Error>} A safe version that returns Results
632
+ *
633
+ * @category Interop
634
+ * @example
635
+ * // Wrapping JSON.parse
636
+ * const safeParseJSON = Result.fromThrowable(JSON.parse);
637
+ *
638
+ * const result = safeParseJSON('{"name": "John"}');
639
+ * // => { success: true, data: { name: 'John' } }
640
+ *
641
+ * const invalid = safeParseJSON('invalid json');
642
+ * // => { success: false, error: Error(...) }
643
+ *
644
+ * @example
645
+ * // Wrapping custom functions
646
+ * function riskyOperation(x: number): number {
647
+ * if (x < 0) throw new Error('Cannot process negative numbers');
648
+ * return Math.sqrt(x);
649
+ * }
650
+ *
651
+ * const safeSqrt = Result.fromThrowable(riskyOperation);
652
+ *
653
+ * @since 2025-07-03
654
+ */
655
+ fromThrowable: function (fn) {
656
+ return function () {
657
+ var args = [];
658
+ for (var _i = 0; _i < arguments.length; _i++) {
659
+ args[_i] = arguments[_i];
660
+ }
661
+ try {
662
+ var result = fn.apply(void 0, args);
663
+ return Result.ok(result);
664
+ }
665
+ catch (error) {
666
+ return Result.err(error instanceof Error ? error : new Error(String(error)));
667
+ }
668
+ };
669
+ },
670
+ };
671
+ /**
672
+ * Utility type guard for checking if a value is a Result.
673
+ * @description Runtime type guard that checks if an unknown value conforms to
674
+ * the Result type structure. Useful for validation and type narrowing at
675
+ * runtime boundaries.
676
+ *
677
+ * @template T - The expected success type
678
+ * @template E - The expected error type
679
+ * @param {any} value - The value to check
680
+ * @returns {value is Result<T, E>} True if the value is a valid Result
681
+ *
682
+ * @category Type Guards
683
+ * @example
684
+ * // API response validation
685
+ * function handleResponse(data: unknown): void {
686
+ * if (isResult(data)) {
687
+ * if (data.success) {
688
+ * console.log('Success:', data.data);
689
+ * } else {
690
+ * console.error('Error:', data.error);
691
+ * }
692
+ * } else {
693
+ * console.error('Invalid response format');
694
+ * }
695
+ * }
696
+ *
697
+ * @example
698
+ * // Type narrowing in mixed arrays
699
+ * const mixed = [Result.ok(1), 'not a result', Result.err('error')];
700
+ * const results = mixed.filter(isResult);
701
+ * // TypeScript knows results contains only Result types
702
+ *
703
+ * @since 2025-07-03
704
+ */
705
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
706
+ export var isResult = function (value) {
707
+ if (typeof value !== "object" || value === null || !("success" in value)) {
708
+ return false;
709
+ }
710
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
711
+ if (value.success === true) {
712
+ return "data" in value;
713
+ }
714
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
715
+ if (value.success === false) {
716
+ return "error" in value;
717
+ }
718
+ return false;
719
+ };
720
+ /**
721
+ * Helper function to unwrap a Result, throwing if it's an error.
722
+ * @description Use sparingly, only when you're certain the Result should be successful.
723
+ * This function bridges Result-based code with exception-based code, but defeats
724
+ * the purpose of using Results for explicit error handling.
725
+ *
726
+ * @template T - The success type
727
+ * @template E - The error type
728
+ * @param {Result<T, E>} result - The Result to unwrap
729
+ * @returns {T} The success value
730
+ * @throws {Error} If the Result is a failure
731
+ *
732
+ * @category Extraction
733
+ * @example
734
+ * // In tests where you expect success
735
+ * test('calculation succeeds', () => {
736
+ * const result = calculate(10, 2);
737
+ * expect(unwrap(result)).toBe(5);
738
+ * });
739
+ *
740
+ * @example
741
+ * // At system boundaries where errors are exceptional
742
+ * const config = unwrap(loadConfig());
743
+ * // If this fails, the app cannot start anyway
744
+ *
745
+ * @warning Avoid using unwrap in normal application flow.
746
+ * Prefer Result.fold, Result.getOrElse, or pattern matching.
747
+ *
748
+ * @since 2025-07-03
749
+ */
750
+ export var unwrap = function (result) {
751
+ if (result.success) {
752
+ return result.data;
753
+ }
754
+ var errorMessage = result.error instanceof Error
755
+ ? result.error.message
756
+ : String(result.error);
757
+ throw new Error("Attempted to unwrap failed Result: ".concat(errorMessage));
758
+ };
759
+ /**
760
+ * Helper function to safely access nested properties that might not exist.
761
+ * @description Returns a Result instead of throwing or returning undefined.
762
+ * This provides a safe way to access deeply nested properties without
763
+ * optional chaining or null checks.
764
+ *
765
+ * @template T - The type of the object
766
+ * @template U - The type of the extracted value
767
+ * @param {function(T): U} getter - Function that extracts a value from the object
768
+ * @param {string} errorMessage - Error message if extraction fails
769
+ * @returns {function(T): Result<U, string>} A function that safely extracts values
770
+ *
771
+ * @category Utilities
772
+ * @example
773
+ * // Safe property access
774
+ * interface User {
775
+ * profile?: {
776
+ * address?: {
777
+ * city?: string;
778
+ * };
779
+ * };
780
+ * }
781
+ *
782
+ * const getCity = safe((user: User) => user.profile!.address!.city!);
783
+ *
784
+ * const result = getCity({ profile: { address: { city: 'NYC' } } });
785
+ * // => { success: true, data: 'NYC' }
786
+ *
787
+ * const missing = getCity({});
788
+ * // => { success: false, error: 'Property access failed' }
789
+ *
790
+ * @example
791
+ * // Custom error messages
792
+ * const getName = safe(
793
+ * (data: any) => data.user.name as string,
794
+ * 'User name not found'
795
+ * );
796
+ *
797
+ * @since 2025-07-03
798
+ */
799
+ export var safe = function (getter, errorMessage) {
800
+ if (errorMessage === void 0) { errorMessage = "Property access failed"; }
801
+ return function (obj) {
802
+ try {
803
+ var value = getter(obj);
804
+ if (value === undefined || value === null) {
805
+ return Result.err(errorMessage);
806
+ }
807
+ return Result.ok(value);
808
+ }
809
+ catch (_a) {
810
+ return Result.err(errorMessage);
811
+ }
812
+ };
813
+ };
814
+ //# sourceMappingURL=result.mjs.map