/** * inspired by https://github.com/tusharmath/qio/pull/22 (revised) */ export const _GenR = Symbol.for("@effect/core/io/Effect/Gen/R") export type _GenR = typeof _GenR export const _GenE = Symbol.for("@effect/core/io/Effect/Gen/E") export type _GenE = typeof _GenE export const _GenA = Symbol.for("@effect/core/io/Effect/Gen/A") export type _GenA = typeof _GenA export class GenEffect { readonly [_GenR]!: () => R readonly [_GenE]!: () => E readonly [_GenA]!: () => A constructor(readonly effect: Effect) {} *[Symbol.iterator](): Generator, A, any> { return yield this } } function adapter(_: any, __?: any) { if (Either.isEither(_)) { return new GenEffect( Effect.fromEither(_) ) } if (Maybe.isMaybe(_)) { if (__ && typeof __ === "function") { return new GenEffect( _._tag === "None" ? Effect.failSync(() => __()) : Effect.sync(() => _.value) ) } return new GenEffect(Effect.getOrFail(_)) } if (Tag.is(_)) { return new GenEffect(Effect.service(_)) } return new GenEffect(_) } export interface Adapter { (_: Tag): GenEffect (_: Maybe, onNone: () => E): GenEffect< unknown, E, A > (_: Maybe): GenEffect< unknown, NoSuchElement, A > (_: Either): GenEffect (_: Effect): GenEffect } export interface AdapterWithScope extends Adapter { (_: Effect): GenEffect } /** * @tsplus static effect/core/io/Effect.Ops genWithManaged */ export function genScoped, AEff>( f: (i: AdapterWithScope) => Generator ): Effect< [Eff] extends [{ [_GenR]: () => infer R }] ? R : never, [Eff] extends [{ [_GenE]: () => infer E }] ? E : never, AEff > { return Effect.suspendSucceed(() => { const iterator = f(adapter as any) const state = iterator.next() function run( scope: Scope.Closeable, state: IteratorYieldResult | IteratorReturnResult ): Effect { if (state.done) { return Effect.succeed(state.value) } return Effect.suspendSucceed(() => state.value.effect).flatMap( (val) => { const next = iterator.next(val) return run(scope, next) } ) } return Scope.make.flatMap((scope) => Effect.acquireUseReleaseExit( Effect.unit, () => run(scope, state), (_, exit) => scope.close(exit) ) ) }) } /** * @tsplus static effect/core/io/Effect.Ops gen */ export function gen, AEff>( f: (i: Adapter) => Generator ): Effect< [Eff] extends [{ [_GenR]: () => infer R }] ? R : never, [Eff] extends [{ [_GenE]: () => infer E }] ? E : never, AEff > { return Effect.suspendSucceed(() => { const iterator = f(adapter as any) const state = iterator.next() function run( state: IteratorYieldResult | IteratorReturnResult ): Effect { if (state.done) { return Effect.succeed(state.value) } return Effect.suspendSucceed(() => state.value["effect"] as Effect) .flatMap((val: any) => run(iterator.next(val))) } return run(state) }) }