effect@3.8.0
Minor Changes
-
#3541
fcfa6eeThanks @Schniz! - addLogger.withLeveledConsoleIn browsers and different platforms,
console.errorrenders differently thanconsole.info. This helps to distinguish between different levels of logging.Logger.withLeveledConsoletakes any logger and calls the respectiveConsolemethod based on the log level. For instance,Effect.logErrorwill callConsole.errorandEffect.logInfowill callConsole.info.To use it, you can replace the default logger with a
Logger.withLeveledConsolelogger:import { Logger, Effect } from "effect" const loggerLayer = Logger.withLeveledConsole(Logger.stringLogger) Effect.gen(function* () { yield* Effect.logError("an error") yield* Effect.logInfo("an info") }).pipe(Effect.provide(loggerLayer))
-
#3541
bb9931bThanks @KhraksMamtsov! - MadeRef,SynchronizedRedandSubscriptionRefa subtype ofEffect -
#3541
5798f76Thanks @tim-smart! - add Semaphore.withPermitsIfAvailableYou can now use
Semaphore.withPermitsIfAvailableto run an Effect only if the
Semaphore has enough permits available. This is useful when you want to run an
Effect only if you can acquire a permit without blocking.It will return an
Option.Somewith the result of the Effect if the permits were
available, orNoneif they were not.import { Effect } from "effect" Effect.gen(function* () { const semaphore = yield* Effect.makeSemaphore(1) semaphore.withPermitsIfAvailable(1)(Effect.void) })
-
#3541
5f0bfa1Thanks @KhraksMamtsov! - TheDeferred<A>is now a subtype ofEffect<A>. This change simplifies handling of deferred values, removing the need for explicit callDeffer.await.import { Effect, Deferred } from "effect" Effect.gen(function* () { const deferred = yield* Deferred.make<string>() const before = yield* Deferred.await(deferred) const after = yield* deferred })
-
#3541
812a4e8Thanks @tim-smart! - add Logger.prettyLoggerDefault, to prevent duplicate pretty loggers -
#3541
273565eThanks @tim-smart! - add Effect.makeLatch, for creating a simple async latchimport { Effect } from "effect" Effect.gen(function* () { // Create a latch, starting in the closed state const latch = yield* Effect.makeLatch(false) // Fork a fiber that logs "open sesame" when the latch is opened const fiber = yield* Effect.log("open sesame").pipe( latch.whenOpen, Effect.fork ) // Open the latch yield* latch.open yield* fiber.await })
-
#3541
569a801Thanks @KhraksMamtsov! -Dequeue<A>andQueue<A>is subtype ofEffect<A>. This means that now it can be used as anEffect, and when called, it will automatically extract and return an item from the queue, without having to explicitly use theQueue.takefunction.Effect.gen(function* () { const queue = yield* Queue.unbounded<number>() yield* Queue.offer(queue, 1) yield* Queue.offer(queue, 2) const oldWay = yield* Queue.take(queue) const newWay = yield* queue })
-
#3541
aa1fa53Thanks @vinassefranche! - Add Number.round -
#3541
02f6b06Thanks @fubhy! - Add additionalDurationconversion apisDuration.toMinutesDuration.toHoursDuration.toDaysDuration.toWeeks
-
#3541
12b893eThanks @KhraksMamtsov! - TheFiber<A, E>is now a subtype ofEffect<A, E>. This change removes the need for explicit callFiber.join.import { Effect, Fiber } from "effect" Effect.gen(function*() { const fiber = yield* Effect.fork(Effect.succeed(1)) const oldWay = yield* Fiber.join(fiber) const now = yield* fiber }))
-
#3541
bbad27eThanks @dilame! - addStream.shareapiThe
Stream.shareapi is a ref counted variant of the broadcast apis.It allows you to share a stream between multiple consumers, and will close the
upstream when the last consumer ends. -
#3541
adf7d7aThanks @tim-smart! - add Mailbox module, a queue which can have done or failure signalsimport { Chunk, Effect, Mailbox } from "effect" import * as assert from "node:assert" Effect.gen(function* () { const mailbox = yield* Mailbox.make<number, string>() // add messages to the mailbox yield* mailbox.offer(1) yield* mailbox.offer(2) yield* mailbox.offerAll([3, 4, 5]) // take messages from the mailbox const [messages, done] = yield* mailbox.takeAll assert.deepStrictEqual(Chunk.toReadonlyArray(messages), [1, 2, 3, 4, 5]) assert.strictEqual(done, false) // signal that the mailbox is done yield* mailbox.end const [messages2, done2] = yield* mailbox.takeAll assert.deepStrictEqual(messages2, Chunk.empty()) assert.strictEqual(done2, true) // signal that the mailbox is failed yield* mailbox.fail("boom") })
-
#3541
007289aThanks @mikearnaldi! - Cache some fiber references in the runtime to optimize reading in hot-paths -
#3541
42a8f99Thanks @fubhy! - AddedRcMap.keysandMutableHashMap.keys.These functions allow you to get a list of keys currently stored in the underlying hash map.
const map = MutableHashMap.make([ ["a", "a"], ["b", "b"], ["c", "c"] ]) const keys = MutableHashMap.keys(map) // ["a", "b", "c"]
Effect.gen(function* () { const map = yield* RcMap.make({ lookup: (key) => Effect.succeed(key) }) yield* RcMap.get(map, "a") yield* RcMap.get(map, "b") yield* RcMap.get(map, "c") const keys = yield* RcMap.keys(map) // ["a", "b", "c"] })
-
#3541
eebfd29Thanks @fubhy! - AddDuration.partsapiconst parts = Duration.parts(Duration.sum("5 minutes", "20 seconds")) assert.equal(parts.minutes, 5) assert.equal(parts.seconds, 20)
-
#3541
040703dThanks @KhraksMamtsov! - TheFiberRef<A>is now a subtype ofEffect<A>. This change simplifies handling of deferred values, removing the need for explicit callFiberRef.get.import { Effect, FiberRef } from "effect" Effect.gen(function* () { const fiberRef = yield* FiberRef.make("value") const before = yield* FiberRef.get(fiberRef) const after = yield* fiberRef })