errore 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -125,6 +125,71 @@ const posts = andThen(user, u => fetchPosts(u.id))
|
|
|
125
125
|
const logged = tap(user, u => console.log('Got user:', u.name))
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
+
### Composing Operations
|
|
129
|
+
|
|
130
|
+
Chain multiple operations together:
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
import { map, andThen, mapError, isError } from 'errore'
|
|
134
|
+
|
|
135
|
+
// Define operations that can fail
|
|
136
|
+
function parseNumber(s: string): ValidationError | number { ... }
|
|
137
|
+
function validatePositive(n: number): ValidationError | number { ... }
|
|
138
|
+
function divide(a: number, b: number): DivisionError | number { ... }
|
|
139
|
+
|
|
140
|
+
// Compose with nested calls
|
|
141
|
+
const result = andThen(
|
|
142
|
+
andThen(parseNumber(input), validatePositive),
|
|
143
|
+
n => divide(100, n)
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
// Or step by step (often clearer)
|
|
147
|
+
function calculate(input: string): ValidationError | DivisionError | number {
|
|
148
|
+
const parsed = parseNumber(input)
|
|
149
|
+
if (isError(parsed)) return parsed
|
|
150
|
+
|
|
151
|
+
const validated = validatePositive(parsed)
|
|
152
|
+
if (isError(validated)) return validated
|
|
153
|
+
|
|
154
|
+
return divide(100, validated)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Transform errors at the end
|
|
158
|
+
const appResult = mapError(
|
|
159
|
+
calculate(userInput),
|
|
160
|
+
e => new AppError({ source: e._tag, message: e.message })
|
|
161
|
+
)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Real-world async composition:
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
async function processOrder(orderId: string): Promise<OrderError | Receipt> {
|
|
168
|
+
const order = await fetchOrder(orderId)
|
|
169
|
+
if (isError(order)) return order
|
|
170
|
+
|
|
171
|
+
const validated = validateOrder(order)
|
|
172
|
+
if (isError(validated)) return validated
|
|
173
|
+
|
|
174
|
+
const payment = await processPayment(validated)
|
|
175
|
+
if (isError(payment)) return payment
|
|
176
|
+
|
|
177
|
+
return generateReceipt(payment)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Caller gets union of all possible errors
|
|
181
|
+
const receipt = await processOrder('123')
|
|
182
|
+
if (isError(receipt)) {
|
|
183
|
+
const message = matchError(receipt, {
|
|
184
|
+
NotFoundError: e => `Order ${e.id} not found`,
|
|
185
|
+
ValidationError: e => `Invalid: ${e.field}`,
|
|
186
|
+
PaymentError: e => `Payment failed: ${e.reason}`,
|
|
187
|
+
})
|
|
188
|
+
console.log(message)
|
|
189
|
+
return
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
128
193
|
### Extraction
|
|
129
194
|
|
|
130
195
|
```ts
|
|
@@ -166,15 +231,17 @@ class NetworkError extends TaggedError('NetworkError')<{
|
|
|
166
231
|
type AppError = ValidationError | NetworkError
|
|
167
232
|
|
|
168
233
|
// Exhaustive matching (TypeScript ensures all cases handled)
|
|
169
|
-
matchError(error, {
|
|
234
|
+
const message = matchError(error, {
|
|
170
235
|
ValidationError: e => `Invalid ${e.field}`,
|
|
171
236
|
NetworkError: e => `Failed to fetch ${e.url}`
|
|
172
237
|
})
|
|
238
|
+
console.log(message)
|
|
173
239
|
|
|
174
240
|
// Partial matching with fallback
|
|
175
|
-
matchErrorPartial(error, {
|
|
241
|
+
const fallbackMsg = matchErrorPartial(error, {
|
|
176
242
|
ValidationError: e => `Invalid ${e.field}`
|
|
177
243
|
}, e => `Unknown error: ${e.message}`)
|
|
244
|
+
console.log(fallbackMsg)
|
|
178
245
|
|
|
179
246
|
// Type guards
|
|
180
247
|
ValidationError.is(value) // specific class
|