effect 3.16.17 → 3.17.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 (100) hide show
  1. package/dist/cjs/Array.js +35 -2
  2. package/dist/cjs/Array.js.map +1 -1
  3. package/dist/cjs/Effect.js +72 -4
  4. package/dist/cjs/Effect.js.map +1 -1
  5. package/dist/cjs/FiberRef.js +6 -1
  6. package/dist/cjs/FiberRef.js.map +1 -1
  7. package/dist/cjs/GlobalValue.js +1 -4
  8. package/dist/cjs/GlobalValue.js.map +1 -1
  9. package/dist/cjs/HashMap.js +18 -1
  10. package/dist/cjs/HashMap.js.map +1 -1
  11. package/dist/cjs/Layer.js +35 -2
  12. package/dist/cjs/Layer.js.map +1 -1
  13. package/dist/cjs/Random.js +33 -1
  14. package/dist/cjs/Random.js.map +1 -1
  15. package/dist/cjs/Schedule.js.map +1 -1
  16. package/dist/cjs/Struct.js +22 -1
  17. package/dist/cjs/Struct.js.map +1 -1
  18. package/dist/cjs/internal/core.js +5 -3
  19. package/dist/cjs/internal/core.js.map +1 -1
  20. package/dist/cjs/internal/fiberRuntime.js +5 -1
  21. package/dist/cjs/internal/fiberRuntime.js.map +1 -1
  22. package/dist/cjs/internal/hashMap.js +11 -1
  23. package/dist/cjs/internal/hashMap.js.map +1 -1
  24. package/dist/cjs/internal/layer.js +28 -1
  25. package/dist/cjs/internal/layer.js.map +1 -1
  26. package/dist/cjs/internal/random.js +64 -1
  27. package/dist/cjs/internal/random.js.map +1 -1
  28. package/dist/cjs/internal/schedule.js +6 -3
  29. package/dist/cjs/internal/schedule.js.map +1 -1
  30. package/dist/cjs/internal/version.js +1 -1
  31. package/dist/cjs/internal/version.js.map +1 -1
  32. package/dist/dts/Array.d.ts +120 -0
  33. package/dist/dts/Array.d.ts.map +1 -1
  34. package/dist/dts/Effect.d.ts +101 -1
  35. package/dist/dts/Effect.d.ts.map +1 -1
  36. package/dist/dts/FiberRef.d.ts +5 -0
  37. package/dist/dts/FiberRef.d.ts.map +1 -1
  38. package/dist/dts/GlobalValue.d.ts.map +1 -1
  39. package/dist/dts/HashMap.d.ts +52 -0
  40. package/dist/dts/HashMap.d.ts.map +1 -1
  41. package/dist/dts/Layer.d.ts +96 -0
  42. package/dist/dts/Layer.d.ts.map +1 -1
  43. package/dist/dts/Random.d.ts +32 -0
  44. package/dist/dts/Random.d.ts.map +1 -1
  45. package/dist/dts/Schedule.d.ts +1 -0
  46. package/dist/dts/Schedule.d.ts.map +1 -1
  47. package/dist/dts/Struct.d.ts +20 -0
  48. package/dist/dts/Struct.d.ts.map +1 -1
  49. package/dist/dts/internal/fiberRuntime.d.ts.map +1 -1
  50. package/dist/dts/internal/hashMap.d.ts.map +1 -1
  51. package/dist/dts/internal/layer.d.ts.map +1 -1
  52. package/dist/dts/internal/random.d.ts.map +1 -1
  53. package/dist/esm/Array.js +33 -0
  54. package/dist/esm/Array.js.map +1 -1
  55. package/dist/esm/Effect.js +65 -0
  56. package/dist/esm/Effect.js.map +1 -1
  57. package/dist/esm/FiberRef.js +5 -0
  58. package/dist/esm/FiberRef.js.map +1 -1
  59. package/dist/esm/GlobalValue.js +1 -2
  60. package/dist/esm/GlobalValue.js.map +1 -1
  61. package/dist/esm/HashMap.js +17 -0
  62. package/dist/esm/HashMap.js.map +1 -1
  63. package/dist/esm/Layer.js +32 -0
  64. package/dist/esm/Layer.js.map +1 -1
  65. package/dist/esm/Random.js +32 -0
  66. package/dist/esm/Random.js.map +1 -1
  67. package/dist/esm/Schedule.js.map +1 -1
  68. package/dist/esm/Struct.js +20 -0
  69. package/dist/esm/Struct.js.map +1 -1
  70. package/dist/esm/internal/core.js +2 -0
  71. package/dist/esm/internal/core.js.map +1 -1
  72. package/dist/esm/internal/fiberRuntime.js +5 -1
  73. package/dist/esm/internal/fiberRuntime.js.map +1 -1
  74. package/dist/esm/internal/hashMap.js +10 -0
  75. package/dist/esm/internal/hashMap.js.map +1 -1
  76. package/dist/esm/internal/layer.js +28 -1
  77. package/dist/esm/internal/layer.js.map +1 -1
  78. package/dist/esm/internal/random.js +62 -0
  79. package/dist/esm/internal/random.js.map +1 -1
  80. package/dist/esm/internal/schedule.js +6 -3
  81. package/dist/esm/internal/schedule.js.map +1 -1
  82. package/dist/esm/internal/version.js +1 -1
  83. package/dist/esm/internal/version.js.map +1 -1
  84. package/package.json +1 -1
  85. package/src/Array.ts +143 -0
  86. package/src/Effect.ts +114 -1
  87. package/src/FiberRef.ts +7 -0
  88. package/src/GlobalValue.ts +1 -3
  89. package/src/HashMap.ts +56 -0
  90. package/src/Layer.ts +114 -0
  91. package/src/Random.ts +33 -0
  92. package/src/Schedule.ts +1 -0
  93. package/src/Struct.ts +22 -0
  94. package/src/internal/core.ts +6 -0
  95. package/src/internal/fiberRuntime.ts +9 -5
  96. package/src/internal/hashMap.ts +14 -0
  97. package/src/internal/layer.ts +38 -1
  98. package/src/internal/random.ts +72 -0
  99. package/src/internal/schedule.ts +7 -3
  100. package/src/internal/version.ts +1 -1
package/src/HashMap.ts CHANGED
@@ -403,6 +403,62 @@ export const toEntries = <K, V>(self: HashMap<K, V>): Array<[K, V]> => Array.fro
403
403
  */
404
404
  export const size: <K, V>(self: HashMap<K, V>) => number = HM.size
405
405
 
406
+ /**
407
+ * Counts all the element of the given HashMap that pass the given predicate
408
+ *
409
+ * **Example**
410
+ *
411
+ * ```ts
412
+ * import { HashMap } from "effect"
413
+ *
414
+ * const map = HashMap.make([1, "a"], [2, "b"], [3, "c"])
415
+ * const result = HashMap.countBy(map, (_v, key) => key % 2 === 1)
416
+ * console.log(result) // 2
417
+ * ```
418
+ *
419
+ * @since 3.17.0
420
+ * @category folding
421
+ */
422
+ export const countBy: {
423
+ /**
424
+ * Counts all the element of the given HashMap that pass the given predicate
425
+ *
426
+ * **Example**
427
+ *
428
+ * ```ts
429
+ * import { HashMap } from "effect"
430
+ *
431
+ * const map = HashMap.make([1, "a"], [2, "b"], [3, "c"])
432
+ * const result = HashMap.countBy(map, (_v, key) => key % 2 === 1)
433
+ * console.log(result) // 2
434
+ * ```
435
+ *
436
+ * @since 3.17.0
437
+ * @category folding
438
+ */
439
+ <K, V>(predicate: (value: NoInfer<V>, key: NoInfer<K>) => boolean): (self: HashMap<K, V>) => number
440
+ /**
441
+ * Counts all the element of the given HashMap that pass the given predicate
442
+ *
443
+ * **Example**
444
+ *
445
+ * ```ts
446
+ * import { HashMap } from "effect"
447
+ *
448
+ * const map = HashMap.make([1, "a"], [2, "b"], [3, "c"])
449
+ * const result = HashMap.countBy(map, (_v, key) => key % 2 === 1)
450
+ * console.log(result) // 2
451
+ * ```
452
+ *
453
+ * @since 3.17.0
454
+ * @category folding
455
+ */
456
+ <K, V>(
457
+ self: HashMap<K, V>,
458
+ predicate: (value: NoInfer<V>, key: NoInfer<K>) => boolean
459
+ ): number
460
+ } = HM.countBy
461
+
406
462
  /**
407
463
  * Marks the `HashMap` as mutable.
408
464
  *
package/src/Layer.ts CHANGED
@@ -498,6 +498,109 @@ export const flatten: {
498
498
  */
499
499
  export const fresh: <A, E, R>(self: Layer<A, E, R>) => Layer<A, E, R> = internal.fresh
500
500
 
501
+ /**
502
+ * @since 3.17.0
503
+ * @category Testing
504
+ */
505
+ export type PartialEffectful<A extends object> = Types.Simplify<
506
+ & {
507
+ [
508
+ K in keyof A as A[K] extends Effect.Effect<any, any, any> | ((...args: any) => Effect.Effect<any, any, any>) ? K
509
+ : never
510
+ ]?: A[K]
511
+ }
512
+ & {
513
+ [
514
+ K in keyof A as A[K] extends Effect.Effect<any, any, any> | ((...args: any) => Effect.Effect<any, any, any>) ?
515
+ never
516
+ : K
517
+ ]: A[K]
518
+ }
519
+ >
520
+
521
+ /**
522
+ * Creates a mock layer for testing purposes. You can provide a partial
523
+ * implementation of the service, and any methods not provided will
524
+ * throw an `UnimplementedError` defect when called.
525
+ *
526
+ * **Example**
527
+ *
528
+ * ```ts
529
+ * import { Context, Effect, Layer } from "effect"
530
+ *
531
+ * class MyService extends Context.Tag("MyService")<
532
+ * MyService,
533
+ * {
534
+ * one: Effect.Effect<number>
535
+ * two(): Effect.Effect<number>
536
+ * }
537
+ * >() {}
538
+ *
539
+ * const MyServiceTest = Layer.mock(MyService, {
540
+ * two: () => Effect.succeed(2)
541
+ * })
542
+ * ```
543
+ *
544
+ * @since 3.17.0
545
+ * @category Testing
546
+ */
547
+ export const mock: {
548
+ /**
549
+ * Creates a mock layer for testing purposes. You can provide a partial
550
+ * implementation of the service, and any methods not provided will
551
+ * throw an `UnimplementedError` defect when called.
552
+ *
553
+ * **Example**
554
+ *
555
+ * ```ts
556
+ * import { Context, Effect, Layer } from "effect"
557
+ *
558
+ * class MyService extends Context.Tag("MyService")<
559
+ * MyService,
560
+ * {
561
+ * one: Effect.Effect<number>
562
+ * two(): Effect.Effect<number>
563
+ * }
564
+ * >() {}
565
+ *
566
+ * const MyServiceTest = Layer.mock(MyService, {
567
+ * two: () => Effect.succeed(2)
568
+ * })
569
+ * ```
570
+ *
571
+ * @since 3.17.0
572
+ * @category Testing
573
+ */
574
+ <I, S extends object>(tag: Context.Tag<I, S>): (service: PartialEffectful<S>) => Layer<I>
575
+ /**
576
+ * Creates a mock layer for testing purposes. You can provide a partial
577
+ * implementation of the service, and any methods not provided will
578
+ * throw an `UnimplementedError` defect when called.
579
+ *
580
+ * **Example**
581
+ *
582
+ * ```ts
583
+ * import { Context, Effect, Layer } from "effect"
584
+ *
585
+ * class MyService extends Context.Tag("MyService")<
586
+ * MyService,
587
+ * {
588
+ * one: Effect.Effect<number>
589
+ * two(): Effect.Effect<number>
590
+ * }
591
+ * >() {}
592
+ *
593
+ * const MyServiceTest = Layer.mock(MyService, {
594
+ * two: () => Effect.succeed(2)
595
+ * })
596
+ * ```
597
+ *
598
+ * @since 3.17.0
599
+ * @category Testing
600
+ */
601
+ <I, S extends object>(tag: Context.Tag<I, S>, service: PartialEffectful<S>): Layer<I>
602
+ } = internal.mock
603
+
501
604
  const fromFunction: <I1, S1, I2, S2>(
502
605
  tagA: Context.Tag<I1, S1>,
503
606
  tagB: Context.Tag<I2, S2>,
@@ -1400,6 +1503,17 @@ export const setUnhandledErrorLogLevel: (level: Option.Option<LogLevel>) => Laye
1400
1503
  fiberRuntime.fiberRefLocallyScoped(core.currentUnhandledErrorLogLevel, level)
1401
1504
  )
1402
1505
 
1506
+ /**
1507
+ * @since 3.17.0
1508
+ * @category logging
1509
+ */
1510
+ export const setVersionMismatchErrorLogLevel: (level: Option.Option<LogLevel>) => Layer<never> = (
1511
+ level: Option.Option<LogLevel>
1512
+ ): Layer<never> =>
1513
+ scopedDiscard(
1514
+ fiberRuntime.fiberRefLocallyScoped(core.currentVersionMismatchErrorLogLevel, level)
1515
+ )
1516
+
1403
1517
  /**
1404
1518
  * @since 2.0.0
1405
1519
  * @category tracing
package/src/Random.ts CHANGED
@@ -169,3 +169,36 @@ export const Random: Context.Tag<Random, Random> = internal.randomTag
169
169
  * @category constructors
170
170
  */
171
171
  export const make: <A>(seed: A) => Random = internal.make
172
+
173
+ /**
174
+ * Constructs the `Random` service from an array of literal values.
175
+ * The service will cycle through the provided values in order when generating random values.
176
+ * This constructor is useful for creating deterministic sequences for testing or when specific values need to be returned.
177
+ *
178
+ * @example
179
+ * ```ts
180
+ * import { Effect, Random } from "effect"
181
+ *
182
+ * Effect.gen(function* () {
183
+ * console.log(yield* Random.next) // 0.2
184
+ * console.log(yield* Random.next) // 0.5
185
+ * console.log(yield* Random.next) // 0.8
186
+ * console.log(yield* Random.next) // 0.2 (cycles back)
187
+ * }).pipe(Effect.withRandom(Random.fixed([0.2, 0.5, 0.8])))
188
+ * ```
189
+ *
190
+ * @example
191
+ * ```ts
192
+ * import { Effect, Random } from "effect"
193
+ *
194
+ * Effect.gen(function* () {
195
+ * console.log(yield* Random.nextBoolean) // true
196
+ * console.log(yield* Random.nextBoolean) // false
197
+ * console.log(yield* Random.nextBoolean) // true
198
+ * }).pipe(Effect.withRandom(Random.fixed([true, false, true])))
199
+ * ```
200
+ *
201
+ * @since 3.11.0
202
+ * @category constructors
203
+ */
204
+ export const fixed: <const T extends Array.NonEmptyArray<any>>(values: T) => Random = internal.fixed
package/src/Schedule.ts CHANGED
@@ -3722,6 +3722,7 @@ export interface CurrentIterationMetadata {
3722
3722
  */
3723
3723
  export interface IterationMetadata {
3724
3724
  readonly input: unknown
3725
+ readonly output: unknown
3725
3726
  readonly recurrence: number
3726
3727
  readonly start: number
3727
3728
  readonly now: number
package/src/Struct.ts CHANGED
@@ -311,3 +311,25 @@ export const get =
311
311
  * @since 3.6.0
312
312
  */
313
313
  export const keys = <T extends {}>(o: T): Array<(keyof T) & string> => Object.keys(o) as Array<(keyof T) & string>
314
+
315
+ /**
316
+ * Retrieves the entries (key-value pairs) of an object, where keys are strings,
317
+ * in a type-safe manner. Symbol keys are excluded from the result.
318
+ *
319
+ * @example
320
+ * ```ts
321
+ * import * as assert from "node:assert"
322
+ * import { Struct } from "effect"
323
+ *
324
+ * const c = Symbol("c")
325
+ * const value = { a: "foo", b: 1, [c]: true }
326
+ *
327
+ * const entries: Array<["a" | "b", string | number]> = Struct.entries(value)
328
+ *
329
+ * assert.deepStrictEqual(entries, [["a", "foo"], ["b", 1]])
330
+ * ```
331
+ *
332
+ * @since 3.17.0
333
+ */
334
+ export const entries = <const R>(obj: R): Array<[keyof R & string, R[keyof R & string]]> =>
335
+ Object.entries(obj as any) as any
@@ -2082,6 +2082,12 @@ export const currentUnhandledErrorLogLevel: FiberRef.FiberRef<Option.Option<LogL
2082
2082
  () => fiberRefUnsafeMake(Option.some<LogLevel.LogLevel>(logLevelDebug))
2083
2083
  )
2084
2084
 
2085
+ /** @internal */
2086
+ export const currentVersionMismatchErrorLogLevel: FiberRef.FiberRef<Option.Option<LogLevel.LogLevel>> = globalValue(
2087
+ Symbol.for("effect/FiberRef/versionMismatchErrorLogLevel"),
2088
+ () => fiberRefUnsafeMake(Option.some<LogLevel.LogLevel>(logLevelWarning))
2089
+ )
2090
+
2085
2091
  /** @internal */
2086
2092
  export const withUnhandledErrorLogLevel = dual<
2087
2093
  (level: Option.Option<LogLevel.LogLevel>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>,
@@ -1370,11 +1370,15 @@ export class FiberRuntime<in out A, in out E = never> extends Effectable.Class<A
1370
1370
  cur = this.currentTracer.context(
1371
1371
  () => {
1372
1372
  if (_version !== (cur as core.Primitive)[core.EffectTypeId]._V) {
1373
- return core.dieMessage(
1374
- `Cannot execute an Effect versioned ${
1375
- (cur as core.Primitive)[core.EffectTypeId]._V
1376
- } with a Runtime of version ${version.getCurrentVersion()}`
1377
- )
1373
+ const level = this.getFiberRef(core.currentVersionMismatchErrorLogLevel)
1374
+ if (level._tag === "Some") {
1375
+ const effectVersion = (cur as core.Primitive)[core.EffectTypeId]._V
1376
+ this.log(
1377
+ `Executing an Effect versioned ${effectVersion} with a Runtime of version ${version.getCurrentVersion()}, you may want to dedupe the effect dependencies, you can use the language service plugin to detect this at compile time: https://github.com/Effect-TS/language-service`,
1378
+ internalCause.empty,
1379
+ level
1380
+ )
1381
+ }
1378
1382
  }
1379
1383
  // @ts-expect-error
1380
1384
  return this[(cur as core.Primitive)._op](cur as core.Primitive)
@@ -334,6 +334,20 @@ export const entries = <K, V>(self: HM.HashMap<K, V>): IterableIterator<[K, V]>
334
334
  /** @internal */
335
335
  export const size = <K, V>(self: HM.HashMap<K, V>): number => (self as HashMapImpl<K, V>)._size
336
336
 
337
+ /** @internal */
338
+ export const countBy = Dual.dual<
339
+ <K, V>(predicate: (value: NoInfer<V>, key: NoInfer<K>) => boolean) => (self: HM.HashMap<K, V>) => number,
340
+ <K, V>(self: HM.HashMap<K, V>, predicate: (value: NoInfer<V>, key: NoInfer<K>) => boolean) => number
341
+ >(2, (self, f) => {
342
+ let count = 0
343
+ for (const [k, a] of self) {
344
+ if (f(a, k)) {
345
+ count++
346
+ }
347
+ }
348
+ return count
349
+ })
350
+
337
351
  /** @internal */
338
352
  export const beginMutation = <K, V>(self: HM.HashMap<K, V>): HM.HashMap<K, V> =>
339
353
  makeImpl(
@@ -7,7 +7,7 @@ import type * as Exit from "../Exit.js"
7
7
  import type { FiberRef } from "../FiberRef.js"
8
8
  import * as FiberRefsPatch from "../FiberRefsPatch.js"
9
9
  import type { LazyArg } from "../Function.js"
10
- import { dual, pipe } from "../Function.js"
10
+ import { constTrue, dual, pipe } from "../Function.js"
11
11
  import * as HashMap from "../HashMap.js"
12
12
  import type * as Layer from "../Layer.js"
13
13
  import type * as ManagedRuntime from "../ManagedRuntime.js"
@@ -638,6 +638,43 @@ export const launch = <RIn, E, ROut>(self: Layer.Layer<ROut, E, RIn>): Effect.Ef
638
638
  )
639
639
  )
640
640
 
641
+ /** @internal */
642
+ export const mock: {
643
+ <I, S extends object>(tag: Context.Tag<I, S>): (service: Layer.PartialEffectful<S>) => Layer.Layer<I>
644
+ <I, S extends object>(tag: Context.Tag<I, S>, service: Layer.PartialEffectful<S>): Layer.Layer<I>
645
+ } = dual(
646
+ 2,
647
+ <I, S extends object>(tag: Context.Tag<I, S>, service: Layer.PartialEffectful<S>): Layer.Layer<I> =>
648
+ succeed(
649
+ tag,
650
+ new Proxy({ ...service as object } as S, {
651
+ get(target, prop, _receiver) {
652
+ if (prop in target) {
653
+ return target[prop as keyof S]
654
+ }
655
+ const prevLimit = Error.stackTraceLimit
656
+ Error.stackTraceLimit = 2
657
+ const error = new Error(`${tag.key}: Unimplemented method "${prop.toString()}"`)
658
+ Error.stackTraceLimit = prevLimit
659
+ error.name = "UnimplementedError"
660
+ return makeUnimplemented(error)
661
+ },
662
+ has: constTrue
663
+ })
664
+ )
665
+ )
666
+
667
+ const makeUnimplemented = (error: Error) => {
668
+ const dead = core.die(error)
669
+ function unimplemented() {
670
+ return dead
671
+ }
672
+ // @effect-diagnostics-next-line floatingEffect:off
673
+ Object.assign(unimplemented, dead)
674
+ Object.setPrototypeOf(unimplemented, Object.getPrototypeOf(dead))
675
+ return unimplemented
676
+ }
677
+
641
678
  /** @internal */
642
679
  export const map = dual<
643
680
  <A, B>(
@@ -1,3 +1,4 @@
1
+ import type * as Arr from "../Array.js"
1
2
  import * as Chunk from "../Chunk.js"
2
3
  import * as Context from "../Context.js"
3
4
  import type * as Effect from "../Effect.js"
@@ -87,3 +88,74 @@ const swap = <A>(buffer: Array<A>, index1: number, index2: number): Array<A> =>
87
88
  }
88
89
 
89
90
  export const make = <A>(seed: A): Random.Random => new RandomImpl(Hash.hash(seed))
91
+
92
+ /** @internal */
93
+ class FixedRandomImpl implements Random.Random {
94
+ readonly [RandomTypeId]: Random.RandomTypeId = RandomTypeId
95
+
96
+ private index = 0
97
+
98
+ constructor(readonly values: Arr.NonEmptyArray<any>) {
99
+ if (values.length === 0) {
100
+ throw new Error("Requires at least one value")
101
+ }
102
+ }
103
+
104
+ private getNextValue(): any {
105
+ const value = this.values[this.index]
106
+ this.index = (this.index + 1) % this.values.length
107
+ return value
108
+ }
109
+
110
+ get next(): Effect.Effect<number> {
111
+ return core.sync(() => {
112
+ const value = this.getNextValue()
113
+ if (typeof value === "number") {
114
+ return Math.max(0, Math.min(1, value))
115
+ }
116
+ return Hash.hash(value) / 2147483647
117
+ })
118
+ }
119
+
120
+ get nextBoolean(): Effect.Effect<boolean> {
121
+ return core.sync(() => {
122
+ const value = this.getNextValue()
123
+ if (typeof value === "boolean") {
124
+ return value
125
+ }
126
+ return Hash.hash(value) % 2 === 0
127
+ })
128
+ }
129
+
130
+ get nextInt(): Effect.Effect<number> {
131
+ return core.sync(() => {
132
+ const value = this.getNextValue()
133
+ if (typeof value === "number" && Number.isFinite(value)) {
134
+ return Math.round(value)
135
+ }
136
+ return Math.abs(Hash.hash(value))
137
+ })
138
+ }
139
+
140
+ nextRange(min: number, max: number): Effect.Effect<number> {
141
+ return core.map(this.next, (n) => (max - min) * n + min)
142
+ }
143
+
144
+ nextIntBetween(min: number, max: number): Effect.Effect<number> {
145
+ return core.sync(() => {
146
+ const value = this.getNextValue()
147
+ if (typeof value === "number" && Number.isFinite(value)) {
148
+ return Math.max(min, Math.min(max - 1, Math.round(value)))
149
+ }
150
+ const hash = Math.abs(Hash.hash(value))
151
+ return min + (hash % (max - min))
152
+ })
153
+ }
154
+
155
+ shuffle<A>(elements: Iterable<A>): Effect.Effect<Chunk.Chunk<A>> {
156
+ return shuffleWith(elements, (n) => this.nextIntBetween(0, n))
157
+ }
158
+ }
159
+
160
+ /** @internal */
161
+ export const fixed = <T extends Arr.NonEmptyArray<any>>(values: T): Random.Random => new FixedRandomImpl(values)
@@ -53,6 +53,7 @@ const defaultIterationMetadata: Schedule.IterationMetadata = {
53
53
  start: 0,
54
54
  now: 0,
55
55
  input: undefined,
56
+ output: undefined,
56
57
  elapsed: Duration.zero,
57
58
  elapsedSincePrevious: Duration.zero,
58
59
  recurrence: 0
@@ -103,13 +104,15 @@ class ScheduleImpl<S, Out, In, R> implements Schedule.Schedule<Out, In, R> {
103
104
  const updateInfo = (
104
105
  iterationMetaRef: Ref.Ref<Schedule.IterationMetadata>,
105
106
  now: number,
106
- input: unknown
107
+ input: unknown,
108
+ output: unknown
107
109
  ) =>
108
110
  ref.update(iterationMetaRef, (prev) =>
109
111
  (prev.recurrence === 0) ?
110
112
  {
111
113
  now,
112
114
  input,
115
+ output,
113
116
  recurrence: prev.recurrence + 1,
114
117
  elapsed: Duration.zero,
115
118
  elapsedSincePrevious: Duration.zero,
@@ -118,6 +121,7 @@ const updateInfo = (
118
121
  {
119
122
  now,
120
123
  input,
124
+ output,
121
125
  recurrence: prev.recurrence + 1,
122
126
  elapsed: Duration.millis(now - prev.start),
123
127
  elapsedSincePrevious: Duration.millis(now - prev.now),
@@ -177,14 +181,14 @@ class ScheduleDriverImpl<Out, In, R> implements Schedule.ScheduleDriver<Out, In,
177
181
  const millis = Intervals.start(decision.intervals) - now
178
182
  if (millis <= 0) {
179
183
  return setState.pipe(
180
- core.zipRight(updateInfo(this.iterationMeta, now, input)),
184
+ core.zipRight(updateInfo(this.iterationMeta, now, input, out)),
181
185
  core.as(out)
182
186
  )
183
187
  }
184
188
  const duration = Duration.millis(millis)
185
189
  return pipe(
186
190
  setState,
187
- core.zipRight(updateInfo(this.iterationMeta, now, input)),
191
+ core.zipRight(updateInfo(this.iterationMeta, now, input, out)),
188
192
  core.zipRight(effect.sleep(duration)),
189
193
  core.as(out)
190
194
  )
@@ -1,4 +1,4 @@
1
- let moduleVersion = "3.16.17"
1
+ let moduleVersion = "3.17.0"
2
2
 
3
3
  export const getCurrentVersion = () => moduleVersion
4
4