@nlozgachev/pipekit 0.1.6

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 (100) hide show
  1. package/README.md +182 -0
  2. package/esm/mod.js +3 -0
  3. package/esm/package.json +3 -0
  4. package/esm/src/Composition/compose.js +3 -0
  5. package/esm/src/Composition/curry.js +42 -0
  6. package/esm/src/Composition/flip.js +20 -0
  7. package/esm/src/Composition/flow.js +8 -0
  8. package/esm/src/Composition/fn.js +85 -0
  9. package/esm/src/Composition/index.js +10 -0
  10. package/esm/src/Composition/memoize.js +66 -0
  11. package/esm/src/Composition/not.js +25 -0
  12. package/esm/src/Composition/pipe.js +3 -0
  13. package/esm/src/Composition/tap.js +33 -0
  14. package/esm/src/Composition/uncurry.js +32 -0
  15. package/esm/src/Core/Arr.js +461 -0
  16. package/esm/src/Core/InternalTypes.js +1 -0
  17. package/esm/src/Core/Option.js +195 -0
  18. package/esm/src/Core/Rec.js +167 -0
  19. package/esm/src/Core/RemoteData.js +210 -0
  20. package/esm/src/Core/Result.js +173 -0
  21. package/esm/src/Core/Task.js +108 -0
  22. package/esm/src/Core/TaskResult.js +63 -0
  23. package/esm/src/Core/Validation.js +215 -0
  24. package/esm/src/Core/index.js +8 -0
  25. package/esm/src/Types/NonEmptyList.js +14 -0
  26. package/esm/src/Types/index.js +1 -0
  27. package/package.json +60 -0
  28. package/script/mod.js +19 -0
  29. package/script/package.json +3 -0
  30. package/script/src/Composition/compose.js +6 -0
  31. package/script/src/Composition/curry.js +48 -0
  32. package/script/src/Composition/flip.js +24 -0
  33. package/script/src/Composition/flow.js +11 -0
  34. package/script/src/Composition/fn.js +98 -0
  35. package/script/src/Composition/index.js +26 -0
  36. package/script/src/Composition/memoize.js +71 -0
  37. package/script/src/Composition/not.js +29 -0
  38. package/script/src/Composition/pipe.js +6 -0
  39. package/script/src/Composition/tap.js +37 -0
  40. package/script/src/Composition/uncurry.js +38 -0
  41. package/script/src/Core/Arr.js +464 -0
  42. package/script/src/Core/InternalTypes.js +2 -0
  43. package/script/src/Core/Option.js +198 -0
  44. package/script/src/Core/Rec.js +170 -0
  45. package/script/src/Core/RemoteData.js +213 -0
  46. package/script/src/Core/Result.js +176 -0
  47. package/script/src/Core/Task.js +111 -0
  48. package/script/src/Core/TaskResult.js +66 -0
  49. package/script/src/Core/Validation.js +218 -0
  50. package/script/src/Core/index.js +24 -0
  51. package/script/src/Types/NonEmptyList.js +18 -0
  52. package/script/src/Types/index.js +17 -0
  53. package/types/mod.d.ts +4 -0
  54. package/types/mod.d.ts.map +1 -0
  55. package/types/src/Composition/compose.d.ts +33 -0
  56. package/types/src/Composition/compose.d.ts.map +1 -0
  57. package/types/src/Composition/curry.d.ts +43 -0
  58. package/types/src/Composition/curry.d.ts.map +1 -0
  59. package/types/src/Composition/flip.d.ts +21 -0
  60. package/types/src/Composition/flip.d.ts.map +1 -0
  61. package/types/src/Composition/flow.d.ts +56 -0
  62. package/types/src/Composition/flow.d.ts.map +1 -0
  63. package/types/src/Composition/fn.d.ts +76 -0
  64. package/types/src/Composition/fn.d.ts.map +1 -0
  65. package/types/src/Composition/index.d.ts +11 -0
  66. package/types/src/Composition/index.d.ts.map +1 -0
  67. package/types/src/Composition/memoize.d.ts +46 -0
  68. package/types/src/Composition/memoize.d.ts.map +1 -0
  69. package/types/src/Composition/not.d.ts +26 -0
  70. package/types/src/Composition/not.d.ts.map +1 -0
  71. package/types/src/Composition/pipe.d.ts +56 -0
  72. package/types/src/Composition/pipe.d.ts.map +1 -0
  73. package/types/src/Composition/tap.d.ts +31 -0
  74. package/types/src/Composition/tap.d.ts.map +1 -0
  75. package/types/src/Composition/uncurry.d.ts +54 -0
  76. package/types/src/Composition/uncurry.d.ts.map +1 -0
  77. package/types/src/Core/Arr.d.ts +355 -0
  78. package/types/src/Core/Arr.d.ts.map +1 -0
  79. package/types/src/Core/InternalTypes.d.ts +14 -0
  80. package/types/src/Core/InternalTypes.d.ts.map +1 -0
  81. package/types/src/Core/Option.d.ts +214 -0
  82. package/types/src/Core/Option.d.ts.map +1 -0
  83. package/types/src/Core/Rec.d.ts +121 -0
  84. package/types/src/Core/Rec.d.ts.map +1 -0
  85. package/types/src/Core/RemoteData.d.ts +196 -0
  86. package/types/src/Core/RemoteData.d.ts.map +1 -0
  87. package/types/src/Core/Result.d.ts +185 -0
  88. package/types/src/Core/Result.d.ts.map +1 -0
  89. package/types/src/Core/Task.d.ts +125 -0
  90. package/types/src/Core/Task.d.ts.map +1 -0
  91. package/types/src/Core/TaskResult.d.ts +78 -0
  92. package/types/src/Core/TaskResult.d.ts.map +1 -0
  93. package/types/src/Core/Validation.d.ts +217 -0
  94. package/types/src/Core/Validation.d.ts.map +1 -0
  95. package/types/src/Core/index.d.ts +9 -0
  96. package/types/src/Core/index.d.ts.map +1 -0
  97. package/types/src/Types/NonEmptyList.d.ts +29 -0
  98. package/types/src/Types/NonEmptyList.d.ts.map +1 -0
  99. package/types/src/Types/index.d.ts +2 -0
  100. package/types/src/Types/index.d.ts.map +1 -0
@@ -0,0 +1,198 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Option = void 0;
4
+ const Result_js_1 = require("./Result.js");
5
+ var Option;
6
+ (function (Option) {
7
+ /**
8
+ * Wraps a value in a Some.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * Option.of(42); // Some(42)
13
+ * ```
14
+ */
15
+ Option.of = (value) => Option.toSome(value);
16
+ /**
17
+ * Creates a Some containing the given value.
18
+ */
19
+ Option.toSome = (value) => ({ kind: "Some", value });
20
+ /**
21
+ * Type guard that checks if a Option is Some.
22
+ */
23
+ Option.isSome = (data) => data.kind === "Some";
24
+ /**
25
+ * Creates a None (empty Option).
26
+ */
27
+ Option.toNone = () => ({ kind: "None" });
28
+ /**
29
+ * Type guard that checks if a Option is None.
30
+ */
31
+ Option.isNone = (data) => data.kind === "None";
32
+ /**
33
+ * Creates a Option from a nullable value.
34
+ * Returns None if the value is null or undefined, Some otherwise.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * Option.fromNullable(null); // None
39
+ * Option.fromNullable(42); // Some(42)
40
+ * ```
41
+ */
42
+ Option.fromNullable = (value) => value === null || value === undefined ? Option.toNone() : Option.toSome(value);
43
+ /**
44
+ * Extracts the value from a Option, returning null if None.
45
+ */
46
+ Option.toNullable = (data) => Option.isSome(data) ? data.value : null;
47
+ /**
48
+ * Extracts the value from a Option, returning undefined if None.
49
+ */
50
+ Option.toUndefined = (data) => Option.isSome(data) ? data.value : undefined;
51
+ /**
52
+ * Creates a Option from a possibly undefined value.
53
+ * Returns None if undefined, Some otherwise.
54
+ */
55
+ Option.fromUndefined = (value) => value === undefined ? Option.toNone() : Option.toSome(value);
56
+ /**
57
+ * Converts an Option to a Result.
58
+ * Some becomes Ok, None becomes Err with the provided error.
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * pipe(
63
+ * Option.of(42),
64
+ * Option.toResult(() => "Value was missing")
65
+ * ); // Ok(42)
66
+ *
67
+ * pipe(
68
+ * Option.toNone(),
69
+ * Option.toResult(() => "Value was missing")
70
+ * ); // Err("Value was missing")
71
+ * ```
72
+ */
73
+ Option.toResult = (onNone) => (data) => Option.isSome(data) ? Result_js_1.Result.toOk(data.value) : Result_js_1.Result.toErr(onNone());
74
+ /**
75
+ * Creates an Option from a Result.
76
+ * Ok becomes Some, Err becomes None (the error is discarded).
77
+ *
78
+ * @example
79
+ * ```ts
80
+ * Option.fromResult(Result.toOk(42)); // Some(42)
81
+ * Option.fromResult(Result.toErr("oops")); // None
82
+ * ```
83
+ */
84
+ Option.fromResult = (data) => Result_js_1.Result.isOk(data) ? Option.toSome(data.value) : Option.toNone();
85
+ /**
86
+ * Transforms the value inside a Option if it exists.
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * pipe(Option.of(5), Option.map(n => n * 2)); // Some(10)
91
+ * pipe(Option.toNone(), Option.map(n => n * 2)); // None
92
+ * ```
93
+ */
94
+ Option.map = (f) => (data) => Option.isSome(data) ? Option.toSome(f(data.value)) : data;
95
+ /**
96
+ * Chains Option computations. If the first is Some, passes the value to f.
97
+ * If the first is None, propagates None.
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * const parseNumber = (s: string): Option<number> => {
102
+ * const n = parseInt(s, 10);
103
+ * return isNaN(n) ? Option.toNone() : Option.of(n);
104
+ * };
105
+ *
106
+ * pipe(Option.of("42"), Option.chain(parseNumber)); // Some(42)
107
+ * pipe(Option.of("abc"), Option.chain(parseNumber)); // None
108
+ * ```
109
+ */
110
+ Option.chain = (f) => (data) => Option.isSome(data) ? f(data.value) : data;
111
+ /**
112
+ * Extracts the value from a Option by providing handlers for both cases.
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * pipe(
117
+ * Option.of(5),
118
+ * Option.fold(
119
+ * () => "No value",
120
+ * n => `Value: ${n}`
121
+ * )
122
+ * ); // "Value: 5"
123
+ * ```
124
+ */
125
+ Option.fold = (onNone, onSome) => (data) => Option.isSome(data) ? onSome(data.value) : onNone();
126
+ /**
127
+ * Pattern matches on a Option, returning the result of the matching case.
128
+ *
129
+ * @example
130
+ * ```ts
131
+ * pipe(
132
+ * optionUser,
133
+ * Option.match({
134
+ * some: user => `Hello, ${user.name}`,
135
+ * none: () => "Hello, stranger"
136
+ * })
137
+ * );
138
+ * ```
139
+ */
140
+ Option.match = (cases) => (data) => Option.isSome(data) ? cases.some(data.value) : cases.none();
141
+ /**
142
+ * Returns the value inside a Option, or a default value if None.
143
+ *
144
+ * @example
145
+ * ```ts
146
+ * pipe(Option.of(5), Option.getOrElse(0)); // 5
147
+ * pipe(Option.toNone(), Option.getOrElse(0)); // 0
148
+ * ```
149
+ */
150
+ Option.getOrElse = (defaultValue) => (data) => Option.isSome(data) ? data.value : defaultValue;
151
+ /**
152
+ * Executes a side effect on the value without changing the Option.
153
+ * Useful for logging or debugging.
154
+ *
155
+ * @example
156
+ * ```ts
157
+ * pipe(
158
+ * Option.of(5),
159
+ * Option.tap(n => console.log("Value:", n)),
160
+ * Option.map(n => n * 2)
161
+ * );
162
+ * ```
163
+ */
164
+ Option.tap = (f) => (data) => {
165
+ if (Option.isSome(data))
166
+ f(data.value);
167
+ return data;
168
+ };
169
+ /**
170
+ * Filters a Option based on a predicate.
171
+ * Returns None if the predicate returns false or if the Option is already None.
172
+ *
173
+ * @example
174
+ * ```ts
175
+ * pipe(Option.of(5), Option.filter(n => n > 3)); // Some(5)
176
+ * pipe(Option.of(2), Option.filter(n => n > 3)); // None
177
+ * ```
178
+ */
179
+ Option.filter = (predicate) => (data) => Option.isSome(data) && predicate(data.value) ? data : Option.toNone();
180
+ /**
181
+ * Recovers from a None by providing a fallback Option.
182
+ */
183
+ Option.recover = (fallback) => (data) => Option.isSome(data) ? data : fallback();
184
+ /**
185
+ * Applies a function wrapped in a Option to a value wrapped in a Option.
186
+ *
187
+ * @example
188
+ * ```ts
189
+ * const add = (a: number) => (b: number) => a + b;
190
+ * pipe(
191
+ * Option.of(add),
192
+ * Option.ap(Option.of(5)),
193
+ * Option.ap(Option.of(3))
194
+ * ); // Some(8)
195
+ * ```
196
+ */
197
+ Option.ap = (arg) => (data) => Option.isSome(data) && Option.isSome(arg) ? Option.toSome(data.value(arg.value)) : Option.toNone();
198
+ })(Option || (exports.Option = Option = {}));
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Rec = void 0;
4
+ const Option_js_1 = require("./Option.js");
5
+ /**
6
+ * Functional record/object utilities that compose well with pipe.
7
+ * All functions are data-last and curried where applicable.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * pipe(
12
+ * { a: 1, b: 2, c: 3 },
13
+ * Rec.filter(n => n > 1),
14
+ * Rec.map(n => n * 10)
15
+ * ); // { b: 20, c: 30 }
16
+ * ```
17
+ */
18
+ var Rec;
19
+ (function (Rec) {
20
+ /**
21
+ * Transforms each value in a record.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * pipe({ a: 1, b: 2 }, Rec.map(n => n * 2)); // { a: 2, b: 4 }
26
+ * ```
27
+ */
28
+ Rec.map = (f) => (data) => {
29
+ const result = {};
30
+ for (const key of Object.keys(data)) {
31
+ result[key] = f(data[key]);
32
+ }
33
+ return result;
34
+ };
35
+ /**
36
+ * Transforms each value in a record, also receiving the key.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * pipe({ a: 1, b: 2 }, Rec.mapWithKey((k, v) => `${k}:${v}`));
41
+ * // { a: "a:1", b: "b:2" }
42
+ * ```
43
+ */
44
+ Rec.mapWithKey = (f) => (data) => {
45
+ const result = {};
46
+ for (const key of Object.keys(data)) {
47
+ result[key] = f(key, data[key]);
48
+ }
49
+ return result;
50
+ };
51
+ /**
52
+ * Filters values in a record by a predicate.
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * pipe({ a: 1, b: 2, c: 3 }, Rec.filter(n => n > 1)); // { b: 2, c: 3 }
57
+ * ```
58
+ */
59
+ Rec.filter = (predicate) => (data) => {
60
+ const result = {};
61
+ for (const key of Object.keys(data)) {
62
+ if (predicate(data[key]))
63
+ result[key] = data[key];
64
+ }
65
+ return result;
66
+ };
67
+ /**
68
+ * Filters values in a record by a predicate that also receives the key.
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * pipe({ a: 1, b: 2 }, Rec.filterWithKey((k, v) => k !== "a" && v > 0));
73
+ * // { b: 2 }
74
+ * ```
75
+ */
76
+ Rec.filterWithKey = (predicate) => (data) => {
77
+ const result = {};
78
+ for (const key of Object.keys(data)) {
79
+ if (predicate(key, data[key]))
80
+ result[key] = data[key];
81
+ }
82
+ return result;
83
+ };
84
+ /**
85
+ * Looks up a value by key, returning Option.
86
+ *
87
+ * @example
88
+ * ```ts
89
+ * pipe({ a: 1, b: 2 }, Rec.lookup("a")); // Some(1)
90
+ * pipe({ a: 1, b: 2 }, Rec.lookup("c")); // None
91
+ * ```
92
+ */
93
+ Rec.lookup = (key) => (data) => Object.prototype.hasOwnProperty.call(data, key) ? Option_js_1.Option.toSome(data[key]) : Option_js_1.Option.toNone();
94
+ /**
95
+ * Returns all keys of a record.
96
+ */
97
+ Rec.keys = (data) => Object.keys(data);
98
+ /**
99
+ * Returns all values of a record.
100
+ */
101
+ Rec.values = (data) => Object.values(data);
102
+ /**
103
+ * Returns all key-value pairs of a record.
104
+ */
105
+ Rec.entries = (data) => Object.entries(data);
106
+ /**
107
+ * Creates a record from key-value pairs.
108
+ *
109
+ * @example
110
+ * ```ts
111
+ * Rec.fromEntries([["a", 1], ["b", 2]]); // { a: 1, b: 2 }
112
+ * ```
113
+ */
114
+ Rec.fromEntries = (data) => Object.fromEntries(data);
115
+ /**
116
+ * Picks specific keys from a record.
117
+ *
118
+ * @example
119
+ * ```ts
120
+ * pipe({ a: 1, b: 2, c: 3 }, Rec.pick("a", "c")); // { a: 1, c: 3 }
121
+ * ```
122
+ */
123
+ Rec.pick = (...pickedKeys) => (data) => {
124
+ const result = {};
125
+ for (const key of pickedKeys) {
126
+ if (Object.prototype.hasOwnProperty.call(data, key)) {
127
+ result[key] = data[key];
128
+ }
129
+ }
130
+ return result;
131
+ };
132
+ /**
133
+ * Omits specific keys from a record.
134
+ *
135
+ * @example
136
+ * ```ts
137
+ * pipe({ a: 1, b: 2, c: 3 }, Rec.omit("b")); // { a: 1, c: 3 }
138
+ * ```
139
+ */
140
+ Rec.omit = (...omittedKeys) => (data) => {
141
+ const omitSet = new Set(omittedKeys);
142
+ const result = {};
143
+ for (const key of Object.keys(data)) {
144
+ if (!omitSet.has(key)) {
145
+ result[key] = data[key];
146
+ }
147
+ }
148
+ return result;
149
+ };
150
+ /**
151
+ * Merges two records. Values from the second record take precedence.
152
+ *
153
+ * @example
154
+ * ```ts
155
+ * pipe({ a: 1, b: 2 }, Rec.merge({ b: 3, c: 4 })); // { a: 1, b: 3, c: 4 }
156
+ * ```
157
+ */
158
+ Rec.merge = (other) => (data) => ({
159
+ ...data,
160
+ ...other,
161
+ });
162
+ /**
163
+ * Returns true if the record has no keys.
164
+ */
165
+ Rec.isEmpty = (data) => Object.keys(data).length === 0;
166
+ /**
167
+ * Returns the number of keys in a record.
168
+ */
169
+ Rec.size = (data) => Object.keys(data).length;
170
+ })(Rec || (exports.Rec = Rec = {}));
@@ -0,0 +1,213 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RemoteData = void 0;
4
+ var RemoteData;
5
+ (function (RemoteData) {
6
+ /**
7
+ * Creates a NotAsked RemoteData.
8
+ */
9
+ RemoteData.notAsked = () => ({ kind: "NotAsked" });
10
+ /**
11
+ * Creates a Loading RemoteData.
12
+ */
13
+ RemoteData.loading = () => ({ kind: "Loading" });
14
+ /**
15
+ * Creates a Failure RemoteData with the given error.
16
+ */
17
+ RemoteData.failure = (error) => ({
18
+ kind: "Failure",
19
+ error,
20
+ });
21
+ /**
22
+ * Creates a Success RemoteData with the given value.
23
+ */
24
+ RemoteData.success = (value) => ({
25
+ kind: "Success",
26
+ value,
27
+ });
28
+ /**
29
+ * Wraps a value in a Success RemoteData. Alias for `success`.
30
+ */
31
+ RemoteData.of = RemoteData.success;
32
+ /**
33
+ * Type guard that checks if a RemoteData is NotAsked.
34
+ */
35
+ RemoteData.isNotAsked = (data) => data.kind === "NotAsked";
36
+ /**
37
+ * Type guard that checks if a RemoteData is Loading.
38
+ */
39
+ RemoteData.isLoading = (data) => data.kind === "Loading";
40
+ /**
41
+ * Type guard that checks if a RemoteData is Failure.
42
+ */
43
+ RemoteData.isFailure = (data) => data.kind === "Failure";
44
+ /**
45
+ * Type guard that checks if a RemoteData is Success.
46
+ */
47
+ RemoteData.isSuccess = (data) => data.kind === "Success";
48
+ /**
49
+ * Transforms the success value inside a RemoteData.
50
+ *
51
+ * @example
52
+ * ```ts
53
+ * pipe(RemoteData.of(5), RemoteData.map(n => n * 2)); // Success(10)
54
+ * pipe(RemoteData.loading(), RemoteData.map(n => n * 2)); // Loading
55
+ * ```
56
+ */
57
+ RemoteData.map = (f) => (data) => RemoteData.isSuccess(data) ? RemoteData.success(f(data.value)) : data;
58
+ /**
59
+ * Transforms the error value inside a RemoteData.
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * pipe(RemoteData.failure("oops"), RemoteData.mapError(e => e.toUpperCase())); // Failure("OOPS")
64
+ * ```
65
+ */
66
+ RemoteData.mapError = (f) => (data) => RemoteData.isFailure(data) ? RemoteData.failure(f(data.error)) : data;
67
+ /**
68
+ * Chains RemoteData computations. If the input is Success, passes the value to f.
69
+ * Otherwise, propagates the current state.
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * pipe(
74
+ * RemoteData.of(5),
75
+ * RemoteData.chain(n => n > 0 ? RemoteData.of(n) : RemoteData.failure("negative"))
76
+ * );
77
+ * ```
78
+ */
79
+ RemoteData.chain = (f) => (data) => RemoteData.isSuccess(data) ? f(data.value) : data;
80
+ /**
81
+ * Applies a function wrapped in a RemoteData to a value wrapped in a RemoteData.
82
+ *
83
+ * @example
84
+ * ```ts
85
+ * const add = (a: number) => (b: number) => a + b;
86
+ * pipe(
87
+ * RemoteData.of(add),
88
+ * RemoteData.ap(RemoteData.of(5)),
89
+ * RemoteData.ap(RemoteData.of(3))
90
+ * ); // Success(8)
91
+ * ```
92
+ */
93
+ RemoteData.ap = (arg) => (data) => {
94
+ if (RemoteData.isSuccess(data) && RemoteData.isSuccess(arg)) {
95
+ return RemoteData.success(data.value(arg.value));
96
+ }
97
+ if (RemoteData.isFailure(data))
98
+ return data;
99
+ if (RemoteData.isFailure(arg))
100
+ return arg;
101
+ if (RemoteData.isLoading(data) || RemoteData.isLoading(arg))
102
+ return RemoteData.loading();
103
+ return RemoteData.notAsked();
104
+ };
105
+ /**
106
+ * Extracts the value from a RemoteData by providing handlers for all four cases.
107
+ *
108
+ * @example
109
+ * ```ts
110
+ * pipe(
111
+ * userData,
112
+ * RemoteData.fold(
113
+ * () => "Not asked",
114
+ * () => "Loading...",
115
+ * e => `Error: ${e}`,
116
+ * value => `Got: ${value}`
117
+ * )
118
+ * );
119
+ * ```
120
+ */
121
+ RemoteData.fold = (onNotAsked, onLoading, onFailure, onSuccess) => (data) => {
122
+ switch (data.kind) {
123
+ case "NotAsked":
124
+ return onNotAsked();
125
+ case "Loading":
126
+ return onLoading();
127
+ case "Failure":
128
+ return onFailure(data.error);
129
+ case "Success":
130
+ return onSuccess(data.value);
131
+ }
132
+ };
133
+ /**
134
+ * Pattern matches on a RemoteData, returning the result of the matching case.
135
+ *
136
+ * @example
137
+ * ```ts
138
+ * pipe(
139
+ * userData,
140
+ * RemoteData.match({
141
+ * notAsked: () => "Click to load",
142
+ * loading: () => "Loading...",
143
+ * failure: e => `Error: ${e}`,
144
+ * success: user => `Hello, ${user.name}!`
145
+ * })
146
+ * );
147
+ * ```
148
+ */
149
+ RemoteData.match = (cases) => (data) => {
150
+ switch (data.kind) {
151
+ case "NotAsked":
152
+ return cases.notAsked();
153
+ case "Loading":
154
+ return cases.loading();
155
+ case "Failure":
156
+ return cases.failure(data.error);
157
+ case "Success":
158
+ return cases.success(data.value);
159
+ }
160
+ };
161
+ /**
162
+ * Returns the success value or a default value if the RemoteData is not Success.
163
+ *
164
+ * @example
165
+ * ```ts
166
+ * pipe(RemoteData.of(5), RemoteData.getOrElse(0)); // 5
167
+ * pipe(RemoteData.loading(), RemoteData.getOrElse(0)); // 0
168
+ * ```
169
+ */
170
+ RemoteData.getOrElse = (defaultValue) => (data) => RemoteData.isSuccess(data) ? data.value : defaultValue;
171
+ /**
172
+ * Executes a side effect on the success value without changing the RemoteData.
173
+ *
174
+ * @example
175
+ * ```ts
176
+ * pipe(
177
+ * RemoteData.of(5),
178
+ * RemoteData.tap(n => console.log("Value:", n)),
179
+ * RemoteData.map(n => n * 2)
180
+ * );
181
+ * ```
182
+ */
183
+ RemoteData.tap = (f) => (data) => {
184
+ if (RemoteData.isSuccess(data))
185
+ f(data.value);
186
+ return data;
187
+ };
188
+ /**
189
+ * Recovers from a Failure state by providing a fallback RemoteData.
190
+ */
191
+ RemoteData.recover = (fallback) => (data) => RemoteData.isFailure(data) ? fallback(data.error) : data;
192
+ /**
193
+ * Converts a RemoteData to an Option.
194
+ * Success becomes Some, all other states become None.
195
+ */
196
+ RemoteData.toOption = (data) => RemoteData.isSuccess(data) ? { kind: "Some", value: data.value } : { kind: "None" };
197
+ /**
198
+ * Converts a RemoteData to a Result.
199
+ * Success becomes Ok, Failure becomes Err.
200
+ * NotAsked and Loading become Err with the provided fallback error.
201
+ *
202
+ * @example
203
+ * ```ts
204
+ * pipe(
205
+ * RemoteData.of(42),
206
+ * RemoteData.toResult(() => "not loaded")
207
+ * ); // Ok(42)
208
+ * ```
209
+ */
210
+ RemoteData.toResult = (onNotReady) => (data) => RemoteData.isSuccess(data)
211
+ ? { kind: "Ok", value: data.value }
212
+ : { kind: "Error", error: RemoteData.isFailure(data) ? data.error : onNotReady() };
213
+ })(RemoteData || (exports.RemoteData = RemoteData = {}));