effect 3.12.4 → 3.12.6

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 (131) hide show
  1. package/dist/cjs/Arbitrary.js +72 -14
  2. package/dist/cjs/Arbitrary.js.map +1 -1
  3. package/dist/cjs/Array.js +11 -9
  4. package/dist/cjs/Array.js.map +1 -1
  5. package/dist/cjs/Cause.js +26 -2
  6. package/dist/cjs/Cause.js.map +1 -1
  7. package/dist/cjs/Cron.js +55 -23
  8. package/dist/cjs/Cron.js.map +1 -1
  9. package/dist/cjs/Duration.js.map +1 -1
  10. package/dist/cjs/Effect.js +32 -23
  11. package/dist/cjs/Effect.js.map +1 -1
  12. package/dist/cjs/FiberHandle.js +8 -8
  13. package/dist/cjs/FiberMap.js +8 -8
  14. package/dist/cjs/FiberSet.js +8 -8
  15. package/dist/cjs/Inspectable.js +0 -4
  16. package/dist/cjs/Inspectable.js.map +1 -1
  17. package/dist/cjs/LogLevel.js +30 -2
  18. package/dist/cjs/LogLevel.js.map +1 -1
  19. package/dist/cjs/ParseResult.js +38 -18
  20. package/dist/cjs/ParseResult.js.map +1 -1
  21. package/dist/cjs/Schema.js +192 -118
  22. package/dist/cjs/Schema.js.map +1 -1
  23. package/dist/cjs/internal/cause.js.map +1 -1
  24. package/dist/cjs/internal/core-effect.js +6 -5
  25. package/dist/cjs/internal/core-effect.js.map +1 -1
  26. package/dist/cjs/internal/core.js +6 -5
  27. package/dist/cjs/internal/core.js.map +1 -1
  28. package/dist/cjs/internal/dateTime.js +12 -3
  29. package/dist/cjs/internal/dateTime.js.map +1 -1
  30. package/dist/cjs/internal/effect/circular.js +15 -2
  31. package/dist/cjs/internal/effect/circular.js.map +1 -1
  32. package/dist/cjs/internal/fiberRuntime.js.map +1 -1
  33. package/dist/cjs/internal/groupBy.js +7 -7
  34. package/dist/cjs/internal/groupBy.js.map +1 -1
  35. package/dist/cjs/internal/rateLimiter.js +8 -7
  36. package/dist/cjs/internal/rateLimiter.js.map +1 -1
  37. package/dist/cjs/internal/runtime.js +7 -11
  38. package/dist/cjs/internal/runtime.js.map +1 -1
  39. package/dist/cjs/internal/stream.js +5 -5
  40. package/dist/cjs/internal/stream.js.map +1 -1
  41. package/dist/cjs/internal/version.js +1 -1
  42. package/dist/dts/Arbitrary.d.ts.map +1 -1
  43. package/dist/dts/Array.d.ts +62 -16
  44. package/dist/dts/Array.d.ts.map +1 -1
  45. package/dist/dts/Cause.d.ts +27 -3
  46. package/dist/dts/Cause.d.ts.map +1 -1
  47. package/dist/dts/Cron.d.ts +10 -3
  48. package/dist/dts/Cron.d.ts.map +1 -1
  49. package/dist/dts/Duration.d.ts +5 -5
  50. package/dist/dts/Duration.d.ts.map +1 -1
  51. package/dist/dts/Effect.d.ts +31 -22
  52. package/dist/dts/Effect.d.ts.map +1 -1
  53. package/dist/dts/FiberHandle.d.ts +8 -8
  54. package/dist/dts/FiberMap.d.ts +8 -8
  55. package/dist/dts/FiberSet.d.ts +8 -8
  56. package/dist/dts/Inspectable.d.ts.map +1 -1
  57. package/dist/dts/LogLevel.d.ts +90 -6
  58. package/dist/dts/LogLevel.d.ts.map +1 -1
  59. package/dist/dts/ParseResult.d.ts +11 -0
  60. package/dist/dts/ParseResult.d.ts.map +1 -1
  61. package/dist/dts/Schema.d.ts +53 -33
  62. package/dist/dts/Schema.d.ts.map +1 -1
  63. package/dist/dts/internal/core-effect.d.ts.map +1 -1
  64. package/dist/dts/internal/core.d.ts.map +1 -1
  65. package/dist/dts/internal/stream.d.ts.map +1 -1
  66. package/dist/esm/Arbitrary.js +72 -14
  67. package/dist/esm/Arbitrary.js.map +1 -1
  68. package/dist/esm/Array.js +11 -9
  69. package/dist/esm/Array.js.map +1 -1
  70. package/dist/esm/Cause.js +26 -2
  71. package/dist/esm/Cause.js.map +1 -1
  72. package/dist/esm/Cron.js +53 -22
  73. package/dist/esm/Cron.js.map +1 -1
  74. package/dist/esm/Duration.js.map +1 -1
  75. package/dist/esm/Effect.js +32 -23
  76. package/dist/esm/Effect.js.map +1 -1
  77. package/dist/esm/FiberHandle.js +8 -8
  78. package/dist/esm/FiberMap.js +8 -8
  79. package/dist/esm/FiberSet.js +8 -8
  80. package/dist/esm/Inspectable.js +0 -3
  81. package/dist/esm/Inspectable.js.map +1 -1
  82. package/dist/esm/LogLevel.js +30 -2
  83. package/dist/esm/LogLevel.js.map +1 -1
  84. package/dist/esm/ParseResult.js +38 -18
  85. package/dist/esm/ParseResult.js.map +1 -1
  86. package/dist/esm/Schema.js +186 -110
  87. package/dist/esm/Schema.js.map +1 -1
  88. package/dist/esm/internal/cause.js.map +1 -1
  89. package/dist/esm/internal/core-effect.js +6 -5
  90. package/dist/esm/internal/core-effect.js.map +1 -1
  91. package/dist/esm/internal/core.js +6 -5
  92. package/dist/esm/internal/core.js.map +1 -1
  93. package/dist/esm/internal/dateTime.js +11 -2
  94. package/dist/esm/internal/dateTime.js.map +1 -1
  95. package/dist/esm/internal/effect/circular.js +15 -2
  96. package/dist/esm/internal/effect/circular.js.map +1 -1
  97. package/dist/esm/internal/fiberRuntime.js.map +1 -1
  98. package/dist/esm/internal/groupBy.js +7 -7
  99. package/dist/esm/internal/groupBy.js.map +1 -1
  100. package/dist/esm/internal/rateLimiter.js +8 -7
  101. package/dist/esm/internal/rateLimiter.js.map +1 -1
  102. package/dist/esm/internal/runtime.js +7 -11
  103. package/dist/esm/internal/runtime.js.map +1 -1
  104. package/dist/esm/internal/stream.js +5 -5
  105. package/dist/esm/internal/stream.js.map +1 -1
  106. package/dist/esm/internal/version.js +1 -1
  107. package/package.json +1 -1
  108. package/src/Arbitrary.ts +84 -14
  109. package/src/Array.ts +65 -19
  110. package/src/Cause.ts +27 -3
  111. package/src/Cron.ts +30 -27
  112. package/src/Duration.ts +11 -3
  113. package/src/Effect.ts +35 -23
  114. package/src/FiberHandle.ts +8 -8
  115. package/src/FiberMap.ts +8 -8
  116. package/src/FiberSet.ts +8 -8
  117. package/src/Inspectable.ts +0 -1
  118. package/src/LogLevel.ts +90 -6
  119. package/src/ParseResult.ts +52 -28
  120. package/src/Schema.ts +233 -124
  121. package/src/internal/cause.ts +1 -1
  122. package/src/internal/core-effect.ts +16 -9
  123. package/src/internal/core.ts +9 -4
  124. package/src/internal/dateTime.ts +12 -2
  125. package/src/internal/effect/circular.ts +19 -17
  126. package/src/internal/fiberRuntime.ts +2 -1
  127. package/src/internal/groupBy.ts +35 -39
  128. package/src/internal/rateLimiter.ts +8 -7
  129. package/src/internal/runtime.ts +6 -14
  130. package/src/internal/stream.ts +13 -15
  131. package/src/internal/version.ts +1 -1
@@ -1,4 +1,4 @@
1
- let moduleVersion = "3.12.4";
1
+ let moduleVersion = "3.12.6";
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.12.4",
3
+ "version": "3.12.6",
4
4
  "description": "The missing standard library for TypeScript, for writing production-grade software.",
5
5
  "license": "MIT",
6
6
  "repository": {
package/src/Arbitrary.ts CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  import * as Arr from "./Array.js"
6
6
  import * as FastCheck from "./FastCheck.js"
7
+ import { globalValue } from "./GlobalValue.js"
7
8
  import * as errors_ from "./internal/schema/errors.js"
8
9
  import * as schemaId_ from "./internal/schema/schemaId.js"
9
10
  import * as util_ from "./internal/schema/util.js"
@@ -276,6 +277,11 @@ const makeArrayConfig = (options: {
276
277
 
277
278
  type Config = StringConstraints | NumberConstraints | BigIntConstraints | DateConstraints | ArrayConfig
278
279
 
280
+ const arbitraryMemoMap = globalValue(
281
+ Symbol.for("effect/Arbitrary/arbitraryMemoMap"),
282
+ () => new WeakMap<AST.AST, LazyArbitrary<any>>()
283
+ )
284
+
279
285
  const go = (
280
286
  ast: AST.AST,
281
287
  ctx: ArbitraryGenerationContext,
@@ -311,6 +317,7 @@ const go = (
311
317
  const constStringConstraints = makeStringConstraints({})
312
318
  const constNumberConstraints = makeNumberConstraints({})
313
319
  const constBigIntConstraints = makeBigIntConstraints({})
320
+ const defaultSuspendedArrayConstraints: FastCheck.ArrayConstraints = { maxLength: 2 }
314
321
 
315
322
  /** @internal */
316
323
  export const toOp = (
@@ -439,8 +446,22 @@ export const toOp = (
439
446
  const value = indexSignatures[i][1](fc)
440
447
  output = output.chain((o) => {
441
448
  const item = fc.tuple(key, value)
449
+ /*
450
+
451
+ `getSuspendedArray` is used to generate less key/value pairs in
452
+ the context of a recursive schema. Without it, the following schema
453
+ would generate an big amount of values possibly leading to a stack
454
+ overflow:
455
+
456
+ ```ts
457
+ type A = { [_: string]: A }
458
+
459
+ const schema = S.Record({ key: S.String, value: S.suspend((): S.Schema<A> => schema) })
460
+ ```
461
+
462
+ */
442
463
  const arr = ctx.depthIdentifier !== undefined ?
443
- getSuspendedArray(fc, ctx.depthIdentifier, ctx.maxDepth, item) :
464
+ getSuspendedArray(fc, ctx.depthIdentifier, ctx.maxDepth, item, defaultSuspendedArrayConstraints) :
444
465
  fc.array(item)
445
466
  return arr.map((tuples) => ({ ...Object.fromEntries(tuples), ...o }))
446
467
  })
@@ -454,16 +475,39 @@ export const toOp = (
454
475
  return new Succeed((fc) => fc.oneof(...types.map((arb) => arb(fc))))
455
476
  }
456
477
  case "Suspend": {
478
+ const memo = arbitraryMemoMap.get(ast)
479
+ if (memo) {
480
+ return new Succeed(memo)
481
+ }
457
482
  const get = util_.memoizeThunk(() => {
458
483
  return go(ast.f(), getSuspendedContext(ctx, ast), path)
459
484
  })
460
- return new Succeed((fc) => fc.constant(null).chain(() => get()(fc)))
485
+ const out: LazyArbitrary<any> = (fc) => fc.constant(null).chain(() => get()(fc))
486
+ arbitraryMemoMap.set(ast, out)
487
+ return new Succeed(out)
461
488
  }
462
489
  case "Transformation":
463
490
  return toOp(ast.to, ctx, path)
464
491
  }
465
492
  }
466
493
 
494
+ function subtractElementsLength(
495
+ constraints: FastCheck.ArrayConstraints,
496
+ elementsLength: number
497
+ ): FastCheck.ArrayConstraints {
498
+ if (elementsLength === 0 || (constraints.minLength === undefined && constraints.maxLength === undefined)) {
499
+ return constraints
500
+ }
501
+ const out = { ...constraints }
502
+ if (out.minLength !== undefined) {
503
+ out.minLength = Math.max(out.minLength - elementsLength, 0)
504
+ }
505
+ if (out.maxLength !== undefined) {
506
+ out.maxLength = Math.max(out.maxLength - elementsLength, 0)
507
+ }
508
+ return out
509
+ }
510
+
467
511
  const goTupleType = (
468
512
  ast: AST.TupleType,
469
513
  ctx: ArbitraryGenerationContext,
@@ -508,9 +552,36 @@ const goTupleType = (
508
552
  const [head, ...tail] = rest
509
553
  const item = head(fc)
510
554
  output = output.chain((as) => {
511
- return (ctx.depthIdentifier !== undefined
512
- ? getSuspendedArray(fc, ctx.depthIdentifier, ctx.maxDepth, item, constraints)
513
- : fc.array(item, constraints)).map((rest) => [...as, ...rest])
555
+ const len = as.length
556
+ // We must adjust the constraints for the rest element
557
+ // because the elements might have generated some values
558
+ const restArrayConstraints = subtractElementsLength(constraints, len)
559
+ if (restArrayConstraints.maxLength === 0) {
560
+ return fc.constant(as)
561
+ }
562
+ /*
563
+
564
+ `getSuspendedArray` is used to generate less values in
565
+ the context of a recursive schema. Without it, the following schema
566
+ would generate an big amount of values possibly leading to a stack
567
+ overflow:
568
+
569
+ ```ts
570
+ type A = ReadonlyArray<A | null>
571
+
572
+ const schema = S.Array(
573
+ S.NullOr(S.suspend((): S.Schema<A> => schema))
574
+ )
575
+ ```
576
+
577
+ */
578
+ const arr = ctx.depthIdentifier !== undefined
579
+ ? getSuspendedArray(fc, ctx.depthIdentifier, ctx.maxDepth, item, restArrayConstraints)
580
+ : fc.array(item, restArrayConstraints)
581
+ if (len === 0) {
582
+ return arr
583
+ }
584
+ return arr.map((rest) => [...as, ...rest])
514
585
  })
515
586
  // ---------------------------------------------
516
587
  // handle post rest elements
@@ -660,20 +731,19 @@ const getSuspendedArray = (
660
731
  depthIdentifier: string,
661
732
  maxDepth: number,
662
733
  item: FastCheck.Arbitrary<any>,
663
- constraints?: FastCheck.ArrayConstraints
734
+ constraints: FastCheck.ArrayConstraints
664
735
  ) => {
665
- let minLength = 1
666
- let maxLength = 2
667
- if (constraints && constraints.minLength !== undefined && constraints.minLength > minLength) {
668
- minLength = constraints.minLength
669
- if (minLength > maxLength) {
670
- maxLength = minLength
671
- }
736
+ // In the context of a recursive schema, we don't want a `maxLength` greater than 2.
737
+ // The only exception is when `minLength` is also set, in which case we set
738
+ // `maxLength` to the minimum value, which is `minLength`.
739
+ const maxLengthLimit = Math.max(2, constraints.minLength ?? 0)
740
+ if (constraints.maxLength !== undefined && constraints.maxLength > maxLengthLimit) {
741
+ constraints = { ...constraints, maxLength: maxLengthLimit }
672
742
  }
673
743
  return fc.oneof(
674
744
  { maxDepth, depthIdentifier },
675
745
  fc.constant([]),
676
- fc.array(item, { minLength, maxLength })
746
+ fc.array(item, constraints)
677
747
  )
678
748
  }
679
749
 
package/src/Array.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * @since 2.0.0
5
5
  */
6
6
 
7
- import type { Either as array_ } from "./Either.js"
7
+ import type { Either } from "./Either.js"
8
8
  import * as E from "./Either.js"
9
9
  import * as Equal from "./Equal.js"
10
10
  import * as Equivalence from "./Equivalence.js"
@@ -4787,7 +4787,7 @@ export const partitionMap: {
4787
4787
  * @category filtering
4788
4788
  * @since 2.0.0
4789
4789
  */
4790
- <A, B, C>(f: (a: A, i: number) => array_<C, B>): (self: Iterable<A>) => [left: Array<B>, right: Array<C>]
4790
+ <A, B, C>(f: (a: A, i: number) => Either<C, B>): (self: Iterable<A>) => [left: Array<B>, right: Array<C>]
4791
4791
  /**
4792
4792
  * Applies a function to each element of the `Iterable`, categorizing the results into two separate arrays.
4793
4793
  * This function is particularly useful for operations where each element can result in two possible types,
@@ -4813,10 +4813,10 @@ export const partitionMap: {
4813
4813
  * @category filtering
4814
4814
  * @since 2.0.0
4815
4815
  */
4816
- <A, B, C>(self: Iterable<A>, f: (a: A, i: number) => array_<C, B>): [left: Array<B>, right: Array<C>]
4816
+ <A, B, C>(self: Iterable<A>, f: (a: A, i: number) => Either<C, B>): [left: Array<B>, right: Array<C>]
4817
4817
  } = dual(
4818
4818
  2,
4819
- <A, B, C>(self: Iterable<A>, f: (a: A, i: number) => array_<C, B>): [left: Array<B>, right: Array<C>] => {
4819
+ <A, B, C>(self: Iterable<A>, f: (a: A, i: number) => Either<C, B>): [left: Array<B>, right: Array<C>] => {
4820
4820
  const left: Array<B> = []
4821
4821
  const right: Array<C> = []
4822
4822
  const as = fromIterable(self)
@@ -4869,7 +4869,7 @@ export const getSomes: <T extends Iterable<Option<X>>, X = any>(
4869
4869
  * @category filtering
4870
4870
  * @since 2.0.0
4871
4871
  */
4872
- export const getLefts = <T extends Iterable<array_<any, any>>>(self: T): Array<array_.Left<ReadonlyArray.Infer<T>>> => {
4872
+ export const getLefts = <T extends Iterable<Either<any, any>>>(self: T): Array<Either.Left<ReadonlyArray.Infer<T>>> => {
4873
4873
  const out: Array<any> = []
4874
4874
  for (const a of self) {
4875
4875
  if (E.isLeft(a)) {
@@ -4896,9 +4896,9 @@ export const getLefts = <T extends Iterable<array_<any, any>>>(self: T): Array<a
4896
4896
  * @category filtering
4897
4897
  * @since 2.0.0
4898
4898
  */
4899
- export const getRights = <T extends Iterable<array_<any, any>>>(
4899
+ export const getRights = <T extends Iterable<Either<any, any>>>(
4900
4900
  self: T
4901
- ): Array<array_.Right<ReadonlyArray.Infer<T>>> => {
4901
+ ): Array<Either.Right<ReadonlyArray.Infer<T>>> => {
4902
4902
  const out: Array<any> = []
4903
4903
  for (const a of self) {
4904
4904
  if (E.isRight(a)) {
@@ -4951,6 +4951,17 @@ export const filter: {
4951
4951
  /**
4952
4952
  * Separate elements based on a predicate that also exposes the index of the element.
4953
4953
  *
4954
+ * @example
4955
+ * ```ts
4956
+ * import { Array } from "effect"
4957
+ *
4958
+ * const numbers = [1, 2, 3, 4]
4959
+ *
4960
+ * const result = Array.partition(numbers, n => n % 2 === 0)
4961
+ *
4962
+ * assert.deepStrictEqual(result, [[1, 3], [2, 4]])
4963
+ * ```
4964
+ *
4954
4965
  * @category filtering
4955
4966
  * @since 2.0.0
4956
4967
  */
@@ -4958,6 +4969,17 @@ export const partition: {
4958
4969
  /**
4959
4970
  * Separate elements based on a predicate that also exposes the index of the element.
4960
4971
  *
4972
+ * @example
4973
+ * ```ts
4974
+ * import { Array } from "effect"
4975
+ *
4976
+ * const numbers = [1, 2, 3, 4]
4977
+ *
4978
+ * const result = Array.partition(numbers, n => n % 2 === 0)
4979
+ *
4980
+ * assert.deepStrictEqual(result, [[1, 3], [2, 4]])
4981
+ * ```
4982
+ *
4961
4983
  * @category filtering
4962
4984
  * @since 2.0.0
4963
4985
  */
@@ -4967,6 +4989,17 @@ export const partition: {
4967
4989
  /**
4968
4990
  * Separate elements based on a predicate that also exposes the index of the element.
4969
4991
  *
4992
+ * @example
4993
+ * ```ts
4994
+ * import { Array } from "effect"
4995
+ *
4996
+ * const numbers = [1, 2, 3, 4]
4997
+ *
4998
+ * const result = Array.partition(numbers, n => n % 2 === 0)
4999
+ *
5000
+ * assert.deepStrictEqual(result, [[1, 3], [2, 4]])
5001
+ * ```
5002
+ *
4970
5003
  * @category filtering
4971
5004
  * @since 2.0.0
4972
5005
  */
@@ -4976,6 +5009,17 @@ export const partition: {
4976
5009
  /**
4977
5010
  * Separate elements based on a predicate that also exposes the index of the element.
4978
5011
  *
5012
+ * @example
5013
+ * ```ts
5014
+ * import { Array } from "effect"
5015
+ *
5016
+ * const numbers = [1, 2, 3, 4]
5017
+ *
5018
+ * const result = Array.partition(numbers, n => n % 2 === 0)
5019
+ *
5020
+ * assert.deepStrictEqual(result, [[1, 3], [2, 4]])
5021
+ * ```
5022
+ *
4979
5023
  * @category filtering
4980
5024
  * @since 2.0.0
4981
5025
  */
@@ -4986,6 +5030,17 @@ export const partition: {
4986
5030
  /**
4987
5031
  * Separate elements based on a predicate that also exposes the index of the element.
4988
5032
  *
5033
+ * @example
5034
+ * ```ts
5035
+ * import { Array } from "effect"
5036
+ *
5037
+ * const numbers = [1, 2, 3, 4]
5038
+ *
5039
+ * const result = Array.partition(numbers, n => n % 2 === 0)
5040
+ *
5041
+ * assert.deepStrictEqual(result, [[1, 3], [2, 4]])
5042
+ * ```
5043
+ *
4989
5044
  * @category filtering
4990
5045
  * @since 2.0.0
4991
5046
  */
@@ -5010,21 +5065,12 @@ export const partition: {
5010
5065
  /**
5011
5066
  * Separates an `Iterable` into two arrays based on a predicate.
5012
5067
  *
5013
- * @example
5014
- * ```ts
5015
- * import { Array } from "effect"
5016
- *
5017
- * const numbers = [1, 2, 3, 4]
5018
- * const result = Array.partition(numbers, n => n % 2 === 0)
5019
- * assert.deepStrictEqual(result, [[1, 3], [2, 4]])
5020
- * ```
5021
- *
5022
5068
  * @category filtering
5023
5069
  * @since 2.0.0
5024
5070
  */
5025
- export const separate: <T extends Iterable<array_<any, any>>>(
5071
+ export const separate: <T extends Iterable<Either<any, any>>>(
5026
5072
  self: T
5027
- ) => [Array<array_.Left<ReadonlyArray.Infer<T>>>, Array<array_.Right<ReadonlyArray.Infer<T>>>] = partitionMap(
5073
+ ) => [Array<Either.Left<ReadonlyArray.Infer<T>>>, Array<Either.Right<ReadonlyArray.Infer<T>>>] = partitionMap(
5028
5074
  identity
5029
5075
  )
5030
5076
 
@@ -5296,7 +5342,7 @@ export const flatMapNullable: {
5296
5342
  * @since 2.0.0
5297
5343
  */
5298
5344
  export const liftEither = <A extends Array<unknown>, E, B>(
5299
- f: (...a: A) => array_<B, E>
5345
+ f: (...a: A) => Either<B, E>
5300
5346
  ) =>
5301
5347
  (...a: A): Array<B> => {
5302
5348
  const e = f(...a)
package/src/Cause.ts CHANGED
@@ -453,7 +453,7 @@ export const sequential: <E, E2>(left: Cause<E>, right: Cause<E2>) => Cause<E |
453
453
  * @since 2.0.0
454
454
  * @category refinements
455
455
  */
456
- export const isCause: (u: unknown) => u is Cause<never> = internal.isCause
456
+ export const isCause: (u: unknown) => u is Cause<unknown> = internal.isCause
457
457
 
458
458
  /**
459
459
  * Returns `true` if the specified `Cause` is an `Empty` type, `false`
@@ -1089,8 +1089,32 @@ export const isRuntimeException: (u: unknown) => u is RuntimeException = core.is
1089
1089
  export const TimeoutException: new(message?: string | undefined) => TimeoutException = core.TimeoutException
1090
1090
 
1091
1091
  /**
1092
- * Represents a checked exception which occurs when an unknown error is thrown, such as
1093
- * from a rejected promise.
1092
+ * Creates an instance of `UnknownException`, an error object used to handle
1093
+ * unknown errors such as those from rejected promises.
1094
+ *
1095
+ * **Details**
1096
+ *
1097
+ * This function constructs an `UnknownException` with flexible behavior for
1098
+ * managing the error message and cause.
1099
+ *
1100
+ * The required `error` argument is passed as the `cause` to the global `Error`
1101
+ * constructor, ensuring that the original cause is preserved in the error chain
1102
+ * for debugging purposes. This ensures that the origin stack trace is
1103
+ * preserved.
1104
+ *
1105
+ * The `error` argument is always stored in the `error` property of the
1106
+ * `UnknownException` instance for reference, regardless of its type.
1107
+ *
1108
+ * Additionally, if you provide a `message` argument, it is used as the error
1109
+ * message. If no `message` is provided, the error message defaults to `"An
1110
+ * unknown error occurred"`.
1111
+ *
1112
+ * **When to Use**
1113
+ *
1114
+ * Use this function when you need to handle unexpected or unknown errors in
1115
+ * your application, particularly when the source of the error might not provide
1116
+ * a clear message. This is useful for wrapping generic errors thrown from
1117
+ * promises or external APIs.
1094
1118
  *
1095
1119
  * @since 2.0.0
1096
1120
  * @category errors
package/src/Cron.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  * @since 2.0.0
3
3
  */
4
4
  import * as Arr from "./Array.js"
5
+ import * as Data from "./Data.js"
5
6
  import type * as DateTime from "./DateTime.js"
6
7
  import * as Either from "./Either.js"
7
8
  import * as Equal from "./Equal.js"
@@ -202,25 +203,14 @@ export type ParseErrorTypeId = typeof ParseErrorTypeId
202
203
  * @since 2.0.0
203
204
  * @category models
204
205
  */
205
- export interface ParseError {
206
- readonly _tag: "ParseError"
207
- readonly [ParseErrorTypeId]: ParseErrorTypeId
206
+ export class ParseError extends Data.TaggedError("CronParseError")<{
208
207
  readonly message: string
209
208
  readonly input?: string
210
- }
211
-
212
- const ParseErrorProto = {
213
- _tag: "ParseError",
214
- [ParseErrorTypeId]: ParseErrorTypeId
215
- }
216
-
217
- const ParseError = (message: string, input?: string): ParseError => {
218
- const o: Mutable<ParseError> = Object.create(ParseErrorProto)
219
- o.message = message
220
- if (input !== undefined) {
221
- o.input = input
222
- }
223
- return o
209
+ }> {
210
+ /**
211
+ * @since 2.0.0
212
+ */
213
+ readonly [ParseErrorTypeId] = ParseErrorTypeId
224
214
  }
225
215
 
226
216
  /**
@@ -259,7 +249,12 @@ export const isParseError = (u: unknown): u is ParseError => hasProperty(u, Pars
259
249
  export const parse = (cron: string, tz?: DateTime.TimeZone | string): Either.Either<Cron, ParseError> => {
260
250
  const segments = cron.split(" ").filter(String.isNonEmpty)
261
251
  if (segments.length !== 5 && segments.length !== 6) {
262
- return Either.left(ParseError(`Invalid number of segments in cron expression`, cron))
252
+ return Either.left(
253
+ new ParseError({
254
+ message: `Invalid number of segments in cron expression`,
255
+ input: cron
256
+ })
257
+ )
263
258
  }
264
259
 
265
260
  if (segments.length === 5) {
@@ -269,7 +264,11 @@ export const parse = (cron: string, tz?: DateTime.TimeZone | string): Either.Eit
269
264
  const [seconds, minutes, hours, days, months, weekdays] = segments
270
265
  const zone = tz === undefined || dateTime.isTimeZone(tz) ?
271
266
  Either.right(tz) :
272
- Either.fromOption(dateTime.zoneFromString(tz), () => ParseError(`Invalid time zone in cron expression`, tz))
267
+ Either.fromOption(dateTime.zoneFromString(tz), () =>
268
+ new ParseError({
269
+ message: `Invalid time zone in cron expression`,
270
+ input: tz
271
+ }))
273
272
 
274
273
  return Either.all({
275
274
  tz: zone,
@@ -639,13 +638,13 @@ const parseSegment = (
639
638
 
640
639
  if (step !== undefined) {
641
640
  if (!Number.isInteger(step)) {
642
- return Either.left(ParseError(`Expected step value to be a positive integer`, input))
641
+ return Either.left(new ParseError({ message: `Expected step value to be a positive integer`, input }))
643
642
  }
644
643
  if (step < 1) {
645
- return Either.left(ParseError(`Expected step value to be greater than 0`, input))
644
+ return Either.left(new ParseError({ message: `Expected step value to be greater than 0`, input }))
646
645
  }
647
646
  if (step > options.max) {
648
- return Either.left(ParseError(`Expected step value to be less than ${options.max}`, input))
647
+ return Either.left(new ParseError({ message: `Expected step value to be less than ${options.max}`, input }))
649
648
  }
650
649
  }
651
650
 
@@ -656,23 +655,27 @@ const parseSegment = (
656
655
  } else {
657
656
  const [left, right] = splitRange(raw, options.aliases)
658
657
  if (!Number.isInteger(left)) {
659
- return Either.left(ParseError(`Expected a positive integer`, input))
658
+ return Either.left(new ParseError({ message: `Expected a positive integer`, input }))
660
659
  }
661
660
  if (left < options.min || left > options.max) {
662
- return Either.left(ParseError(`Expected a value between ${options.min} and ${options.max}`, input))
661
+ return Either.left(
662
+ new ParseError({ message: `Expected a value between ${options.min} and ${options.max}`, input })
663
+ )
663
664
  }
664
665
 
665
666
  if (right === undefined) {
666
667
  values.add(left)
667
668
  } else {
668
669
  if (!Number.isInteger(right)) {
669
- return Either.left(ParseError(`Expected a positive integer`, input))
670
+ return Either.left(new ParseError({ message: `Expected a positive integer`, input }))
670
671
  }
671
672
  if (right < options.min || right > options.max) {
672
- return Either.left(ParseError(`Expected a value between ${options.min} and ${options.max}`, input))
673
+ return Either.left(
674
+ new ParseError({ message: `Expected a value between ${options.min} and ${options.max}`, input })
675
+ )
673
676
  }
674
677
  if (left > right) {
675
- return Either.left(ParseError(`Invalid value range`, input))
678
+ return Either.left(new ParseError({ message: `Invalid value range`, input }))
676
679
  }
677
680
 
678
681
  for (let i = left; i <= right; i += step ?? 1) {
package/src/Duration.ts CHANGED
@@ -41,9 +41,17 @@ export interface Duration extends Equal.Equal, Pipeable, Inspectable {
41
41
  * @category models
42
42
  */
43
43
  export type DurationValue =
44
- | { _tag: "Millis"; millis: number }
45
- | { _tag: "Nanos"; nanos: bigint }
46
- | { _tag: "Infinity" }
44
+ | {
45
+ readonly _tag: "Millis"
46
+ readonly millis: number
47
+ }
48
+ | {
49
+ readonly _tag: "Nanos"
50
+ readonly nanos: bigint
51
+ }
52
+ | {
53
+ readonly _tag: "Infinity"
54
+ }
47
55
 
48
56
  /**
49
57
  * @since 2.0.0
package/src/Effect.ts CHANGED
@@ -15712,13 +15712,14 @@ export {
15712
15712
  * original effect succeeds, the success value is wrapped in `Option.some`. If
15713
15713
  * the effect fails, the failure is converted to `Option.none`.
15714
15714
  *
15715
- * This is useful for handling cases where you want to explicitly represent the
15716
- * absence of a value due to a failure, while preventing direct failure of the
15717
- * resulting effect (its error type is `never`). Note that fatal errors, such as
15718
- * defects, are not wrapped and will still result in failure.
15715
+ * This is particularly useful for scenarios where you want to represent the
15716
+ * absence of a value explicitly, without causing the resulting effect to fail.
15717
+ * The resulting effect has an error type of `never`, meaning it cannot fail
15718
+ * directly. However, unrecoverable errors, also referred to as defects, are
15719
+ * not captured and will still result in failure.
15719
15720
  *
15720
15721
  * @see {@link either} for a version that uses `Either` instead.
15721
- * @see {@link exit} for a version that uses `Exit` instead.
15722
+ * @see {@link exit} for a version that encapsulates both recoverable errors and defects in an `Exit`.
15722
15723
  *
15723
15724
  * @example
15724
15725
  * ```ts
@@ -15768,18 +15769,24 @@ export const option: <A, E, R>(self: Effect<A, E, R>) => Effect<Option.Option<A>
15768
15769
  *
15769
15770
  * This function converts an effect that may fail into an effect that always
15770
15771
  * succeeds, wrapping the outcome in an `Either` type. The result will be
15771
- * `Either.Left` if the effect fails, containing the error, or `Either.Right` if
15772
- * it succeeds, containing the result.
15772
+ * `Either.Left` if the effect fails, containing the recoverable error, or
15773
+ * `Either.Right` if it succeeds, containing the result.
15773
15774
  *
15774
- * Using this function, you can handle errors explicitly without causing the
15775
- * effect to fail. This can be especially useful in scenarios where you want to
15776
- * chain effects and deal with success and failure in the same logical flow.
15775
+ * Using this function, you can handle recoverable errors explicitly without
15776
+ * causing the effect to fail. This is particularly useful in scenarios where
15777
+ * you want to chain effects and manage both success and failure in the same
15778
+ * logical flow.
15777
15779
  *
15778
- * The resulting effect cannot fail directly because failures are represented
15779
- * inside the `Either` type.
15780
+ * It's important to note that unrecoverable errors, often referred to as
15781
+ * "defects," are still thrown and not captured within the `Either` type. Only
15782
+ * failures that are explicitly represented as recoverable errors in the effect
15783
+ * are encapsulated.
15784
+ *
15785
+ * The resulting effect cannot fail directly because all recoverable failures
15786
+ * are represented inside the `Either` type.
15780
15787
  *
15781
15788
  * @see {@link option} for a version that uses `Option` instead.
15782
- * @see {@link exit} for a version that uses `Exit` instead.
15789
+ * @see {@link exit} for a version that encapsulates both recoverable errors and defects in an `Exit`.
15783
15790
  *
15784
15791
  * @example
15785
15792
  * ```ts
@@ -15831,16 +15838,18 @@ export const either: <A, E, R>(self: Effect<A, E, R>) => Effect<Either.Either<A,
15831
15838
  * **Details**
15832
15839
  *
15833
15840
  * This function converts an effect into one that always succeeds, wrapping its
15834
- * outcome in the `Exit` type. The `Exit` type allows explicit handling of both
15835
- * success (`Exit.Success`) and failure (`Exit.Failure`) cases.
15841
+ * outcome in the `Exit` type. The `Exit` type provides explicit handling of
15842
+ * both success (`Exit.Success`) and failure (`Exit.Failure`) cases, including
15843
+ * defects (unrecoverable errors).
15836
15844
  *
15837
- * The failure is no longer propagated directly but encapsulated inside the
15838
- * `Exit.Failure` type. This makes the resulting effect robust and incapable of
15839
- * direct failure (the error type is set to `never`).
15845
+ * Unlike {@link either} or {@link option}, this function also encapsulates
15846
+ * defects, which are typically unrecoverable and would otherwise terminate the
15847
+ * effect. With the `Exit` type, defects are represented in `Exit.Failure`,
15848
+ * allowing for detailed introspection and structured error handling.
15840
15849
  *
15841
- * This function is useful for managing and reasoning about effects with complex
15842
- * outcomes, as it allows for detailed introspection of errors, including
15843
- * defects and unexpected failures.
15850
+ * This makes the resulting effect robust and incapable of direct failure (its
15851
+ * error type is `never`). It is particularly useful for workflows where all
15852
+ * outcomes, including unexpected defects, must be managed and analyzed.
15844
15853
  *
15845
15854
  * @see {@link option} for a version that uses `Option` instead.
15846
15855
  * @see {@link either} for a version that uses `Either` instead.
@@ -26848,6 +26857,9 @@ export const Tag: <const Id extends string>(id: Id) => <
26848
26857
  return makeTagProxy(TagClass as any)
26849
26858
  }
26850
26859
 
26860
+ /** @internal */
26861
+ type MissingSelfGeneric = `Missing \`Self\` generic - use \`class Self extends Effect.Service<Self>()...\``
26862
+
26851
26863
  /**
26852
26864
  * Simplifies the creation and management of services in Effect by defining both
26853
26865
  * a `Tag` and a `Layer`.
@@ -26892,7 +26904,7 @@ export const Tag: <const Id extends string>(id: Id) => <
26892
26904
  * @category Context
26893
26905
  * @experimental might be up for breaking changes
26894
26906
  */
26895
- export const Service: <Self>() => {
26907
+ export const Service: <Self = never>() => [Self] extends [never] ? MissingSelfGeneric : {
26896
26908
  <
26897
26909
  const Key extends string,
26898
26910
  const Make extends
@@ -27065,7 +27077,7 @@ export const Service: <Self>() => {
27065
27077
 
27066
27078
  return proxy === true ? makeTagProxy(TagClass) : TagClass
27067
27079
  }
27068
- }
27080
+ } as any
27069
27081
 
27070
27082
  /**
27071
27083
  * @since 3.9.0
@@ -90,15 +90,15 @@ const unsafeMake = <A = unknown, E = unknown>(
90
90
  * ```ts
91
91
  * import { Effect, FiberHandle } from "effect"
92
92
  *
93
- * Effect.gen(function*(_) {
94
- * const handle = yield* _(FiberHandle.make())
93
+ * Effect.gen(function*() {
94
+ * const handle = yield* FiberHandle.make()
95
95
  *
96
96
  * // run some effects
97
- * yield* _(FiberHandle.run(handle, Effect.never))
97
+ * yield* FiberHandle.run(handle, Effect.never)
98
98
  * // this will interrupt the previous fiber
99
- * yield* _(FiberHandle.run(handle, Effect.never))
99
+ * yield* FiberHandle.run(handle, Effect.never)
100
100
  *
101
- * yield* _(Effect.sleep(1000))
101
+ * yield* Effect.sleep(1000)
102
102
  * }).pipe(
103
103
  * Effect.scoped // The fiber will be interrupted when the scope is closed
104
104
  * )
@@ -434,9 +434,9 @@ export const run: {
434
434
  * getAll: Effect.Effect<Array<unknown>>
435
435
  * }>("Users")
436
436
  *
437
- * Effect.gen(function*(_) {
438
- * const handle = yield* _(FiberHandle.make())
439
- * const run = yield* _(FiberHandle.runtime(handle)<Users>())
437
+ * Effect.gen(function*() {
438
+ * const handle = yield* FiberHandle.make()
439
+ * const run = yield* FiberHandle.runtime(handle)<Users>()
440
440
  *
441
441
  * // run an effect and set the fiber in the handle
442
442
  * run(Effect.andThen(Users, _ => _.getAll))