|
| 1 | +// @title: Error Handling Patterns |
| 2 | +// @description: Use Either patterns for safe data operations with proper error handling. |
| 3 | +import assert from "node:assert/strict" |
| 4 | +import { Either, pipe } from "effect" |
| 5 | +import { Data } from "@evolution-sdk/evolution" |
| 6 | + |
| 7 | +// #region main |
| 8 | +// Use built-in Either-based functions for safe operations |
| 9 | +const safeData = new Data.Constr({ index: 0n, fields: ["74657374", 42n] }) // 'test' as hex |
| 10 | + |
| 11 | +// Safe encoding using Data.Either namespace |
| 12 | +const encodingResult = Data.Either.toCBORHex(safeData) |
| 13 | +assert.equal(Either.isRight(encodingResult), true) |
| 14 | + |
| 15 | +// Extract values using Either.match for type safety |
| 16 | +const encodedHex = Either.match(encodingResult, { |
| 17 | + onLeft: (error: Data.DataError) => { |
| 18 | + throw new Error(`Encoding failed: ${error.message}`) |
| 19 | + }, |
| 20 | + onRight: (hex: string) => { |
| 21 | + console.log("Encoded successfully:", hex) |
| 22 | + return hex |
| 23 | + } |
| 24 | +}) |
| 25 | + |
| 26 | +// Safe decoding using the encoded hex |
| 27 | +const decodingResult = Data.Either.fromCBORHex(encodedHex) |
| 28 | +assert.equal(Either.isRight(decodingResult), true) |
| 29 | + |
| 30 | +Either.match(decodingResult, { |
| 31 | + onLeft: (error: Data.DataError) => { |
| 32 | + throw new Error(`Decoding failed: ${error.message}`) |
| 33 | + }, |
| 34 | + onRight: (decoded: Data.Data) => { |
| 35 | + console.log("Decoded successfully") |
| 36 | + assert.deepStrictEqual(decoded, safeData) |
| 37 | + } |
| 38 | +}) |
| 39 | + |
| 40 | +// Test error handling with invalid input |
| 41 | +const invalidResult = Data.Either.fromCBORHex("invalid-hex-data") |
| 42 | +assert.equal(Either.isLeft(invalidResult), true) |
| 43 | + |
| 44 | +Either.match(invalidResult, { |
| 45 | + onLeft: (error: Data.DataError) => { |
| 46 | + console.log("Expected error:", error.message) |
| 47 | + }, |
| 48 | + onRight: () => { |
| 49 | + throw new Error("Should not succeed with invalid input") |
| 50 | + } |
| 51 | +}) |
| 52 | + |
| 53 | +// Compose operations using pipe and Either |
| 54 | +const processDataSafely = (data: Data.Data) => |
| 55 | + pipe( |
| 56 | + Data.Either.toCBORHex(data), |
| 57 | + Either.flatMap((hex: string) => Data.Either.fromCBORHex(hex)), |
| 58 | + Either.map((result: Data.Data) => `Roundtrip successful`) |
| 59 | + ) |
| 60 | + |
| 61 | +const pipeResult = processDataSafely(safeData) |
| 62 | +assert.equal(Either.isRight(pipeResult), true) |
| 63 | + |
| 64 | +// Pattern matching for comprehensive error handling |
| 65 | +const finalMessage = Either.match(pipeResult, { |
| 66 | + onLeft: (error: Data.DataError) => `Operation failed: ${error.message}`, |
| 67 | + onRight: (value: string) => `Operation succeeded: ${value}` |
| 68 | +}) |
| 69 | + |
| 70 | +console.log("Final result:", finalMessage) |
| 71 | +// #endregion main |
0 commit comments