effect 3.5.8 → 3.6.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 (123) hide show
  1. package/DateTime/package.json +6 -0
  2. package/dist/cjs/Context.js.map +1 -1
  3. package/dist/cjs/DateTime.js +1514 -0
  4. package/dist/cjs/DateTime.js.map +1 -0
  5. package/dist/cjs/Effect.js +3 -3
  6. package/dist/cjs/Effect.js.map +1 -1
  7. package/dist/cjs/Either.js +3 -3
  8. package/dist/cjs/List.js.map +1 -1
  9. package/dist/cjs/Metric.js.map +1 -1
  10. package/dist/cjs/Micro.js +93 -41
  11. package/dist/cjs/Micro.js.map +1 -1
  12. package/dist/cjs/Option.js +3 -3
  13. package/dist/cjs/Predicate.js +8 -0
  14. package/dist/cjs/Predicate.js.map +1 -1
  15. package/dist/cjs/Random.js +16 -1
  16. package/dist/cjs/Random.js.map +1 -1
  17. package/dist/cjs/Stream.js +86 -7
  18. package/dist/cjs/Stream.js.map +1 -1
  19. package/dist/cjs/Struct.js +23 -1
  20. package/dist/cjs/Struct.js.map +1 -1
  21. package/dist/cjs/index.js +4 -2
  22. package/dist/cjs/index.js.map +1 -1
  23. package/dist/cjs/internal/configProvider.js.map +1 -1
  24. package/dist/cjs/internal/core.js +1 -1
  25. package/dist/cjs/internal/core.js.map +1 -1
  26. package/dist/cjs/internal/defaultServices.js +9 -2
  27. package/dist/cjs/internal/defaultServices.js.map +1 -1
  28. package/dist/cjs/internal/metric.js.map +1 -1
  29. package/dist/cjs/internal/stream/emit.js +73 -1
  30. package/dist/cjs/internal/stream/emit.js.map +1 -1
  31. package/dist/cjs/internal/stream.js +30 -22
  32. package/dist/cjs/internal/stream.js.map +1 -1
  33. package/dist/cjs/internal/version.js +1 -1
  34. package/dist/dts/ConfigProvider.d.ts +2 -2
  35. package/dist/dts/ConfigProvider.d.ts.map +1 -1
  36. package/dist/dts/Context.d.ts +3 -1
  37. package/dist/dts/Context.d.ts.map +1 -1
  38. package/dist/dts/DateTime.d.ts +1265 -0
  39. package/dist/dts/DateTime.d.ts.map +1 -0
  40. package/dist/dts/Effect.d.ts +18 -4
  41. package/dist/dts/Effect.d.ts.map +1 -1
  42. package/dist/dts/Either.d.ts +4 -4
  43. package/dist/dts/List.d.ts +2 -1
  44. package/dist/dts/List.d.ts.map +1 -1
  45. package/dist/dts/Metric.d.ts +1 -1
  46. package/dist/dts/Metric.d.ts.map +1 -1
  47. package/dist/dts/MetricRegistry.d.ts +1 -1
  48. package/dist/dts/MetricRegistry.d.ts.map +1 -1
  49. package/dist/dts/Micro.d.ts +60 -0
  50. package/dist/dts/Micro.d.ts.map +1 -1
  51. package/dist/dts/Option.d.ts +4 -4
  52. package/dist/dts/Predicate.d.ts +63 -2
  53. package/dist/dts/Predicate.d.ts.map +1 -1
  54. package/dist/dts/Random.d.ts +18 -0
  55. package/dist/dts/Random.d.ts.map +1 -1
  56. package/dist/dts/Stream.d.ts +95 -4
  57. package/dist/dts/Stream.d.ts.map +1 -1
  58. package/dist/dts/StreamEmit.d.ts +44 -0
  59. package/dist/dts/StreamEmit.d.ts.map +1 -1
  60. package/dist/dts/Struct.d.ts +21 -0
  61. package/dist/dts/Struct.d.ts.map +1 -1
  62. package/dist/dts/index.d.ts +4 -0
  63. package/dist/dts/index.d.ts.map +1 -1
  64. package/dist/dts/internal/core.d.ts.map +1 -1
  65. package/dist/dts/internal/defaultServices.d.ts.map +1 -1
  66. package/dist/dts/internal/stream.d.ts.map +1 -1
  67. package/dist/esm/Context.js.map +1 -1
  68. package/dist/esm/DateTime.js +1465 -0
  69. package/dist/esm/DateTime.js.map +1 -0
  70. package/dist/esm/Effect.js +4 -4
  71. package/dist/esm/Effect.js.map +1 -1
  72. package/dist/esm/Either.js +4 -4
  73. package/dist/esm/List.js.map +1 -1
  74. package/dist/esm/Metric.js.map +1 -1
  75. package/dist/esm/Micro.js +88 -38
  76. package/dist/esm/Micro.js.map +1 -1
  77. package/dist/esm/Option.js +4 -4
  78. package/dist/esm/Predicate.js +8 -0
  79. package/dist/esm/Predicate.js.map +1 -1
  80. package/dist/esm/Random.js +15 -0
  81. package/dist/esm/Random.js.map +1 -1
  82. package/dist/esm/Stream.js +84 -5
  83. package/dist/esm/Stream.js.map +1 -1
  84. package/dist/esm/Struct.js +21 -0
  85. package/dist/esm/Struct.js.map +1 -1
  86. package/dist/esm/index.js +4 -0
  87. package/dist/esm/index.js.map +1 -1
  88. package/dist/esm/internal/configProvider.js.map +1 -1
  89. package/dist/esm/internal/core.js +1 -1
  90. package/dist/esm/internal/core.js.map +1 -1
  91. package/dist/esm/internal/defaultServices.js +6 -0
  92. package/dist/esm/internal/defaultServices.js.map +1 -1
  93. package/dist/esm/internal/metric.js.map +1 -1
  94. package/dist/esm/internal/stream/emit.js +71 -0
  95. package/dist/esm/internal/stream/emit.js.map +1 -1
  96. package/dist/esm/internal/stream.js +24 -18
  97. package/dist/esm/internal/stream.js.map +1 -1
  98. package/dist/esm/internal/version.js +1 -1
  99. package/package.json +9 -1
  100. package/src/ConfigProvider.ts +2 -2
  101. package/src/Context.ts +3 -1
  102. package/src/DateTime.ts +2104 -0
  103. package/src/Effect.ts +28 -4
  104. package/src/Either.ts +4 -4
  105. package/src/List.ts +3 -2
  106. package/src/Metric.ts +1 -1
  107. package/src/MetricRegistry.ts +1 -1
  108. package/src/Micro.ts +117 -45
  109. package/src/Option.ts +4 -4
  110. package/src/Predicate.ts +68 -8
  111. package/src/Random.ts +24 -0
  112. package/src/Stream.ts +110 -5
  113. package/src/StreamEmit.ts +53 -0
  114. package/src/Struct.ts +22 -0
  115. package/src/index.ts +5 -0
  116. package/src/internal/configProvider.ts +20 -20
  117. package/src/internal/core.ts +37 -12
  118. package/src/internal/defaultServices.ts +14 -0
  119. package/src/internal/metric/registry.ts +1 -1
  120. package/src/internal/metric.ts +2 -2
  121. package/src/internal/stream/emit.ts +77 -0
  122. package/src/internal/stream.ts +86 -18
  123. package/src/internal/version.ts +1 -1
package/src/Stream.ts CHANGED
@@ -373,6 +373,46 @@ export const asyncEffect: <A, E = never, R = never>(
373
373
  } | undefined
374
374
  ) => Stream<A, E, R> = internal.asyncEffect
375
375
 
376
+ /**
377
+ * Creates a stream from an external push-based resource.
378
+ *
379
+ * You can use the `emit` helper to emit values to the stream. The `emit` helper
380
+ * returns a boolean indicating whether the value was emitted or not.
381
+ *
382
+ * You can also use the `emit` helper to signal the end of the stream by
383
+ * using apis such as `emit.end` or `emit.fail`.
384
+ *
385
+ * By default it uses an "unbounded" buffer size.
386
+ * You can customize the buffer size and strategy by passing an object as the
387
+ * second argument with the `bufferSize` and `strategy` fields.
388
+ *
389
+ * @example
390
+ * import { Effect, Stream } from "effect"
391
+ *
392
+ * Stream.asyncPush<string>((emit) =>
393
+ * Effect.acquireRelease(
394
+ * Effect.gen(function*() {
395
+ * yield* Effect.log("subscribing")
396
+ * return setInterval(() => emit.single("tick"), 1000)
397
+ * }),
398
+ * (handle) =>
399
+ * Effect.gen(function*() {
400
+ * yield* Effect.log("unsubscribing")
401
+ * clearInterval(handle)
402
+ * })
403
+ * ), { bufferSize: 16, strategy: "dropping" })
404
+ *
405
+ * @since 3.6.0
406
+ * @category constructors
407
+ */
408
+ export const asyncPush: <A, E = never, R = never>(
409
+ register: (emit: Emit.EmitOpsPush<E, A>) => Effect.Effect<unknown, never, R | Scope.Scope>,
410
+ options?: { readonly bufferSize: "unbounded" } | {
411
+ readonly bufferSize?: number | undefined
412
+ readonly strategy?: "dropping" | "sliding" | undefined
413
+ } | undefined
414
+ ) => Stream<A, E, Exclude<R, Scope.Scope>> = internal.asyncPush
415
+
376
416
  /**
377
417
  * Creates a stream from an asynchronous callback that can be called multiple
378
418
  * times. The registration of the callback itself returns an a scoped
@@ -2887,6 +2927,38 @@ export const mkString: <E, R>(self: Stream<string, E, R>) => Effect.Effect<strin
2887
2927
  */
2888
2928
  export const never: Stream<never> = internal.never
2889
2929
 
2930
+ /**
2931
+ * Adds an effect to be executed at the end of the stream.
2932
+ *
2933
+ * @example
2934
+ * import { Console, Effect, Stream } from "effect"
2935
+ *
2936
+ * const stream = Stream.make(1, 2, 3).pipe(
2937
+ * Stream.map((n) => n * 2),
2938
+ * Stream.tap((n) => Console.log(`after mapping: ${n}`)),
2939
+ * Stream.onEnd(Console.log("Stream ended"))
2940
+ * )
2941
+ *
2942
+ * Effect.runPromise(Stream.runCollect(stream)).then(console.log)
2943
+ * // after mapping: 2
2944
+ * // after mapping: 4
2945
+ * // after mapping: 6
2946
+ * // Stream ended
2947
+ * // { _id: 'Chunk', values: [ 2, 4, 6 ] }
2948
+ *
2949
+ * @since 3.6.0
2950
+ * @category sequencing
2951
+ */
2952
+ export const onEnd: {
2953
+ <_, E2, R2>(
2954
+ effect: Effect.Effect<_, E2, R2>
2955
+ ): <A, E, R>(self: Stream<A, E, R>) => Stream<A, E2 | E, R2 | R>
2956
+ <A, E, R, _, E2, R2>(
2957
+ self: Stream<A, E, R>,
2958
+ effect: Effect.Effect<_, E2, R2>
2959
+ ): Stream<A, E | E2, R | R2>
2960
+ } = internal.onEnd
2961
+
2890
2962
  /**
2891
2963
  * Runs the specified effect if this stream fails, providing the error to the
2892
2964
  * effect if it exists.
@@ -2918,6 +2990,38 @@ export const onDone: {
2918
2990
  <A, E, R, X, R2>(self: Stream<A, E, R>, cleanup: () => Effect.Effect<X, never, R2>): Stream<A, E, R | R2>
2919
2991
  } = internal.onDone
2920
2992
 
2993
+ /**
2994
+ * Adds an effect to be executed at the start of the stream.
2995
+ *
2996
+ * @example
2997
+ * import { Console, Effect, Stream } from "effect"
2998
+ *
2999
+ * const stream = Stream.make(1, 2, 3).pipe(
3000
+ * Stream.onStart(Console.log("Stream started")),
3001
+ * Stream.map((n) => n * 2),
3002
+ * Stream.tap((n) => Console.log(`after mapping: ${n}`))
3003
+ * )
3004
+ *
3005
+ * // Effect.runPromise(Stream.runCollect(stream)).then(console.log)
3006
+ * // Stream started
3007
+ * // after mapping: 2
3008
+ * // after mapping: 4
3009
+ * // after mapping: 6
3010
+ * // { _id: 'Chunk', values: [ 2, 4, 6 ] }
3011
+ *
3012
+ * @since 3.6.0
3013
+ * @category sequencing
3014
+ */
3015
+ export const onStart: {
3016
+ <_, E2, R2>(
3017
+ effect: Effect.Effect<_, E2, R2>
3018
+ ): <A, E, R>(self: Stream<A, E, R>) => Stream<A, E2 | E, R2 | R>
3019
+ <A, E, R, _, E2, R2>(
3020
+ self: Stream<A, E, R>,
3021
+ effect: Effect.Effect<_, E2, R2>
3022
+ ): Stream<A, E | E2, R | R2>
3023
+ } = internal.onStart
3024
+
2921
3025
  /**
2922
3026
  * Translates any failure into a stream termination, making the stream
2923
3027
  * infallible and all failures unchecked.
@@ -5676,11 +5780,11 @@ export const zipWithPreviousAndNext: <A, E, R>(
5676
5780
  export const zipWithIndex: <A, E, R>(self: Stream<A, E, R>) => Stream<[A, number], E, R> = internal.zipWithIndex
5677
5781
 
5678
5782
  // -------------------------------------------------------------------------------------
5679
- // Do notation
5783
+ // do notation
5680
5784
  // -------------------------------------------------------------------------------------
5681
5785
 
5682
5786
  /**
5683
- * The "do simulation" in allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
5787
+ * The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
5684
5788
  *
5685
5789
  * Here's how the do simulation works:
5686
5790
  *
@@ -5711,7 +5815,7 @@ export const zipWithIndex: <A, E, R>(self: Stream<A, E, R>) => Stream<[A, number
5711
5815
  export const Do: Stream<{}> = internal.Do
5712
5816
 
5713
5817
  /**
5714
- * The "do simulation" in allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
5818
+ * The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
5715
5819
  *
5716
5820
  * Here's how the do simulation works:
5717
5821
  *
@@ -5787,7 +5891,7 @@ export const bindEffect: {
5787
5891
  } = _groupBy.bindEffect
5788
5892
 
5789
5893
  /**
5790
- * The "do simulation" in allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
5894
+ * The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
5791
5895
  *
5792
5896
  * Here's how the do simulation works:
5793
5897
  *
@@ -5834,7 +5938,7 @@ const let_: {
5834
5938
 
5835
5939
  export {
5836
5940
  /**
5837
- * The "do simulation" in allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
5941
+ * The "do simulation" in Effect allows you to write code in a more declarative style, similar to the "do notation" in other programming languages. It provides a way to define variables and perform operations on them using functions like `bind` and `let`.
5838
5942
  *
5839
5943
  * Here's how the do simulation works:
5840
5944
  *
@@ -5923,5 +6027,6 @@ export const fromEventListener: <A = unknown>(
5923
6027
  readonly capture?: boolean
5924
6028
  readonly passive?: boolean
5925
6029
  readonly once?: boolean
6030
+ readonly bufferSize?: number | "unbounded" | undefined
5926
6031
  } | undefined
5927
6032
  ) => Stream<A> = internal.fromEventListener
package/src/StreamEmit.ts CHANGED
@@ -81,3 +81,56 @@ export interface EmitOps<in R, in E, in A, out B> {
81
81
  */
82
82
  single(value: A): Promise<B>
83
83
  }
84
+
85
+ /**
86
+ * @since 3.6.0
87
+ * @category models
88
+ */
89
+ export interface EmitOpsPush<in E, in A> {
90
+ /**
91
+ * Emits a chunk containing the specified values.
92
+ */
93
+ chunk(chunk: Chunk.Chunk<A>): boolean
94
+
95
+ /**
96
+ * Emits a chunk containing the specified values.
97
+ */
98
+ array(chunk: ReadonlyArray<A>): boolean
99
+
100
+ /**
101
+ * Terminates with a cause that dies with the specified defect.
102
+ */
103
+ die<Err>(defect: Err): void
104
+
105
+ /**
106
+ * Terminates with a cause that dies with a `Throwable` with the specified
107
+ * message.
108
+ */
109
+ dieMessage(message: string): void
110
+
111
+ /**
112
+ * Either emits the specified value if this `Exit` is a `Success` or else
113
+ * terminates with the specified cause if this `Exit` is a `Failure`.
114
+ */
115
+ done(exit: Exit.Exit<A, E>): void
116
+
117
+ /**
118
+ * Terminates with an end of stream signal.
119
+ */
120
+ end(): void
121
+
122
+ /**
123
+ * Terminates with the specified error.
124
+ */
125
+ fail(error: E): void
126
+
127
+ /**
128
+ * Terminates the stream with the specified cause.
129
+ */
130
+ halt(cause: Cause.Cause<E>): void
131
+
132
+ /**
133
+ * Emits a chunk containing the specified value.
134
+ */
135
+ single(value: A): boolean
136
+ }
package/src/Struct.ts CHANGED
@@ -179,3 +179,25 @@ export const evolve: {
179
179
  export const get =
180
180
  <K extends PropertyKey>(key: K) => <S extends { [P in K]?: any }>(s: S): MatchRecord<S, S[K] | undefined, S[K]> =>
181
181
  s[key]
182
+
183
+ /**
184
+ * Retrieves the object keys that are strings in a typed manner
185
+ *
186
+ * @example
187
+ * import { Struct } from "effect"
188
+ *
189
+ * const symbol: unique symbol = Symbol()
190
+ *
191
+ * const value = {
192
+ * a: 1,
193
+ * b: 2,
194
+ * [symbol]: 3
195
+ * }
196
+ *
197
+ * const keys: Array<"a" | "b"> = Struct.keys(value)
198
+ *
199
+ * assert.deepStrictEqual(keys, ["a", "b"])
200
+ *
201
+ * @since 3.6.0
202
+ */
203
+ export const keys = <T extends {}>(o: T): Array<(keyof T) & string> => Object.keys(o) as Array<(keyof T) & string>
package/src/index.ts CHANGED
@@ -187,6 +187,11 @@ export * as Cron from "./Cron.js"
187
187
  */
188
188
  export * as Data from "./Data.js"
189
189
 
190
+ /**
191
+ * @since 3.6.0
192
+ */
193
+ export * as DateTime from "./DateTime.js"
194
+
190
195
  /**
191
196
  * @since 2.0.0
192
197
  */
@@ -68,7 +68,7 @@ export const makeFlat = (
68
68
  path: ReadonlyArray<string>,
69
69
  config: Config.Config.Primitive<A>,
70
70
  split: boolean
71
- ) => Effect.Effect<ReadonlyArray<A>, ConfigError.ConfigError>
71
+ ) => Effect.Effect<Array<A>, ConfigError.ConfigError>
72
72
  readonly enumerateChildren: (
73
73
  path: ReadonlyArray<string>
74
74
  ) => Effect.Effect<HashSet.HashSet<string>, ConfigError.ConfigError>
@@ -114,7 +114,7 @@ export const fromEnv = (
114
114
  path: ReadonlyArray<string>,
115
115
  primitive: Config.Config.Primitive<A>,
116
116
  split = true
117
- ): Effect.Effect<ReadonlyArray<A>, ConfigError.ConfigError> => {
117
+ ): Effect.Effect<Array<A>, ConfigError.ConfigError> => {
118
118
  const pathString = makePathString(path)
119
119
  const current = getEnv()
120
120
  const valueOpt = pathString in current ? Option.some(current[pathString]!) : Option.none()
@@ -165,7 +165,7 @@ export const fromMap = (
165
165
  path: ReadonlyArray<string>,
166
166
  primitive: Config.Config.Primitive<A>,
167
167
  split = true
168
- ): Effect.Effect<ReadonlyArray<A>, ConfigError.ConfigError> => {
168
+ ): Effect.Effect<Array<A>, ConfigError.ConfigError> => {
169
169
  const pathString = makePathString(path)
170
170
  const valueOpt = mapWithIndexSplit.has(pathString) ?
171
171
  Option.some(mapWithIndexSplit.get(pathString)!) :
@@ -240,20 +240,20 @@ const fromFlatLoop = <A>(
240
240
  prefix: ReadonlyArray<string>,
241
241
  config: Config.Config<A>,
242
242
  split: boolean
243
- ): Effect.Effect<ReadonlyArray<A>, ConfigError.ConfigError> => {
243
+ ): Effect.Effect<Array<A>, ConfigError.ConfigError> => {
244
244
  const op = config as _config.ConfigPrimitive
245
245
  switch (op._tag) {
246
246
  case OpCodes.OP_CONSTANT: {
247
- return core.succeed(Arr.of(op.value)) as Effect.Effect<ReadonlyArray<A>, ConfigError.ConfigError>
247
+ return core.succeed(Arr.of(op.value)) as Effect.Effect<Array<A>, ConfigError.ConfigError>
248
248
  }
249
249
  case OpCodes.OP_DESCRIBED: {
250
250
  return core.suspend(
251
251
  () => fromFlatLoop(flat, prefix, op.config, split)
252
- ) as unknown as Effect.Effect<ReadonlyArray<A>, ConfigError.ConfigError>
252
+ ) as unknown as Effect.Effect<Array<A>, ConfigError.ConfigError>
253
253
  }
254
254
  case OpCodes.OP_FAIL: {
255
255
  return core.fail(configError.MissingData(prefix, op.message)) as Effect.Effect<
256
- ReadonlyArray<A>,
256
+ Array<A>,
257
257
  ConfigError.ConfigError
258
258
  >
259
259
  }
@@ -269,11 +269,11 @@ const fromFlatLoop = <A>(
269
269
  }
270
270
  return core.fail(error1)
271
271
  })
272
- ) as unknown as Effect.Effect<ReadonlyArray<A>, ConfigError.ConfigError>
272
+ ) as unknown as Effect.Effect<Array<A>, ConfigError.ConfigError>
273
273
  }
274
274
  case OpCodes.OP_LAZY: {
275
275
  return core.suspend(() => fromFlatLoop(flat, prefix, op.config(), split)) as Effect.Effect<
276
- ReadonlyArray<A>,
276
+ Array<A>,
277
277
  ConfigError.ConfigError
278
278
  >
279
279
  }
@@ -290,7 +290,7 @@ const fromFlatLoop = <A>(
290
290
  )
291
291
  )
292
292
  )
293
- ) as unknown as Effect.Effect<ReadonlyArray<A>, ConfigError.ConfigError>
293
+ ) as unknown as Effect.Effect<Array<A>, ConfigError.ConfigError>
294
294
  }
295
295
  case OpCodes.OP_NESTED: {
296
296
  return core.suspend(() =>
@@ -300,7 +300,7 @@ const fromFlatLoop = <A>(
300
300
  op.config,
301
301
  split
302
302
  )
303
- ) as unknown as Effect.Effect<ReadonlyArray<A>, ConfigError.ConfigError>
303
+ ) as unknown as Effect.Effect<Array<A>, ConfigError.ConfigError>
304
304
  }
305
305
  case OpCodes.OP_PRIMITIVE: {
306
306
  return pipe(
@@ -317,7 +317,7 @@ const fromFlatLoop = <A>(
317
317
  })
318
318
  )
319
319
  )
320
- ) as unknown as Effect.Effect<ReadonlyArray<A>, ConfigError.ConfigError>
320
+ ) as unknown as Effect.Effect<Array<A>, ConfigError.ConfigError>
321
321
  }
322
322
  case OpCodes.OP_SEQUENCE: {
323
323
  return pipe(
@@ -330,7 +330,7 @@ const fromFlatLoop = <A>(
330
330
  if (indices.length === 0) {
331
331
  return core.suspend(() =>
332
332
  core.map(fromFlatLoop(flat, patchedPrefix, op.config, true), Arr.of)
333
- ) as unknown as Effect.Effect<ReadonlyArray<A>, ConfigError.ConfigError>
333
+ ) as unknown as Effect.Effect<Array<A>, ConfigError.ConfigError>
334
334
  }
335
335
  return pipe(
336
336
  core.forEachSequential(
@@ -344,7 +344,7 @@ const fromFlatLoop = <A>(
344
344
  }
345
345
  return Arr.of(flattened)
346
346
  })
347
- ) as unknown as Effect.Effect<ReadonlyArray<A>, ConfigError.ConfigError>
347
+ ) as unknown as Effect.Effect<Array<A>, ConfigError.ConfigError>
348
348
  })
349
349
  )
350
350
  )
@@ -382,7 +382,7 @@ const fromFlatLoop = <A>(
382
382
  )
383
383
  )
384
384
  )
385
- ) as unknown as Effect.Effect<ReadonlyArray<A>, ConfigError.ConfigError>
385
+ ) as unknown as Effect.Effect<Array<A>, ConfigError.ConfigError>
386
386
  }
387
387
  case OpCodes.OP_ZIP_WITH: {
388
388
  return core.suspend(() =>
@@ -430,7 +430,7 @@ const fromFlatLoop = <A>(
430
430
  )
431
431
  )
432
432
  )
433
- ) as unknown as Effect.Effect<ReadonlyArray<A>, ConfigError.ConfigError>
433
+ ) as unknown as Effect.Effect<Array<A>, ConfigError.ConfigError>
434
434
  }
435
435
  }
436
436
  }
@@ -592,7 +592,7 @@ export const within = dual<
592
592
  return orElse(nest, () => self)
593
593
  })
594
594
 
595
- const splitPathString = (text: string, delim: string): ReadonlyArray<string> => {
595
+ const splitPathString = (text: string, delim: string): Array<string> => {
596
596
  const split = text.split(new RegExp(`\\s*${regexp.escape(delim)}\\s*`))
597
597
  return split
598
598
  }
@@ -603,7 +603,7 @@ const parsePrimitive = <A>(
603
603
  primitive: Config.Config.Primitive<A>,
604
604
  delimiter: string,
605
605
  split: boolean
606
- ): Effect.Effect<ReadonlyArray<A>, ConfigError.ConfigError> => {
606
+ ): Effect.Effect<Array<A>, ConfigError.ConfigError> => {
607
607
  if (!split) {
608
608
  return pipe(
609
609
  primitive.parse(text),
@@ -620,11 +620,11 @@ const parsePrimitive = <A>(
620
620
  )
621
621
  }
622
622
 
623
- const transpose = <A>(array: ReadonlyArray<ReadonlyArray<A>>): ReadonlyArray<ReadonlyArray<A>> => {
623
+ const transpose = <A>(array: ReadonlyArray<ReadonlyArray<A>>): Array<Array<A>> => {
624
624
  return Object.keys(array[0]).map((column) => array.map((row) => row[column as any]))
625
625
  }
626
626
 
627
- const indicesFrom = (quotedIndices: HashSet.HashSet<string>): Effect.Effect<ReadonlyArray<number>> =>
627
+ const indicesFrom = (quotedIndices: HashSet.HashSet<string>): Effect.Effect<Array<number>> =>
628
628
  pipe(
629
629
  core.forEachSequential(quotedIndices, parseQuotedIndex),
630
630
  core.mapBoth({
@@ -1250,6 +1250,12 @@ export const tap = dual<
1250
1250
  ) => [X] extends [Effect.Effect<infer _A1, infer E1, infer R1>] ? Effect.Effect<A, E | E1, R | R1>
1251
1251
  : [X] extends [PromiseLike<infer _A1>] ? Effect.Effect<A, E | Cause.UnknownException, R>
1252
1252
  : Effect.Effect<A, E, R>
1253
+ <A, X, E1, R1>(
1254
+ f: (a: NoInfer<A>) => Effect.Effect<X, E1, R1>,
1255
+ options: { onlyEffect: true }
1256
+ ): <E, R>(
1257
+ self: Effect.Effect<A, E, R>
1258
+ ) => Effect.Effect<A, E | E1, R | R1>
1253
1259
  <X>(
1254
1260
  f: NotFunction<X>
1255
1261
  ): <A, E, R>(
@@ -1257,6 +1263,12 @@ export const tap = dual<
1257
1263
  ) => [X] extends [Effect.Effect<infer _A1, infer E1, infer R1>] ? Effect.Effect<A, E | E1, R | R1>
1258
1264
  : [X] extends [PromiseLike<infer _A1>] ? Effect.Effect<A, E | Cause.UnknownException, R>
1259
1265
  : Effect.Effect<A, E, R>
1266
+ <X, E1, R1>(
1267
+ f: Effect.Effect<X, E1, R1>,
1268
+ options: { onlyEffect: true }
1269
+ ): <A, E, R>(
1270
+ self: Effect.Effect<A, E, R>
1271
+ ) => Effect.Effect<A, E | E1, R | R1>
1260
1272
  },
1261
1273
  {
1262
1274
  <A, E, R, X>(
@@ -1265,25 +1277,38 @@ export const tap = dual<
1265
1277
  ): [X] extends [Effect.Effect<infer _A1, infer E1, infer R1>] ? Effect.Effect<A, E | E1, R | R1>
1266
1278
  : [X] extends [PromiseLike<infer _A1>] ? Effect.Effect<A, E | Cause.UnknownException, R>
1267
1279
  : Effect.Effect<A, E, R>
1280
+ <A, E, R, X, E1, R1>(
1281
+ self: Effect.Effect<A, E, R>,
1282
+ f: (a: NoInfer<A>) => Effect.Effect<X, E1, R1>,
1283
+ options: { onlyEffect: true }
1284
+ ): Effect.Effect<A, E | E1, R | R1>
1268
1285
  <A, E, R, X>(
1269
1286
  self: Effect.Effect<A, E, R>,
1270
1287
  f: NotFunction<X>
1271
1288
  ): [X] extends [Effect.Effect<infer _A1, infer E1, infer R1>] ? Effect.Effect<A, E | E1, R | R1>
1272
1289
  : [X] extends [PromiseLike<infer _A1>] ? Effect.Effect<A, E | Cause.UnknownException, R>
1273
1290
  : Effect.Effect<A, E, R>
1291
+ <A, E, R, X, E1, R1>(
1292
+ self: Effect.Effect<A, E, R>,
1293
+ f: Effect.Effect<X, E1, R1>,
1294
+ options: { onlyEffect: true }
1295
+ ): Effect.Effect<A, E | E1, R | R1>
1274
1296
  }
1275
- >(2, (self, f) =>
1276
- flatMap(self, (a) => {
1277
- const b = typeof f === "function" ? (f as any)(a) : f
1278
- if (isEffect(b)) {
1279
- return as(b, a)
1280
- } else if (isPromiseLike(b)) {
1281
- return async<any, Cause.UnknownException>((resume) => {
1282
- b.then((_) => resume(succeed(a)), (e) => resume(fail(new UnknownException(e))))
1283
- })
1284
- }
1285
- return succeed(a)
1286
- }))
1297
+ >(
1298
+ (args) => args.length === 3 || args.length === 2 && !(isObject(args[1]) && "onlyEffect" in args[1]),
1299
+ <A, E, R, X>(self: Effect.Effect<A, E, R>, f: X) =>
1300
+ flatMap(self, (a) => {
1301
+ const b = typeof f === "function" ? (f as any)(a) : f
1302
+ if (isEffect(b)) {
1303
+ return as(b, a)
1304
+ } else if (isPromiseLike(b)) {
1305
+ return async<any, Cause.UnknownException>((resume) => {
1306
+ b.then((_) => resume(succeed(a)), (e) => resume(fail(new UnknownException(e))))
1307
+ })
1308
+ }
1309
+ return succeed(a)
1310
+ })
1311
+ )
1287
1312
 
1288
1313
  /* @internal */
1289
1314
  export const transplant = <A, E, R>(
@@ -1,3 +1,4 @@
1
+ import * as Array from "../Array.js"
1
2
  import type * as Chunk from "../Chunk.js"
2
3
  import type * as Clock from "../Clock.js"
3
4
  import type * as Config from "../Config.js"
@@ -133,6 +134,19 @@ export const nextIntBetween = (min: number, max: number): Effect.Effect<number>
133
134
  export const shuffle = <A>(elements: Iterable<A>): Effect.Effect<Chunk.Chunk<A>> =>
134
135
  randomWith((random) => random.shuffle(elements))
135
136
 
137
+ /** @internal */
138
+ export const choice = <Self extends Iterable<unknown>>(
139
+ elements: Self
140
+ ) => {
141
+ const array = Array.fromIterable(elements)
142
+ return core.map(
143
+ array.length === 0
144
+ ? core.fail(new core.NoSuchElementException("Cannot select a random element from an empty array"))
145
+ : randomWith((random) => random.nextIntBetween(0, array.length)),
146
+ (i) => array[i]
147
+ ) as any
148
+ }
149
+
136
150
  // circular with Tracer
137
151
 
138
152
  /** @internal */
@@ -27,7 +27,7 @@ class MetricRegistryImpl implements MetricRegistry.MetricRegistry {
27
27
  MetricHook.MetricHook.Root
28
28
  >()
29
29
 
30
- snapshot(): ReadonlyArray<MetricPair.MetricPair.Untyped> {
30
+ snapshot(): Array<MetricPair.MetricPair.Untyped> {
31
31
  const result: Array<MetricPair.MetricPair.Untyped> = []
32
32
  for (const [key, hook] of this.map) {
33
33
  result.push(metricPair.unsafeMake(key, hook.get()))
@@ -525,9 +525,9 @@ export const zip = dual<
525
525
  )
526
526
 
527
527
  /** @internal */
528
- export const unsafeSnapshot = (): ReadonlyArray<MetricPair.MetricPair.Untyped> => globalMetricRegistry.snapshot()
528
+ export const unsafeSnapshot = (): Array<MetricPair.MetricPair.Untyped> => globalMetricRegistry.snapshot()
529
529
 
530
530
  /** @internal */
531
- export const snapshot: Effect.Effect<ReadonlyArray<MetricPair.MetricPair.Untyped>> = core.sync(
531
+ export const snapshot: Effect.Effect<Array<MetricPair.MetricPair.Untyped>> = core.sync(
532
532
  unsafeSnapshot
533
533
  )
@@ -4,6 +4,8 @@ import * as Effect from "../../Effect.js"
4
4
  import * as Exit from "../../Exit.js"
5
5
  import { pipe } from "../../Function.js"
6
6
  import * as Option from "../../Option.js"
7
+ import type * as Queue from "../../Queue.js"
8
+ import type * as Scheduler from "../../Scheduler.js"
7
9
  import type * as Emit from "../../StreamEmit.js"
8
10
 
9
11
  /** @internal */
@@ -44,3 +46,78 @@ export const make = <R, E, A, B>(
44
46
  }
45
47
  return Object.assign(emit, ops)
46
48
  }
49
+
50
+ /** @internal */
51
+ export const makePush = <E, A>(
52
+ queue: Queue.Queue<Array<A> | Exit.Exit<void, E>>,
53
+ scheduler: Scheduler.Scheduler
54
+ ): Emit.EmitOpsPush<E, A> => {
55
+ let finished = false
56
+ let buffer: Array<A> = []
57
+ let running = false
58
+ function array(items: ReadonlyArray<A>) {
59
+ if (finished) return false
60
+ if (items.length <= 50_000) {
61
+ buffer.push.apply(buffer, items as Array<A>)
62
+ } else {
63
+ for (let i = 0; i < items.length; i++) {
64
+ buffer.push(items[0])
65
+ }
66
+ }
67
+ if (!running) {
68
+ running = true
69
+ scheduler.scheduleTask(flush, 0)
70
+ }
71
+ return true
72
+ }
73
+ function flush() {
74
+ running = false
75
+ if (buffer.length > 0) {
76
+ queue.unsafeOffer(buffer)
77
+ buffer = []
78
+ }
79
+ }
80
+ function done(exit: Exit.Exit<A, E>) {
81
+ if (finished) return
82
+ finished = true
83
+ if (exit._tag === "Success") {
84
+ buffer.push(exit.value)
85
+ }
86
+ flush()
87
+ queue.unsafeOffer(exit._tag === "Success" ? Exit.void : exit)
88
+ }
89
+ return {
90
+ single(value: A) {
91
+ if (finished) return false
92
+ buffer.push(value)
93
+ if (!running) {
94
+ running = true
95
+ scheduler.scheduleTask(flush, 0)
96
+ }
97
+ return true
98
+ },
99
+ array,
100
+ chunk(chunk) {
101
+ return array(Chunk.toReadonlyArray(chunk))
102
+ },
103
+ done,
104
+ end() {
105
+ if (finished) return
106
+ finished = true
107
+ flush()
108
+ queue.unsafeOffer(Exit.void)
109
+ },
110
+ halt(cause: Cause.Cause<E>) {
111
+ return done(Exit.failCause(cause))
112
+ },
113
+ fail(error: E) {
114
+ return done(Exit.fail(error))
115
+ },
116
+ die<Err>(defect: Err): void {
117
+ return done(Exit.die(defect))
118
+ },
119
+ dieMessage(message: string): void {
120
+ return done(Exit.die(new Error(message)))
121
+ }
122
+ }
123
+ }