Creating an Effect-based client for a REST API is a great way to leverage the power of the Effect...

There's a simple REST API (which I don't control) that I'd like to write a client for in Effect. The client has a base url and an API-key as dependencies, so it's all very standard. Does anyone know of a repo or tutorial showing an idiomatic way of doing this?

I've got something like this working (here simplified for the benefit of the discussion)

import {
  HttpClient,
  HttpClientRequest,
  HttpClientResponse,
} from '@effect/platform'
import { NodeHttpClient } from '@effect/platform-node'
import { Context, Effect, Redacted, Schema } from 'effect'

class GetByIdResponse extends Schema.Class<GetByIdResponse>('GetByIdResponse')({
  id: Schema.String,
  name: Schema.String,
}) {}

class APIKey extends Context.Tag('src/services/SKODA/SkodaAPIKey')<
  APIKey,
  Redacted.Redacted
>() {}

class BaseURL extends Context.Tag('src/services/SKODA/SkodaBaseURL')<
  BaseURL,
  string
>() {}

export class EffectfulSkodaClient extends Effect.Service<EffectfulSkodaClient>()(
  'EffectfulSkodaClient',
  {
    dependencies: [NodeHttpClient.layerUndici],
    effect: Effect.gen(function* () {
      const httpClient = yield* HttpClient.HttpClient
      const apiKey = yield* APIKey
      const baseUrl = yield* BaseURL

      const composeRequest = (request: HttpClientRequest.HttpClientRequest) =>
        request.pipe(
          HttpClientRequest.prependUrl(baseUrl),
          HttpClientRequest.setHeader('Content-Type', 'application/json'),
          HttpClientRequest.setHeader('x-api-key', Redacted.value(apiKey)),
        )

      const getById = Effect.fn('getById')(function* (id: string) {
        const response = yield* HttpClientRequest.get(
          `/api/v1/todo/${id}`,
        ).pipe(composeRequest, httpClient.execute)

        return yield* HttpClientResponse.schemaBodyJson(GetByIdResponse)(
          response,
        )
      })

      return {
        getById,
      }
    }),
  },
) {}


But I'm not sure if this is good or if it sucks
Was this page helpful?