Implement shared API definition

The shared HttpApi we defined inside api-client provides the API definition for the server implementation.

Each group inside HttpApi is implemented using HttpApiBuilder.group:

export const PaddleApiLive = HttpApiBuilder.group(
  MainApi,
  "paddle", // 👈 Group identifier
  (handlers) => /// ...
);

Using handlers we define each endpoint implementation with .handle:

export const PaddleApiLive = HttpApiBuilder.group(
  MainApi,
  "paddle",
  (handlers) =>
    handlers
      .handle("webhook", ({ headers }) => /* ... */ )
      .handle("product", ({ path: { slug } }) => /* ... */ )
);

The function inside handle provides all the headers, path parameters and other information that we defined in the API definition (type-safe).

It's also possible to extract the full request by yielding HttpServerRequest:

export const PaddleApiLive = HttpApiBuilder.group(
  MainApi,
  "paddle",
  (handlers) =>
    handlers
      .handle("webhook", ({ headers }) =>
        Effect.gen(function* () {
          const request = yield* HttpServerRequest.HttpServerRequest;
          /// ...
        })
      )
      .handle("product", ({ path: { slug } }) => /* ... */ )
);

Each handle requires an Effect returning the response for the endpoint. The response type must be the same as defined with addSuccess.