@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.
- package/README.md +182 -0
- package/esm/mod.js +3 -0
- package/esm/package.json +3 -0
- package/esm/src/Composition/compose.js +3 -0
- package/esm/src/Composition/curry.js +42 -0
- package/esm/src/Composition/flip.js +20 -0
- package/esm/src/Composition/flow.js +8 -0
- package/esm/src/Composition/fn.js +85 -0
- package/esm/src/Composition/index.js +10 -0
- package/esm/src/Composition/memoize.js +66 -0
- package/esm/src/Composition/not.js +25 -0
- package/esm/src/Composition/pipe.js +3 -0
- package/esm/src/Composition/tap.js +33 -0
- package/esm/src/Composition/uncurry.js +32 -0
- package/esm/src/Core/Arr.js +461 -0
- package/esm/src/Core/InternalTypes.js +1 -0
- package/esm/src/Core/Option.js +195 -0
- package/esm/src/Core/Rec.js +167 -0
- package/esm/src/Core/RemoteData.js +210 -0
- package/esm/src/Core/Result.js +173 -0
- package/esm/src/Core/Task.js +108 -0
- package/esm/src/Core/TaskResult.js +63 -0
- package/esm/src/Core/Validation.js +215 -0
- package/esm/src/Core/index.js +8 -0
- package/esm/src/Types/NonEmptyList.js +14 -0
- package/esm/src/Types/index.js +1 -0
- package/package.json +60 -0
- package/script/mod.js +19 -0
- package/script/package.json +3 -0
- package/script/src/Composition/compose.js +6 -0
- package/script/src/Composition/curry.js +48 -0
- package/script/src/Composition/flip.js +24 -0
- package/script/src/Composition/flow.js +11 -0
- package/script/src/Composition/fn.js +98 -0
- package/script/src/Composition/index.js +26 -0
- package/script/src/Composition/memoize.js +71 -0
- package/script/src/Composition/not.js +29 -0
- package/script/src/Composition/pipe.js +6 -0
- package/script/src/Composition/tap.js +37 -0
- package/script/src/Composition/uncurry.js +38 -0
- package/script/src/Core/Arr.js +464 -0
- package/script/src/Core/InternalTypes.js +2 -0
- package/script/src/Core/Option.js +198 -0
- package/script/src/Core/Rec.js +170 -0
- package/script/src/Core/RemoteData.js +213 -0
- package/script/src/Core/Result.js +176 -0
- package/script/src/Core/Task.js +111 -0
- package/script/src/Core/TaskResult.js +66 -0
- package/script/src/Core/Validation.js +218 -0
- package/script/src/Core/index.js +24 -0
- package/script/src/Types/NonEmptyList.js +18 -0
- package/script/src/Types/index.js +17 -0
- package/types/mod.d.ts +4 -0
- package/types/mod.d.ts.map +1 -0
- package/types/src/Composition/compose.d.ts +33 -0
- package/types/src/Composition/compose.d.ts.map +1 -0
- package/types/src/Composition/curry.d.ts +43 -0
- package/types/src/Composition/curry.d.ts.map +1 -0
- package/types/src/Composition/flip.d.ts +21 -0
- package/types/src/Composition/flip.d.ts.map +1 -0
- package/types/src/Composition/flow.d.ts +56 -0
- package/types/src/Composition/flow.d.ts.map +1 -0
- package/types/src/Composition/fn.d.ts +76 -0
- package/types/src/Composition/fn.d.ts.map +1 -0
- package/types/src/Composition/index.d.ts +11 -0
- package/types/src/Composition/index.d.ts.map +1 -0
- package/types/src/Composition/memoize.d.ts +46 -0
- package/types/src/Composition/memoize.d.ts.map +1 -0
- package/types/src/Composition/not.d.ts +26 -0
- package/types/src/Composition/not.d.ts.map +1 -0
- package/types/src/Composition/pipe.d.ts +56 -0
- package/types/src/Composition/pipe.d.ts.map +1 -0
- package/types/src/Composition/tap.d.ts +31 -0
- package/types/src/Composition/tap.d.ts.map +1 -0
- package/types/src/Composition/uncurry.d.ts +54 -0
- package/types/src/Composition/uncurry.d.ts.map +1 -0
- package/types/src/Core/Arr.d.ts +355 -0
- package/types/src/Core/Arr.d.ts.map +1 -0
- package/types/src/Core/InternalTypes.d.ts +14 -0
- package/types/src/Core/InternalTypes.d.ts.map +1 -0
- package/types/src/Core/Option.d.ts +214 -0
- package/types/src/Core/Option.d.ts.map +1 -0
- package/types/src/Core/Rec.d.ts +121 -0
- package/types/src/Core/Rec.d.ts.map +1 -0
- package/types/src/Core/RemoteData.d.ts +196 -0
- package/types/src/Core/RemoteData.d.ts.map +1 -0
- package/types/src/Core/Result.d.ts +185 -0
- package/types/src/Core/Result.d.ts.map +1 -0
- package/types/src/Core/Task.d.ts +125 -0
- package/types/src/Core/Task.d.ts.map +1 -0
- package/types/src/Core/TaskResult.d.ts +78 -0
- package/types/src/Core/TaskResult.d.ts.map +1 -0
- package/types/src/Core/Validation.d.ts +217 -0
- package/types/src/Core/Validation.d.ts.map +1 -0
- package/types/src/Core/index.d.ts +9 -0
- package/types/src/Core/index.d.ts.map +1 -0
- package/types/src/Types/NonEmptyList.d.ts +29 -0
- package/types/src/Types/NonEmptyList.d.ts.map +1 -0
- package/types/src/Types/index.d.ts +2 -0
- 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 = {}));
|