Effect provides a composable service to handle configuration values: Config
.
Config
is responsible to extract configuration values and provide them in our code. In our example we create a Config
for the PokéApi base url using Config.string
.
Config.string
accepts a string
parameter that specifies the key of the configuration value to extract ("BASE_URL"
):
import { Config } from "effect";
const config = Config.string("BASE_URL");
Config
can then be used just like a normal Effect
inside .gen
. We first update fetchRequest
to accept a baseUrl
parameter:
const fetchRequest = (baseUrl: string) =>
Effect.tryPromise({
try: () => fetch(`${baseUrl}/api/v2/pokemon/garchomp/`),
catch: () => new FetchError(),
});
We then provide it from config
:
const config = Config.string("BASE_URL");
const program = Effect.gen(function* () {
const baseUrl = yield* config;
const response = yield* fetchRequest(baseUrl);
if (!response.ok) {
return yield* new FetchError();
}
const json = yield* jsonResponse(response);
return yield* decodePokemon(json);
});
Since extracting configuration is an effectful operation that may fail, using
Config
requiresyield*
.It also adds a
ConfigError
to the union of errors of theprogram
type.
program
now is of typeEffect<Pokemon, FetchError | JsonError | ParseError | ConfigError>
.See how handy is to have all the errors in the type signature? 🚀
Since a missing configuration value is an implementation error, it's common to not handle
ConfigError
(not usecatchTag
on it).Instead it's usually better to let the app fail, since we cannot recover anyway from these kind of errors (you should fix your configuration!).