In the live version of the app BASE_URL
is retrieved from process.env
, which is the default configuration provider in effect.
{
"name": "effect-getting-started-course",
"version": "1.0.0",
"main": "src/index.js",
"author": "Sandro Maglione",
"license": "MIT",
"scripts": {
"dev": "BASE_URL=https://pokeapi.co tsx src/index.ts",
"tsc": "tsc",
"test": "vitest"
},
"devDependencies": {
"@types/node": "^20.14.10",
"msw": "^2.3.1",
"tsx": "^4.16.2",
"typescript": "^5.5.3",
"vitest": "^2.0.2"
},
"dependencies": {
"@effect/platform": "^0.69.2",
"effect": "^3.10.0"
}
}
For testing instead we want to define a new provider that returns http://localhost:3000
instead of https://pokeapi.co
.
All requests to http://localhost:3000
will be intercepted by msw
that will return the mock response.
ConfigProvider: provider for configuration
Config
is a service that retrieves primitive values based on a key:
export class PokeApiUrl extends Context.Tag("PokeApiUrl")<
PokeApiUrl,
string
>() {
static readonly Live = Layer.effect(
this,
Effect.gen(function* () {
// 👇 Get value with `BASE_URL` key using `Config`
const baseUrl = yield* Config.string("BASE_URL");
return `${baseUrl}/api/v2/pokemon`;
})
);
}
The source of the values passed to Config
is defined with ConfigProvider
.
For testing we usually define a new ConfigProvider
that provides static values instead of accessing process.env
.
We do this by using ConfigProvider.fromMap
:
import { ConfigProvider } from "effect";
const TestConfigProvider = ConfigProvider.fromMap(
new Map([["BASE_URL", "http://localhost:3000"]])
);
ConfigProvider.fromMap
takes a Map
of key-value pairs and returns a new ConfigProvider
that provides the values defined in the map.
There are other ways to define a
ConfigProvider
, you can check the API reference to learn about them all.
Providing ConfigProvider as a layer
Since ConfigProvider
is a service, we can wrap it in a layer to provide it to our program.
We use Layer.setConfigProvider
to create a layer from a ConfigProvider
:
import { ConfigProvider, Layer } from "effect";
const TestConfigProvider = ConfigProvider.fromMap(
new Map([["BASE_URL", "http://localhost:3000"]])
);
const ConfigProviderLayer = Layer.setConfigProvider(TestConfigProvider);
With this we have ConfigProviderLayer
that we can compose as a normal layer. We are going to provide this to our program next.