effect 3.22.0 → 3.22.1

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 (56) hide show
  1. package/dist/cjs/Context.js +1 -1
  2. package/dist/cjs/Mailbox.js +3 -2
  3. package/dist/cjs/Mailbox.js.map +1 -1
  4. package/dist/cjs/ParseResult.js +18 -0
  5. package/dist/cjs/ParseResult.js.map +1 -1
  6. package/dist/cjs/internal/config.js +5 -1
  7. package/dist/cjs/internal/config.js.map +1 -1
  8. package/dist/cjs/internal/configProvider.js +14 -1
  9. package/dist/cjs/internal/configProvider.js.map +1 -1
  10. package/dist/cjs/internal/effect/circular.js +5 -4
  11. package/dist/cjs/internal/effect/circular.js.map +1 -1
  12. package/dist/cjs/internal/mailbox.js +11 -19
  13. package/dist/cjs/internal/mailbox.js.map +1 -1
  14. package/dist/cjs/internal/opCodes/config.js +3 -1
  15. package/dist/cjs/internal/opCodes/config.js.map +1 -1
  16. package/dist/cjs/internal/stream/emit.js +6 -34
  17. package/dist/cjs/internal/stream/emit.js.map +1 -1
  18. package/dist/cjs/internal/stream.js +26 -16
  19. package/dist/cjs/internal/stream.js.map +1 -1
  20. package/dist/cjs/internal/version.js +1 -1
  21. package/dist/dts/Context.d.ts +1 -1
  22. package/dist/dts/Mailbox.d.ts.map +1 -1
  23. package/dist/dts/ParseResult.d.ts.map +1 -1
  24. package/dist/dts/internal/stream.d.ts.map +1 -1
  25. package/dist/esm/Context.js +1 -1
  26. package/dist/esm/Mailbox.js +3 -2
  27. package/dist/esm/Mailbox.js.map +1 -1
  28. package/dist/esm/ParseResult.js +18 -0
  29. package/dist/esm/ParseResult.js.map +1 -1
  30. package/dist/esm/internal/config.js +5 -1
  31. package/dist/esm/internal/config.js.map +1 -1
  32. package/dist/esm/internal/configProvider.js +14 -1
  33. package/dist/esm/internal/configProvider.js.map +1 -1
  34. package/dist/esm/internal/effect/circular.js +5 -4
  35. package/dist/esm/internal/effect/circular.js.map +1 -1
  36. package/dist/esm/internal/mailbox.js +10 -17
  37. package/dist/esm/internal/mailbox.js.map +1 -1
  38. package/dist/esm/internal/opCodes/config.js +2 -0
  39. package/dist/esm/internal/opCodes/config.js.map +1 -1
  40. package/dist/esm/internal/stream/emit.js +6 -34
  41. package/dist/esm/internal/stream/emit.js.map +1 -1
  42. package/dist/esm/internal/stream.js +22 -13
  43. package/dist/esm/internal/stream.js.map +1 -1
  44. package/dist/esm/internal/version.js +1 -1
  45. package/package.json +1 -1
  46. package/src/Context.ts +1 -1
  47. package/src/Mailbox.ts +3 -2
  48. package/src/ParseResult.ts +18 -0
  49. package/src/internal/config.ts +14 -1
  50. package/src/internal/configProvider.ts +24 -1
  51. package/src/internal/effect/circular.ts +5 -4
  52. package/src/internal/mailbox.ts +13 -52
  53. package/src/internal/opCodes/config.ts +6 -0
  54. package/src/internal/stream/emit.ts +7 -39
  55. package/src/internal/stream.ts +62 -24
  56. package/src/internal/version.ts +1 -1
@@ -1,4 +1,4 @@
1
- let moduleVersion = "3.22.0";
1
+ let moduleVersion = "3.22.1";
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.22.0",
3
+ "version": "3.22.1",
4
4
  "description": "The missing standard library for TypeScript, for writing production-grade software.",
5
5
  "license": "MIT",
6
6
  "repository": {
package/src/Context.ts CHANGED
@@ -165,7 +165,7 @@ export declare namespace Tag {
165
165
  }
166
166
 
167
167
  /**
168
- * Creates a new `Tag` instance with an optional key parameter.
168
+ * Creates a new `Tag` instance with the specified key.
169
169
  *
170
170
  * @example
171
171
  * ```ts
package/src/Mailbox.ts CHANGED
@@ -9,6 +9,7 @@ import type { Effect } from "./Effect.js"
9
9
  import type { Exit } from "./Exit.js"
10
10
  import type { Inspectable } from "./Inspectable.js"
11
11
  import * as internal from "./internal/mailbox.js"
12
+ import * as internalStream from "./internal/stream.js"
12
13
  import type { Option } from "./Option.js"
13
14
  import { hasProperty } from "./Predicate.js"
14
15
  import type { Scope } from "./Scope.js"
@@ -258,7 +259,7 @@ export const toChannel: <A, E>(self: ReadonlyMailbox<A, E>) => Channel<Chunk<A>,
258
259
  * @experimental
259
260
  * @category conversions
260
261
  */
261
- export const toStream: <A, E>(self: ReadonlyMailbox<A, E>) => Stream<A, E> = internal.toStream
262
+ export const toStream: <A, E>(self: ReadonlyMailbox<A, E>) => Stream<A, E> = internalStream.mailboxToStream
262
263
 
263
264
  /**
264
265
  * Create a `ReadonlyMailbox` from a `Stream`.
@@ -295,4 +296,4 @@ export const fromStream: {
295
296
  readonly strategy?: "suspend" | "dropping" | "sliding" | undefined
296
297
  }
297
298
  ): Effect<ReadonlyMailbox<A, E>, never, R | Scope>
298
- } = internal.fromStream
299
+ } = internalStream.mailboxFromStream
@@ -914,6 +914,24 @@ const go = (ast: AST.AST, isDecoding: boolean): Parser => {
914
914
  case "Enums":
915
915
  return fromRefinement(ast, (u): u is any => ast.enums.some(([_, value]) => value === u))
916
916
  case "TemplateLiteral": {
917
+ if (ast.spans.every((span) => AST.isStringKeyword(span.type))) {
918
+ return fromRefinement(ast, (u): u is any => {
919
+ if (!Predicate.isString(u) || !u.startsWith(ast.head)) {
920
+ return false
921
+ }
922
+ let position = ast.head.length
923
+ for (let i = 0; i < ast.spans.length - 1; i++) {
924
+ const literal = ast.spans[i].literal
925
+ const index = u.indexOf(literal, position)
926
+ if (index === -1) {
927
+ return false
928
+ }
929
+ position = index + literal.length
930
+ }
931
+ const literal = ast.spans[ast.spans.length - 1].literal
932
+ return u.endsWith(literal) && u.length - literal.length >= position
933
+ })
934
+ }
917
935
  const regex = AST.getTemplateLiteralRegExp(ast)
918
936
  return fromRefinement(ast, (u): u is any => Predicate.isString(u) && regex.test(u))
919
937
  }
@@ -39,6 +39,7 @@ export type ConfigPrimitive =
39
39
  | MapOrFail
40
40
  | Nested
41
41
  | Primitive
42
+ | RedactedConfig
42
43
  | Sequence
43
44
  | Table
44
45
  | Zipped
@@ -125,6 +126,14 @@ export interface Primitive extends
125
126
  }>
126
127
  {}
127
128
 
129
+ /** @internal */
130
+ export interface RedactedConfig extends
131
+ Op<OpCodes.OP_REDACTED, {
132
+ readonly original: Config.Config<unknown>
133
+ redact(value: unknown): Redacted.Redacted<unknown>
134
+ }>
135
+ {}
136
+
128
137
  /** @internal */
129
138
  export interface Sequence extends
130
139
  Op<OpCodes.OP_SEQUENCE, {
@@ -475,7 +484,11 @@ export const redacted = <A>(
475
484
  nameOrConfig?: string | Config.Config<A>
476
485
  ): Config.Config<Redacted.Redacted<A | string>> => {
477
486
  const config: Config.Config<A | string> = isConfig(nameOrConfig) ? nameOrConfig : string(nameOrConfig)
478
- return map(config, redacted_.make)
487
+ const redacted = Object.create(proto)
488
+ redacted._tag = OpCodes.OP_REDACTED
489
+ redacted.original = config
490
+ redacted.redact = redacted_.make
491
+ return redacted
479
492
  }
480
493
 
481
494
  /** @internal */
@@ -236,6 +236,18 @@ const appendConfigPath = (path: ReadonlyArray<string>, config: Config.Config<unk
236
236
  return path
237
237
  }
238
238
 
239
+ const RedactedConfigErrorReducer: ConfigError.ConfigErrorReducer<unknown, ConfigError.ConfigError> = {
240
+ andCase: (_, left, right) => configError.And(left, right),
241
+ orCase: (_, left, right) => configError.Or(left, right),
242
+ invalidDataCase: (_, path) => configError.InvalidData(path, "<redacted>"),
243
+ missingDataCase: (_, path) => configError.MissingData(path, "<redacted>"),
244
+ sourceUnavailableCase: (_, path, _message, cause) => configError.SourceUnavailable(path, "<redacted>", cause),
245
+ unsupportedCase: (_, path) => configError.Unsupported(path, "<redacted>")
246
+ }
247
+
248
+ const redactConfigError = (error: ConfigError.ConfigError): ConfigError.ConfigError =>
249
+ configError.reduceWithContext(error, void 0, RedactedConfigErrorReducer)
250
+
239
251
  const fromFlatLoop = <A>(
240
252
  flat: ConfigProvider.ConfigProvider.Flat,
241
253
  prefix: ReadonlyArray<string>,
@@ -320,6 +332,15 @@ const fromFlatLoop = <A>(
320
332
  )
321
333
  ) as unknown as Effect.Effect<Array<A>, ConfigError.ConfigError>
322
334
  }
335
+ case OpCodes.OP_REDACTED: {
336
+ return core.suspend(() =>
337
+ pipe(
338
+ fromFlatLoop(flat, prefix, op.original, split),
339
+ core.mapError(redactConfigError),
340
+ core.map(Arr.map(op.redact))
341
+ )
342
+ ) as unknown as Effect.Effect<Array<A>, ConfigError.ConfigError>
343
+ }
323
344
  case OpCodes.OP_SEQUENCE: {
324
345
  return pipe(
325
346
  pathPatch.patch(prefix, flat.patch),
@@ -719,7 +740,9 @@ interface JsonArray extends Array<string | number | boolean | null | JsonArray |
719
740
  export const fromJson = (json: unknown): ConfigProvider.ConfigProvider => {
720
741
  const hiddenDelimiter = "\ufeff"
721
742
  const indexedEntries = Arr.map(
722
- getIndexedEntries(json as JsonMap),
743
+ getIndexedEntries(json as JsonMap).filter(([path]) =>
744
+ path.every((component) => component._tag === "KeyIndex" || !component.name.includes(hiddenDelimiter))
745
+ ),
723
746
  ([key, value]): [string, string] => [configPathToString(key).join(hiddenDelimiter), value]
724
747
  )
725
748
  return fromMap(new Map(indexedEntries), {
@@ -604,26 +604,27 @@ export const timeoutTo = dual<
604
604
  core.fiberIdWith((parentFiberId) =>
605
605
  core.uninterruptibleMask((restore) =>
606
606
  fiberRuntime.raceFibersWith(
607
- restore(self),
607
+ core.exit(restore(self)),
608
608
  core.interruptible(effect.sleep(duration)),
609
609
  {
610
610
  onSelfWin: (winner, loser) =>
611
611
  core.flatMap(
612
612
  winner.await,
613
613
  (exit) => {
614
- if (exit._tag === "Success") {
614
+ const selfExit = core.exitFlatten(exit)
615
+ if (selfExit._tag === "Success") {
615
616
  return core.flatMap(
616
617
  winner.inheritAll,
617
618
  () =>
618
619
  core.as(
619
620
  core.interruptAsFiber(loser, parentFiberId),
620
- onSuccess(exit.value)
621
+ onSuccess(selfExit.value)
621
622
  )
622
623
  )
623
624
  } else {
624
625
  return core.flatMap(
625
626
  core.interruptAsFiber(loser, parentFiberId),
626
- () => core.exitFailCause(exit.cause)
627
+ () => core.exitFailCause(selfExit.cause)
627
628
  )
628
629
  }
629
630
  }
@@ -13,15 +13,9 @@ import * as Option from "../Option.js"
13
13
  import { pipeArguments } from "../Pipeable.js"
14
14
  import { hasProperty } from "../Predicate.js"
15
15
  import type { Scheduler } from "../Scheduler.js"
16
- import type { Scope } from "../Scope.js"
17
- import type { Stream } from "../Stream.js"
18
16
  import * as channel from "./channel.js"
19
- import * as channelExecutor from "./channel/channelExecutor.js"
20
17
  import * as coreChannel from "./core-stream.js"
21
18
  import * as core from "./core.js"
22
- import * as circular from "./effect/circular.js"
23
- import * as fiberRuntime from "./fiberRuntime.js"
24
- import * as stream from "./stream.js"
25
19
 
26
20
  /** @internal */
27
21
  export const TypeId: Api.TypeId = Symbol.for("effect/Mailbox") as Api.TypeId
@@ -255,8 +249,17 @@ class MailboxImpl<A, E> extends Effectable.Class<readonly [messages: Chunk.Chunk
255
249
  return core.exitAs(this.state.exit, constDone)
256
250
  } else if (n <= 0) {
257
251
  return core.succeed([empty, false])
252
+ } else if (
253
+ this.capacity <= 0 && this.messages.length === 0 && this.messagesChunk.length === 0 &&
254
+ this.state.offers.size > 0
255
+ ) {
256
+ this.capacity = 1
257
+ this.releaseCapacity()
258
+ this.capacity = 0
259
+ const messages = Chunk.of(this.messages.pop()!)
260
+ return core.succeed([messages, this.releaseCapacity()])
258
261
  }
259
- n = Math.min(n, this.capacity)
262
+ n = Math.min(n, this.capacity || 1)
260
263
  let messages: Chunk.Chunk<A>
261
264
  if (n <= this.messagesChunk.length) {
262
265
  messages = Chunk.take(this.messagesChunk, n)
@@ -288,7 +291,9 @@ class MailboxImpl<A, E> extends Effectable.Class<readonly [messages: Chunk.Chunk
288
291
  this.capacity = 1
289
292
  this.releaseCapacity()
290
293
  this.capacity = 0
291
- return this.messages.length > 0 ? core.exitSucceed(this.messages.pop()!) : undefined
294
+ const message = this.messages.pop()!
295
+ this.releaseCapacity()
296
+ return core.exitSucceed(message)
292
297
  } else {
293
298
  return undefined
294
299
  }
@@ -515,47 +520,3 @@ export const toChannel = <A, E>(self: Api.ReadonlyMailbox<A, E>): Channel<Chunk.
515
520
  : channel.zipRight(coreChannel.write(messages), loop))
516
521
  return loop
517
522
  }
518
-
519
- /** @internal */
520
- export const toStream = <A, E>(self: Api.ReadonlyMailbox<A, E>): Stream<A, E> => stream.fromChannel(toChannel(self))
521
-
522
- /** @internal */
523
- export const fromStream: {
524
- (options?: {
525
- readonly capacity?: number | undefined
526
- readonly strategy?: "suspend" | "dropping" | "sliding" | undefined
527
- }): <A, E, R>(self: Stream<A, E, R>) => Effect<Api.ReadonlyMailbox<A, E>, never, R | Scope>
528
- <A, E, R>(
529
- self: Stream<A, E, R>,
530
- options?: {
531
- readonly capacity?: number | undefined
532
- readonly strategy?: "suspend" | "dropping" | "sliding" | undefined
533
- }
534
- ): Effect<Api.ReadonlyMailbox<A, E>, never, R | Scope>
535
- } = dual((args) => stream.isStream(args[0]), <A, E, R>(
536
- self: Stream<A, E, R>,
537
- options?: {
538
- readonly capacity?: number | undefined
539
- readonly strategy?: "suspend" | "dropping" | "sliding" | undefined
540
- }
541
- ): Effect<Api.ReadonlyMailbox<A, E>, never, R | Scope> =>
542
- core.tap(
543
- fiberRuntime.acquireRelease(
544
- make<A, E>(options),
545
- (mailbox) => mailbox.shutdown
546
- ),
547
- (mailbox) => {
548
- const writer: Channel<never, Chunk.Chunk<A>, never, E> = coreChannel.readWithCause({
549
- onInput: (input: Chunk.Chunk<A>) => coreChannel.flatMap(mailbox.offerAll(input), () => writer),
550
- onFailure: (cause: Cause<E>) => mailbox.failCause(cause),
551
- onDone: () => mailbox.end
552
- })
553
- return fiberRuntime.scopeWith((scope) =>
554
- stream.toChannel(self).pipe(
555
- coreChannel.pipeTo(writer),
556
- channelExecutor.runIn(scope),
557
- circular.forkIn(scope)
558
- )
559
- )
560
- }
561
- ))
@@ -46,6 +46,12 @@ export type OP_PRIMITIVE = typeof OP_PRIMITIVE
46
46
  /** @internal */
47
47
  export const OP_PRIMITIVE = "Primitive" as const
48
48
 
49
+ /** @internal */
50
+ export type OP_REDACTED = typeof OP_REDACTED
51
+
52
+ /** @internal */
53
+ export const OP_REDACTED = "Redacted" as const
54
+
49
55
  /** @internal */
50
56
  export type OP_SEQUENCE = typeof OP_SEQUENCE
51
57
 
@@ -3,9 +3,8 @@ import * as Chunk from "../../Chunk.js"
3
3
  import * as Effect from "../../Effect.js"
4
4
  import * as Exit from "../../Exit.js"
5
5
  import { pipe } from "../../Function.js"
6
+ import type * as Mailbox from "../../Mailbox.js"
6
7
  import * as Option from "../../Option.js"
7
- import type * as Queue from "../../Queue.js"
8
- import type * as Scheduler from "../../Scheduler.js"
9
8
  import type * as Emit from "../../StreamEmit.js"
10
9
 
11
10
  /** @internal */
@@ -48,53 +47,23 @@ export const make = <R, E, A, B>(
48
47
  }
49
48
 
50
49
  /** @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> => {
50
+ export const makePush = <E, A>(mailbox: Mailbox.Mailbox<A, E>): Emit.EmitOpsPush<E, A> => {
55
51
  let finished = false
56
- let buffer: Array<A> = []
57
- let running = false
58
52
  function array(items: ReadonlyArray<A>) {
59
53
  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
- }
54
+ return Chunk.isEmpty(mailbox.unsafeOfferAll(items))
79
55
  }
80
56
  function done(exit: Exit.Exit<A, E>) {
81
57
  if (finished) return
82
58
  finished = true
83
59
  if (exit._tag === "Success") {
84
- buffer.push(exit.value)
60
+ mailbox.unsafeOffer(exit.value)
85
61
  }
86
- flush()
87
- queue.unsafeOffer(exit._tag === "Success" ? Exit.void : exit)
62
+ mailbox.unsafeDone(exit._tag === "Success" ? Exit.void : exit)
88
63
  }
89
64
  return {
90
65
  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
66
+ return finished ? false : mailbox.unsafeOffer(value)
98
67
  },
99
68
  array,
100
69
  chunk(chunk) {
@@ -104,8 +73,7 @@ export const makePush = <E, A>(
104
73
  end() {
105
74
  if (finished) return
106
75
  finished = true
107
- flush()
108
- queue.unsafeOffer(Exit.void)
76
+ mailbox.unsafeDone(Exit.void)
109
77
  },
110
78
  halt(cause: Cause.Cause<E>) {
111
79
  return done(Exit.failCause(cause))
@@ -11,11 +11,11 @@ import * as Equal from "../Equal.js"
11
11
  import type { ExecutionPlan } from "../ExecutionPlan.js"
12
12
  import * as Exit from "../Exit.js"
13
13
  import * as Fiber from "../Fiber.js"
14
- import * as FiberRef from "../FiberRef.js"
15
14
  import type { LazyArg } from "../Function.js"
16
15
  import { constTrue, dual, identity, pipe } from "../Function.js"
17
16
  import * as internalExecutionPlan from "../internal/executionPlan.js"
18
17
  import * as Layer from "../Layer.js"
18
+ import type * as Mailbox from "../Mailbox.js"
19
19
  import * as MergeDecision from "../MergeDecision.js"
20
20
  import * as Option from "../Option.js"
21
21
  import type * as Order from "../Order.js"
@@ -42,7 +42,11 @@ import * as channel from "./channel.js"
42
42
  import * as channelExecutor from "./channel/channelExecutor.js"
43
43
  import * as MergeStrategy from "./channel/mergeStrategy.js"
44
44
  import * as core from "./core-stream.js"
45
+ import * as effectCore from "./core.js"
45
46
  import * as doNotation from "./doNotation.js"
47
+ import * as circular from "./effect/circular.js"
48
+ import * as fiberRuntime from "./fiberRuntime.js"
49
+ import * as mailbox from "./mailbox.js"
46
50
  import { RingBuffer } from "./ringBuffer.js"
47
51
  import * as InternalSchedule from "./schedule.js"
48
52
  import * as sink_ from "./sink.js"
@@ -592,21 +596,19 @@ export const asyncEffect = <A, E = never, R = never>(
592
596
  fromChannel
593
597
  )
594
598
 
595
- const queueFromBufferOptionsPush = <A, E>(
599
+ const mailboxFromBufferOptionsPush = <A, E>(
596
600
  options?: { readonly bufferSize: "unbounded" } | {
597
601
  readonly bufferSize?: number | undefined
598
602
  readonly strategy?: "dropping" | "sliding" | undefined
599
603
  } | undefined
600
- ): Effect.Effect<Queue.Queue<Array<A> | Exit.Exit<void, E>>> => {
604
+ ): Effect.Effect<Mailbox.Mailbox<A, E>> => {
601
605
  if (options?.bufferSize === "unbounded" || (options?.bufferSize === undefined && options?.strategy === undefined)) {
602
- return Queue.unbounded()
603
- }
604
- switch (options?.strategy) {
605
- case "sliding":
606
- return Queue.sliding(options.bufferSize ?? 16)
607
- default:
608
- return Queue.dropping(options?.bufferSize ?? 16)
606
+ return mailbox.make()
609
607
  }
608
+ return mailbox.make({
609
+ capacity: options?.bufferSize ?? 16,
610
+ strategy: options?.strategy ?? "dropping"
611
+ })
610
612
  }
611
613
 
612
614
  /** @internal */
@@ -620,21 +622,12 @@ export const asyncPush = <A, E = never, R = never>(
620
622
  } | undefined
621
623
  ): Stream.Stream<A, E, Exclude<R, Scope.Scope>> =>
622
624
  Effect.acquireRelease(
623
- queueFromBufferOptionsPush<A, E>(options),
624
- Queue.shutdown
625
+ mailboxFromBufferOptionsPush<A, E>(options),
626
+ (mailbox) => mailbox.shutdown
625
627
  ).pipe(
626
- Effect.tap((queue) =>
627
- FiberRef.getWith(FiberRef.currentScheduler, (scheduler) => register(emit.makePush(queue, scheduler)))
628
- ),
629
- Effect.map((queue) => {
630
- const loop: Channel.Channel<Chunk.Chunk<A>, unknown, E> = core.flatMap(Queue.take(queue), (item) =>
631
- Exit.isExit(item)
632
- ? Exit.isSuccess(item) ? core.void : core.failCause(item.cause)
633
- : channel.zipRight(core.write(Chunk.unsafeFromArray(item)), loop))
634
- return loop
635
- }),
636
- channel.unwrapScoped,
637
- fromChannel
628
+ Effect.tap((mailbox) => register(emit.makePush(mailbox))),
629
+ Effect.map(mailboxToStream),
630
+ unwrapScoped
638
631
  )
639
632
 
640
633
  /** @internal */
@@ -3011,6 +3004,51 @@ export const toChannel = <A, E, R>(
3011
3004
  }
3012
3005
  }
3013
3006
 
3007
+ /** @internal */
3008
+ export const mailboxToStream = <A, E>(self: Mailbox.ReadonlyMailbox<A, E>): Stream.Stream<A, E> =>
3009
+ fromChannel(mailbox.toChannel(self))
3010
+
3011
+ /** @internal */
3012
+ export const mailboxFromStream: {
3013
+ (options?: {
3014
+ readonly capacity?: number | undefined
3015
+ readonly strategy?: "suspend" | "dropping" | "sliding" | undefined
3016
+ }): <A, E, R>(self: Stream.Stream<A, E, R>) => Effect.Effect<Mailbox.ReadonlyMailbox<A, E>, never, R | Scope.Scope>
3017
+ <A, E, R>(
3018
+ self: Stream.Stream<A, E, R>,
3019
+ options?: {
3020
+ readonly capacity?: number | undefined
3021
+ readonly strategy?: "suspend" | "dropping" | "sliding" | undefined
3022
+ }
3023
+ ): Effect.Effect<Mailbox.ReadonlyMailbox<A, E>, never, R | Scope.Scope>
3024
+ } = dual((args) => isStream(args[0]), <A, E, R>(
3025
+ self: Stream.Stream<A, E, R>,
3026
+ options?: {
3027
+ readonly capacity?: number | undefined
3028
+ readonly strategy?: "suspend" | "dropping" | "sliding" | undefined
3029
+ }
3030
+ ): Effect.Effect<Mailbox.ReadonlyMailbox<A, E>, never, R | Scope.Scope> =>
3031
+ effectCore.tap(
3032
+ fiberRuntime.acquireRelease(
3033
+ mailbox.make<A, E>(options),
3034
+ (mailbox) => mailbox.shutdown
3035
+ ),
3036
+ (mailbox) => {
3037
+ const writer: Channel.Channel<never, Chunk.Chunk<A>, never, E> = core.readWithCause({
3038
+ onInput: (input: Chunk.Chunk<A>) => core.flatMap(mailbox.offerAll(input), () => writer),
3039
+ onFailure: (cause: Cause.Cause<E>) => mailbox.failCause(cause),
3040
+ onDone: () => mailbox.end
3041
+ })
3042
+ return fiberRuntime.scopeWith((scope) =>
3043
+ toChannel(self).pipe(
3044
+ core.pipeTo(writer),
3045
+ channelExecutor.runIn(scope),
3046
+ circular.forkIn(scope)
3047
+ )
3048
+ )
3049
+ }
3050
+ ))
3051
+
3014
3052
  /** @internal */
3015
3053
  export const fromChunk = <A>(chunk: Chunk.Chunk<A>): Stream.Stream<A> =>
3016
3054
  new StreamImpl(Chunk.isEmpty(chunk) ? core.void : core.write(chunk))
@@ -1,4 +1,4 @@
1
- let moduleVersion = "3.22.0"
1
+ let moduleVersion = "3.22.1"
2
2
 
3
3
  export const getCurrentVersion = () => moduleVersion
4
4