@nlozgachev/pipelined 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/LICENCE +28 -0
  2. package/README.md +1 -1
  3. package/{types/src/Types/NonEmptyList.d.ts → dist/NonEmptyList-BlGFjor5.d.mts} +4 -3
  4. package/dist/NonEmptyList-BlGFjor5.d.ts +30 -0
  5. package/dist/Task-Bd3gXPRQ.d.mts +677 -0
  6. package/dist/Task-BjAkkD6t.d.ts +677 -0
  7. package/dist/chunk-4TXC322E.mjs +136 -0
  8. package/dist/chunk-BYWKZLHM.mjs +10 -0
  9. package/dist/chunk-DBIC62UV.mjs +6 -0
  10. package/dist/chunk-FAZN3IWZ.mjs +554 -0
  11. package/dist/chunk-QPTGO5AS.mjs +150 -0
  12. package/dist/chunk-UV2HMF2A.mjs +514 -0
  13. package/dist/composition.d.mts +495 -0
  14. package/dist/composition.d.ts +495 -0
  15. package/dist/composition.js +188 -0
  16. package/dist/composition.mjs +58 -0
  17. package/dist/core.d.mts +2170 -0
  18. package/dist/core.d.ts +2170 -0
  19. package/dist/core.js +698 -0
  20. package/dist/core.mjs +42 -0
  21. package/dist/index.d.mts +6 -0
  22. package/dist/index.d.ts +6 -0
  23. package/dist/index.js +1421 -0
  24. package/dist/index.mjs +120 -0
  25. package/dist/types.d.mts +54 -0
  26. package/{types/src/Types/Brand.d.ts → dist/types.d.ts} +6 -4
  27. package/dist/types.js +41 -0
  28. package/dist/types.mjs +10 -0
  29. package/dist/utils.d.mts +1285 -0
  30. package/dist/utils.d.ts +1285 -0
  31. package/dist/utils.js +722 -0
  32. package/dist/utils.mjs +18 -0
  33. package/package.json +64 -69
  34. package/esm/mod.js +0 -3
  35. package/esm/package.json +0 -3
  36. package/esm/src/Composition/compose.js +0 -3
  37. package/esm/src/Composition/converge.js +0 -3
  38. package/esm/src/Composition/curry.js +0 -42
  39. package/esm/src/Composition/flip.js +0 -20
  40. package/esm/src/Composition/flow.js +0 -8
  41. package/esm/src/Composition/fn.js +0 -85
  42. package/esm/src/Composition/index.js +0 -13
  43. package/esm/src/Composition/juxt.js +0 -3
  44. package/esm/src/Composition/memoize.js +0 -66
  45. package/esm/src/Composition/not.js +0 -25
  46. package/esm/src/Composition/on.js +0 -12
  47. package/esm/src/Composition/pipe.js +0 -3
  48. package/esm/src/Composition/tap.js +0 -33
  49. package/esm/src/Composition/uncurry.js +0 -32
  50. package/esm/src/Core/Deferred.js +0 -30
  51. package/esm/src/Core/InternalTypes.js +0 -1
  52. package/esm/src/Core/Lens.js +0 -98
  53. package/esm/src/Core/Logged.js +0 -111
  54. package/esm/src/Core/Option.js +0 -191
  55. package/esm/src/Core/Optional.js +0 -160
  56. package/esm/src/Core/Predicate.js +0 -133
  57. package/esm/src/Core/Reader.js +0 -134
  58. package/esm/src/Core/Refinement.js +0 -115
  59. package/esm/src/Core/RemoteData.js +0 -211
  60. package/esm/src/Core/Result.js +0 -170
  61. package/esm/src/Core/State.js +0 -181
  62. package/esm/src/Core/Task.js +0 -223
  63. package/esm/src/Core/TaskOption.js +0 -106
  64. package/esm/src/Core/TaskResult.js +0 -127
  65. package/esm/src/Core/TaskValidation.js +0 -128
  66. package/esm/src/Core/These.js +0 -245
  67. package/esm/src/Core/Tuple.js +0 -112
  68. package/esm/src/Core/Validation.js +0 -212
  69. package/esm/src/Core/index.js +0 -18
  70. package/esm/src/Types/Brand.js +0 -28
  71. package/esm/src/Types/NonEmptyList.js +0 -14
  72. package/esm/src/Types/index.js +0 -2
  73. package/esm/src/Utils/Arr.js +0 -570
  74. package/esm/src/Utils/Dict.js +0 -421
  75. package/esm/src/Utils/Num.js +0 -124
  76. package/esm/src/Utils/Rec.js +0 -241
  77. package/esm/src/Utils/Str.js +0 -134
  78. package/esm/src/Utils/Uniq.js +0 -265
  79. package/esm/src/Utils/index.js +0 -6
  80. package/script/mod.js +0 -19
  81. package/script/package.json +0 -3
  82. package/script/src/Composition/compose.js +0 -6
  83. package/script/src/Composition/converge.js +0 -6
  84. package/script/src/Composition/curry.js +0 -48
  85. package/script/src/Composition/flip.js +0 -24
  86. package/script/src/Composition/flow.js +0 -11
  87. package/script/src/Composition/fn.js +0 -98
  88. package/script/src/Composition/index.js +0 -29
  89. package/script/src/Composition/juxt.js +0 -6
  90. package/script/src/Composition/memoize.js +0 -71
  91. package/script/src/Composition/not.js +0 -29
  92. package/script/src/Composition/on.js +0 -16
  93. package/script/src/Composition/pipe.js +0 -6
  94. package/script/src/Composition/tap.js +0 -37
  95. package/script/src/Composition/uncurry.js +0 -38
  96. package/script/src/Core/Deferred.js +0 -33
  97. package/script/src/Core/InternalTypes.js +0 -2
  98. package/script/src/Core/Lens.js +0 -101
  99. package/script/src/Core/Logged.js +0 -114
  100. package/script/src/Core/Option.js +0 -194
  101. package/script/src/Core/Optional.js +0 -163
  102. package/script/src/Core/Predicate.js +0 -136
  103. package/script/src/Core/Reader.js +0 -137
  104. package/script/src/Core/Refinement.js +0 -118
  105. package/script/src/Core/RemoteData.js +0 -214
  106. package/script/src/Core/Result.js +0 -173
  107. package/script/src/Core/State.js +0 -184
  108. package/script/src/Core/Task.js +0 -226
  109. package/script/src/Core/TaskOption.js +0 -109
  110. package/script/src/Core/TaskResult.js +0 -130
  111. package/script/src/Core/TaskValidation.js +0 -131
  112. package/script/src/Core/These.js +0 -248
  113. package/script/src/Core/Tuple.js +0 -115
  114. package/script/src/Core/Validation.js +0 -215
  115. package/script/src/Core/index.js +0 -34
  116. package/script/src/Types/Brand.js +0 -31
  117. package/script/src/Types/NonEmptyList.js +0 -18
  118. package/script/src/Types/index.js +0 -18
  119. package/script/src/Utils/Arr.js +0 -573
  120. package/script/src/Utils/Dict.js +0 -424
  121. package/script/src/Utils/Num.js +0 -127
  122. package/script/src/Utils/Rec.js +0 -244
  123. package/script/src/Utils/Str.js +0 -137
  124. package/script/src/Utils/Uniq.js +0 -268
  125. package/script/src/Utils/index.js +0 -22
  126. package/types/mod.d.ts +0 -4
  127. package/types/mod.d.ts.map +0 -1
  128. package/types/src/Composition/compose.d.ts +0 -33
  129. package/types/src/Composition/compose.d.ts.map +0 -1
  130. package/types/src/Composition/converge.d.ts +0 -21
  131. package/types/src/Composition/converge.d.ts.map +0 -1
  132. package/types/src/Composition/curry.d.ts +0 -43
  133. package/types/src/Composition/curry.d.ts.map +0 -1
  134. package/types/src/Composition/flip.d.ts +0 -21
  135. package/types/src/Composition/flip.d.ts.map +0 -1
  136. package/types/src/Composition/flow.d.ts +0 -56
  137. package/types/src/Composition/flow.d.ts.map +0 -1
  138. package/types/src/Composition/fn.d.ts +0 -76
  139. package/types/src/Composition/fn.d.ts.map +0 -1
  140. package/types/src/Composition/index.d.ts +0 -14
  141. package/types/src/Composition/index.d.ts.map +0 -1
  142. package/types/src/Composition/juxt.d.ts +0 -18
  143. package/types/src/Composition/juxt.d.ts.map +0 -1
  144. package/types/src/Composition/memoize.d.ts +0 -46
  145. package/types/src/Composition/memoize.d.ts.map +0 -1
  146. package/types/src/Composition/not.d.ts +0 -26
  147. package/types/src/Composition/not.d.ts.map +0 -1
  148. package/types/src/Composition/on.d.ts +0 -13
  149. package/types/src/Composition/on.d.ts.map +0 -1
  150. package/types/src/Composition/pipe.d.ts +0 -56
  151. package/types/src/Composition/pipe.d.ts.map +0 -1
  152. package/types/src/Composition/tap.d.ts +0 -31
  153. package/types/src/Composition/tap.d.ts.map +0 -1
  154. package/types/src/Composition/uncurry.d.ts +0 -54
  155. package/types/src/Composition/uncurry.d.ts.map +0 -1
  156. package/types/src/Core/Deferred.d.ts +0 -49
  157. package/types/src/Core/Deferred.d.ts.map +0 -1
  158. package/types/src/Core/InternalTypes.d.ts +0 -23
  159. package/types/src/Core/InternalTypes.d.ts.map +0 -1
  160. package/types/src/Core/Lens.d.ts +0 -118
  161. package/types/src/Core/Lens.d.ts.map +0 -1
  162. package/types/src/Core/Logged.d.ts +0 -126
  163. package/types/src/Core/Logged.d.ts.map +0 -1
  164. package/types/src/Core/Option.d.ts +0 -209
  165. package/types/src/Core/Option.d.ts.map +0 -1
  166. package/types/src/Core/Optional.d.ts +0 -158
  167. package/types/src/Core/Optional.d.ts.map +0 -1
  168. package/types/src/Core/Predicate.d.ts +0 -161
  169. package/types/src/Core/Predicate.d.ts.map +0 -1
  170. package/types/src/Core/Reader.d.ts +0 -156
  171. package/types/src/Core/Reader.d.ts.map +0 -1
  172. package/types/src/Core/Refinement.d.ts +0 -138
  173. package/types/src/Core/Refinement.d.ts.map +0 -1
  174. package/types/src/Core/RemoteData.d.ts +0 -197
  175. package/types/src/Core/RemoteData.d.ts.map +0 -1
  176. package/types/src/Core/Result.d.ts +0 -182
  177. package/types/src/Core/Result.d.ts.map +0 -1
  178. package/types/src/Core/State.d.ts +0 -192
  179. package/types/src/Core/State.d.ts.map +0 -1
  180. package/types/src/Core/Task.d.ts +0 -219
  181. package/types/src/Core/Task.d.ts.map +0 -1
  182. package/types/src/Core/TaskOption.d.ts +0 -121
  183. package/types/src/Core/TaskOption.d.ts.map +0 -1
  184. package/types/src/Core/TaskResult.d.ts +0 -119
  185. package/types/src/Core/TaskResult.d.ts.map +0 -1
  186. package/types/src/Core/TaskValidation.d.ts +0 -144
  187. package/types/src/Core/TaskValidation.d.ts.map +0 -1
  188. package/types/src/Core/These.d.ts +0 -225
  189. package/types/src/Core/These.d.ts.map +0 -1
  190. package/types/src/Core/Tuple.d.ts +0 -129
  191. package/types/src/Core/Tuple.d.ts.map +0 -1
  192. package/types/src/Core/Validation.d.ts +0 -203
  193. package/types/src/Core/Validation.d.ts.map +0 -1
  194. package/types/src/Core/index.d.ts +0 -19
  195. package/types/src/Core/index.d.ts.map +0 -1
  196. package/types/src/Types/Brand.d.ts.map +0 -1
  197. package/types/src/Types/NonEmptyList.d.ts.map +0 -1
  198. package/types/src/Types/index.d.ts +0 -3
  199. package/types/src/Types/index.d.ts.map +0 -1
  200. package/types/src/Utils/Arr.d.ts +0 -403
  201. package/types/src/Utils/Arr.d.ts.map +0 -1
  202. package/types/src/Utils/Dict.d.ts +0 -310
  203. package/types/src/Utils/Dict.d.ts.map +0 -1
  204. package/types/src/Utils/Num.d.ts +0 -110
  205. package/types/src/Utils/Num.d.ts.map +0 -1
  206. package/types/src/Utils/Rec.d.ts +0 -159
  207. package/types/src/Utils/Rec.d.ts.map +0 -1
  208. package/types/src/Utils/Str.d.ts +0 -128
  209. package/types/src/Utils/Str.d.ts.map +0 -1
  210. package/types/src/Utils/Uniq.d.ts +0 -179
  211. package/types/src/Utils/Uniq.d.ts.map +0 -1
  212. package/types/src/Utils/index.d.ts +0 -7
  213. package/types/src/Utils/index.d.ts.map +0 -1
@@ -1,111 +0,0 @@
1
- export var Logged;
2
- (function (Logged) {
3
- /**
4
- * Wraps a pure value into a `Logged` with an empty log.
5
- *
6
- * @example
7
- * ```ts
8
- * Logged.make<string, number>(42); // { value: 42, log: [] }
9
- * ```
10
- */
11
- Logged.make = (value) => ({ value, log: [] });
12
- /**
13
- * Creates a `Logged` that records a single log entry and produces no
14
- * meaningful value. Use this to append to the log inside a `chain`.
15
- *
16
- * @example
17
- * ```ts
18
- * Logged.tell("operation completed"); // { value: undefined, log: ["operation completed"] }
19
- * ```
20
- */
21
- Logged.tell = (entry) => ({ value: undefined, log: [entry] });
22
- /**
23
- * Transforms the value inside a `Logged` without affecting the log.
24
- *
25
- * @example
26
- * ```ts
27
- * pipe(
28
- * Logged.make<string, number>(5),
29
- * Logged.map(n => n * 2),
30
- * ); // { value: 10, log: [] }
31
- * ```
32
- */
33
- Logged.map = (f) => (data) => ({
34
- value: f(data.value),
35
- log: data.log,
36
- });
37
- /**
38
- * Sequences two `Logged` computations, concatenating their logs.
39
- * The value from the first is passed to `f`; the resulting log entries are
40
- * appended after the entries from the first.
41
- *
42
- * Data-last — the first computation is the data being piped.
43
- *
44
- * @example
45
- * ```ts
46
- * const result = pipe(
47
- * Logged.make<string, number>(1),
48
- * Logged.chain(n => pipe(Logged.tell("step"), Logged.map(() => n + 1))),
49
- * Logged.chain(n => pipe(Logged.tell("done"), Logged.map(() => n * 10))),
50
- * );
51
- *
52
- * Logged.run(result); // [20, ["step", "done"]]
53
- * ```
54
- */
55
- Logged.chain = (f) => (data) => {
56
- const next = f(data.value);
57
- return { value: next.value, log: [...data.log, ...next.log] };
58
- };
59
- /**
60
- * Applies a function wrapped in a `Logged` to a value wrapped in a `Logged`,
61
- * concatenating both logs.
62
- *
63
- * @example
64
- * ```ts
65
- * const fn: Logged<string, (n: number) => number> = {
66
- * value: n => n * 2,
67
- * log: ["fn-loaded"],
68
- * };
69
- * const arg: Logged<string, number> = { value: 5, log: ["arg-loaded"] };
70
- *
71
- * const result = pipe(fn, Logged.ap(arg));
72
- * Logged.run(result); // [10, ["fn-loaded", "arg-loaded"]]
73
- * ```
74
- */
75
- Logged.ap = (arg) => (data) => ({
76
- value: data.value(arg.value),
77
- log: [...data.log, ...arg.log],
78
- });
79
- /**
80
- * Runs a side effect on the value without changing the `Logged`.
81
- * Useful for debugging or inspecting intermediate values.
82
- *
83
- * @example
84
- * ```ts
85
- * pipe(
86
- * Logged.make<string, number>(42),
87
- * Logged.tap(n => console.log("value:", n)),
88
- * );
89
- * ```
90
- */
91
- Logged.tap = (f) => (data) => {
92
- f(data.value);
93
- return data;
94
- };
95
- /**
96
- * Extracts the value and log as a `readonly [A, ReadonlyArray<W>]` tuple.
97
- * Use this at the boundary where you need to consume both.
98
- *
99
- * @example
100
- * ```ts
101
- * const result = pipe(
102
- * Logged.make<string, number>(1),
103
- * Logged.chain(n => pipe(Logged.tell("incremented"), Logged.map(() => n + 1))),
104
- * );
105
- *
106
- * const [value, log] = Logged.run(result);
107
- * // value = 2, log = ["incremented"]
108
- * ```
109
- */
110
- Logged.run = (data) => [data.value, data.log];
111
- })(Logged || (Logged = {}));
@@ -1,191 +0,0 @@
1
- import { Result } from "./Result.js";
2
- const _none = { kind: "None" };
3
- export var Option;
4
- (function (Option) {
5
- /**
6
- * Creates a Some containing the given value.
7
- */
8
- Option.some = (value) => ({ kind: "Some", value });
9
- /**
10
- * Type guard that checks if a Option is Some.
11
- */
12
- Option.isSome = (data) => data.kind === "Some";
13
- /**
14
- * Creates a None (empty Option).
15
- */
16
- Option.none = () => _none;
17
- /**
18
- * Type guard that checks if a Option is None.
19
- */
20
- Option.isNone = (data) => data.kind === "None";
21
- /**
22
- * Creates a Option from a nullable value.
23
- * Returns None if the value is null or undefined, Some otherwise.
24
- *
25
- * @example
26
- * ```ts
27
- * Option.fromNullable(null); // None
28
- * Option.fromNullable(42); // Some(42)
29
- * ```
30
- */
31
- Option.fromNullable = (value) => value === null || value === undefined ? Option.none() : Option.some(value);
32
- /**
33
- * Extracts the value from a Option, returning null if None.
34
- */
35
- Option.toNullable = (data) => Option.isSome(data) ? data.value : null;
36
- /**
37
- * Extracts the value from a Option, returning undefined if None.
38
- */
39
- Option.toUndefined = (data) => Option.isSome(data) ? data.value : undefined;
40
- /**
41
- * Creates a Option from a possibly undefined value.
42
- * Returns None if undefined, Some otherwise.
43
- */
44
- Option.fromUndefined = (value) => value === undefined ? Option.none() : Option.some(value);
45
- /**
46
- * Converts an Option to a Result.
47
- * Some becomes Ok, None becomes Err with the provided error.
48
- *
49
- * @example
50
- * ```ts
51
- * pipe(
52
- * Option.some(42),
53
- * Option.toResult(() => "Value was missing")
54
- * ); // Ok(42)
55
- *
56
- * pipe(
57
- * Option.none(),
58
- * Option.toResult(() => "Value was missing")
59
- * ); // Err("Value was missing")
60
- * ```
61
- */
62
- Option.toResult = (onNone) => (data) => Option.isSome(data) ? Result.ok(data.value) : Result.err(onNone());
63
- /**
64
- * Creates an Option from a Result.
65
- * Ok becomes Some, Err becomes None (the error is discarded).
66
- *
67
- * @example
68
- * ```ts
69
- * Option.fromResult(Result.ok(42)); // Some(42)
70
- * Option.fromResult(Result.err("oops")); // None
71
- * ```
72
- */
73
- Option.fromResult = (data) => Result.isOk(data) ? Option.some(data.value) : Option.none();
74
- /**
75
- * Transforms the value inside a Option if it exists.
76
- *
77
- * @example
78
- * ```ts
79
- * pipe(Option.some(5), Option.map(n => n * 2)); // Some(10)
80
- * pipe(Option.none(), Option.map(n => n * 2)); // None
81
- * ```
82
- */
83
- Option.map = (f) => (data) => Option.isSome(data) ? Option.some(f(data.value)) : data;
84
- /**
85
- * Chains Option computations. If the first is Some, passes the value to f.
86
- * If the first is None, propagates None.
87
- *
88
- * @example
89
- * ```ts
90
- * const parseNumber = (s: string): Option<number> => {
91
- * const n = parseInt(s, 10);
92
- * return isNaN(n) ? Option.none() : Option.some(n);
93
- * };
94
- *
95
- * pipe(Option.some("42"), Option.chain(parseNumber)); // Some(42)
96
- * pipe(Option.some("abc"), Option.chain(parseNumber)); // None
97
- * ```
98
- */
99
- Option.chain = (f) => (data) => Option.isSome(data) ? f(data.value) : data;
100
- /**
101
- * Extracts the value from a Option by providing handlers for both cases.
102
- *
103
- * @example
104
- * ```ts
105
- * pipe(
106
- * Option.some(5),
107
- * Option.fold(
108
- * () => "No value",
109
- * n => `Value: ${n}`
110
- * )
111
- * ); // "Value: 5"
112
- * ```
113
- */
114
- Option.fold = (onNone, onSome) => (data) => Option.isSome(data) ? onSome(data.value) : onNone();
115
- /**
116
- * Pattern matches on a Option, returning the result of the matching case.
117
- *
118
- * @example
119
- * ```ts
120
- * pipe(
121
- * optionUser,
122
- * Option.match({
123
- * some: user => `Hello, ${user.name}`,
124
- * none: () => "Hello, stranger"
125
- * })
126
- * );
127
- * ```
128
- */
129
- Option.match = (cases) => (data) => Option.isSome(data) ? cases.some(data.value) : cases.none();
130
- /**
131
- * Returns the value inside an Option, or a default value if None.
132
- * The default is a thunk `() => B` — evaluated only when the Option is None.
133
- * The default can be a different type, widening the result to `A | B`.
134
- *
135
- * @example
136
- * ```ts
137
- * pipe(Option.some(5), Option.getOrElse(() => 0)); // 5
138
- * pipe(Option.none(), Option.getOrElse(() => 0)); // 0
139
- * pipe(Option.none<string>(), Option.getOrElse(() => null)); // null — typed as string | null
140
- * ```
141
- */
142
- Option.getOrElse = (defaultValue) => (data) => Option.isSome(data) ? data.value : defaultValue();
143
- /**
144
- * Executes a side effect on the value without changing the Option.
145
- * Useful for logging or debugging.
146
- *
147
- * @example
148
- * ```ts
149
- * pipe(
150
- * Option.some(5),
151
- * Option.tap(n => console.log("Value:", n)),
152
- * Option.map(n => n * 2)
153
- * );
154
- * ```
155
- */
156
- Option.tap = (f) => (data) => {
157
- if (Option.isSome(data))
158
- f(data.value);
159
- return data;
160
- };
161
- /**
162
- * Filters a Option based on a predicate.
163
- * Returns None if the predicate returns false or if the Option is already None.
164
- *
165
- * @example
166
- * ```ts
167
- * pipe(Option.some(5), Option.filter(n => n > 3)); // Some(5)
168
- * pipe(Option.some(2), Option.filter(n => n > 3)); // None
169
- * ```
170
- */
171
- Option.filter = (predicate) => (data) => Option.isSome(data) ? (predicate(data.value) ? data : Option.none()) : data;
172
- /**
173
- * Recovers from a None by providing a fallback Option.
174
- * The fallback can produce a different type, widening the result to `Option<A | B>`.
175
- */
176
- Option.recover = (fallback) => (data) => Option.isSome(data) ? data : fallback();
177
- /**
178
- * Applies a function wrapped in a Option to a value wrapped in a Option.
179
- *
180
- * @example
181
- * ```ts
182
- * const add = (a: number) => (b: number) => a + b;
183
- * pipe(
184
- * Option.some(add),
185
- * Option.ap(Option.some(5)),
186
- * Option.ap(Option.some(3))
187
- * ); // Some(8)
188
- * ```
189
- */
190
- Option.ap = (arg) => (data) => Option.isSome(data) && Option.isSome(arg) ? Option.some(data.value(arg.value)) : Option.none();
191
- })(Option || (Option = {}));
@@ -1,160 +0,0 @@
1
- import { Option } from "./Option.js";
2
- export var Optional;
3
- (function (Optional) {
4
- /**
5
- * Constructs an Optional from a getter (returning Option<A>) and a setter.
6
- *
7
- * @example
8
- * ```ts
9
- * const firstChar = Optional.make(
10
- * (s: string) => s.length > 0 ? Option.some(s[0]) : Option.none(),
11
- * (c) => (s) => s.length > 0 ? c + s.slice(1) : s,
12
- * );
13
- * ```
14
- */
15
- Optional.make = (get, set) => ({ get, set });
16
- /**
17
- * Creates an Optional that focuses on an optional property of an object.
18
- * Only keys whose type includes undefined (i.e. `field?: T`) are accepted.
19
- * Call with the structure type first, then the key.
20
- *
21
- * @example
22
- * ```ts
23
- * type Profile = { username: string; bio?: string };
24
- * const bioOpt = Optional.prop<Profile>()("bio");
25
- * ```
26
- */
27
- Optional.prop = () => (key) => Optional.make((s) => {
28
- const val = s[key];
29
- return val != null ? Option.some(val) : Option.none();
30
- }, (a) => (s) => ({ ...s, [key]: a }));
31
- /**
32
- * Creates an Optional that focuses on an element at a given index in an array.
33
- * Returns None when the index is out of bounds; set is a no-op when out of bounds.
34
- *
35
- * @example
36
- * ```ts
37
- * const firstItem = Optional.index<string>(0);
38
- *
39
- * pipe(["a", "b"], Optional.get(firstItem)); // Some("a")
40
- * pipe([], Optional.get(firstItem)); // None
41
- * ```
42
- */
43
- Optional.index = (i) => Optional.make((arr) => i >= 0 && i < arr.length ? Option.some(arr[i]) : Option.none(), (a) => (arr) => {
44
- if (i < 0 || i >= arr.length)
45
- return arr;
46
- const copy = [...arr];
47
- copy[i] = a;
48
- return copy;
49
- });
50
- /**
51
- * Reads the focused value from a structure, returning Option<A>.
52
- *
53
- * @example
54
- * ```ts
55
- * pipe(profile, Optional.get(bioOpt)); // Some("...") or None
56
- * ```
57
- */
58
- Optional.get = (opt) => (s) => opt.get(s);
59
- /**
60
- * Replaces the focused value within a structure.
61
- * For indexed focuses, this is a no-op when the index is out of bounds.
62
- *
63
- * @example
64
- * ```ts
65
- * pipe(profile, Optional.set(bioOpt)("hello"));
66
- * ```
67
- */
68
- Optional.set = (opt) => (a) => (s) => opt.set(a)(s);
69
- /**
70
- * Applies a function to the focused value if it is present; returns the
71
- * structure unchanged if the focus is absent.
72
- *
73
- * @example
74
- * ```ts
75
- * pipe(profile, Optional.modify(bioOpt)(s => s.toUpperCase()));
76
- * ```
77
- */
78
- Optional.modify = (opt) => (f) => (s) => {
79
- const val = opt.get(s);
80
- return val.kind === "None" ? s : opt.set(f(val.value))(s);
81
- };
82
- /**
83
- * Returns the focused value or a default when the focus is absent.
84
- *
85
- * @example
86
- * ```ts
87
- * pipe(profile, Optional.getOrElse(bioOpt)(() => "no bio"));
88
- * ```
89
- */
90
- Optional.getOrElse = (opt) => (defaultValue) => (s) => {
91
- const val = opt.get(s);
92
- return val.kind === "Some" ? val.value : defaultValue();
93
- };
94
- /**
95
- * Extracts a value from an Optional focus using handlers for the present
96
- * and absent cases.
97
- *
98
- * @example
99
- * ```ts
100
- * pipe(profile, Optional.fold(bioOpt)(() => "no bio", (bio) => bio.toUpperCase()));
101
- * ```
102
- */
103
- Optional.fold = (opt) => (onNone, onSome) => (s) => {
104
- const val = opt.get(s);
105
- return val.kind === "Some" ? onSome(val.value) : onNone();
106
- };
107
- /**
108
- * Pattern matches on an Optional focus using a named-case object.
109
- *
110
- * @example
111
- * ```ts
112
- * pipe(
113
- * profile,
114
- * Optional.match(bioOpt)({ none: () => "no bio", some: (bio) => bio }),
115
- * );
116
- * ```
117
- */
118
- Optional.match = (opt) => (cases) => (s) => {
119
- const val = opt.get(s);
120
- return val.kind === "Some" ? cases.some(val.value) : cases.none();
121
- };
122
- /**
123
- * Composes two Optionals: focuses through the outer, then through the inner.
124
- * Returns None if either focus is absent.
125
- *
126
- * @example
127
- * ```ts
128
- * const deepOpt = pipe(
129
- * Optional.prop<User>()("address"),
130
- * Optional.andThen(Optional.prop<Address>()("landmark")),
131
- * );
132
- * ```
133
- */
134
- Optional.andThen = (inner) => (outer) => Optional.make((s) => {
135
- const mid = outer.get(s);
136
- return mid.kind === "None" ? Option.none() : inner.get(mid.value);
137
- }, (b) => (s) => {
138
- const mid = outer.get(s);
139
- return mid.kind === "None" ? s : outer.set(inner.set(b)(mid.value))(s);
140
- });
141
- /**
142
- * Composes an Optional with a Lens, producing an Optional.
143
- * The Lens focuses within the value found by the Optional.
144
- *
145
- * @example
146
- * ```ts
147
- * const cityOpt = pipe(
148
- * Optional.prop<User>()("address"),
149
- * Optional.andThenLens(Lens.prop<Address>()("city")),
150
- * );
151
- * ```
152
- */
153
- Optional.andThenLens = (inner) => (outer) => Optional.make((s) => {
154
- const mid = outer.get(s);
155
- return mid.kind === "None" ? Option.none() : Option.some(inner.get(mid.value));
156
- }, (b) => (s) => {
157
- const mid = outer.get(s);
158
- return mid.kind === "None" ? s : outer.set(inner.set(b)(mid.value))(s);
159
- });
160
- })(Optional || (Optional = {}));
@@ -1,133 +0,0 @@
1
- export var Predicate;
2
- (function (Predicate) {
3
- /**
4
- * Negates a predicate: the result passes exactly when the original fails.
5
- *
6
- * @example
7
- * ```ts
8
- * const isBlank: Predicate<string> = s => s.trim().length === 0;
9
- * const isNotBlank = Predicate.not(isBlank);
10
- *
11
- * isNotBlank("hello"); // true
12
- * isNotBlank(" "); // false
13
- * ```
14
- */
15
- Predicate.not = (p) => (a) => !p(a);
16
- /**
17
- * Combines two predicates with logical AND: passes only when both hold.
18
- *
19
- * Data-last — the first predicate is the data being piped.
20
- *
21
- * @example
22
- * ```ts
23
- * const isPositive: Predicate<number> = n => n > 0;
24
- * const isEven: Predicate<number> = n => n % 2 === 0;
25
- *
26
- * const isPositiveEven: Predicate<number> = pipe(isPositive, Predicate.and(isEven));
27
- *
28
- * isPositiveEven(4); // true
29
- * isPositiveEven(3); // false — positive but odd
30
- * isPositiveEven(-2); // false — even but not positive
31
- * ```
32
- */
33
- Predicate.and = (second) => (first) => (a) => first(a) && second(a);
34
- /**
35
- * Combines two predicates with logical OR: passes when either holds.
36
- *
37
- * Data-last — the first predicate is the data being piped.
38
- *
39
- * @example
40
- * ```ts
41
- * const isChild: Predicate<number> = n => n < 13;
42
- * const isSenior: Predicate<number> = n => n >= 65;
43
- *
44
- * const getsDiscount: Predicate<number> = pipe(isChild, Predicate.or(isSenior));
45
- *
46
- * getsDiscount(8); // true
47
- * getsDiscount(70); // true
48
- * getsDiscount(30); // false
49
- * ```
50
- */
51
- Predicate.or = (second) => (first) => (a) => first(a) || second(a);
52
- /**
53
- * Adapts a `Predicate<A>` to work on a different input type `B` by applying `f`
54
- * to extract the relevant `A` from a `B` before running the check.
55
- *
56
- * Data-last — the predicate is the data being piped; `f` is the extractor.
57
- *
58
- * @example
59
- * ```ts
60
- * type User = { name: string; age: number };
61
- *
62
- * const isAdult: Predicate<number> = n => n >= 18;
63
- *
64
- * // Lift isAdult to work on Users by extracting the age field
65
- * const isAdultUser: Predicate<User> = pipe(
66
- * isAdult,
67
- * Predicate.using((u: User) => u.age)
68
- * );
69
- *
70
- * isAdultUser({ name: "Alice", age: 30 }); // true
71
- * isAdultUser({ name: "Bob", age: 15 }); // false
72
- * ```
73
- */
74
- Predicate.using = (f) => (p) => (b) => p(f(b));
75
- /**
76
- * Combines an array of predicates with AND: passes only when every predicate holds.
77
- * Returns `true` for an empty array (vacuous truth).
78
- *
79
- * @example
80
- * ```ts
81
- * const checks: Predicate<string>[] = [
82
- * s => s.length > 0,
83
- * s => s.length <= 100,
84
- * s => !s.includes("<"),
85
- * ];
86
- *
87
- * Predicate.all(checks)("hello"); // true
88
- * Predicate.all(checks)(""); // false — too short
89
- * Predicate.all(checks)("<b>"); // false — contains "<"
90
- * Predicate.all([])("anything"); // true
91
- * ```
92
- */
93
- Predicate.all = (predicates) => (a) => predicates.every((p) => p(a));
94
- /**
95
- * Combines an array of predicates with OR: passes when at least one holds.
96
- * Returns `false` for an empty array.
97
- *
98
- * @example
99
- * ```ts
100
- * const acceptedFormats: Predicate<string>[] = [
101
- * s => s.endsWith(".jpg"),
102
- * s => s.endsWith(".png"),
103
- * s => s.endsWith(".webp"),
104
- * ];
105
- *
106
- * Predicate.any(acceptedFormats)("photo.jpg"); // true
107
- * Predicate.any(acceptedFormats)("photo.gif"); // false
108
- * Predicate.any([])("anything"); // false
109
- * ```
110
- */
111
- Predicate.any = (predicates) => (a) => predicates.some((p) => p(a));
112
- /**
113
- * Converts a `Refinement<A, B>` into a `Predicate<A>`, discarding the compile-time
114
- * narrowing. Use this when you want to combine a type guard with plain predicates
115
- * using `and`, `or`, or `all`.
116
- *
117
- * @example
118
- * ```ts
119
- * const isString: Refinement<unknown, string> =
120
- * Refinement.make(x => typeof x === "string");
121
- *
122
- * const isShortString: Predicate<unknown> = pipe(
123
- * Predicate.fromRefinement(isString),
124
- * Predicate.and(x => (x as string).length < 10)
125
- * );
126
- *
127
- * isShortString("hi"); // true
128
- * isShortString("a very long string that exceeds ten characters"); // false
129
- * isShortString(42); // false
130
- * ```
131
- */
132
- Predicate.fromRefinement = (r) => r;
133
- })(Predicate || (Predicate = {}));