@nicolastoulemont/std 0.4.0 → 0.5.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 (122) hide show
  1. package/dist/adt/index.d.mts +1 -1
  2. package/dist/adt/index.mjs +1 -3
  3. package/dist/adt-DZmVJG4P.mjs +2 -0
  4. package/dist/adt-DZmVJG4P.mjs.map +1 -0
  5. package/dist/{apply-fn.types-0g_9eXRy.d.mts → apply-fn.types-CMgY6WQe.d.mts} +1 -1
  6. package/dist/{apply-fn.types-0g_9eXRy.d.mts.map → apply-fn.types-CMgY6WQe.d.mts.map} +1 -1
  7. package/dist/brand/index.d.mts +1 -1
  8. package/dist/brand/index.mjs +1 -3
  9. package/dist/brand-BUqMmkzC.mjs +2 -0
  10. package/dist/{brand-BqcqFXj5.mjs.map → brand-BUqMmkzC.mjs.map} +1 -1
  11. package/dist/data/index.d.mts +1 -1
  12. package/dist/data/index.mjs +1 -3
  13. package/dist/data-DzqKBCQg.mjs +2 -0
  14. package/dist/data-DzqKBCQg.mjs.map +1 -0
  15. package/dist/{discriminator.types-D-UbMmAD.d.mts → discriminator.types-DkThfvNE.d.mts} +1 -1
  16. package/dist/discriminator.types-DkThfvNE.d.mts.map +1 -0
  17. package/dist/either/index.d.mts +2 -2
  18. package/dist/either/index.mjs +1 -3
  19. package/dist/either-BDY9T5oz.mjs +2 -0
  20. package/dist/either-BDY9T5oz.mjs.map +1 -0
  21. package/dist/equality-D2EJvZm4.mjs +2 -0
  22. package/dist/{equality-C2l3BIi8.mjs.map → equality-D2EJvZm4.mjs.map} +1 -1
  23. package/dist/err/index.d.mts +1 -1
  24. package/dist/err/index.mjs +1 -3
  25. package/dist/err-CYs4b1RV.mjs +2 -0
  26. package/dist/{err-BM-svBaK.mjs.map → err-CYs4b1RV.mjs.map} +1 -1
  27. package/dist/flow/index.d.mts +1 -1
  28. package/dist/flow/index.mjs +1 -3
  29. package/dist/flow-CxKQ5yac.mjs +2 -0
  30. package/dist/{flow-D4cE0EAg.mjs.map → flow-CxKQ5yac.mjs.map} +1 -1
  31. package/dist/fx/index.d.mts +3 -3
  32. package/dist/fx/index.mjs +1 -4
  33. package/dist/fx-C4UuWCqP.mjs +2 -0
  34. package/dist/fx-C4UuWCqP.mjs.map +1 -0
  35. package/dist/fx.types-CXTwEa1G.mjs +2 -0
  36. package/dist/{fx.types-DpIQILok.mjs.map → fx.types-CXTwEa1G.mjs.map} +1 -1
  37. package/dist/{fx.types-aTmhyidu.d.mts → fx.types-DO-8yG4c.d.mts} +1 -1
  38. package/dist/{fx.types-aTmhyidu.d.mts.map → fx.types-DO-8yG4c.d.mts.map} +1 -1
  39. package/dist/{index-USQPafrR.d.mts → index-78LWwTds.d.mts} +1 -1
  40. package/dist/{index-USQPafrR.d.mts.map → index-78LWwTds.d.mts.map} +1 -1
  41. package/dist/{index-BO6bxBeo.d.mts → index-BQ5wVDSP.d.mts} +8 -24
  42. package/dist/index-BQ5wVDSP.d.mts.map +1 -0
  43. package/dist/{index-BOrJQBPO.d.mts → index-BahMvQpA.d.mts} +2 -2
  44. package/dist/{index-BOrJQBPO.d.mts.map → index-BahMvQpA.d.mts.map} +1 -1
  45. package/dist/{index-ClxPiGP9.d.mts → index-Bs5TTFlK.d.mts} +40 -44
  46. package/dist/index-Bs5TTFlK.d.mts.map +1 -0
  47. package/dist/{index-D5tzehjf.d.mts → index-BuLJRX1e.d.mts} +11 -11
  48. package/dist/{index-D5tzehjf.d.mts.map → index-BuLJRX1e.d.mts.map} +1 -1
  49. package/dist/{index-CQxzD1YM.d.mts → index-CDio8mJY.d.mts} +4 -4
  50. package/dist/{index-CQxzD1YM.d.mts.map → index-CDio8mJY.d.mts.map} +1 -1
  51. package/dist/{index-FySViSfh.d.mts → index-DLlx9jiG.d.mts} +5 -105
  52. package/dist/index-DLlx9jiG.d.mts.map +1 -0
  53. package/dist/{index-CLspOlBH.d.mts → index-DQoTXLSm.d.mts} +192 -83
  54. package/dist/index-DQoTXLSm.d.mts.map +1 -0
  55. package/dist/{index-Cydt5ocm.d.mts → index-DjjJIDaA.d.mts} +2 -2
  56. package/dist/{index-Cydt5ocm.d.mts.map → index-DjjJIDaA.d.mts.map} +1 -1
  57. package/dist/{index-EmWRCTY3.d.mts → index-DtAPrec7.d.mts} +2 -2
  58. package/dist/{index-EmWRCTY3.d.mts.map → index-DtAPrec7.d.mts.map} +1 -1
  59. package/dist/{index-CLlcoy8B.d.mts → index-IdejL485.d.mts} +2 -2
  60. package/dist/{index-CLlcoy8B.d.mts.map → index-IdejL485.d.mts.map} +1 -1
  61. package/dist/index.d.mts +16 -40
  62. package/dist/index.mjs +1 -15
  63. package/dist/option/index.d.mts +3 -3
  64. package/dist/option/index.mjs +1 -4
  65. package/dist/option-Qiv7Ls7L.mjs +2 -0
  66. package/dist/option-Qiv7Ls7L.mjs.map +1 -0
  67. package/dist/option.types-By5UOfC2.mjs +2 -0
  68. package/dist/option.types-By5UOfC2.mjs.map +1 -0
  69. package/dist/{option.types-CVvowfmd.d.mts → option.types-Cluybn30.d.mts} +22 -20
  70. package/dist/option.types-Cluybn30.d.mts.map +1 -0
  71. package/dist/pipe/index.d.mts +1 -1
  72. package/dist/pipe/index.mjs +1 -3
  73. package/dist/pipe-BROILDeC.mjs +2 -0
  74. package/dist/{pipe-BF4G4SLo.mjs.map → pipe-BROILDeC.mjs.map} +1 -1
  75. package/dist/{pipeable-Dr0d_q4F.d.mts → pipeable-KHu4D8ol.d.mts} +1 -1
  76. package/dist/{pipeable-Dr0d_q4F.d.mts.map → pipeable-KHu4D8ol.d.mts.map} +1 -1
  77. package/dist/pipeable-rQvolRqh.mjs +2 -0
  78. package/dist/{pipeable-DYNrUps7.mjs.map → pipeable-rQvolRqh.mjs.map} +1 -1
  79. package/dist/predicate/index.d.mts +1 -1
  80. package/dist/predicate/index.mjs +1 -3
  81. package/dist/predicate-DvXnfmeJ.mjs +2 -0
  82. package/dist/{predicate-Dt9Qsbav.mjs.map → predicate-DvXnfmeJ.mjs.map} +1 -1
  83. package/dist/result/index.d.mts +2 -2
  84. package/dist/result/index.mjs +1 -3
  85. package/dist/result-B68pxC7l.mjs +2 -0
  86. package/dist/result-B68pxC7l.mjs.map +1 -0
  87. package/dist/result-uRORQlAQ.mjs +1 -0
  88. package/dist/{result.types-_W95221K.d.mts → result.types-fIbuBwVQ.d.mts} +129 -20
  89. package/dist/result.types-fIbuBwVQ.d.mts.map +1 -0
  90. package/package.json +1 -1
  91. package/dist/adt-DH37Pprw.mjs +0 -318
  92. package/dist/adt-DH37Pprw.mjs.map +0 -1
  93. package/dist/brand-BqcqFXj5.mjs +0 -165
  94. package/dist/chunk-DRYujVrt.mjs +0 -18
  95. package/dist/data-Cg8ySt6-.mjs +0 -244
  96. package/dist/data-Cg8ySt6-.mjs.map +0 -1
  97. package/dist/discriminator.types-D-UbMmAD.d.mts.map +0 -1
  98. package/dist/either-jkBX8xS1.mjs +0 -735
  99. package/dist/either-jkBX8xS1.mjs.map +0 -1
  100. package/dist/equality-C2l3BIi8.mjs +0 -201
  101. package/dist/err-BM-svBaK.mjs +0 -176
  102. package/dist/flow-D4cE0EAg.mjs +0 -28
  103. package/dist/fx-B-0MxGTM.mjs +0 -1306
  104. package/dist/fx-B-0MxGTM.mjs.map +0 -1
  105. package/dist/fx.types-DpIQILok.mjs +0 -13
  106. package/dist/index-BO6bxBeo.d.mts.map +0 -1
  107. package/dist/index-CLspOlBH.d.mts.map +0 -1
  108. package/dist/index-ClxPiGP9.d.mts.map +0 -1
  109. package/dist/index-FySViSfh.d.mts.map +0 -1
  110. package/dist/index.d.mts.map +0 -1
  111. package/dist/option-C2QpGffy.mjs +0 -530
  112. package/dist/option-C2QpGffy.mjs.map +0 -1
  113. package/dist/option.types-BiAiZ8Ks.mjs +0 -33
  114. package/dist/option.types-BiAiZ8Ks.mjs.map +0 -1
  115. package/dist/option.types-CVvowfmd.d.mts.map +0 -1
  116. package/dist/pipe-BF4G4SLo.mjs +0 -10
  117. package/dist/pipeable-DYNrUps7.mjs +0 -92
  118. package/dist/predicate-Dt9Qsbav.mjs +0 -293
  119. package/dist/result-BmqdTN5o.mjs +0 -1
  120. package/dist/result-DhYA-J-M.mjs +0 -542
  121. package/dist/result-DhYA-J-M.mjs.map +0 -1
  122. package/dist/result.types-_W95221K.d.mts.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"either-jkBX8xS1.mjs","names":["mapped","Option.some","Option.none"],"sources":["../src/either/either.ts"],"sourcesContent":["import { FxTypeId } from \"../fx/fx.types\"\nimport { Option } from \"../option\"\nimport type { Option as OptionType } from \"../option/option.types\"\nimport { Result } from \"../result\"\nimport type { Result as ResultType } from \"../result/result.types\"\nimport { dual } from \"../shared/dual\"\nimport { pipeMethod } from \"../shared/pipeable\"\nimport type {\n Either as EitherType,\n EitherAll,\n EitherBimap,\n EitherFilter,\n EitherFlatMap,\n EitherMap,\n EitherMapLeft,\n EitherMatch,\n EitherOrElse,\n EitherTap,\n EitherTapLeft,\n EitherUnwrapOr,\n EitherUnwrapOrElse,\n} from \"./either.types\"\n\n// ============================================================================\n// Constructors\n// ============================================================================\n\n/**\n * Create a right Either value (success/preferred path).\n *\n * By convention, right represents the correct/preferred outcome.\n * In Fx.gen(), this returns the value without short-circuiting.\n *\n * @param value - The right value\n * @returns An Either in the right state\n *\n * @example\n * ```ts\n * const result = right(42)\n * // => { right: true, value: 42 }\n *\n * // In Fx.gen() - never short-circuits\n * const fx = Fx.gen(function* () {\n * const a = yield* Either.right(10) // Returns 10\n * return a * 2 // Executes, returns 20\n * })\n * ```\n */\nexport const right = <R, L = never>(value: R): EitherType<L, R> => ({\n right: true,\n value,\n [FxTypeId]: {\n _A: () => value as L | R,\n _E: () => undefined as never,\n _R: () => undefined as never,\n },\n pipe: pipeMethod,\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<never, R, unknown> {\n return value\n },\n})\n\n/**\n * Create a left Either value (alternative path).\n *\n * By convention, left represents the alternative outcome.\n * Unlike Result's err(), left doesn't imply an error - it's a valid value.\n *\n * In Fx.gen(), left returns its value without short-circuiting.\n * This is the key difference from Result.err() which short-circuits.\n *\n * @param value - The left value\n * @returns An Either in the left state\n *\n * @example\n * ```ts\n * const cached = left({ source: \"cache\", data: cachedValue })\n * // => { right: false, value: { source: \"cache\", data: cachedValue } }\n *\n * // In Fx.gen() - never short-circuits (unlike Result.err)\n * const fx = Fx.gen(function* () {\n * const a = yield* Either.left(\"cached\") // Returns \"cached\"\n * return a.toUpperCase() // Executes, returns \"CACHED\"\n * })\n * ```\n */\nexport const left = <L, R = never>(value: L): EitherType<L, R> => ({\n right: false,\n value,\n [FxTypeId]: {\n _A: () => value as L | R,\n _E: () => undefined as never,\n _R: () => undefined as never,\n },\n pipe: pipeMethod,\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<never, L, unknown> {\n return value\n },\n})\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Type guard to check if an Either is in the right state.\n *\n * @param either - The Either to check\n * @returns True if right, false if left (with type narrowing)\n *\n * @example\n * ```ts\n * const either = right(42)\n * if (isRight(either)) {\n * console.log(either.value) // Type: number\n * }\n * ```\n */\nexport const isRight = <L, R>(either: EitherType<L, R>): either is Extract<EitherType<L, R>, { right: true }> =>\n either.right\n\n/**\n * Type guard to check if an Either is in the left state.\n *\n * @param either - The Either to check\n * @returns True if left, false if right (with type narrowing)\n *\n * @example\n * ```ts\n * const either = left(\"error\")\n * if (isLeft(either)) {\n * console.log(either.value) // Type: string\n * }\n * ```\n */\nexport const isLeft = <L, R>(either: EitherType<L, R>): either is Extract<EitherType<L, R>, { right: false }> =>\n !either.right\n\n// ============================================================================\n// Right-biased Transformations\n// ============================================================================\n\n/**\n * Transform the right value of an Either.\n * Left values pass through unchanged.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `map(either, fn)`\n * - Data-last: `pipe(either, map(fn))`\n *\n * Supports async functions.\n *\n * @param fn - Transformation function for right values\n * @returns A curried function that transforms an Either\n *\n * @example\n * ```ts\n * // Data-first (direct call)\n * map(right(5), x => x * 2) // => right(10)\n *\n * // Data-last (curried for pipe)\n * pipe(\n * right(5),\n * map(x => x * 2)\n * ) // => right(10)\n *\n * pipe(\n * left(\"error\"),\n * map(x => x * 2)\n * ) // => left(\"error\")\n *\n * // Async usage\n * await pipe(\n * right(userId),\n * map(async id => await fetchUser(id))\n * ) // => Promise<Either<L, User>>\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types in curried functions */\nexport const map: EitherMap = dual(2, (either: EitherType<unknown, unknown>, fn: (value: unknown) => unknown) => {\n if (!either.right) return either as any\n const mapped = fn(either.value)\n if (mapped instanceof Promise) {\n return mapped.then(right) as any\n }\n return right(mapped) as any\n})\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n\n/**\n * Transform the left value of an Either.\n * Right values pass through unchanged.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `mapLeft(either, fn)`\n * - Data-last: `pipe(either, mapLeft(fn))`\n *\n * Supports async functions.\n *\n * @param fn - Transformation function for left values\n * @returns A curried function that transforms an Either\n *\n * @example\n * ```ts\n * // Data-first (direct call)\n * mapLeft(left(\"error\"), e => e.toUpperCase()) // => left(\"ERROR\")\n *\n * // Data-last (curried for pipe)\n * pipe(\n * left(\"error\"),\n * mapLeft(e => e.toUpperCase())\n * ) // => left(\"ERROR\")\n *\n * pipe(\n * right(42),\n * mapLeft(e => e.toUpperCase())\n * ) // => right(42)\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types in curried functions */\nexport const mapLeft: EitherMapLeft = dual(\n 2,\n (either: EitherType<unknown, unknown>, fn: (value: unknown) => unknown) => {\n if (either.right) return either as any\n const mapped = fn(either.value)\n if (mapped instanceof Promise) {\n return mapped.then(left) as any\n }\n return left(mapped) as any\n },\n)\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n/**\n * Transform both sides of an Either simultaneously.\n * Unique to Either - not available in Result/Option.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `bimap(either, fnLeft, fnRight)`\n * - Data-last: `pipe(either, bimap(fnLeft, fnRight))`\n *\n * Supports async functions.\n *\n * @param fnLeft - Transformation function for left values\n * @param fnRight - Transformation function for right values\n * @returns A curried function that transforms an Either\n *\n * @example\n * ```ts\n * // Data-first (direct call)\n * bimap(right(5), e => e.toUpperCase(), x => x * 2) // => right(10)\n *\n * // Data-last (curried for pipe)\n * pipe(\n * right(5),\n * bimap(\n * e => e.toUpperCase(),\n * x => x * 2\n * )\n * ) // => right(10)\n *\n * pipe(\n * left(\"error\"),\n * bimap(\n * e => e.toUpperCase(),\n * x => x * 2\n * )\n * ) // => left(\"ERROR\")\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types in curried functions */\nexport const bimap: EitherBimap = dual(\n 3,\n (either: EitherType<unknown, unknown>, fnLeft: (value: unknown) => unknown, fnRight: (value: unknown) => unknown) => {\n if (either.right) {\n const mapped = fnRight(either.value)\n if (mapped instanceof Promise) {\n return mapped.then(right) as any\n }\n return right(mapped) as any\n }\n const mapped = fnLeft(either.value)\n if (mapped instanceof Promise) {\n return mapped.then(left) as any\n }\n return left(mapped) as any\n },\n)\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n/**\n * Chain operations that return Either.\n * Left values short-circuit the chain.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `flatMap(either, fn)`\n * - Data-last: `pipe(either, flatMap(fn))`\n *\n * Supports async functions. Combines left error unions.\n *\n * @param fn - Function that returns an Either\n * @returns A curried function that chains Eithers\n *\n * @example\n * ```ts\n * // Data-first (direct call)\n * flatMap(right(5), x => right(x * 2)) // => right(10)\n *\n * // Data-last (curried for pipe)\n * pipe(\n * right(5),\n * flatMap(x => right(x * 2)),\n * flatMap(x => right(x + 1))\n * ) // => right(11)\n *\n * pipe(\n * right(5),\n * flatMap(x => left(\"error\")),\n * flatMap(x => right(x + 1)) // Not executed\n * ) // => left(\"error\")\n *\n * // Async usage\n * await pipe(\n * right(userId),\n * flatMap(async id => right(await fetchUser(id))),\n * flatMap(async user => right(await enrichProfile(user)))\n * ) // => Promise<Either<L, EnrichedUser>>\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types in curried functions */\nexport const flatMap: EitherFlatMap = dual(\n 2,\n (either: EitherType<unknown, unknown>, fn: (value: unknown) => unknown) => {\n if (!either.right) return either as any\n const result = fn(either.value)\n return result as any\n },\n)\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n/**\n * Execute a side effect on right values without modifying the Either.\n * Left values pass through unchanged.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `tap(either, fn)`\n * - Data-last: `pipe(either, tap(fn))`\n *\n * Supports async functions.\n *\n * @param fn - Side effect function for right values\n * @returns A curried function that executes side effects\n *\n * @example\n * ```ts\n * // Data-first (direct call)\n * tap(right(42), x => console.log(x)) // Logs: 42, returns right(42)\n *\n * // Data-last (curried for pipe)\n * pipe(\n * right(42),\n * tap(x => console.log(x)), // Logs: 42\n * map(x => x * 2)\n * ) // => right(84)\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types in curried functions */\nexport const tap: EitherTap = dual(2, (either: EitherType<unknown, unknown>, fn: (value: unknown) => unknown) => {\n if (!either.right) return either as any\n const result = fn(either.value)\n if (result instanceof Promise) {\n return result.then(() => either) as any\n }\n return either as any\n})\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n/**\n * Execute a side effect on left values without modifying the Either.\n * Right values pass through unchanged.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `tapLeft(either, fn)`\n * - Data-last: `pipe(either, tapLeft(fn))`\n *\n * Supports async functions.\n *\n * @param fn - Side effect function for left values\n * @returns A curried function that executes side effects\n *\n * @example\n * ```ts\n * // Data-first (direct call)\n * tapLeft(left(\"error\"), e => console.error(e)) // Logs: error, returns left(\"error\")\n *\n * // Data-last (curried for pipe)\n * pipe(\n * left(\"error\"),\n * tapLeft(e => console.error(e)), // Logs: error\n * mapLeft(e => e.toUpperCase())\n * ) // => left(\"ERROR\")\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types in curried functions */\nexport const tapLeft: EitherTapLeft = dual(\n 2,\n (either: EitherType<unknown, unknown>, fn: (value: unknown) => unknown) => {\n if (either.right) return either as any\n const result = fn(either.value)\n if (result instanceof Promise) {\n return result.then(() => either) as any\n }\n return either as any\n },\n)\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n// ============================================================================\n// Recovery/Fallback\n// ============================================================================\n\n/**\n * Recover from a left value by providing an alternative Either.\n * Right values pass through unchanged.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `orElse(either, fn)`\n * - Data-last: `pipe(either, orElse(fn))`\n *\n * Supports async functions. Combines right value unions.\n *\n * @param fn - Function that returns an alternative Either\n * @returns A curried function that recovers from left\n *\n * @example\n * ```ts\n * // Data-first (direct call)\n * orElse(left(\"error\"), () => right(42)) // => right(42)\n *\n * // Data-last (curried for pipe)\n * pipe(\n * left(\"error\"),\n * orElse(() => right(42))\n * ) // => right(42)\n *\n * pipe(\n * right(10),\n * orElse(() => right(42))\n * ) // => right(10)\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types in curried functions */\nexport const orElse: EitherOrElse = dual(2, (either: EitherType<unknown, unknown>, fn: (value: unknown) => unknown) => {\n if (either.right) return either as any\n const result = fn(either.value)\n return result as any\n})\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n/**\n * Swap left and right values.\n * Unique to Either - not available in Result/Option.\n *\n * Curried for use with pipe().\n *\n * @returns A curried function that swaps left and right\n *\n * @example\n * ```ts\n * pipe(\n * left(\"error\"),\n * swap()\n * ) // => right(\"error\")\n *\n * pipe(\n * right(42),\n * swap()\n * ) // => left(42)\n * ```\n */\nexport const swap =\n <L, R>() =>\n (either: EitherType<L, R>): EitherType<R, L> =>\n either.right ? left(either.value) : right(either.value)\n\n// ============================================================================\n// Filtering\n// ============================================================================\n\n/**\n * Filter right values based on a predicate.\n * Failed predicates convert to left with onFail callback.\n * Left values pass through unchanged.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `filter(either, predicate, onFail)`\n * - Data-last: `pipe(either, filter(predicate, onFail))`\n *\n * @param predicate - Function to test right values\n * @param onFail - Function to produce left value on failure\n * @returns A curried function that filters an Either\n *\n * @example\n * ```ts\n * // Data-first (direct call)\n * filter(right(5), x => x > 3, x => `${x} is too small`) // => right(5)\n *\n * // Data-last (curried for pipe)\n * pipe(\n * right(5),\n * filter(x => x > 3, x => `${x} is too small`)\n * ) // => right(5)\n *\n * pipe(\n * right(2),\n * filter(x => x > 3, x => `${x} is too small`)\n * ) // => left(\"2 is too small\")\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types in curried functions */\nexport const filter: EitherFilter = dual(\n 3,\n (\n either: EitherType<unknown, unknown>,\n predicate: (value: unknown) => boolean,\n onFail: (value: unknown) => unknown,\n ) => {\n if (!either.right) return either as any\n return predicate(either.value) ? (either as any) : left(onFail(either.value))\n },\n)\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n// ============================================================================\n// Combinators\n// ============================================================================\n\n/**\n * Combine multiple Eithers into a single Either.\n * Short-circuits on the first left value.\n *\n * Supports both array and object inputs with full type preservation.\n * For arrays of 1-6 elements, tuple types are inferred automatically.\n * For longer arrays, use `as const` to preserve tuple structure.\n *\n * @param eithers - Array or object of Eithers to combine\n * @returns Either with all right values or first left\n *\n * @example\n * ```ts\n * // Array form - tuple types inferred automatically for up to 6 elements\n * all([right(1), right(\"hello\")])\n * // => right([1, \"hello\"])\n *\n * all([right(1), left(\"error\"), right(3)])\n * // => left(\"error\")\n *\n * // Object form\n * all({ a: right(1), b: right(\"hello\") })\n * // => right({ a: 1, b: \"hello\" })\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-member-access, strict-boolean-expressions, no-unsafe-assignment -- Required for handling union types in overloaded function */\nexport const all: EitherAll = (eithers: any): any => {\n // Array case\n if (Array.isArray(eithers)) {\n const values: unknown[] = []\n for (const either of eithers) {\n if (!either.right) return either\n values.push(either.value)\n }\n return right(values)\n }\n\n // Object case\n const result: Record<string, unknown> = {}\n for (const key in eithers) {\n const either = eithers[key]\n if (!either.right) return either\n result[key] = either.value\n }\n return right(result)\n}\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-member-access, strict-boolean-expressions, no-unsafe-assignment */\n// ============================================================================\n// Extraction\n// ============================================================================\n\n/**\n * Extract the right value or return a default.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `unwrapOr(either, defaultValue)`\n * - Data-last: `pipe(either, unwrapOr(defaultValue))`\n *\n * Uses NoInfer to prevent type inference from the default value.\n *\n * @param defaultValue - Value to return if Either is left\n * @returns A curried function that extracts the value\n *\n * @example\n * ```ts\n * // Data-first (direct call)\n * unwrapOr(right(42), 0) // => 42\n * unwrapOr(left(\"error\"), 0) // => 0\n *\n * // Data-last (curried for pipe)\n * pipe(\n * right(42),\n * unwrapOr(0)\n * ) // => 42\n *\n * pipe(\n * left(\"error\"),\n * unwrapOr(0)\n * ) // => 0\n * ```\n */\nexport const unwrapOr: EitherUnwrapOr = dual(\n 2,\n <L, R>(either: EitherType<L, R>, defaultValue: NoInfer<R>): R => (either.right ? either.value : defaultValue),\n)\n\n/**\n * Extract the right value or compute one from the left value.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `unwrapOrElse(either, fn)`\n * - Data-last: `pipe(either, unwrapOrElse(fn))`\n *\n * @param fn - Function to compute default from left value\n * @returns A curried function that extracts the value\n *\n * @example\n * ```ts\n * // Data-first (direct call)\n * unwrapOrElse(right(42), () => 0) // => 42\n * unwrapOrElse(left(\"error\"), e => e.length) // => 5\n *\n * // Data-last (curried for pipe)\n * pipe(\n * right(42),\n * unwrapOrElse(() => 0)\n * ) // => 42\n *\n * pipe(\n * left(\"error\"),\n * unwrapOrElse(e => e.length)\n * ) // => 5\n * ```\n */\nexport const unwrapOrElse: EitherUnwrapOrElse = dual(\n 2,\n <L, R>(either: EitherType<L, R>, fn: (left: L) => R): R => (either.right ? either.value : fn(either.value)),\n)\n\n/**\n * Pattern match on an Either with handlers for both cases.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `match(either, { left: ..., right: ... })`\n * - Data-last: `pipe(either, match({ left: ..., right: ... }))`\n *\n * @param handlers - Object with left and right handler functions\n * @returns A curried function that pattern matches\n *\n * @example\n * ```ts\n * // Data-first (direct call)\n * match(right(42), {\n * left: e => `Error: ${e}`,\n * right: x => `Success: ${x}`\n * }) // => \"Success: 42\"\n *\n * // Data-last (curried for pipe)\n * pipe(\n * right(42),\n * match({\n * left: e => `Error: ${e}`,\n * right: x => `Success: ${x}`\n * })\n * ) // => \"Success: 42\"\n * ```\n */\nexport const match: EitherMatch = dual(\n 2,\n <L, R, U>(either: EitherType<L, R>, handlers: { left: (value: L) => U; right: (value: R) => U }): U =>\n either.right ? handlers.right(either.value) : handlers.left(either.value),\n)\n\n// ============================================================================\n// Conversions\n// ============================================================================\n\n/**\n * Convert a Result to an Either.\n * Result's ok becomes right, err becomes left.\n *\n * @param result - The Result to convert\n * @returns An Either with the same semantics\n *\n * @example\n * ```ts\n * fromResult(Result.ok(42)) // => right(42)\n * fromResult(Result.err(\"error\")) // => left(\"error\")\n * ```\n */\nexport const fromResult = <R, E>(result: ResultType<R, E>): EitherType<E, R> =>\n result.ok ? right(result.value) : left(result.error)\n\n/**\n * Convert an Either to a Result.\n * Either's right becomes ok, left becomes err.\n *\n * Curried for use with pipe().\n *\n * @param either - The Either to convert\n * @returns A Result with error semantics\n *\n * @example\n * ```ts\n * pipe(\n * right(42),\n * toResult\n * ) // => Result.ok(42)\n *\n * pipe(\n * left(\"error\"),\n * toResult\n * ) // => Result.err(\"error\")\n * ```\n */\nexport const toResult = <L, R>(either: EitherType<L, R>): ResultType<R, L> =>\n either.right ? Result.ok(either.value) : Result.err(either.value)\n\n/**\n * Convert an Option to an Either.\n * Option's some becomes right, none becomes left with onNone callback.\n *\n * @param option - The Option to convert\n * @param onNone - Function to produce left value for none\n * @returns An Either\n *\n * @example\n * ```ts\n * fromOption(Option.some(42), () => \"not found\") // => right(42)\n * fromOption(Option.none(), () => \"not found\") // => left(\"not found\")\n * ```\n */\nexport const fromOption = <R, L>(option: OptionType<R>, onNone: () => L): EitherType<L, R> =>\n option.some ? right(option.value) : left(onNone())\n\n/**\n * Convert an Either to an Option.\n * Either's right becomes some, left is discarded.\n *\n * Curried for use with pipe().\n *\n * @param either - The Either to convert\n * @returns An Option (left value is discarded)\n *\n * @example\n * ```ts\n * pipe(\n * right(42),\n * toOption\n * ) // => Option.some(42)\n *\n * pipe(\n * left(\"error\"),\n * toOption\n * ) // => Option.none()\n * ```\n */\nexport const toOption = <L, R>(either: EitherType<L, R>): OptionType<R> =>\n either.right ? Option.some(either.value) : Option.none<R>()\n\n/**\n * Convert a nullable value to an Either.\n * null/undefined becomes left with onNull callback, otherwise right.\n *\n * @param value - The nullable value\n * @param onNull - Function to produce left value for null/undefined\n * @returns An Either\n *\n * @example\n * ```ts\n * fromNullable(42, () => \"not found\") // => right(42)\n * fromNullable(null, () => \"not found\") // => left(\"not found\")\n * fromNullable(undefined, () => \"not found\") // => left(\"not found\")\n * ```\n */\nexport const fromNullable = <R, L>(value: R | null | undefined, onNull: () => L): EitherType<L, R> =>\n value === null || value === undefined ? left(onNull()) : right(value)\n\n/**\n * Create an Either from a predicate.\n * Predicate success becomes right, failure becomes left with onFail callback.\n *\n * @param value - The value to test\n * @param predicate - Function to test the value\n * @param onFail - Function to produce left value on failure\n * @returns An Either\n *\n * @example\n * ```ts\n * fromPredicate(5, x => x > 3, x => `${x} is too small`)\n * // => right(5)\n *\n * fromPredicate(2, x => x > 3, x => `${x} is too small`)\n * // => left(\"2 is too small\")\n * ```\n */\nexport const fromPredicate = <R, L>(\n value: R,\n predicate: (value: R) => boolean,\n onFail: (value: R) => L,\n): EitherType<L, R> => (predicate(value) ? right(value) : left(onFail(value)))\n\n// ============================================================================\n// Namespace Export\n// ============================================================================\n\n/**\n * Either namespace containing all utility functions for working with Either types.\n *\n * Either represents a value that can be one of two types: Left<L> or Right<R>.\n * By convention, Right is the \"success\" or preferred path, while Left represents\n * an alternative outcome (not necessarily an error, unlike Result).\n *\n * Use Either when both outcomes are valid and meaningful, not just success/failure.\n * For error handling, prefer Result instead.\n *\n * @see {@link Result} for success/error semantics\n * @see {@link Option} for presence/absence semantics\n *\n * @example\n * ```ts\n * import { Either, pipe } from '@repo/std'\n * import type { Either as EitherType } from '@repo/std'\n *\n * // Either for branching logic (cache vs fresh data)\n * const fetchOrCache = (id: number): EitherType<CachedData, FreshData> =>\n * cache.has(id) ? Either.left(cache.get(id)) : Either.right(fetch(id))\n *\n * const result = pipe(\n * fetchOrCache(1),\n * Either.map(data => data.value),\n * Either.unwrapOr(defaultValue)\n * )\n *\n * // Async example\n * const processed = await pipe(\n * Either.right(userId),\n * Either.map(async id => await fetchUser(id)),\n * Either.flatMap(async user => Either.right(await enrichUser(user)))\n * )\n * ```\n */\nexport const Either = {\n // Constructors\n left,\n right,\n\n // Type guards\n isLeft,\n isRight,\n\n // Transformations\n map,\n mapLeft,\n bimap,\n flatMap,\n tap,\n tapLeft,\n\n // Recovery\n orElse,\n swap,\n\n // Filtering\n filter,\n\n // Combinators\n all,\n\n // Extraction\n unwrapOr,\n unwrapOrElse,\n match,\n\n // Conversions\n fromResult,\n toResult,\n fromOption,\n toOption,\n fromNullable,\n fromPredicate,\n} as const\n"],"mappings":"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"}
@@ -1,201 +0,0 @@
1
- //#region src/equality/equality.ts
2
- const FNV_OFFSET = 2166136261;
3
- const FNV_PRIME = 16777619;
4
- /**
5
- * Compute a 32-bit hash code for any value using an FNV-1a inspired algorithm.
6
- *
7
- * Handles: primitives, null, undefined, Date, arrays, and plain objects.
8
- * Object keys are sorted for deterministic hashing regardless of insertion order.
9
- *
10
- * @param value - The value to hash (any type)
11
- * @returns A 32-bit unsigned integer hash code
12
- *
13
- * @example
14
- * ```ts
15
- * deepHash({ a: 1, b: 2 }) // deterministic number
16
- * deepHash({ b: 2, a: 1 }) // same number (keys sorted)
17
- * deepHash([1, 2, 3]) === deepHash([1, 2, 3]) // true
18
- * ```
19
- */
20
- function deepHash(value) {
21
- let hash = FNV_OFFSET;
22
- if (value === null) return hash ^ 1853189228;
23
- if (value === void 0) return hash ^ 1970168933;
24
- switch (typeof value) {
25
- case "boolean": return hash ^ (value ? 1 : 0);
26
- case "number":
27
- if (Number.isNaN(value)) return hash ^ 5136718;
28
- if (!Number.isFinite(value)) return hash ^ (value > 0 ? 4812390 : 759787110);
29
- return hash ^ (value | 0) ^ (value * 1e6 | 0);
30
- case "string":
31
- for (let i = 0; i < value.length; i++) {
32
- hash ^= value.codePointAt(i);
33
- hash = Math.imul(hash, FNV_PRIME);
34
- }
35
- return hash >>> 0;
36
- case "object": {
37
- if (value instanceof Date) return hash ^ deepHash(value.getTime());
38
- if (Array.isArray(value)) {
39
- hash ^= 23389;
40
- for (let i = 0; i < value.length; i++) {
41
- hash ^= deepHash(value[i]);
42
- hash = Math.imul(hash, FNV_PRIME);
43
- }
44
- return hash >>> 0;
45
- }
46
- hash ^= 31613;
47
- const obj = value;
48
- const keys = Object.keys(obj).toSorted();
49
- for (const key of keys) {
50
- hash ^= deepHash(key);
51
- hash = Math.imul(hash, FNV_PRIME);
52
- hash ^= deepHash(obj[key]);
53
- hash = Math.imul(hash, FNV_PRIME);
54
- }
55
- return hash >>> 0;
56
- }
57
- default: return hash;
58
- }
59
- }
60
- /**
61
- * Deep structural equality comparison for two values.
62
- *
63
- * Compares by value rather than reference. Handles:
64
- * - Primitives (===)
65
- * - null and undefined
66
- * - Date objects (by timestamp)
67
- * - Arrays (element-wise, same length required)
68
- * - Plain objects (key-value pairs, same keys required)
69
- *
70
- * @param a - First value to compare
71
- * @param b - Second value to compare
72
- * @returns true if values are structurally equal
73
- *
74
- * @example
75
- * ```ts
76
- * deepEquals({ x: 1 }, { x: 1 }) // true
77
- * deepEquals([1, 2], [1, 2]) // true
78
- * deepEquals(new Date(0), new Date(0)) // true
79
- * deepEquals({ a: 1 }, { a: 1, b: 2 }) // false (different keys)
80
- * ```
81
- */
82
- function deepEquals(a, b) {
83
- if (a === b) return true;
84
- if (typeof a !== typeof b) return false;
85
- if (a === null || b === null) return false;
86
- if (typeof a !== "object") return false;
87
- if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
88
- if (Array.isArray(a) && Array.isArray(b)) {
89
- if (a.length !== b.length) return false;
90
- return a.every((item, index) => deepEquals(item, b[index]));
91
- }
92
- if (Array.isArray(a) !== Array.isArray(b)) return false;
93
- const aObj = a;
94
- const bObj = b;
95
- const aKeys = Object.keys(aObj);
96
- const bKeys = Object.keys(bObj);
97
- if (aKeys.length !== bKeys.length) return false;
98
- return aKeys.every((key) => deepEquals(aObj[key], bObj[key]));
99
- }
100
- /**
101
- * Create an equals method for a specific record type.
102
- *
103
- * Returns a function that compares two values of the same record type.
104
- * Returns false if either value doesn't have the expected _tag.
105
- *
106
- * @template Tag - The discriminator string literal type
107
- * @template T - The record's data type (excluding _tag)
108
- * @param _tag - The expected _tag discriminator value
109
- * @returns A binary equality function for the record type
110
- *
111
- * @example
112
- * ```ts
113
- * const equalsPoint = createEqualsMethod<'Point', { x: number; y: number }>('Point')
114
- * equalsPoint(
115
- * { _tag: 'Point', x: 1, y: 2 },
116
- * { _tag: 'Point', x: 1, y: 2 }
117
- * ) // true
118
- * ```
119
- */
120
- function createEqualsMethod(_tag) {
121
- return (a, b) => {
122
- if (a === b) return true;
123
- if (a._tag !== _tag || b._tag !== _tag) return false;
124
- return deepEquals(a, b);
125
- };
126
- }
127
- /**
128
- * Create a hash method for a specific record type.
129
- *
130
- * Returns a function that computes a hash code for values of the record type.
131
- * Returns 0 if the value doesn't have the expected _tag.
132
- *
133
- * @template Tag - The discriminator string literal type
134
- * @template T - The record's data type (excluding _tag)
135
- * @param _tag - The expected _tag discriminator value
136
- * @returns A unary hash function for the record type
137
- *
138
- * @example
139
- * ```ts
140
- * const hashPoint = createHashMethod<'Point', { x: number; y: number }>('Point')
141
- * hashPoint({ _tag: 'Point', x: 1, y: 2 }) // number
142
- * ```
143
- */
144
- function createHashMethod(_tag) {
145
- return (value) => {
146
- if (value._tag !== _tag) return 0;
147
- return deepHash(value);
148
- };
149
- }
150
- /**
151
- * Create an equals method for an ADT (any variant).
152
- *
153
- * Returns a function that compares two ADT values for structural equality.
154
- * Values must have the same _tag and be a known variant.
155
- *
156
- * @template T - The ADT type (union of all variants with _tag)
157
- * @param tags - Array of valid _tag values for this ADT
158
- * @returns A binary equality function for any variant of the ADT
159
- *
160
- * @example
161
- * ```ts
162
- * const equalsShape = createADTEqualsMethod<Circle | Square>(['Circle', 'Square'])
163
- * equalsShape(circle1, circle2) // true if structurally equal
164
- * equalsShape(circle, square) // false (different _tag)
165
- * ```
166
- */
167
- function createADTEqualsMethod(tags) {
168
- return (a, b) => {
169
- if (a === b) return true;
170
- if (a._tag !== b._tag) return false;
171
- if (!tags.includes(a._tag)) return false;
172
- return deepEquals(a, b);
173
- };
174
- }
175
- /**
176
- * Create a hash method for an ADT (any variant).
177
- *
178
- * Returns a function that computes a hash code for any variant of the ADT.
179
- * Returns 0 if the value's _tag is not a known variant.
180
- *
181
- * @template T - The ADT type (union of all variants with _tag)
182
- * @param tags - Array of valid _tag values for this ADT
183
- * @returns A unary hash function for any variant of the ADT
184
- *
185
- * @example
186
- * ```ts
187
- * const hashShape = createADTHashMethod<Circle | Square>(['Circle', 'Square'])
188
- * hashShape(circle) // number
189
- * hashShape(square) // number
190
- * ```
191
- */
192
- function createADTHashMethod(tags) {
193
- return (value) => {
194
- if (!tags.includes(value._tag)) return 0;
195
- return deepHash(value);
196
- };
197
- }
198
-
199
- //#endregion
200
- export { deepEquals as a, createHashMethod as i, createADTHashMethod as n, deepHash as o, createEqualsMethod as r, createADTEqualsMethod as t };
201
- //# sourceMappingURL=equality-C2l3BIi8.mjs.map
@@ -1,176 +0,0 @@
1
- import { t as FxTypeId } from "./fx.types-DpIQILok.mjs";
2
-
3
- //#region src/err/err.ts
4
- /**
5
- * Create a constructor function for a tagged error type.
6
- * If the error has no additional data, returns a function that takes no arguments.
7
- * If the error has data, returns a function that requires the data object.
8
- *
9
- * @template E - The tagged error type
10
- * @param tag - The error tag (must match E's _tag)
11
- * @returns A constructor function for the error type
12
- *
13
- * @example
14
- * ```ts
15
- * // Error with data
16
- * type NotFoundError = TaggedError<"NotFoundError", { resourceId: string }>
17
- * const NotFound = Err.tagged<NotFoundError>("NotFoundError")
18
- * const err = NotFound({ resourceId: "user-123" })
19
- * // { _tag: "NotFoundError", resourceId: "user-123" }
20
- *
21
- * // Error without data
22
- * type UnauthorizedError = TaggedError<"UnauthorizedError">
23
- * const Unauthorized = Err.tagged<UnauthorizedError>("UnauthorizedError")
24
- * const err = Unauthorized()
25
- * // { _tag: "UnauthorizedError" }
26
- * ```
27
- */
28
- const tagged = (tag) => {
29
- return ((data) => ({
30
- _tag: tag,
31
- ...data
32
- }));
33
- };
34
- /**
35
- * Create a class-based tagged error type (Effect-style syntax).
36
- * Returns a class that can be extended to create custom error types.
37
- * Errors are native Error objects with proper stack traces and instanceof support.
38
- * Implements Yieldable protocol so errors can be directly yielded in Do computations.
39
- *
40
- * @template Tag - The error tag (discriminator string)
41
- * @param tag - The error tag
42
- * @returns A class that can be extended with custom data
43
- *
44
- * @example
45
- * ```ts
46
- * // Error with data
47
- * class NotFoundError extends TaggedError("NotFoundError")<{ id: string }> {}
48
- * const err = new NotFoundError({ id: "123" })
49
- * err.id // "123"
50
- * err._tag // "NotFoundError"
51
- * err.stack // Error stack trace
52
- *
53
- * // Error without data
54
- * class UnauthorizedError extends TaggedError("UnauthorizedError") {}
55
- * const err2 = new UnauthorizedError()
56
- *
57
- * // Direct yielding in Do computation
58
- * const program = Fx.gen(function* () {
59
- * yield* new NotFoundError({ id: "123" }) // Short-circuits with error
60
- * })
61
- *
62
- * // instanceof checks work
63
- * if (err instanceof NotFoundError) {
64
- * console.log(err.id)
65
- * }
66
- * ```
67
- */
68
- function TaggedError(tag) {
69
- return class TaggedErrorImpl extends Error {
70
- static _tag = tag;
71
- _tag = tag;
72
- [FxTypeId] = {
73
- _A: () => void 0,
74
- _E: () => this,
75
- _R: () => void 0
76
- };
77
- constructor(...args) {
78
- super(tag);
79
- this.name = tag;
80
- const data = args[0];
81
- if (data) Object.assign(this, data);
82
- Object.setPrototypeOf(this, new.target.prototype);
83
- }
84
- *[Symbol.iterator]() {
85
- yield this;
86
- throw new Error("Unreachable: Do should short-circuit on error");
87
- }
88
- };
89
- }
90
- /**
91
- * Create a type guard for a tagged error type.
92
- * Returns a curried function that checks if a value is the specified error type.
93
- *
94
- * @template E - The tagged error type to check for
95
- * @param tag - The error tag to match
96
- * @returns A type guard function
97
- *
98
- * @example
99
- * ```ts
100
- * type NotFoundError = TaggedError<"NotFoundError", { id: string }>
101
- *
102
- * const error: unknown = getError()
103
- *
104
- * if (Err.is<NotFoundError>("NotFoundError")(error)) {
105
- * console.log(error.id) // TypeScript knows error is NotFoundError
106
- * }
107
- *
108
- * // Works with union error types
109
- * type AppError = NotFoundError | ValidationError | DbError
110
- *
111
- * function handleError(error: AppError) {
112
- * if (Err.is<NotFoundError>("NotFoundError")(error)) {
113
- * // Handle not found
114
- * } else if (Err.is<ValidationError>("ValidationError")(error)) {
115
- * // Handle validation error
116
- * }
117
- * }
118
- * ```
119
- */
120
- const is = (tag) => {
121
- return (error) => typeof error === "object" && error !== null && "_tag" in error && error._tag === tag;
122
- };
123
- /**
124
- * Err namespace containing utilities for creating and checking tagged errors.
125
- *
126
- * Tagged errors are plain objects with a `_tag` discriminator field,
127
- * making them serializable and easy to pattern match.
128
- *
129
- * @example
130
- * ```ts
131
- * import { Err, Result, Do } from "@repo/std"
132
- * import type { TaggedError } from "@repo/std"
133
- *
134
- * // Define error types
135
- * type NotFoundError = TaggedError<"NotFoundError", { resourceId: string }>
136
- * type ValidationError = TaggedError<"ValidationError", { field: string; message: string }>
137
- *
138
- * // Create constructors
139
- * const NotFound = Err.tagged<NotFoundError>("NotFoundError")
140
- * const Validation = Err.tagged<ValidationError>("ValidationError")
141
- *
142
- * // Use with Result
143
- * function findUser(id: string): Result<User, NotFoundError> {
144
- * const user = db.find(id)
145
- * if (!user) return Result.err(NotFound({ resourceId: id }))
146
- * return Result.ok(user)
147
- * }
148
- *
149
- * // Use with Do computation
150
- * const program = Fx.gen(function* () {
151
- * const user = yield* findUser("123")
152
- * return user
153
- * })
154
- *
155
- * // Pattern match on error types
156
- * pipe(
157
- * program.run(),
158
- * Result.match({
159
- * ok: (user) => console.log(user),
160
- * err: (error) => {
161
- * if (Err.is<NotFoundError>("NotFoundError")(error)) {
162
- * console.log(`Not found: ${error.resourceId}`)
163
- * }
164
- * }
165
- * })
166
- * )
167
- * ```
168
- */
169
- const Err = {
170
- tagged,
171
- is
172
- };
173
-
174
- //#endregion
175
- export { tagged as i, TaggedError as n, is as r, Err as t };
176
- //# sourceMappingURL=err-BM-svBaK.mjs.map
@@ -1,28 +0,0 @@
1
- //#region src/shared/is-promise.ts
2
- /**
3
- * Check if a value is a Promise.
4
- */
5
- function isPromise(value) {
6
- return value instanceof Promise;
7
- }
8
-
9
- //#endregion
10
- //#region src/flow/flow.ts
11
- function flow(...fns) {
12
- return ((...args) => {
13
- let nextArgs = args;
14
- for (let i = 0; i < fns.length; i++) {
15
- const [result] = nextArgs = [fns[i]?.(...nextArgs)];
16
- if (isPromise(result)) return resolveAsync(result, fns.slice(i + 1));
17
- }
18
- return nextArgs[0];
19
- });
20
- }
21
- const resolveAsync = async (result, funs) => {
22
- for (const fun of funs) result = fun(await result);
23
- return await result;
24
- };
25
-
26
- //#endregion
27
- export { isPromise as n, flow as t };
28
- //# sourceMappingURL=flow-D4cE0EAg.mjs.map