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.
- package/dist/cjs/Array.js +35 -2
- package/dist/cjs/Array.js.map +1 -1
- package/dist/cjs/Effect.js +72 -4
- package/dist/cjs/Effect.js.map +1 -1
- package/dist/cjs/FiberRef.js +6 -1
- package/dist/cjs/FiberRef.js.map +1 -1
- package/dist/cjs/GlobalValue.js +1 -4
- package/dist/cjs/GlobalValue.js.map +1 -1
- package/dist/cjs/HashMap.js +18 -1
- package/dist/cjs/HashMap.js.map +1 -1
- package/dist/cjs/Layer.js +35 -2
- package/dist/cjs/Layer.js.map +1 -1
- package/dist/cjs/Random.js +33 -1
- package/dist/cjs/Random.js.map +1 -1
- package/dist/cjs/Schedule.js.map +1 -1
- package/dist/cjs/Struct.js +22 -1
- package/dist/cjs/Struct.js.map +1 -1
- package/dist/cjs/internal/core.js +5 -3
- package/dist/cjs/internal/core.js.map +1 -1
- package/dist/cjs/internal/fiberRuntime.js +5 -1
- package/dist/cjs/internal/fiberRuntime.js.map +1 -1
- package/dist/cjs/internal/hashMap.js +11 -1
- package/dist/cjs/internal/hashMap.js.map +1 -1
- package/dist/cjs/internal/layer.js +28 -1
- package/dist/cjs/internal/layer.js.map +1 -1
- package/dist/cjs/internal/random.js +64 -1
- package/dist/cjs/internal/random.js.map +1 -1
- package/dist/cjs/internal/schedule.js +6 -3
- package/dist/cjs/internal/schedule.js.map +1 -1
- package/dist/cjs/internal/version.js +1 -1
- package/dist/cjs/internal/version.js.map +1 -1
- package/dist/dts/Array.d.ts +120 -0
- package/dist/dts/Array.d.ts.map +1 -1
- package/dist/dts/Effect.d.ts +101 -1
- package/dist/dts/Effect.d.ts.map +1 -1
- package/dist/dts/FiberRef.d.ts +5 -0
- package/dist/dts/FiberRef.d.ts.map +1 -1
- package/dist/dts/GlobalValue.d.ts.map +1 -1
- package/dist/dts/HashMap.d.ts +52 -0
- package/dist/dts/HashMap.d.ts.map +1 -1
- package/dist/dts/Layer.d.ts +96 -0
- package/dist/dts/Layer.d.ts.map +1 -1
- package/dist/dts/Random.d.ts +32 -0
- package/dist/dts/Random.d.ts.map +1 -1
- package/dist/dts/Schedule.d.ts +1 -0
- package/dist/dts/Schedule.d.ts.map +1 -1
- package/dist/dts/Struct.d.ts +20 -0
- package/dist/dts/Struct.d.ts.map +1 -1
- package/dist/dts/internal/fiberRuntime.d.ts.map +1 -1
- package/dist/dts/internal/hashMap.d.ts.map +1 -1
- package/dist/dts/internal/layer.d.ts.map +1 -1
- package/dist/dts/internal/random.d.ts.map +1 -1
- package/dist/esm/Array.js +33 -0
- package/dist/esm/Array.js.map +1 -1
- package/dist/esm/Effect.js +65 -0
- package/dist/esm/Effect.js.map +1 -1
- package/dist/esm/FiberRef.js +5 -0
- package/dist/esm/FiberRef.js.map +1 -1
- package/dist/esm/GlobalValue.js +1 -2
- package/dist/esm/GlobalValue.js.map +1 -1
- package/dist/esm/HashMap.js +17 -0
- package/dist/esm/HashMap.js.map +1 -1
- package/dist/esm/Layer.js +32 -0
- package/dist/esm/Layer.js.map +1 -1
- package/dist/esm/Random.js +32 -0
- package/dist/esm/Random.js.map +1 -1
- package/dist/esm/Schedule.js.map +1 -1
- package/dist/esm/Struct.js +20 -0
- package/dist/esm/Struct.js.map +1 -1
- package/dist/esm/internal/core.js +2 -0
- package/dist/esm/internal/core.js.map +1 -1
- package/dist/esm/internal/fiberRuntime.js +5 -1
- package/dist/esm/internal/fiberRuntime.js.map +1 -1
- package/dist/esm/internal/hashMap.js +10 -0
- package/dist/esm/internal/hashMap.js.map +1 -1
- package/dist/esm/internal/layer.js +28 -1
- package/dist/esm/internal/layer.js.map +1 -1
- package/dist/esm/internal/random.js +62 -0
- package/dist/esm/internal/random.js.map +1 -1
- package/dist/esm/internal/schedule.js +6 -3
- package/dist/esm/internal/schedule.js.map +1 -1
- package/dist/esm/internal/version.js +1 -1
- package/dist/esm/internal/version.js.map +1 -1
- package/package.json +1 -1
- package/src/Array.ts +143 -0
- package/src/Effect.ts +114 -1
- package/src/FiberRef.ts +7 -0
- package/src/GlobalValue.ts +1 -3
- package/src/HashMap.ts +56 -0
- package/src/Layer.ts +114 -0
- package/src/Random.ts +33 -0
- package/src/Schedule.ts +1 -0
- package/src/Struct.ts +22 -0
- package/src/internal/core.ts +6 -0
- package/src/internal/fiberRuntime.ts +9 -5
- package/src/internal/hashMap.ts +14 -0
- package/src/internal/layer.ts +38 -1
- package/src/internal/random.ts +72 -0
- package/src/internal/schedule.ts +7 -3
- 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
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
|
package/src/internal/core.ts
CHANGED
|
@@ -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
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
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)
|
package/src/internal/hashMap.ts
CHANGED
|
@@ -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(
|
package/src/internal/layer.ts
CHANGED
|
@@ -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>(
|
package/src/internal/random.ts
CHANGED
|
@@ -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)
|
package/src/internal/schedule.ts
CHANGED
|
@@ -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
|
)
|
package/src/internal/version.ts
CHANGED