effect 3.17.10 → 3.17.12

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.
package/src/LayerMap.ts CHANGED
@@ -12,7 +12,7 @@ import * as Layer from "./Layer.js"
12
12
  import * as RcMap from "./RcMap.js"
13
13
  import * as Runtime from "./Runtime.js"
14
14
  import * as Scope from "./Scope.js"
15
- import type { Mutable } from "./Types.js"
15
+ import type { Mutable, NoExcessProperties } from "./Types.js"
16
16
 
17
17
  /**
18
18
  * @since 3.14.0
@@ -113,11 +113,13 @@ export interface LayerMap<in K, in out I, out E = never> {
113
113
  */
114
114
  export const make: <
115
115
  K,
116
- L extends Layer.Layer<any, any, any>
116
+ L extends Layer.Layer<any, any, any>,
117
+ PreloadKeys extends Iterable<K> | undefined = undefined
117
118
  >(
118
119
  lookup: (key: K) => L,
119
120
  options?: {
120
121
  readonly idleTimeToLive?: Duration.DurationInput | undefined
122
+ readonly preloadKeys?: PreloadKeys
121
123
  } | undefined
122
124
  ) => Effect.Effect<
123
125
  LayerMap<
@@ -125,12 +127,13 @@ export const make: <
125
127
  L extends Layer.Layer<infer _A, infer _E, infer _R> ? _A : never,
126
128
  L extends Layer.Layer<infer _A, infer _E, infer _R> ? _E : never
127
129
  >,
128
- never,
130
+ PreloadKeys extends undefined ? never : L extends Layer.Layer<infer _A, infer _E, infer _R> ? _E : never,
129
131
  Scope.Scope | (L extends Layer.Layer<infer _A, infer _E, infer _R> ? _R : never)
130
132
  > = Effect.fnUntraced(function*<I, K, EL, RL>(
131
133
  lookup: (key: K) => Layer.Layer<I, EL, RL>,
132
134
  options?: {
133
135
  readonly idleTimeToLive?: Duration.DurationInput | undefined
136
+ readonly preloadKeys?: Iterable<K> | undefined
134
137
  } | undefined
135
138
  ) {
136
139
  const context = yield* Effect.context<never>()
@@ -174,6 +177,12 @@ export const make: <
174
177
  idleTimeToLive: options?.idleTimeToLive
175
178
  })
176
179
 
180
+ if (options?.preloadKeys) {
181
+ for (const key of options.preloadKeys) {
182
+ yield* (RcMap.get(rcMap, key) as Effect.Effect<any, EL, RL | Scope.Scope>)
183
+ }
184
+ }
185
+
177
186
  return identity<LayerMap<K, Exclude<I, Scope.Scope>, any>>({
178
187
  [TypeId]: TypeId,
179
188
  rcMap,
@@ -189,21 +198,27 @@ export const make: <
189
198
  * @experimental
190
199
  */
191
200
  export const fromRecord = <
192
- const Layers extends Record<string, Layer.Layer<any, any, any>>
201
+ const Layers extends Record<string, Layer.Layer<any, any, any>>,
202
+ const Preload extends boolean = false
193
203
  >(
194
204
  layers: Layers,
195
205
  options?: {
196
206
  readonly idleTimeToLive?: Duration.DurationInput | undefined
207
+ readonly preload?: Preload | undefined
197
208
  } | undefined
198
209
  ): Effect.Effect<
199
210
  LayerMap<
200
211
  keyof Layers,
201
212
  Layers[keyof Layers] extends Layer.Layer<infer _A, infer _E, infer _R> ? _A : never,
202
- Layers[keyof Layers] extends Layer.Layer<infer _A, infer _E, infer _R> ? _E : never
213
+ Preload extends true ? never : Layers[keyof Layers] extends Layer.Layer<infer _A, infer _E, infer _R> ? _E : never
203
214
  >,
204
- never,
215
+ Preload extends true ? never : Layers[keyof Layers] extends Layer.Layer<infer _A, infer _E, infer _R> ? _E : never,
205
216
  Scope.Scope | (Layers[keyof Layers] extends Layer.Layer<infer _A, infer _E, infer _R> ? _R : never)
206
- > => make((key: keyof Layers) => layers[key], options)
217
+ > =>
218
+ make((key: keyof Layers) => layers[key], {
219
+ ...options,
220
+ preloadKeys: options?.preload ? Object.keys(layers) : undefined
221
+ }) as any
207
222
 
208
223
  /**
209
224
  * @since 3.14.0
@@ -216,6 +231,7 @@ export interface TagClass<
216
231
  in out I,
217
232
  in out E,
218
233
  in out R,
234
+ in out LE,
219
235
  in out Deps extends Layer.Layer<any, any, any>
220
236
  > extends Context.TagClass<Self, Id, LayerMap<K, I, E>> {
221
237
  /**
@@ -223,7 +239,7 @@ export interface TagClass<
223
239
  */
224
240
  readonly Default: Layer.Layer<
225
241
  Self,
226
- (Deps extends Layer.Layer<infer _A, infer _E, infer _R> ? _E : never),
242
+ (Deps extends Layer.Layer<infer _A, infer _E, infer _R> ? _E : never) | LE,
227
243
  | Exclude<R, (Deps extends Layer.Layer<infer _A, infer _E, infer _R> ? _A : never)>
228
244
  | (Deps extends Layer.Layer<infer _A, infer _E, infer _R> ? _R : never)
229
245
  >
@@ -231,7 +247,7 @@ export interface TagClass<
231
247
  /**
232
248
  * A default layer for the `LayerMap` service without the dependencies provided.
233
249
  */
234
- readonly DefaultWithoutDependencies: Layer.Layer<Self, never, R>
250
+ readonly DefaultWithoutDependencies: Layer.Layer<Self, LE, R>
235
251
 
236
252
  /**
237
253
  * Retrieves a Layer for the resources associated with the key.
@@ -305,28 +321,40 @@ export interface TagClass<
305
321
  export const Service = <Self>() =>
306
322
  <
307
323
  const Id extends string,
308
- Lookup extends {
309
- readonly lookup: (key: any) => Layer.Layer<any, any, any>
310
- } | {
311
- readonly layers: Record<string, Layer.Layer<any, any, any>>
312
- },
313
- const Deps extends ReadonlyArray<Layer.Layer<any, any, any>> = []
324
+ Options extends
325
+ | NoExcessProperties<
326
+ {
327
+ readonly lookup: (key: any) => Layer.Layer<any, any, any>
328
+ readonly dependencies?: ReadonlyArray<Layer.Layer<any, any, any>>
329
+ readonly idleTimeToLive?: Duration.DurationInput | undefined
330
+ readonly preloadKeys?:
331
+ | Iterable<Options extends { readonly lookup: (key: infer K) => any } ? K : never>
332
+ | undefined
333
+ },
334
+ Options
335
+ >
336
+ | NoExcessProperties<{
337
+ readonly layers: Record<string, Layer.Layer<any, any, any>>
338
+ readonly dependencies?: ReadonlyArray<Layer.Layer<any, any, any>>
339
+ readonly idleTimeToLive?: Duration.DurationInput | undefined
340
+ readonly preload?: boolean
341
+ }, Options>
314
342
  >(
315
343
  id: Id,
316
- options: Lookup & {
317
- readonly dependencies?: Deps | undefined
318
- readonly idleTimeToLive?: Duration.DurationInput | undefined
319
- }
344
+ options: Options
320
345
  ): TagClass<
321
346
  Self,
322
347
  Id,
323
- Lookup extends { readonly lookup: (key: infer K) => any } ? K
324
- : Lookup extends { readonly layers: infer Layers } ? keyof Layers
348
+ Options extends { readonly lookup: (key: infer K) => any } ? K
349
+ : Options extends { readonly layers: infer Layers } ? keyof Layers
350
+ : never,
351
+ Service.Success<Options>,
352
+ Options extends { readonly preload: true } ? never : Service.Error<Options>,
353
+ Service.Context<Options>,
354
+ Options extends { readonly preload: true } ? Service.Error<Options>
355
+ : Options extends { readonly preloadKey: Iterable<any> } ? Service.Error<Options>
325
356
  : never,
326
- Service.Success<Lookup>,
327
- Service.Error<Lookup>,
328
- Service.Context<Lookup>,
329
- Deps[number]
357
+ Options extends { readonly dependencies: ReadonlyArray<any> } ? Options["dependencies"][number] : never
330
358
  > => {
331
359
  const Err = globalThis.Error as any
332
360
  const limit = Err.stackTraceLimit
@@ -335,7 +363,7 @@ export const Service = <Self>() =>
335
363
  Err.stackTraceLimit = limit
336
364
 
337
365
  function TagClass() {}
338
- const TagClass_ = TagClass as any as Mutable<TagClass<Self, Id, string, any, any, any, any>>
366
+ const TagClass_ = TagClass as any as Mutable<TagClass<Self, Id, string, any, any, any, any, any>>
339
367
  Object.setPrototypeOf(TagClass, Object.getPrototypeOf(Context.GenericTag<Self, any>(id)))
340
368
  TagClass.key = id
341
369
  Object.defineProperty(TagClass, "stack", {
package/src/Predicate.ts CHANGED
@@ -1025,7 +1025,8 @@ export const isDate = (input: unknown): input is Date => input instanceof Date
1025
1025
  * @category guards
1026
1026
  * @since 2.0.0
1027
1027
  */
1028
- export const isIterable = (input: unknown): input is Iterable<unknown> => hasProperty(input, Symbol.iterator)
1028
+ export const isIterable = (input: unknown): input is Iterable<unknown> =>
1029
+ typeof input === "string" || hasProperty(input, Symbol.iterator)
1029
1030
 
1030
1031
  /**
1031
1032
  * A refinement that checks if a value is a record (i.e., a plain object).
@@ -131,11 +131,24 @@ export const interruptAll = (fibers: Iterable<Fiber.Fiber<any, any>>): Effect.Ef
131
131
  export const interruptAllAs = dual<
132
132
  (fiberId: FiberId.FiberId) => (fibers: Iterable<Fiber.Fiber<any, any>>) => Effect.Effect<void>,
133
133
  (fibers: Iterable<Fiber.Fiber<any, any>>, fiberId: FiberId.FiberId) => Effect.Effect<void>
134
- >(2, (fibers, fiberId) =>
135
- pipe(
136
- core.forEachSequentialDiscard(fibers, interruptAsFork(fiberId)),
137
- core.zipRight(pipe(fibers, core.forEachSequentialDiscard(_await)))
138
- ))
134
+ >(
135
+ 2,
136
+ core.fnUntraced(function*(fibers, fiberId) {
137
+ for (const fiber of fibers) {
138
+ if (isRuntimeFiber(fiber)) {
139
+ fiber.unsafeInterruptAsFork(fiberId)
140
+ continue
141
+ }
142
+ yield* fiber.interruptAsFork(fiberId)
143
+ }
144
+ for (const fiber of fibers) {
145
+ if (isRuntimeFiber(fiber) && fiber.unsafePoll()) {
146
+ continue
147
+ }
148
+ yield* fiber.await
149
+ }
150
+ })
151
+ )
139
152
 
140
153
  /** @internal */
141
154
  export const interruptAsFork = dual<
@@ -6,7 +6,6 @@ import type * as Clock from "../Clock.js"
6
6
  import type { ConfigProvider } from "../ConfigProvider.js"
7
7
  import * as Context from "../Context.js"
8
8
  import type { DefaultServices } from "../DefaultServices.js"
9
- import * as Deferred from "../Deferred.js"
10
9
  import type * as Duration from "../Duration.js"
11
10
  import type * as Effect from "../Effect.js"
12
11
  import * as Effectable from "../Effectable.js"
@@ -2630,112 +2629,54 @@ export const raceAll: <Eff extends Effect.Effect<any, any, any>>(
2630
2629
  A,
2631
2630
  E,
2632
2631
  R
2633
- >(all: Iterable<Effect.Effect<A, E, R>>): Effect.Effect<A, E, R> => {
2634
- const list = Chunk.fromIterable(all)
2635
- if (!Chunk.isNonEmpty(list)) {
2636
- return core.dieSync(() => new core.IllegalArgumentException(`Received an empty collection of effects`))
2637
- }
2638
- const self = Chunk.headNonEmpty(list)
2639
- const effects = Chunk.tailNonEmpty(list)
2640
- const inheritAll = (res: readonly [A, Fiber.Fiber<A, E>]) =>
2641
- pipe(
2642
- internalFiber.inheritAll(res[1]),
2643
- core.as(res[0])
2644
- )
2645
- return pipe(
2646
- core.deferredMake<readonly [A, Fiber.Fiber<A, E>], E>(),
2647
- core.flatMap((done) =>
2648
- pipe(
2649
- Ref.make(effects.length),
2650
- core.flatMap((fails) =>
2651
- core.uninterruptibleMask<A, E, R>((restore) =>
2652
- pipe(
2653
- fork(core.interruptible(self)),
2654
- core.flatMap((head) =>
2655
- pipe(
2656
- effects,
2657
- core.forEachSequential((effect) => fork(core.interruptible(effect))),
2658
- core.map((fibers) => Chunk.unsafeFromArray(fibers)),
2659
- core.map((tail) => pipe(tail, Chunk.prepend(head)) as Chunk.Chunk<Fiber.RuntimeFiber<A, E>>),
2660
- core.tap((fibers) =>
2661
- pipe(
2662
- fibers,
2663
- RA.reduce(core.void, (effect, fiber) =>
2664
- pipe(
2665
- effect,
2666
- core.zipRight(
2667
- pipe(
2668
- internalFiber._await(fiber),
2669
- core.flatMap(raceAllArbiter(fibers, fiber, done, fails)),
2670
- fork,
2671
- core.asVoid
2672
- )
2673
- )
2674
- ))
2675
- )
2676
- ),
2677
- core.flatMap((fibers) =>
2678
- pipe(
2679
- restore(pipe(Deferred.await(done), core.flatMap(inheritAll))),
2680
- core.onInterrupt(() =>
2681
- pipe(
2682
- fibers,
2683
- RA.reduce(
2684
- core.void,
2685
- (effect, fiber) => pipe(effect, core.zipLeft(core.interruptFiber(fiber)))
2686
- )
2687
- )
2688
- )
2689
- )
2690
- )
2691
- )
2692
- )
2693
- )
2694
- )
2632
+ >(all: Iterable<Effect.Effect<A, E, R>>): Effect.Effect<A, E, R> =>
2633
+ core.withFiberRuntime((state, status) =>
2634
+ core.async<A, E, R>((resume) => {
2635
+ const fibers = new Set<FiberRuntime<A, E>>()
2636
+ let winner: FiberRuntime<A, E> | undefined
2637
+ let failures: Cause.Cause<E> = internalCause.empty
2638
+ const interruptAll = () => {
2639
+ for (const fiber of fibers) {
2640
+ fiber.unsafeInterruptAsFork(state.id())
2641
+ }
2642
+ }
2643
+ let latch = false
2644
+ let empty = true
2645
+ for (const self of all) {
2646
+ empty = false
2647
+ const fiber = unsafeFork(
2648
+ core.interruptible(self),
2649
+ state,
2650
+ status.runtimeFlags
2695
2651
  )
2696
- )
2697
- )
2652
+ fibers.add(fiber)
2653
+ fiber.addObserver((exit) => {
2654
+ fibers.delete(fiber)
2655
+ if (!winner) {
2656
+ if (exit._tag === "Success") {
2657
+ latch = true
2658
+ winner = fiber
2659
+ failures = internalCause.empty
2660
+ interruptAll()
2661
+ } else {
2662
+ failures = internalCause.parallel(exit.cause, failures)
2663
+ }
2664
+ }
2665
+ if (latch && fibers.size === 0) {
2666
+ resume(
2667
+ winner ? core.zipRight(internalFiber.inheritAll(winner), winner.unsafePoll()!) : core.failCause(failures)
2668
+ )
2669
+ }
2670
+ })
2671
+ if (winner) break
2672
+ }
2673
+ if (empty) {
2674
+ return resume(core.dieSync(() => new core.IllegalArgumentException(`Received an empty collection of effects`)))
2675
+ }
2676
+ latch = true
2677
+ return internalFiber.interruptAllAs(fibers, state.id())
2678
+ })
2698
2679
  )
2699
- }
2700
-
2701
- const raceAllArbiter = <E, E1, A, A1>(
2702
- fibers: Iterable<Fiber.Fiber<A | A1, E | E1>>,
2703
- winner: Fiber.Fiber<A | A1, E | E1>,
2704
- deferred: Deferred.Deferred<readonly [A | A1, Fiber.Fiber<A | A1, E | E1>], E | E1>,
2705
- fails: Ref.Ref<number>
2706
- ) =>
2707
- (exit: Exit.Exit<A | A1, E | E1>): Effect.Effect<void> =>
2708
- core.exitMatchEffect(exit, {
2709
- onFailure: (cause) =>
2710
- pipe(
2711
- Ref.modify(fails, (fails) =>
2712
- [
2713
- fails === 0 ?
2714
- pipe(core.deferredFailCause(deferred, cause), core.asVoid) :
2715
- core.void,
2716
- fails - 1
2717
- ] as const),
2718
- core.flatten
2719
- ),
2720
- onSuccess: (value): Effect.Effect<void> =>
2721
- pipe(
2722
- core.deferredSucceed(deferred, [value, winner] as const),
2723
- core.flatMap((set) =>
2724
- set ?
2725
- pipe(
2726
- Chunk.fromIterable(fibers),
2727
- RA.reduce(
2728
- core.void,
2729
- (effect, fiber) =>
2730
- fiber === winner ?
2731
- effect :
2732
- pipe(effect, core.zipLeft(core.interruptFiber(fiber)))
2733
- )
2734
- ) :
2735
- core.void
2736
- )
2737
- )
2738
- })
2739
2680
 
2740
2681
  /* @internal */
2741
2682
  export const reduceEffect = dual<
@@ -1,4 +1,4 @@
1
- let moduleVersion = "3.17.10"
1
+ let moduleVersion = "3.17.12"
2
2
 
3
3
  export const getCurrentVersion = () => moduleVersion
4
4