effect 3.11.2 → 3.11.4

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 (88) hide show
  1. package/dist/cjs/Arbitrary.js +18 -8
  2. package/dist/cjs/Arbitrary.js.map +1 -1
  3. package/dist/cjs/BigDecimal.js +4 -0
  4. package/dist/cjs/BigDecimal.js.map +1 -1
  5. package/dist/cjs/Context.js +47 -6
  6. package/dist/cjs/Context.js.map +1 -1
  7. package/dist/cjs/Cron.js +122 -68
  8. package/dist/cjs/Cron.js.map +1 -1
  9. package/dist/cjs/Effect.js +25 -5
  10. package/dist/cjs/Effect.js.map +1 -1
  11. package/dist/cjs/Function.js +1 -1
  12. package/dist/cjs/JSONSchema.js +1 -0
  13. package/dist/cjs/JSONSchema.js.map +1 -1
  14. package/dist/cjs/Micro.js +8 -5
  15. package/dist/cjs/Micro.js.map +1 -1
  16. package/dist/cjs/Schema.js +75 -42
  17. package/dist/cjs/Schema.js.map +1 -1
  18. package/dist/cjs/SchemaAST.js +91 -22
  19. package/dist/cjs/SchemaAST.js.map +1 -1
  20. package/dist/cjs/internal/core.js +6 -3
  21. package/dist/cjs/internal/core.js.map +1 -1
  22. package/dist/cjs/internal/effect/circular.js +2 -2
  23. package/dist/cjs/internal/effect/circular.js.map +1 -1
  24. package/dist/cjs/internal/fiberRuntime.js +1 -1
  25. package/dist/cjs/internal/fiberRuntime.js.map +1 -1
  26. package/dist/cjs/internal/mailbox.js +4 -4
  27. package/dist/cjs/internal/mailbox.js.map +1 -1
  28. package/dist/cjs/internal/version.js +1 -1
  29. package/dist/dts/BigDecimal.d.ts +4 -0
  30. package/dist/dts/BigDecimal.d.ts.map +1 -1
  31. package/dist/dts/Context.d.ts +47 -6
  32. package/dist/dts/Context.d.ts.map +1 -1
  33. package/dist/dts/Cron.d.ts +1 -1
  34. package/dist/dts/Cron.d.ts.map +1 -1
  35. package/dist/dts/Effect.d.ts +25 -5
  36. package/dist/dts/Effect.d.ts.map +1 -1
  37. package/dist/dts/Function.d.ts +1 -1
  38. package/dist/dts/Micro.d.ts +16 -11
  39. package/dist/dts/Micro.d.ts.map +1 -1
  40. package/dist/dts/Schema.d.ts +10 -5
  41. package/dist/dts/Schema.d.ts.map +1 -1
  42. package/dist/dts/SchemaAST.d.ts +9 -4
  43. package/dist/dts/SchemaAST.d.ts.map +1 -1
  44. package/dist/dts/internal/core.d.ts.map +1 -1
  45. package/dist/esm/Arbitrary.js +18 -8
  46. package/dist/esm/Arbitrary.js.map +1 -1
  47. package/dist/esm/BigDecimal.js +4 -0
  48. package/dist/esm/BigDecimal.js.map +1 -1
  49. package/dist/esm/Context.js +47 -6
  50. package/dist/esm/Context.js.map +1 -1
  51. package/dist/esm/Cron.js +121 -67
  52. package/dist/esm/Cron.js.map +1 -1
  53. package/dist/esm/Effect.js +25 -5
  54. package/dist/esm/Effect.js.map +1 -1
  55. package/dist/esm/Function.js +1 -1
  56. package/dist/esm/JSONSchema.js +1 -0
  57. package/dist/esm/JSONSchema.js.map +1 -1
  58. package/dist/esm/Micro.js +8 -5
  59. package/dist/esm/Micro.js.map +1 -1
  60. package/dist/esm/Schema.js +74 -41
  61. package/dist/esm/Schema.js.map +1 -1
  62. package/dist/esm/SchemaAST.js +88 -20
  63. package/dist/esm/SchemaAST.js.map +1 -1
  64. package/dist/esm/internal/core.js +2 -0
  65. package/dist/esm/internal/core.js.map +1 -1
  66. package/dist/esm/internal/effect/circular.js +2 -2
  67. package/dist/esm/internal/effect/circular.js.map +1 -1
  68. package/dist/esm/internal/fiberRuntime.js +1 -1
  69. package/dist/esm/internal/fiberRuntime.js.map +1 -1
  70. package/dist/esm/internal/mailbox.js +4 -4
  71. package/dist/esm/internal/mailbox.js.map +1 -1
  72. package/dist/esm/internal/version.js +1 -1
  73. package/package.json +1 -1
  74. package/src/Arbitrary.ts +21 -7
  75. package/src/BigDecimal.ts +4 -0
  76. package/src/Context.ts +47 -6
  77. package/src/Cron.ts +154 -66
  78. package/src/Effect.ts +25 -5
  79. package/src/Function.ts +1 -1
  80. package/src/JSONSchema.ts +1 -0
  81. package/src/Micro.ts +16 -11
  82. package/src/Schema.ts +105 -83
  83. package/src/SchemaAST.ts +107 -31
  84. package/src/internal/core.ts +8 -0
  85. package/src/internal/effect/circular.ts +2 -2
  86. package/src/internal/fiberRuntime.ts +1 -1
  87. package/src/internal/mailbox.ts +4 -4
  88. package/src/internal/version.ts +1 -1
package/src/Micro.ts CHANGED
@@ -4981,13 +4981,14 @@ export const whileLoop: <A, E, R>(options: {
4981
4981
  })
4982
4982
 
4983
4983
  /**
4984
- * For each element of the provided iterable, run the effect and collect the results.
4984
+ * For each element of the provided iterable, run the effect and collect the
4985
+ * results.
4985
4986
  *
4986
4987
  * If the `discard` option is set to `true`, the results will be discarded and
4987
4988
  * the effect will return `void`.
4988
4989
  *
4989
- * The `concurrency` option can be set to control how many effects are run in
4990
- * parallel. By default, the effects are run sequentially.
4990
+ * The `concurrency` option can be set to control how many effects are run
4991
+ * concurrently. By default, the effects are run sequentially.
4991
4992
  *
4992
4993
  * @since 3.4.0
4993
4994
  * @experimental
@@ -4995,13 +4996,14 @@ export const whileLoop: <A, E, R>(options: {
4995
4996
  */
4996
4997
  export const forEach: {
4997
4998
  /**
4998
- * For each element of the provided iterable, run the effect and collect the results.
4999
+ * For each element of the provided iterable, run the effect and collect the
5000
+ * results.
4999
5001
  *
5000
5002
  * If the `discard` option is set to `true`, the results will be discarded and
5001
5003
  * the effect will return `void`.
5002
5004
  *
5003
- * The `concurrency` option can be set to control how many effects are run in
5004
- * parallel. By default, the effects are run sequentially.
5005
+ * The `concurrency` option can be set to control how many effects are run
5006
+ * concurrently. By default, the effects are run sequentially.
5005
5007
  *
5006
5008
  * @since 3.4.0
5007
5009
  * @experimental
@@ -5016,13 +5018,14 @@ export const forEach: {
5016
5018
  }
5017
5019
  ): Micro<Array<B>, E, R>
5018
5020
  /**
5019
- * For each element of the provided iterable, run the effect and collect the results.
5021
+ * For each element of the provided iterable, run the effect and collect the
5022
+ * results.
5020
5023
  *
5021
5024
  * If the `discard` option is set to `true`, the results will be discarded and
5022
5025
  * the effect will return `void`.
5023
5026
  *
5024
- * The `concurrency` option can be set to control how many effects are run in
5025
- * parallel. By default, the effects are run sequentially.
5027
+ * The `concurrency` option can be set to control how many effects are run
5028
+ * concurrently. By default, the effects are run sequentially.
5026
5029
  *
5027
5030
  * @since 3.4.0
5028
5031
  * @experimental
@@ -5133,7 +5136,8 @@ export const forEach: {
5133
5136
  /**
5134
5137
  * Effectfully filter the elements of the provided iterable.
5135
5138
  *
5136
- * Use the `concurrency` option to control how many elements are processed in parallel.
5139
+ * Use the `concurrency` option to control how many elements are processed
5140
+ * concurrently.
5137
5141
  *
5138
5142
  * @since 3.4.0
5139
5143
  * @experimental
@@ -5152,7 +5156,8 @@ export const filter = <A, E, R>(iterable: Iterable<A>, f: (a: NoInfer<A>) => Mic
5152
5156
  /**
5153
5157
  * Effectfully filter the elements of the provided iterable.
5154
5158
  *
5155
- * Use the `concurrency` option to control how many elements are processed in parallel.
5159
+ * Use the `concurrency` option to control how many elements are processed
5160
+ * concurrently.
5156
5161
  *
5157
5162
  * @since 3.4.0
5158
5163
  * @experimental
package/src/Schema.ts CHANGED
@@ -689,9 +689,16 @@ const makeEnumsClass = <A extends EnumsDefinition>(
689
689
  */
690
690
  export const Enums = <A extends EnumsDefinition>(enums: A): Enums<A> => makeEnumsClass(enums)
691
691
 
692
- type Join<Params> = Params extends [infer Head, ...infer Tail] ?
693
- `${(Head extends Schema<infer A> ? A : Head) & (AST.LiteralValue)}${Join<Tail>}`
694
- : ""
692
+ type AppendType<
693
+ Template extends string,
694
+ Next
695
+ > = Next extends AST.LiteralValue ? `${Template}${Next}`
696
+ : Next extends Schema<infer A extends AST.LiteralValue, infer _I, infer _R> ? `${Template}${A}`
697
+ : never
698
+
699
+ type GetTemplateLiteralType<Params> = Params extends [...infer Init, infer Last] ?
700
+ AppendType<GetTemplateLiteralType<Init>, Last>
701
+ : ``
695
702
 
696
703
  /**
697
704
  * @category API interface
@@ -707,77 +714,69 @@ type TemplateLiteralParameter = Schema.AnyNoContext | AST.LiteralValue
707
714
  */
708
715
  export const TemplateLiteral = <Params extends array_.NonEmptyReadonlyArray<TemplateLiteralParameter>>(
709
716
  ...[head, ...tail]: Params
710
- ): TemplateLiteral<Join<Params>> => {
711
- let astOrs: ReadonlyArray<AST.TemplateLiteral | string> = getTemplateLiterals(
712
- getTemplateLiteralParameterAST(head)
713
- )
714
- for (const span of tail) {
715
- astOrs = array_.flatMap(
716
- astOrs,
717
- (a) => getTemplateLiterals(getTemplateLiteralParameterAST(span)).map((b) => combineTemplateLiterals(a, b))
718
- )
717
+ ): TemplateLiteral<GetTemplateLiteralType<Params>> => {
718
+ const spans: Array<AST.TemplateLiteralSpan> = []
719
+ let h = ""
720
+ let ts = tail
721
+
722
+ if (isSchema(head)) {
723
+ if (AST.isLiteral(head.ast)) {
724
+ h = String(head.ast.literal)
725
+ } else {
726
+ ts = [head, ...ts]
727
+ }
728
+ } else {
729
+ h = String(head)
719
730
  }
720
- return make(AST.Union.make(astOrs.map((astOr) => Predicate.isString(astOr) ? new AST.Literal(astOr) : astOr)))
721
- }
722
731
 
723
- const getTemplateLiteralParameterAST = (span: TemplateLiteralParameter): AST.AST =>
724
- isSchema(span) ? span.ast : new AST.Literal(String(span))
725
-
726
- const combineTemplateLiterals = (
727
- a: AST.TemplateLiteral | string,
728
- b: AST.TemplateLiteral | string
729
- ): AST.TemplateLiteral | string => {
730
- if (Predicate.isString(a)) {
731
- return Predicate.isString(b) ?
732
- a + b :
733
- new AST.TemplateLiteral(a + b.head, b.spans)
734
- }
735
- if (Predicate.isString(b)) {
736
- return new AST.TemplateLiteral(
737
- a.head,
738
- array_.modifyNonEmptyLast(
739
- a.spans,
740
- (span) => new AST.TemplateLiteralSpan(span.type, span.literal + b)
741
- )
742
- )
732
+ for (let i = 0; i < ts.length; i++) {
733
+ const item = ts[i]
734
+ if (isSchema(item)) {
735
+ if (i < ts.length - 1) {
736
+ const next = ts[i + 1]
737
+ if (isSchema(next)) {
738
+ if (AST.isLiteral(next.ast)) {
739
+ spans.push(new AST.TemplateLiteralSpan(item.ast, String(next.ast.literal)))
740
+ i++
741
+ continue
742
+ }
743
+ } else {
744
+ spans.push(new AST.TemplateLiteralSpan(item.ast, String(next)))
745
+ i++
746
+ continue
747
+ }
748
+ }
749
+ spans.push(new AST.TemplateLiteralSpan(item.ast, ""))
750
+ } else {
751
+ spans.push(new AST.TemplateLiteralSpan(new AST.Literal(item), ""))
752
+ }
743
753
  }
744
- return new AST.TemplateLiteral(
745
- a.head,
746
- array_.appendAll(
747
- array_.modifyNonEmptyLast(
748
- a.spans,
749
- (span) => new AST.TemplateLiteralSpan(span.type, span.literal + String(b.head))
750
- ),
751
- b.spans
752
- )
753
- )
754
- }
755
754
 
756
- const getTemplateLiterals = (
757
- ast: AST.AST
758
- ): ReadonlyArray<AST.TemplateLiteral | string> => {
759
- switch (ast._tag) {
760
- case "Literal":
761
- return [String(ast.literal)]
762
- case "NumberKeyword":
763
- case "StringKeyword":
764
- return [new AST.TemplateLiteral("", [new AST.TemplateLiteralSpan(ast, "")])]
765
- case "Union":
766
- return array_.flatMap(ast.types, getTemplateLiterals)
755
+ if (array_.isNonEmptyArray(spans)) {
756
+ return make(new AST.TemplateLiteral(h, spans))
757
+ } else {
758
+ return make(new AST.TemplateLiteral("", [new AST.TemplateLiteralSpan(new AST.Literal(h), "")]))
767
759
  }
768
- throw new Error(errors_.getSchemaUnsupportedLiteralSpanErrorMessage(ast))
769
760
  }
770
761
 
771
762
  type TemplateLiteralParserParameters = Schema.Any | AST.LiteralValue
772
763
 
773
- type TemplateLiteralParserParametersType<T> = T extends [infer Head, ...infer Tail] ?
774
- readonly [Head extends Schema<infer A, infer _I, infer _R> ? A : Head, ...TemplateLiteralParserParametersType<Tail>]
764
+ type GetTemplateLiteralParserType<Params> = Params extends [infer Head, ...infer Tail] ? readonly [
765
+ Head extends Schema<infer A, infer _I, infer _R> ? A : Head,
766
+ ...GetTemplateLiteralParserType<Tail>
767
+ ]
775
768
  : []
776
769
 
777
- type TemplateLiteralParserParametersEncoded<T> = T extends [infer Head, ...infer Tail] ? `${
778
- & (Head extends Schema<infer _A, infer I, infer _R> ? I : Head)
779
- & (AST.LiteralValue)}${TemplateLiteralParserParametersEncoded<Tail>}`
780
- : ""
770
+ type AppendEncoded<
771
+ Template extends string,
772
+ Next
773
+ > = Next extends AST.LiteralValue ? `${Template}${Next}`
774
+ : Next extends Schema<infer _A, infer I extends AST.LiteralValue, infer _R> ? `${Template}${I}`
775
+ : never
776
+
777
+ type GetTemplateLiteralParserEncoded<Params> = Params extends [...infer Init, infer Last] ?
778
+ AppendEncoded<GetTemplateLiteralParserEncoded<Init>, Last>
779
+ : ``
781
780
 
782
781
  /**
783
782
  * @category API interface
@@ -786,14 +785,20 @@ type TemplateLiteralParserParametersEncoded<T> = T extends [infer Head, ...infer
786
785
  export interface TemplateLiteralParser<Params extends array_.NonEmptyReadonlyArray<TemplateLiteralParserParameters>>
787
786
  extends
788
787
  Schema<
789
- TemplateLiteralParserParametersType<Params>,
790
- TemplateLiteralParserParametersEncoded<Params>,
788
+ GetTemplateLiteralParserType<Params>,
789
+ GetTemplateLiteralParserEncoded<Params>,
791
790
  Schema.Context<Params[number]>
792
791
  >
793
792
  {
794
793
  readonly params: Params
795
794
  }
796
795
 
796
+ const literalValueCoercions: Record<string, ((v: AST.LiteralValue) => AST.LiteralValue)> = {
797
+ bigint: (v: AST.LiteralValue) => Predicate.isString(v) ? BigInt(v) : v,
798
+ boolean: (v: AST.LiteralValue) => v === "true" ? true : v === "false" ? false : v,
799
+ null: (v: AST.LiteralValue) => v === "null" ? null : v
800
+ }
801
+
797
802
  /**
798
803
  * @category template literal
799
804
  * @since 3.10.0
@@ -803,35 +808,50 @@ export const TemplateLiteralParser = <Params extends array_.NonEmptyReadonlyArra
803
808
  ): TemplateLiteralParser<Params> => {
804
809
  const encodedSchemas: Array<Schema.Any> = []
805
810
  const typeSchemas: Array<Schema.Any> = []
806
- const numbers: Array<number> = []
811
+ const coercions: Record<number, ((v: AST.LiteralValue) => AST.LiteralValue) | undefined> = {}
807
812
  for (let i = 0; i < params.length; i++) {
808
- const p = params[i]
809
- if (isSchema(p)) {
810
- const encoded = encodedSchema(p)
813
+ const param = params[i]
814
+ if (isSchema(param)) {
815
+ const encoded = encodedSchema(param)
811
816
  if (AST.isNumberKeyword(encoded.ast)) {
812
- numbers.push(i)
817
+ coercions[i] = Number
813
818
  }
814
819
  encodedSchemas.push(encoded)
815
- typeSchemas.push(p)
820
+ typeSchemas.push(param)
816
821
  } else {
817
- const literal = Literal(p)
818
- encodedSchemas.push(literal)
819
- typeSchemas.push(literal)
822
+ const schema = Literal(param)
823
+ if (Predicate.isNumber(param)) {
824
+ coercions[i] = Number
825
+ } else if (Predicate.isBigInt(param)) {
826
+ coercions[i] = literalValueCoercions.bigint
827
+ } else if (Predicate.isBoolean(param)) {
828
+ coercions[i] = literalValueCoercions.boolean
829
+ } else if (Predicate.isNull(param)) {
830
+ coercions[i] = literalValueCoercions.null
831
+ }
832
+ encodedSchemas.push(schema)
833
+ typeSchemas.push(schema)
820
834
  }
821
835
  }
822
836
  const from = TemplateLiteral(...encodedSchemas as any)
823
837
  const re = AST.getTemplateLiteralCapturingRegExp(from.ast as AST.TemplateLiteral)
824
- return class TemplateLiteralParserClass extends transform(from, Tuple(...typeSchemas), {
838
+ return class TemplateLiteralParserClass extends transformOrFail(from, Tuple(...typeSchemas), {
825
839
  strict: false,
826
- decode: (s) => {
827
- const out: Array<number | string> = re.exec(s)!.slice(1, params.length + 1)
828
- for (let i = 0; i < numbers.length; i++) {
829
- const index = numbers[i]
830
- out[index] = Number(out[index])
840
+ decode: (s, _, ast) => {
841
+ const match = re.exec(s)
842
+ if (match) {
843
+ const out: Array<AST.LiteralValue> = match.slice(1, params.length + 1)
844
+ for (let i = 0; i < out.length; i++) {
845
+ const coerce = coercions[i]
846
+ if (coerce) {
847
+ out[i] = coerce(out[i])
848
+ }
849
+ }
850
+ return ParseResult.succeed(out)
831
851
  }
832
- return out
852
+ return ParseResult.fail(new ParseResult.Type(ast, s, `${re.source}: no match for ${JSON.stringify(s)}`))
833
853
  },
834
- encode: (tuple) => tuple.join("")
854
+ encode: (tuple) => ParseResult.succeed(tuple.join(""))
835
855
  }) {
836
856
  static params = params.slice()
837
857
  } as any
@@ -2617,6 +2637,8 @@ export interface TypeLiteral<
2617
2637
  ): Simplify<TypeLiteral.Type<Fields, Records>>
2618
2638
  }
2619
2639
 
2640
+ const preserveMissingMessageAnnotation = AST.whiteListAnnotations([AST.MissingMessageAnnotationId])
2641
+
2620
2642
  const getDefaultTypeLiteralAST = <
2621
2643
  Fields extends Struct.Fields,
2622
2644
  const Records extends IndexSignature.Records
@@ -2637,7 +2659,7 @@ const getDefaultTypeLiteralAST = <
2637
2659
  const type = ast.type
2638
2660
  const isOptional = ast.isOptional
2639
2661
  const toAnnotations = ast.annotations
2640
- from.push(new AST.PropertySignature(key, type, isOptional, true))
2662
+ from.push(new AST.PropertySignature(key, type, isOptional, true, preserveMissingMessageAnnotation(ast)))
2641
2663
  to.push(new AST.PropertySignature(key, AST.typeAST(type), isOptional, true, toAnnotations))
2642
2664
  pss.push(
2643
2665
  new AST.PropertySignature(key, type, isOptional, true, toAnnotations)
package/src/SchemaAST.ts CHANGED
@@ -1096,18 +1096,69 @@ export class Enums implements Annotated {
1096
1096
  */
1097
1097
  export const isEnums: (ast: AST) => ast is Enums = createASTGuard("Enums")
1098
1098
 
1099
+ type TemplateLiteralSpanBaseType = StringKeyword | NumberKeyword | Literal
1100
+
1101
+ type TemplateLiteralSpanType = TemplateLiteralSpanBaseType | Union<TemplateLiteralSpanType>
1102
+
1103
+ const isTemplateLiteralSpanType = (ast: AST): ast is TemplateLiteralSpanType => {
1104
+ switch (ast._tag) {
1105
+ case "Literal":
1106
+ case "NumberKeyword":
1107
+ case "StringKeyword":
1108
+ return true
1109
+ case "Union":
1110
+ return ast.types.every(isTemplateLiteralSpanType)
1111
+ }
1112
+ return false
1113
+ }
1114
+
1115
+ const templateLiteralSpanUnionTypeToString = (type: TemplateLiteralSpanType): string => {
1116
+ switch (type._tag) {
1117
+ case "Literal":
1118
+ return JSON.stringify(String(type.literal))
1119
+ case "StringKeyword":
1120
+ return "string"
1121
+ case "NumberKeyword":
1122
+ return "number"
1123
+ case "Union":
1124
+ return type.types.map(templateLiteralSpanUnionTypeToString).join(" | ")
1125
+ }
1126
+ }
1127
+
1128
+ const templateLiteralSpanTypeToString = (type: TemplateLiteralSpanType): string => {
1129
+ switch (type._tag) {
1130
+ case "Literal":
1131
+ return String(type.literal)
1132
+ case "StringKeyword":
1133
+ return "${string}"
1134
+ case "NumberKeyword":
1135
+ return "${number}"
1136
+ case "Union":
1137
+ return "${" + type.types.map(templateLiteralSpanUnionTypeToString).join(" | ") + "}"
1138
+ }
1139
+ }
1140
+
1099
1141
  /**
1100
1142
  * @category model
1101
1143
  * @since 3.10.0
1102
1144
  */
1103
1145
  export class TemplateLiteralSpan {
1104
- constructor(readonly type: StringKeyword | NumberKeyword, readonly literal: string) {}
1146
+ /**
1147
+ * @since 3.10.0
1148
+ */
1149
+ readonly type: TemplateLiteralSpanType
1150
+ constructor(type: AST, readonly literal: string) {
1151
+ if (isTemplateLiteralSpanType(type)) {
1152
+ this.type = type
1153
+ } else {
1154
+ throw new Error(errors_.getSchemaUnsupportedLiteralSpanErrorMessage(type))
1155
+ }
1156
+ }
1105
1157
  /**
1106
1158
  * @since 3.10.0
1107
1159
  */
1108
1160
  toString() {
1109
- const type = "${" + String(this.type) + "}"
1110
- return type + this.literal
1161
+ return templateLiteralSpanTypeToString(this.type) + this.literal
1111
1162
  }
1112
1163
  /**
1113
1164
  * @since 3.10.0
@@ -1154,7 +1205,7 @@ export class TemplateLiteral implements Annotated {
1154
1205
  }
1155
1206
 
1156
1207
  const formatTemplateLiteral = (ast: TemplateLiteral): string =>
1157
- "`" + ast.head + ast.spans.map((span) => String(span)).join("") +
1208
+ "`" + ast.head + ast.spans.map(String).join("") +
1158
1209
  "`"
1159
1210
 
1160
1211
  /**
@@ -1619,7 +1670,7 @@ export const unify = (candidates: ReadonlyArray<AST>): Array<AST> => {
1619
1670
  * @category model
1620
1671
  * @since 3.10.0
1621
1672
  */
1622
- export class Union implements Annotated {
1673
+ export class Union<M extends AST = AST> implements Annotated {
1623
1674
  static make = (types: ReadonlyArray<AST>, annotations?: Annotations): AST => {
1624
1675
  return isMembers(types) ? new Union(types, annotations) : types.length === 1 ? types[0] : neverKeyword
1625
1676
  }
@@ -1631,15 +1682,12 @@ export class Union implements Annotated {
1631
1682
  * @since 3.10.0
1632
1683
  */
1633
1684
  readonly _tag = "Union"
1634
- private constructor(readonly types: Members<AST>, readonly annotations: Annotations = {}) {}
1685
+ private constructor(readonly types: Members<M>, readonly annotations: Annotations = {}) {}
1635
1686
  /**
1636
1687
  * @since 3.10.0
1637
1688
  */
1638
1689
  toString() {
1639
- return Option.getOrElse(
1640
- getExpected(this),
1641
- () => this.types.map(String).join(" | ")
1642
- )
1690
+ return Option.getOrElse(getExpected(this), () => this.types.map(String).join(" | "))
1643
1691
  }
1644
1692
  /**
1645
1693
  * @since 3.10.0
@@ -2040,25 +2088,53 @@ export const keyof = (ast: AST): AST => Union.unify(_keyof(ast))
2040
2088
  const STRING_KEYWORD_PATTERN = ".*"
2041
2089
  const NUMBER_KEYWORD_PATTERN = "[+-]?\\d*\\.?\\d+(?:[Ee][+-]?\\d+)?"
2042
2090
 
2091
+ const getTemplateLiteralPattern = (type: TemplateLiteralSpanType): string => {
2092
+ switch (type._tag) {
2093
+ case "StringKeyword":
2094
+ return STRING_KEYWORD_PATTERN
2095
+ case "NumberKeyword":
2096
+ return NUMBER_KEYWORD_PATTERN
2097
+ case "Literal":
2098
+ return regexp.escape(String(type.literal))
2099
+ case "Union":
2100
+ return type.types.map(getTemplateLiteralPattern).join("|")
2101
+ }
2102
+ }
2103
+
2043
2104
  /**
2044
2105
  * @since 3.10.0
2045
2106
  */
2046
2107
  export const getTemplateLiteralRegExp = (ast: TemplateLiteral): RegExp => {
2047
- let pattern = `^${regexp.escape(ast.head)}`
2108
+ let pattern = `^`
2109
+ if (ast.head !== "") {
2110
+ pattern += regexp.escape(ast.head)
2111
+ }
2048
2112
 
2049
2113
  for (const span of ast.spans) {
2050
- if (isStringKeyword(span.type)) {
2051
- pattern += STRING_KEYWORD_PATTERN
2052
- } else if (isNumberKeyword(span.type)) {
2053
- pattern += NUMBER_KEYWORD_PATTERN
2114
+ const p = getTemplateLiteralPattern(span.type)
2115
+ pattern += isUnion(span.type) ? `(${p})` : p
2116
+ if (span.literal !== "") {
2117
+ pattern += regexp.escape(span.literal)
2054
2118
  }
2055
- pattern += regexp.escape(span.literal)
2056
2119
  }
2057
2120
 
2058
2121
  pattern += "$"
2059
2122
  return new RegExp(pattern)
2060
2123
  }
2061
2124
 
2125
+ const getTemplateLiteralCapturingPattern = (type: TemplateLiteralSpanType): string => {
2126
+ switch (type._tag) {
2127
+ case "StringKeyword":
2128
+ return STRING_KEYWORD_PATTERN
2129
+ case "NumberKeyword":
2130
+ return NUMBER_KEYWORD_PATTERN
2131
+ case "Literal":
2132
+ return regexp.escape(String(type.literal))
2133
+ case "Union":
2134
+ return type.types.map(getTemplateLiteralCapturingPattern).join("|")
2135
+ }
2136
+ }
2137
+
2062
2138
  /**
2063
2139
  * @since 3.10.0
2064
2140
  */
@@ -2069,11 +2145,7 @@ export const getTemplateLiteralCapturingRegExp = (ast: TemplateLiteral): RegExp
2069
2145
  }
2070
2146
 
2071
2147
  for (const span of ast.spans) {
2072
- if (isStringKeyword(span.type)) {
2073
- pattern += `(${STRING_KEYWORD_PATTERN})`
2074
- } else if (isNumberKeyword(span.type)) {
2075
- pattern += `(${NUMBER_KEYWORD_PATTERN})`
2076
- }
2148
+ pattern += `(${getTemplateLiteralCapturingPattern(span.type)})`
2077
2149
  if (span.literal !== "") {
2078
2150
  pattern += `(${regexp.escape(span.literal)})`
2079
2151
  }
@@ -2702,15 +2774,8 @@ export const getParameterBase = (
2702
2774
  }
2703
2775
  }
2704
2776
 
2705
- const equalsTemplateLiteralSpan = Arr.getEquivalence<TemplateLiteralSpan>((self, that) =>
2706
- self.type._tag === that.type._tag && self.literal === that.literal
2707
- )
2708
-
2709
- const equalsEnums = Arr.getEquivalence<readonly [string, string | number]>((self, that) =>
2710
- that[0] === self[0] && that[1] === self[1]
2711
- )
2712
-
2713
- const equals = (self: AST, that: AST) => {
2777
+ /** @internal */
2778
+ export const equals = (self: AST, that: AST): boolean => {
2714
2779
  switch (self._tag) {
2715
2780
  case "Literal":
2716
2781
  return isLiteral(that) && that.literal === self.literal
@@ -2732,10 +2797,11 @@ const equals = (self: AST, that: AST) => {
2732
2797
  return isTemplateLiteral(that) && that.head === self.head && equalsTemplateLiteralSpan(that.spans, self.spans)
2733
2798
  case "Enums":
2734
2799
  return isEnums(that) && equalsEnums(that.enums, self.enums)
2800
+ case "Union":
2801
+ return isUnion(that) && equalsUnion(self.types, that.types)
2735
2802
  case "Refinement":
2736
2803
  case "TupleType":
2737
2804
  case "TypeLiteral":
2738
- case "Union":
2739
2805
  case "Suspend":
2740
2806
  case "Transformation":
2741
2807
  case "Declaration":
@@ -2743,6 +2809,16 @@ const equals = (self: AST, that: AST) => {
2743
2809
  }
2744
2810
  }
2745
2811
 
2812
+ const equalsTemplateLiteralSpan = Arr.getEquivalence<TemplateLiteralSpan>((self, that): boolean => {
2813
+ return self.literal === that.literal && equals(self.type, that.type)
2814
+ })
2815
+
2816
+ const equalsEnums = Arr.getEquivalence<readonly [string, string | number]>((self, that) =>
2817
+ that[0] === self[0] && that[1] === self[1]
2818
+ )
2819
+
2820
+ const equalsUnion = Arr.getEquivalence<AST>(equals)
2821
+
2746
2822
  const intersection = Arr.intersectionWith(equals)
2747
2823
 
2748
2824
  const _keyof = (ast: AST): Array<AST> => {
@@ -528,6 +528,14 @@ export const unsafeAsync = <A, E = never, R = never>(
528
528
  return onInterrupt(effect, (_) => isEffect(cancelerRef) ? cancelerRef : void_)
529
529
  }
530
530
 
531
+ /* @internal */
532
+ export const asyncInterrupt = <A, E = never, R = never>(
533
+ register: (
534
+ callback: (_: Effect.Effect<A, E, R>) => void
535
+ ) => void | Effect.Effect<void, never, R>,
536
+ blockingOn: FiberId.FiberId = FiberId.none
537
+ ): Effect.Effect<A, E, R> => suspend(() => unsafeAsync(register, blockingOn))
538
+
531
539
  /* @internal */
532
540
  export const async = <A, E = never, R = never>(
533
541
  resume: (
@@ -47,7 +47,7 @@ class Semaphore {
47
47
  }
48
48
 
49
49
  readonly take = (n: number): Effect.Effect<number> =>
50
- core.async<number>((resume) => {
50
+ core.asyncInterrupt<number>((resume) => {
51
51
  if (this.free < n) {
52
52
  const observer = () => {
53
53
  if (this.free < n) {
@@ -153,7 +153,7 @@ class Latch extends Effectable.Class<void> implements Effect.Latch {
153
153
  }
154
154
  return this.unsafeSchedule(fiber)
155
155
  })
156
- await = core.unsafeAsync<void>((resume) => {
156
+ await = core.asyncInterrupt<void>((resume) => {
157
157
  if (this.isOpen) {
158
158
  return resume(core.void)
159
159
  }
@@ -1132,7 +1132,7 @@ export class FiberRuntime<in out A, in out E = never> extends Effectable.Class<A
1132
1132
  }
1133
1133
  }
1134
1134
  })
1135
- return core.async<void>((abortResume) => {
1135
+ return core.unsafeAsync<void>((abortResume) => {
1136
1136
  resume = (_: any) => {
1137
1137
  abortResume(core.void)
1138
1138
  }
@@ -299,7 +299,7 @@ class MailboxImpl<A, E> extends Effectable.Class<readonly [messages: Chunk.Chunk
299
299
  take: Effect<A, E | NoSuchElementException> = core.suspend(() =>
300
300
  this.unsafeTake() ?? core.zipRight(this.awaitTake, this.take)
301
301
  )
302
- await: Effect<void, E> = core.unsafeAsync<void, E>((resume) => {
302
+ await: Effect<void, E> = core.asyncInterrupt<void, E>((resume) => {
303
303
  if (this.state._tag === "Done") {
304
304
  return resume(this.state.exit)
305
305
  }
@@ -337,7 +337,7 @@ class MailboxImpl<A, E> extends Effectable.Class<readonly [messages: Chunk.Chunk
337
337
  }
338
338
 
339
339
  private offerRemainingSingle(message: A) {
340
- return core.unsafeAsync<boolean>((resume) => {
340
+ return core.asyncInterrupt<boolean>((resume) => {
341
341
  if (this.state._tag !== "Open") {
342
342
  return resume(exitFalse)
343
343
  }
@@ -351,7 +351,7 @@ class MailboxImpl<A, E> extends Effectable.Class<readonly [messages: Chunk.Chunk
351
351
  })
352
352
  }
353
353
  private offerRemainingArray(remaining: Array<A>) {
354
- return core.unsafeAsync<Chunk.Chunk<A>>((resume) => {
354
+ return core.asyncInterrupt<Chunk.Chunk<A>>((resume) => {
355
355
  if (this.state._tag !== "Open") {
356
356
  return resume(core.exitSucceed(Chunk.unsafeFromArray(remaining)))
357
357
  }
@@ -394,7 +394,7 @@ class MailboxImpl<A, E> extends Effectable.Class<readonly [messages: Chunk.Chunk
394
394
  }
395
395
  return false
396
396
  }
397
- private awaitTake = core.unsafeAsync<void, E>((resume) => {
397
+ private awaitTake = core.asyncInterrupt<void, E>((resume) => {
398
398
  if (this.state._tag === "Done") {
399
399
  return resume(this.state.exit)
400
400
  }
@@ -1,4 +1,4 @@
1
- let moduleVersion = "3.11.2"
1
+ let moduleVersion = "3.11.4"
2
2
 
3
3
  export const getCurrentVersion = () => moduleVersion
4
4