Provide HttpClient inside Api service

By extract HttpClient inside Effect.Service we defined a dependency to Api on HttpClient:

src/services/Api.ts
import { HttpClient, HttpClientRequest } from "@effect/platform";
import { Effect, flow } from "effect";

export class Api extends Effect.Service<Api>()("Api", {
  effect: Effect.gen(function* () {
    // 👇 Extracting a service creates a dependency
    const baseClient = yield* HttpClient.HttpClient;
    const client = baseClient.pipe(
      HttpClient.mapRequest(
        flow(
          HttpClientRequest.prependUrl("https://jsonplaceholder.typicode.com"),
          HttpClientRequest.acceptJson
        )
      )
    );

    return {
      getPosts: client
        .get("/posts")
        .pipe(Effect.scoped),

      getPostById: (id: string) =>
        client
          .get(`/posts/${id}`)
          .pipe(Effect.scoped),
    };
  }),
}) {}

Executing Api therefore requires a valid implementation of HttpClient as a Layer.

Learn more about Layer here: Building and composing layers

@effect/platform already includes a Layer for HttpClient derived from fetch called FetchHttpClient.

FetchHttpClient is a valid HttpClient implementation that uses fetch to make requests.

We can directly provide FetchHttpClient using dependencies inside Effect.Service:

src/services/Api.ts
import { FetchHttpClient, HttpClient, HttpClientRequest } from "@effect/platform";
import { Effect, flow } from "effect";

export class Api extends Effect.Service<Api>()("Api", {
  dependencies: [FetchHttpClient.layer],
  effect: Effect.gen(function* () {
    const baseClient = yield* HttpClient.HttpClient;
    const client = baseClient.pipe(
      HttpClient.mapRequest(
        flow(
          HttpClientRequest.prependUrl("https://jsonplaceholder.typicode.com"),
          HttpClientRequest.acceptJson
        )
      )
    );

    return {
      getPosts: client
        .get("/posts")
        .pipe(Effect.scoped),

      getPostById: (id: string) =>
        client
          .get(`/posts/${id}`)
          .pipe(Effect.scoped),
    };
  }),
}) {}

With this we created the following dependency graph: Api 👉 HttpClient (Api depends on HttpClient).