effect 3.15.4 → 3.16.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 (128) hide show
  1. package/ExecutionPlan/package.json +6 -0
  2. package/dist/cjs/Array.js +67 -5
  3. package/dist/cjs/Array.js.map +1 -1
  4. package/dist/cjs/BigDecimal.js +150 -1
  5. package/dist/cjs/BigDecimal.js.map +1 -1
  6. package/dist/cjs/Chunk.js +16 -3
  7. package/dist/cjs/Chunk.js.map +1 -1
  8. package/dist/cjs/Config.js +16 -2
  9. package/dist/cjs/Config.js.map +1 -1
  10. package/dist/cjs/Effect.js +31 -3
  11. package/dist/cjs/Effect.js.map +1 -1
  12. package/dist/cjs/ExecutionPlan.js +108 -0
  13. package/dist/cjs/ExecutionPlan.js.map +1 -0
  14. package/dist/cjs/HashMap.js +18 -1
  15. package/dist/cjs/HashMap.js.map +1 -1
  16. package/dist/cjs/Iterable.js +27 -1
  17. package/dist/cjs/Iterable.js.map +1 -1
  18. package/dist/cjs/LayerMap.js +86 -64
  19. package/dist/cjs/LayerMap.js.map +1 -1
  20. package/dist/cjs/Schedule.js +7 -1
  21. package/dist/cjs/Schedule.js.map +1 -1
  22. package/dist/cjs/Stream.js +15 -2
  23. package/dist/cjs/Stream.js.map +1 -1
  24. package/dist/cjs/index.js +4 -2
  25. package/dist/cjs/index.js.map +1 -1
  26. package/dist/cjs/internal/config.js +18 -1
  27. package/dist/cjs/internal/config.js.map +1 -1
  28. package/dist/cjs/internal/effect/circular.js +1 -4
  29. package/dist/cjs/internal/effect/circular.js.map +1 -1
  30. package/dist/cjs/internal/executionPlan.js +68 -0
  31. package/dist/cjs/internal/executionPlan.js.map +1 -0
  32. package/dist/cjs/internal/hashMap.js +3 -1
  33. package/dist/cjs/internal/hashMap.js.map +1 -1
  34. package/dist/cjs/internal/metric/polling.js +3 -4
  35. package/dist/cjs/internal/metric/polling.js.map +1 -1
  36. package/dist/cjs/internal/schedule.js +66 -25
  37. package/dist/cjs/internal/schedule.js.map +1 -1
  38. package/dist/cjs/internal/stream.js +60 -10
  39. package/dist/cjs/internal/stream.js.map +1 -1
  40. package/dist/cjs/internal/version.js +1 -1
  41. package/dist/dts/Array.d.ts +110 -0
  42. package/dist/dts/Array.d.ts.map +1 -1
  43. package/dist/dts/BigDecimal.d.ts +235 -0
  44. package/dist/dts/BigDecimal.d.ts.map +1 -1
  45. package/dist/dts/Chunk.d.ts +13 -0
  46. package/dist/dts/Chunk.d.ts.map +1 -1
  47. package/dist/dts/Config.d.ts +38 -1
  48. package/dist/dts/Config.d.ts.map +1 -1
  49. package/dist/dts/Effect.d.ts +99 -27
  50. package/dist/dts/Effect.d.ts.map +1 -1
  51. package/dist/dts/ExecutionPlan.d.ts +213 -0
  52. package/dist/dts/ExecutionPlan.d.ts.map +1 -0
  53. package/dist/dts/HashMap.d.ts +52 -0
  54. package/dist/dts/HashMap.d.ts.map +1 -1
  55. package/dist/dts/Iterable.d.ts +49 -0
  56. package/dist/dts/Iterable.d.ts.map +1 -1
  57. package/dist/dts/LayerMap.d.ts +79 -72
  58. package/dist/dts/LayerMap.d.ts.map +1 -1
  59. package/dist/dts/Schedule.d.ts +26 -0
  60. package/dist/dts/Schedule.d.ts.map +1 -1
  61. package/dist/dts/Stream.d.ts +57 -2
  62. package/dist/dts/Stream.d.ts.map +1 -1
  63. package/dist/dts/index.d.ts +5 -0
  64. package/dist/dts/index.d.ts.map +1 -1
  65. package/dist/dts/internal/executionPlan.d.ts +2 -0
  66. package/dist/dts/internal/executionPlan.d.ts.map +1 -0
  67. package/dist/dts/internal/hashMap.d.ts.map +1 -1
  68. package/dist/dts/internal/stream.d.ts.map +1 -1
  69. package/dist/esm/Array.js +65 -3
  70. package/dist/esm/Array.js.map +1 -1
  71. package/dist/esm/BigDecimal.js +148 -0
  72. package/dist/esm/BigDecimal.js.map +1 -1
  73. package/dist/esm/Chunk.js +15 -2
  74. package/dist/esm/Chunk.js.map +1 -1
  75. package/dist/esm/Config.js +15 -1
  76. package/dist/esm/Config.js.map +1 -1
  77. package/dist/esm/Effect.js +29 -1
  78. package/dist/esm/Effect.js.map +1 -1
  79. package/dist/esm/ExecutionPlan.js +99 -0
  80. package/dist/esm/ExecutionPlan.js.map +1 -0
  81. package/dist/esm/HashMap.js +17 -0
  82. package/dist/esm/HashMap.js.map +1 -1
  83. package/dist/esm/Iterable.js +26 -0
  84. package/dist/esm/Iterable.js.map +1 -1
  85. package/dist/esm/LayerMap.js +86 -64
  86. package/dist/esm/LayerMap.js.map +1 -1
  87. package/dist/esm/Schedule.js +5 -0
  88. package/dist/esm/Schedule.js.map +1 -1
  89. package/dist/esm/Stream.js +13 -0
  90. package/dist/esm/Stream.js.map +1 -1
  91. package/dist/esm/index.js +5 -0
  92. package/dist/esm/index.js.map +1 -1
  93. package/dist/esm/internal/config.js +16 -0
  94. package/dist/esm/internal/config.js.map +1 -1
  95. package/dist/esm/internal/effect/circular.js +0 -3
  96. package/dist/esm/internal/effect/circular.js.map +1 -1
  97. package/dist/esm/internal/executionPlan.js +59 -0
  98. package/dist/esm/internal/executionPlan.js.map +1 -0
  99. package/dist/esm/internal/hashMap.js +2 -0
  100. package/dist/esm/internal/hashMap.js.map +1 -1
  101. package/dist/esm/internal/metric/polling.js +3 -4
  102. package/dist/esm/internal/metric/polling.js.map +1 -1
  103. package/dist/esm/internal/schedule.js +61 -23
  104. package/dist/esm/internal/schedule.js.map +1 -1
  105. package/dist/esm/internal/stream.js +57 -7
  106. package/dist/esm/internal/stream.js.map +1 -1
  107. package/dist/esm/internal/version.js +1 -1
  108. package/package.json +9 -1
  109. package/src/Array.ts +147 -4
  110. package/src/BigDecimal.ts +355 -0
  111. package/src/Chunk.ts +28 -3
  112. package/src/Config.ts +40 -1
  113. package/src/Effect.ts +145 -36
  114. package/src/ExecutionPlan.ts +302 -0
  115. package/src/HashMap.ts +56 -0
  116. package/src/Iterable.ts +66 -0
  117. package/src/LayerMap.ts +126 -114
  118. package/src/Schedule.ts +32 -0
  119. package/src/Stream.ts +51 -2
  120. package/src/index.ts +6 -0
  121. package/src/internal/config.ts +55 -0
  122. package/src/internal/effect/circular.ts +0 -15
  123. package/src/internal/executionPlan.ts +114 -0
  124. package/src/internal/hashMap.ts +6 -0
  125. package/src/internal/metric/polling.ts +3 -4
  126. package/src/internal/schedule.ts +169 -50
  127. package/src/internal/stream.ts +140 -15
  128. package/src/internal/version.ts +1 -1
@@ -1,4 +1,4 @@
1
- let moduleVersion = "3.15.4";
1
+ let moduleVersion = "3.16.0";
2
2
  export const getCurrentVersion = () => moduleVersion;
3
3
  export const setCurrentVersion = version => {
4
4
  moduleVersion = version;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "effect",
3
- "version": "3.15.4",
3
+ "version": "3.16.0",
4
4
  "description": "The missing standard library for TypeScript, for writing production-grade software.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -187,6 +187,11 @@
187
187
  "import": "./dist/esm/Equivalence.js",
188
188
  "default": "./dist/cjs/Equivalence.js"
189
189
  },
190
+ "./ExecutionPlan": {
191
+ "types": "./dist/dts/ExecutionPlan.d.ts",
192
+ "import": "./dist/esm/ExecutionPlan.js",
193
+ "default": "./dist/cjs/ExecutionPlan.js"
194
+ },
190
195
  "./ExecutionStrategy": {
191
196
  "types": "./dist/dts/ExecutionStrategy.d.ts",
192
197
  "import": "./dist/esm/ExecutionStrategy.js",
@@ -991,6 +996,9 @@
991
996
  "Equivalence": [
992
997
  "./dist/dts/Equivalence.d.ts"
993
998
  ],
999
+ "ExecutionPlan": [
1000
+ "./dist/dts/ExecutionPlan.d.ts"
1001
+ ],
994
1002
  "ExecutionStrategy": [
995
1003
  "./dist/dts/ExecutionStrategy.d.ts"
996
1004
  ],
package/src/Array.ts CHANGED
@@ -2103,6 +2103,72 @@ export const findLast: {
2103
2103
  }
2104
2104
  )
2105
2105
 
2106
+ /**
2107
+ * Counts all the element of the given array that pass the given predicate
2108
+ *
2109
+ * **Example**
2110
+ *
2111
+ * ```ts
2112
+ * import { Array } from "effect"
2113
+ *
2114
+ * const result = Array.countBy([1, 2, 3, 4, 5], n => n % 2 === 0)
2115
+ * console.log(result) // 2
2116
+ * ```
2117
+ *
2118
+ * @category folding
2119
+ * @since 3.16.0
2120
+ */
2121
+ export const countBy: {
2122
+ /**
2123
+ * Counts all the element of the given array that pass the given predicate
2124
+ *
2125
+ * **Example**
2126
+ *
2127
+ * ```ts
2128
+ * import { Array } from "effect"
2129
+ *
2130
+ * const result = Array.countBy([1, 2, 3, 4, 5], n => n % 2 === 0)
2131
+ * console.log(result) // 2
2132
+ * ```
2133
+ *
2134
+ * @category folding
2135
+ * @since 3.16.0
2136
+ */
2137
+ <A>(predicate: (a: NoInfer<A>, i: number) => boolean): (self: Iterable<A>) => number
2138
+ /**
2139
+ * Counts all the element of the given array that pass the given predicate
2140
+ *
2141
+ * **Example**
2142
+ *
2143
+ * ```ts
2144
+ * import { Array } from "effect"
2145
+ *
2146
+ * const result = Array.countBy([1, 2, 3, 4, 5], n => n % 2 === 0)
2147
+ * console.log(result) // 2
2148
+ * ```
2149
+ *
2150
+ * @category folding
2151
+ * @since 3.16.0
2152
+ */
2153
+ <A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): number
2154
+ } = dual(
2155
+ 2,
2156
+ <A>(
2157
+ self: Iterable<A>,
2158
+ f: (a: A, i: number) => boolean
2159
+ ): number => {
2160
+ let count = 0
2161
+ const as = fromIterable(self)
2162
+ for (let i = 0; i < as.length; i++) {
2163
+ const a = as[i]
2164
+ if (f(a, i)) {
2165
+ count++
2166
+ }
2167
+ }
2168
+ return count
2169
+ }
2170
+ )
2171
+
2106
2172
  /**
2107
2173
  * Insert an element at the specified index, creating a new `NonEmptyArray`,
2108
2174
  * or return `None` if the index is out of bounds.
@@ -2315,8 +2381,15 @@ export const modify: {
2315
2381
  <A, B, S extends Iterable<A> = Iterable<A>>(self: S, i: number, f: (a: ReadonlyArray.Infer<S>) => B): ReadonlyArray.With<S, ReadonlyArray.Infer<S> | B>
2316
2382
  } = dual(
2317
2383
  3,
2318
- <A, B>(self: Iterable<A>, i: number, f: (a: A) => B): Array<A | B> =>
2319
- Option.getOrElse(modifyOption(self, i, f), () => Array.from(self))
2384
+ <A, B>(self: Iterable<A>, i: number, f: (a: A) => B): Array<A | B> => {
2385
+ const out: Array<A | B> = Array.from(self)
2386
+ if (isOutOfBounds(i, out)) {
2387
+ return out
2388
+ }
2389
+ const b = f(out[i] as A)
2390
+ out[i] = b
2391
+ return out
2392
+ }
2320
2393
  )
2321
2394
 
2322
2395
  /**
@@ -2380,11 +2453,11 @@ export const modifyOption: {
2380
2453
  */
2381
2454
  <A, B, S extends Iterable<A> = Iterable<A>>(self: S, i: number, f: (a: ReadonlyArray.Infer<S>) => B): Option.Option<ReadonlyArray.With<S, ReadonlyArray.Infer<S> | B>>
2382
2455
  } = dual(3, <A, B>(self: Iterable<A>, i: number, f: (a: A) => B): Option.Option<Array<A | B>> => {
2383
- const arr = Array.from(self)
2456
+ const arr = fromIterable(self)
2384
2457
  if (isOutOfBounds(i, arr)) {
2385
2458
  return Option.none()
2386
2459
  }
2387
- const out: Array<A | B> = arr
2460
+ const out: Array<A | B> = Array.isArray(self) ? self.slice() : arr
2388
2461
  const b = f(arr[i])
2389
2462
  out[i] = b
2390
2463
  return Option.some(out)
@@ -2459,6 +2532,76 @@ export const remove: {
2459
2532
  return out
2460
2533
  })
2461
2534
 
2535
+ /**
2536
+ * Delete the element at the specified index, creating a new `Array`,
2537
+ * or return `None` if the index is out of bounds.
2538
+ *
2539
+ * @example
2540
+ * ```ts
2541
+ * import * as assert from "node:assert"
2542
+ * import { Array, Option } from "effect"
2543
+ *
2544
+ * const numbers = [1, 2, 3, 4]
2545
+ * const result = Array.removeOption(numbers, 2)
2546
+ * assert.deepStrictEqual(result, Option.some([1, 2, 4]))
2547
+ *
2548
+ * const outOfBoundsResult = Array.removeOption(numbers, 5)
2549
+ * assert.deepStrictEqual(outOfBoundsResult, Option.none())
2550
+ * ```
2551
+ *
2552
+ * @since 3.16.0
2553
+ */
2554
+ export const removeOption: {
2555
+ /**
2556
+ * Delete the element at the specified index, creating a new `Array`,
2557
+ * or return `None` if the index is out of bounds.
2558
+ *
2559
+ * @example
2560
+ * ```ts
2561
+ * import * as assert from "node:assert"
2562
+ * import { Array, Option } from "effect"
2563
+ *
2564
+ * const numbers = [1, 2, 3, 4]
2565
+ * const result = Array.removeOption(numbers, 2)
2566
+ * assert.deepStrictEqual(result, Option.some([1, 2, 4]))
2567
+ *
2568
+ * const outOfBoundsResult = Array.removeOption(numbers, 5)
2569
+ * assert.deepStrictEqual(outOfBoundsResult, Option.none())
2570
+ * ```
2571
+ *
2572
+ * @since 3.16.0
2573
+ */
2574
+ (i: number): <A>(self: Iterable<A>) => Option.Option<Array<A>>
2575
+ /**
2576
+ * Delete the element at the specified index, creating a new `Array`,
2577
+ * or return `None` if the index is out of bounds.
2578
+ *
2579
+ * @example
2580
+ * ```ts
2581
+ * import * as assert from "node:assert"
2582
+ * import { Array, Option } from "effect"
2583
+ *
2584
+ * const numbers = [1, 2, 3, 4]
2585
+ * const result = Array.removeOption(numbers, 2)
2586
+ * assert.deepStrictEqual(result, Option.some([1, 2, 4]))
2587
+ *
2588
+ * const outOfBoundsResult = Array.removeOption(numbers, 5)
2589
+ * assert.deepStrictEqual(outOfBoundsResult, Option.none())
2590
+ * ```
2591
+ *
2592
+ * @since 3.16.0
2593
+ */
2594
+ <A>(self: Iterable<A>, i: number): Option.Option<Array<A>>
2595
+ } = dual(2, <A>(self: Iterable<A>, i: number): Option.Option<Array<A>> => {
2596
+ const arr = fromIterable(self)
2597
+ if (isOutOfBounds(i, arr)) {
2598
+ return Option.none()
2599
+ }
2600
+ const out = Array.isArray(self) ? self.slice() : arr
2601
+ out.splice(i, 1)
2602
+ return Option.some(out)
2603
+ })
2604
+
2462
2605
  /**
2463
2606
  * Reverse an `Iterable`, creating a new `Array`.
2464
2607
  *
package/src/BigDecimal.ts CHANGED
@@ -1680,3 +1680,358 @@ export const isNegative = (n: BigDecimal): boolean => n.value < bigint0
1680
1680
  * @category predicates
1681
1681
  */
1682
1682
  export const isPositive = (n: BigDecimal): boolean => n.value > bigint0
1683
+
1684
+ const isBigDecimalArgs = (args: IArguments) => isBigDecimal(args[0])
1685
+
1686
+ /**
1687
+ * Calculate the ceiling of a `BigDecimal` at the given scale.
1688
+ *
1689
+ * @example
1690
+ * ```ts
1691
+ * import * as assert from "node:assert"
1692
+ * import { ceil, unsafeFromString } from "effect/BigDecimal"
1693
+ *
1694
+ * assert.deepStrictEqual(ceil(unsafeFromString("145"), -1), unsafeFromString("150"))
1695
+ * assert.deepStrictEqual(ceil(unsafeFromString("-14.5")), unsafeFromString("-14"))
1696
+ * ```
1697
+ *
1698
+ * @since 3.16.0
1699
+ * @category math
1700
+ */
1701
+ export const ceil: {
1702
+ /**
1703
+ * Calculate the ceiling of a `BigDecimal` at the given scale.
1704
+ *
1705
+ * @example
1706
+ * ```ts
1707
+ * import * as assert from "node:assert"
1708
+ * import { ceil, unsafeFromString } from "effect/BigDecimal"
1709
+ *
1710
+ * assert.deepStrictEqual(ceil(unsafeFromString("145"), -1), unsafeFromString("150"))
1711
+ * assert.deepStrictEqual(ceil(unsafeFromString("-14.5")), unsafeFromString("-14"))
1712
+ * ```
1713
+ *
1714
+ * @since 3.16.0
1715
+ * @category math
1716
+ */
1717
+ (scale: number): (self: BigDecimal) => BigDecimal
1718
+ /**
1719
+ * Calculate the ceiling of a `BigDecimal` at the given scale.
1720
+ *
1721
+ * @example
1722
+ * ```ts
1723
+ * import * as assert from "node:assert"
1724
+ * import { ceil, unsafeFromString } from "effect/BigDecimal"
1725
+ *
1726
+ * assert.deepStrictEqual(ceil(unsafeFromString("145"), -1), unsafeFromString("150"))
1727
+ * assert.deepStrictEqual(ceil(unsafeFromString("-14.5")), unsafeFromString("-14"))
1728
+ * ```
1729
+ *
1730
+ * @since 3.16.0
1731
+ * @category math
1732
+ */
1733
+ (self: BigDecimal, scale?: number): BigDecimal
1734
+ } = dual(isBigDecimalArgs, (self: BigDecimal, scale: number = 0): BigDecimal => {
1735
+ const truncated = truncate(self, scale)
1736
+
1737
+ if (isPositive(self) && lessThan(truncated, self)) {
1738
+ return sum(truncated, make(1n, scale))
1739
+ }
1740
+
1741
+ return truncated
1742
+ })
1743
+
1744
+ /**
1745
+ * Calculate the floor of a `BigDecimal` at the given scale.
1746
+ *
1747
+ * @example
1748
+ * ```ts
1749
+ * import * as assert from "node:assert"
1750
+ * import { floor, unsafeFromString } from "effect/BigDecimal"
1751
+ *
1752
+ * assert.deepStrictEqual(floor(unsafeFromString("145"), -1), unsafeFromString("140"))
1753
+ * assert.deepStrictEqual(floor(unsafeFromString("-14.5")), unsafeFromString("-15"))
1754
+ * ```
1755
+ *
1756
+ * @since 3.16.0
1757
+ * @category math
1758
+ */
1759
+ export const floor: {
1760
+ /**
1761
+ * Calculate the floor of a `BigDecimal` at the given scale.
1762
+ *
1763
+ * @example
1764
+ * ```ts
1765
+ * import * as assert from "node:assert"
1766
+ * import { floor, unsafeFromString } from "effect/BigDecimal"
1767
+ *
1768
+ * assert.deepStrictEqual(floor(unsafeFromString("145"), -1), unsafeFromString("140"))
1769
+ * assert.deepStrictEqual(floor(unsafeFromString("-14.5")), unsafeFromString("-15"))
1770
+ * ```
1771
+ *
1772
+ * @since 3.16.0
1773
+ * @category math
1774
+ */
1775
+ (scale: number): (self: BigDecimal) => BigDecimal
1776
+ /**
1777
+ * Calculate the floor of a `BigDecimal` at the given scale.
1778
+ *
1779
+ * @example
1780
+ * ```ts
1781
+ * import * as assert from "node:assert"
1782
+ * import { floor, unsafeFromString } from "effect/BigDecimal"
1783
+ *
1784
+ * assert.deepStrictEqual(floor(unsafeFromString("145"), -1), unsafeFromString("140"))
1785
+ * assert.deepStrictEqual(floor(unsafeFromString("-14.5")), unsafeFromString("-15"))
1786
+ * ```
1787
+ *
1788
+ * @since 3.16.0
1789
+ * @category math
1790
+ */
1791
+ (self: BigDecimal, scale?: number): BigDecimal
1792
+ } = dual(isBigDecimalArgs, (self: BigDecimal, scale: number = 0): BigDecimal => {
1793
+ const truncated = truncate(self, scale)
1794
+
1795
+ if (isNegative(self) && greaterThan(truncated, self)) {
1796
+ return sum(truncated, make(-1n, scale))
1797
+ }
1798
+
1799
+ return truncated
1800
+ })
1801
+
1802
+ /**
1803
+ * Truncate a `BigDecimal` at the given scale. This is the same operation as rounding away from zero.
1804
+ *
1805
+ * @example
1806
+ * ```ts
1807
+ * import * as assert from "node:assert"
1808
+ * import { truncate, unsafeFromString } from "effect/BigDecimal"
1809
+ *
1810
+ * assert.deepStrictEqual(truncate(unsafeFromString("145"), -1), unsafeFromString("140"))
1811
+ * assert.deepStrictEqual(truncate(unsafeFromString("-14.5")), unsafeFromString("-14"))
1812
+ * ```
1813
+ *
1814
+ * @since 3.16.0
1815
+ * @category math
1816
+ */
1817
+ export const truncate: {
1818
+ /**
1819
+ * Truncate a `BigDecimal` at the given scale. This is the same operation as rounding away from zero.
1820
+ *
1821
+ * @example
1822
+ * ```ts
1823
+ * import * as assert from "node:assert"
1824
+ * import { truncate, unsafeFromString } from "effect/BigDecimal"
1825
+ *
1826
+ * assert.deepStrictEqual(truncate(unsafeFromString("145"), -1), unsafeFromString("140"))
1827
+ * assert.deepStrictEqual(truncate(unsafeFromString("-14.5")), unsafeFromString("-14"))
1828
+ * ```
1829
+ *
1830
+ * @since 3.16.0
1831
+ * @category math
1832
+ */
1833
+ (scale: number): (self: BigDecimal) => BigDecimal
1834
+ /**
1835
+ * Truncate a `BigDecimal` at the given scale. This is the same operation as rounding away from zero.
1836
+ *
1837
+ * @example
1838
+ * ```ts
1839
+ * import * as assert from "node:assert"
1840
+ * import { truncate, unsafeFromString } from "effect/BigDecimal"
1841
+ *
1842
+ * assert.deepStrictEqual(truncate(unsafeFromString("145"), -1), unsafeFromString("140"))
1843
+ * assert.deepStrictEqual(truncate(unsafeFromString("-14.5")), unsafeFromString("-14"))
1844
+ * ```
1845
+ *
1846
+ * @since 3.16.0
1847
+ * @category math
1848
+ */
1849
+ (self: BigDecimal, scale?: number): BigDecimal
1850
+ } = dual(isBigDecimalArgs, (self: BigDecimal, scale: number = 0): BigDecimal => {
1851
+ if (self.scale <= scale) {
1852
+ return self
1853
+ }
1854
+
1855
+ // BigInt division truncates towards zero
1856
+ return make(self.value / (10n ** BigInt(self.scale - scale)), scale)
1857
+ })
1858
+
1859
+ /**
1860
+ * Internal function used by `round` for `half-even` and `half-odd` rounding modes.
1861
+ *
1862
+ * Returns the digit at the position of the given `scale` within the `BigDecimal`.
1863
+ *
1864
+ * @internal
1865
+ */
1866
+ export const digitAt: {
1867
+ /**
1868
+ * Internal function used by `round` for `half-even` and `half-odd` rounding modes.
1869
+ *
1870
+ * Returns the digit at the position of the given `scale` within the `BigDecimal`.
1871
+ *
1872
+ * @internal
1873
+ */
1874
+ (scale: number): (self: BigDecimal) => bigint
1875
+ /**
1876
+ * Internal function used by `round` for `half-even` and `half-odd` rounding modes.
1877
+ *
1878
+ * Returns the digit at the position of the given `scale` within the `BigDecimal`.
1879
+ *
1880
+ * @internal
1881
+ */
1882
+ (self: BigDecimal, scale: number): bigint
1883
+ } = dual(2, (self: BigDecimal, scale: number): bigint => {
1884
+ if (self.scale < scale) {
1885
+ return 0n
1886
+ }
1887
+
1888
+ const scaled = self.value / (10n ** BigInt(self.scale - scale))
1889
+ return scaled % 10n
1890
+ })
1891
+
1892
+ /**
1893
+ * Rounding modes for `BigDecimal`.
1894
+ *
1895
+ * `ceil`: round towards positive infinity
1896
+ * `floor`: round towards negative infinity
1897
+ * `to-zero`: round towards zero
1898
+ * `from-zero`: round away from zero
1899
+ * `half-ceil`: round to the nearest neighbor; if equidistant round towards positive infinity
1900
+ * `half-floor`: round to the nearest neighbor; if equidistant round towards negative infinity
1901
+ * `half-to-zero`: round to the nearest neighbor; if equidistant round towards zero
1902
+ * `half-from-zero`: round to the nearest neighbor; if equidistant round away from zero
1903
+ * `half-even`: round to the nearest neighbor; if equidistant round to the neighbor with an even digit
1904
+ * `half-odd`: round to the nearest neighbor; if equidistant round to the neighbor with an odd digit
1905
+ *
1906
+ * @since 3.16.0
1907
+ * @category math
1908
+ */
1909
+ export type RoundingMode =
1910
+ | "ceil"
1911
+ | "floor"
1912
+ | "to-zero"
1913
+ | "from-zero"
1914
+ | "half-ceil"
1915
+ | "half-floor"
1916
+ | "half-to-zero"
1917
+ | "half-from-zero"
1918
+ | "half-even"
1919
+ | "half-odd"
1920
+
1921
+ /**
1922
+ * Rounds a `BigDecimal` at the given scale with the specified rounding mode.
1923
+ *
1924
+ * @example
1925
+ * ```ts
1926
+ * import * as assert from "node:assert"
1927
+ * import { round, unsafeFromString } from "effect/BigDecimal"
1928
+ *
1929
+ * assert.deepStrictEqual(round(unsafeFromString("145"), { mode: "from-zero", scale: -1 }), unsafeFromString("150"))
1930
+ * assert.deepStrictEqual(round(unsafeFromString("-14.5")), unsafeFromString("-15"))
1931
+ * ```
1932
+ *
1933
+ * @since 3.16.0
1934
+ * @category math
1935
+ */
1936
+ export const round: {
1937
+ /**
1938
+ * Rounds a `BigDecimal` at the given scale with the specified rounding mode.
1939
+ *
1940
+ * @example
1941
+ * ```ts
1942
+ * import * as assert from "node:assert"
1943
+ * import { round, unsafeFromString } from "effect/BigDecimal"
1944
+ *
1945
+ * assert.deepStrictEqual(round(unsafeFromString("145"), { mode: "from-zero", scale: -1 }), unsafeFromString("150"))
1946
+ * assert.deepStrictEqual(round(unsafeFromString("-14.5")), unsafeFromString("-15"))
1947
+ * ```
1948
+ *
1949
+ * @since 3.16.0
1950
+ * @category math
1951
+ */
1952
+ (options: { scale?: number; mode?: RoundingMode }): (self: BigDecimal) => BigDecimal
1953
+ /**
1954
+ * Rounds a `BigDecimal` at the given scale with the specified rounding mode.
1955
+ *
1956
+ * @example
1957
+ * ```ts
1958
+ * import * as assert from "node:assert"
1959
+ * import { round, unsafeFromString } from "effect/BigDecimal"
1960
+ *
1961
+ * assert.deepStrictEqual(round(unsafeFromString("145"), { mode: "from-zero", scale: -1 }), unsafeFromString("150"))
1962
+ * assert.deepStrictEqual(round(unsafeFromString("-14.5")), unsafeFromString("-15"))
1963
+ * ```
1964
+ *
1965
+ * @since 3.16.0
1966
+ * @category math
1967
+ */
1968
+ (n: BigDecimal, options?: { scale?: number; mode?: RoundingMode }): BigDecimal
1969
+ } = dual(isBigDecimalArgs, (self: BigDecimal, options?: { scale?: number; mode?: RoundingMode }): BigDecimal => {
1970
+ const mode = options?.mode ?? "half-from-zero"
1971
+ const scale = options?.scale ?? 0
1972
+
1973
+ switch (mode) {
1974
+ case "ceil":
1975
+ return ceil(self, scale)
1976
+
1977
+ case "floor":
1978
+ return floor(self, scale)
1979
+
1980
+ case "to-zero":
1981
+ return truncate(self, scale)
1982
+
1983
+ case "from-zero":
1984
+ return (isPositive(self) ? ceil(self, scale) : floor(self, scale))
1985
+
1986
+ case "half-ceil":
1987
+ return floor(sum(self, make(5n, scale + 1)), scale)
1988
+
1989
+ case "half-floor":
1990
+ return ceil(sum(self, make(-5n, scale + 1)), scale)
1991
+
1992
+ case "half-to-zero":
1993
+ return isNegative(self)
1994
+ ? floor(sum(self, make(5n, scale + 1)), scale)
1995
+ : ceil(sum(self, make(-5n, scale + 1)), scale)
1996
+
1997
+ case "half-from-zero":
1998
+ return isNegative(self)
1999
+ ? ceil(sum(self, make(-5n, scale + 1)), scale)
2000
+ : floor(sum(self, make(5n, scale + 1)), scale)
2001
+ }
2002
+
2003
+ const halfCeil = floor(sum(self, make(5n, scale + 1)), scale)
2004
+ const halfFloor = ceil(sum(self, make(-5n, scale + 1)), scale)
2005
+ const digit = digitAt(halfCeil, scale)
2006
+
2007
+ switch (mode) {
2008
+ case "half-even":
2009
+ return equals(halfCeil, halfFloor) ? halfCeil : (digit % 2n === 0n) ? halfCeil : halfFloor
2010
+
2011
+ case "half-odd":
2012
+ return equals(halfCeil, halfFloor) ? halfCeil : (digit % 2n === 0n) ? halfFloor : halfCeil
2013
+ }
2014
+ })
2015
+
2016
+ /**
2017
+ * Takes an `Iterable` of `BigDecimal`s and returns their sum as a single `BigDecimal`
2018
+ *
2019
+ * @example
2020
+ * ```ts
2021
+ * import * as assert from "node:assert"
2022
+ * import { unsafeFromString, sumAll } from "effect/BigDecimal"
2023
+ *
2024
+ * assert.deepStrictEqual(sumAll([unsafeFromString("2"), unsafeFromString("3"), unsafeFromString("4")]), unsafeFromString("9"))
2025
+ * ```
2026
+ *
2027
+ * @category math
2028
+ * @since 3.16.0
2029
+ */
2030
+ export const sumAll = (collection: Iterable<BigDecimal>): BigDecimal => {
2031
+ let out = zero
2032
+ for (const n of collection) {
2033
+ out = sum(out, n)
2034
+ }
2035
+
2036
+ return out
2037
+ }
package/src/Chunk.ts CHANGED
@@ -1863,7 +1863,30 @@ export const remove: {
1863
1863
  <A>(self: Chunk<A>, i: number): Chunk<A>
1864
1864
  } = dual(
1865
1865
  2,
1866
- <A>(self: Chunk<A>, i: number): Chunk<A> => unsafeFromArray(RA.remove(toReadonlyArray(self), i))
1866
+ <A>(self: Chunk<A>, i: number): Chunk<A> => {
1867
+ if (i < 0 || i >= self.length) return self
1868
+ return unsafeFromArray(RA.remove(toReadonlyArray(self), i))
1869
+ }
1870
+ )
1871
+
1872
+ /**
1873
+ * @since 3.16.0
1874
+ */
1875
+ export const removeOption: {
1876
+ /**
1877
+ * @since 3.16.0
1878
+ */
1879
+ (i: number): <A>(self: Chunk<A>) => Option<Chunk<A>>
1880
+ /**
1881
+ * @since 3.16.0
1882
+ */
1883
+ <A>(self: Chunk<A>, i: number): Option<Chunk<A>>
1884
+ } = dual(
1885
+ 2,
1886
+ <A>(self: Chunk<A>, i: number): Option<Chunk<A>> => {
1887
+ if (i < 0 || i >= self.length) return O.none()
1888
+ return O.some(unsafeFromArray(RA.remove(toReadonlyArray(self), i)))
1889
+ }
1867
1890
  )
1868
1891
 
1869
1892
  /**
@@ -1880,8 +1903,10 @@ export const modifyOption: {
1880
1903
  <A, B>(self: Chunk<A>, i: number, f: (a: A) => B): Option<Chunk<A | B>>
1881
1904
  } = dual(
1882
1905
  3,
1883
- <A, B>(self: Chunk<A>, i: number, f: (a: A) => B): Option<Chunk<A | B>> =>
1884
- O.map(RA.modifyOption(toReadonlyArray(self), i, f), unsafeFromArray)
1906
+ <A, B>(self: Chunk<A>, i: number, f: (a: A) => B): Option<Chunk<A | B>> => {
1907
+ if (i < 0 || i >= self.length) return O.none()
1908
+ return O.some(unsafeFromArray(RA.modify(toReadonlyArray(self), i, f)))
1909
+ }
1885
1910
  )
1886
1911
 
1887
1912
  /**
package/src/Config.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * @since 2.0.0
3
3
  */
4
+ import type * as Brand from "./Brand.js"
4
5
  import type * as Chunk from "./Chunk.js"
5
6
  import type * as ConfigError from "./ConfigError.js"
6
7
  import type * as Duration from "./Duration.js"
@@ -129,7 +130,15 @@ export const array: <A>(config: Config<A>, name?: string) => Config<Array<A>> =
129
130
  export const boolean: (name?: string) => Config<boolean> = internal.boolean
130
131
 
131
132
  /**
132
- * Constructs a config for a URL value.
133
+ * Constructs a config for a network port [1, 65535].
134
+ *
135
+ * @since 3.16.0
136
+ * @category constructors
137
+ */
138
+ export const port: (name?: string) => Config<number> = internal.port
139
+
140
+ /**
141
+ * Constructs a config for an URL value.
133
142
  *
134
143
  * @since 3.11.0
135
144
  * @category constructors
@@ -464,6 +473,36 @@ export const redacted: {
464
473
  <A>(config: Config<A>): Config<Redacted.Redacted<A>>
465
474
  } = internal.redacted
466
475
 
476
+ /**
477
+ * Constructs a config for a branded value.
478
+ *
479
+ * @since 3.16.0
480
+ * @category constructors
481
+ */
482
+ export const branded: {
483
+ /**
484
+ * Constructs a config for a branded value.
485
+ *
486
+ * @since 3.16.0
487
+ * @category constructors
488
+ */
489
+ <A, B extends Brand.Branded<A, any>>(constructor: Brand.Brand.Constructor<B>): (config: Config<A>) => Config<B>
490
+ /**
491
+ * Constructs a config for a branded value.
492
+ *
493
+ * @since 3.16.0
494
+ * @category constructors
495
+ */
496
+ <B extends Brand.Branded<string, any>>(name: string | undefined, constructor: Brand.Brand.Constructor<B>): Config<B>
497
+ /**
498
+ * Constructs a config for a branded value.
499
+ *
500
+ * @since 3.16.0
501
+ * @category constructors
502
+ */
503
+ <A, B extends Brand.Branded<A, any>>(config: Config<A>, constructor: Brand.Brand.Constructor<B>): Config<B>
504
+ } = internal.branded
505
+
467
506
  /**
468
507
  * Constructs a config for a sequence of values.
469
508
  *