Last active
November 8, 2023 21:55
-
-
Save tim-smart/7e15cccab9e87f2fb57b3614e4194114 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as Context from "effect/Context" | |
import * as Effect from "effect/Effect" | |
import * as Exit from "effect/Exit" | |
import * as Layer from "effect/Layer" | |
import * as Runtime from "effect/Runtime" | |
import * as Scope from "effect/Scope" | |
export interface RuntimeClass<R> extends AsyncDisposable { | |
readonly close: () => Promise<void> | |
readonly $effect: <E, A>(effect: Effect.Effect<R, E, A>) => Promise<A> | |
readonly $effectFn: < | |
F extends (...args: Array<any>) => Effect.Effect<R, any, any>, | |
>( | |
fn: F, | |
) => (...args: Parameters<F>) => Promise<Effect.Effect.Success<ReturnType<F>>> | |
readonly $service: <I extends R, S, A>( | |
tag: Context.Tag<I, S>, | |
fn: (service: S) => Effect.Effect<R, unknown, A>, | |
) => () => Promise<A> | |
readonly $serviceFn: < | |
I extends R, | |
S, | |
F extends (...args: Array<any>) => Effect.Effect<R, any, any>, | |
>( | |
tag: Context.Tag<I, S>, | |
fn: (service: S) => F, | |
) => (...args: Parameters<F>) => Promise<Effect.Effect.Success<ReturnType<F>>> | |
} | |
export interface RuntimeClassConstructor<Args extends Array<any>, R> { | |
new (...args: Args): RuntimeClass<R> | |
} | |
export function RuntimeClass<Args extends Array<any>, RE, R>( | |
layer: (...args: Args) => Layer.Layer<never, RE, R>, | |
): RuntimeClassConstructor<Args, R> { | |
return class { | |
#scope = Effect.runSync(Scope.make()) | |
#runtime: Promise<Runtime.Runtime<R>> | |
constructor(...args: Args) { | |
this.#runtime = Effect.runPromise( | |
Layer.toRuntime(layer(...args)).pipe(Scope.extend(this.#scope)), | |
) | |
} | |
close(): Promise<void> { | |
return Effect.runPromise(Scope.close(this.#scope, Exit.unit)) | |
} | |
[Symbol.asyncDispose]() { | |
return this.close() | |
} | |
$effect<E, A>(effect: Effect.Effect<R, E, A>): Promise<A> { | |
return this.#runtime.then(runtime => Runtime.runPromise(runtime)(effect)) | |
} | |
$effectFn<F extends (...args: Array<any>) => Effect.Effect<R, any, any>>( | |
fn: F, | |
): ( | |
...args: Parameters<F> | |
) => Promise<Effect.Effect.Success<ReturnType<F>>> { | |
return (...args) => this.$effect(fn(...args)) | |
} | |
$service<I extends R, S, A>( | |
tag: Context.Tag<I, S>, | |
fn: (service: S) => Effect.Effect<R, unknown, A>, | |
): () => Promise<A> { | |
return () => this.$effect(Effect.flatMap(tag, _ => fn(_))) | |
} | |
$serviceFn< | |
I extends R, | |
S, | |
F extends (...args: Array<any>) => Effect.Effect<R, any, any>, | |
>( | |
tag: Context.Tag<I, S>, | |
fn: (service: S) => F, | |
): ( | |
...args: Parameters<F> | |
) => Promise<Effect.Effect.Success<ReturnType<F>>> { | |
return (...args) => this.$effect(Effect.flatMap(tag, _ => fn(_)(args))) | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface Loggers { | |
readonly make: (name: string) => Logger | |
} | |
interface Logger { | |
readonly log: (message: string) => Effect.Effect<never, never, void> | |
} | |
const Loggers = Context.Tag<Loggers>("app/Loggers") | |
const LoggersLive = Layer.succeed( | |
Loggers, | |
Loggers.of({ | |
make: name => ({ | |
log: message => Effect.sync(() => console.log(`[${name}] ${message}`)), | |
}), | |
}), | |
) | |
// make runtime class | |
class LoggerRuntime extends RuntimeClass(() => LoggersLive) { | |
log = this.$serviceFn(Loggers, _ => _.make("test").log) | |
} | |
const runner = new LoggerRuntime() | |
runner.log("hello world") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment