import { Exit, flow, ManagedRuntime } from "effect"
import { Effect, Layer, Logger } from "effect-app"
import { CauseException } from "effect-app/client/errors"
import { type Context } from "effect-app/Context"
export const makeAppRuntime = Effect.fnUntraced(function*(layer: Layer.Layer) {
const l = layer.pipe(
Layer.provide(Logger.layer([Logger.consolePretty()]))
) as Layer.Layer
const mrt = ManagedRuntime.make(l)
yield* mrt.contextEffect
return Object.assign(mrt, {
[Symbol.dispose]() {
return Effect.runSync(mrt.disposeEffect)
},
[Symbol.asyncDispose]() {
return mrt.dispose()
}
}) // as we initialise here, there is no more error left.
})
export function initializeSync(layer: Layer.Layer) {
const runtime = Effect.runSync(makeAppRuntime(layer))
return runtime
}
export function initializeAsync(layer: Layer.Layer) {
return Effect
.runPromise(makeAppRuntime(layer))
}
// we wrap into CauseException because we want to keep the full cause of the failure.
export const makeRunPromise = (services: Context) =>
flow(Effect.runPromiseExitWith(services), (_) =>
_.then(
Exit.match({
onFailure: (cause) => Promise.reject(new CauseException(cause, "runPromise")),
onSuccess: (value) => Promise.resolve(value)
})
))
export const makeRunSync = (services: Context) =>
flow(
Effect.runSyncExitWith(services),
Exit.match({
onFailure: (cause) => {
throw new CauseException(cause, "runSync")
},
onSuccess: (value) => value
})
)