Managed runtime

Runtime is an advanced concept. Most of the times you won't need to define a full custom Runtime from zero.

Instead, we can use ManagedRuntime.

ManagedRuntime allows to derive a Runtime from a Layer. The new Runtime will include all the services inside the layer we provide:

import { Layer, ManagedRuntime } from "effect";

const MainLayer = Layer.mergeAll(PokeApi.Default);

// 👉 Create a `Runtime` from a layer (`MainLayer`)
const PokemonRuntime = ManagedRuntime.make(MainLayer);

With this we don't need to use Effect.provide anymore since all the services inside MainLayer are included in PokemonRuntime.

We can instead directly use PokemonRuntime.runPromise:

index.ts
import { Effect, Layer, ManagedRuntime } from "effect";
import { PokeApi } from "./PokeApi";

const MainLayer = Layer.mergeAll(PokeApi.Default);

const PokemonRuntime = ManagedRuntime.make(MainLayer);

export const program = Effect.gen(function* () {
  const pokeApi = yield* PokeApi;
  return yield* pokeApi.getPokemon;
});

// Don't need `runnable` nor `Effect.provide` anymore
const runnable = program.pipe(Effect.provide(MainLayer)); 

const main = program.pipe(
  Effect.catchTags({
    FetchError: () => Effect.succeed("Fetch error"),
    JsonError: () => Effect.succeed("Json error"),
    ParseError: () => Effect.succeed("Parse error"),
  })
);

PokemonRuntime.runPromise(main).then(console.log);

A Runtime includes all the run* methods necessary to run the app, included the two we used in this course (runSync and runPromise)