Design
Designing an API means defining the contract of every resource interaction and organizing those contracts into an API Definition, API Groups, and API Endpoints. Each API Endpoint is fulfilled by an API Handler as a separate concern — owning the logic but not the contract.
API Definition (1)└── API Group (1..N) └── API Endpoint (1..N) └── API Handler (1)API Definition
Section titled “API Definition”The API Definition serves as the source of truth, drives the generated OpenAPI specification, and enforces type safety across all API Handlers.
Create an API Definition file:
Directoryapplications
Directorygateway
Directorysrc
Directoryapi
- api.definition.ts
- …
- …
Scaffold it based on the following snippet:
import { HttpApi } from 'effect/unstable/httpapi';export const ApiDefinition = HttpApi.make('Api');
API Group
Section titled “API Group”The API Group gathers API Endpoints that operate on related resources, keeping their contracts defined in one place.
Locate the API Definition file:
Directoryapplications
Directorygateway
Directorysrc
Directoryapi
- api.definition.ts
- …
- …
Add an API Group based on the following snippet:
import { HttpApi, HttpApiGroup } from 'effect/unstable/httpapi';const ApiGroupPlayers = HttpApiGroup.make('Players');export const ApiDefinition = HttpApi.make('Api').add(ApiGroupPlayers);
API Endpoint
Section titled “API Endpoint”The API Endpoint defines the contract for a specific interaction with a resource.
Locate the API Definition file:
Directoryapplications
Directorygateway
Directorysrc
Directoryapi
- api.definition.ts
- …
- …
Add an API Endpoint based on the following snippet:
import { HttpApi, HttpApiEndpoint, HttpApiGroup } from 'effect/unstable/httpapi';const ApiGroupPlayers = HttpApiGroup.make('Players').add(HttpApiEndpoint.post('create-player', '/players'),);export const ApiDefinition = HttpApi.make('Api').add(ApiGroupPlayers);import { HttpApi, HttpApiEndpoint, HttpApiGroup } from 'effect/unstable/httpapi';const ApiGroupPlayers = HttpApiGroup.make('Players').add(HttpApiEndpoint.get('get-players', '/players'),);export const ApiDefinition = HttpApi.make('Api').add(ApiGroupPlayers);import { HttpApi, HttpApiEndpoint, HttpApiGroup } from 'effect/unstable/httpapi';const ApiGroupPlayers = HttpApiGroup.make('Players').add(HttpApiEndpoint.get('get-player', '/players/:id'),);export const ApiDefinition = HttpApi.make('Api').add(ApiGroupPlayers);import { HttpApi, HttpApiEndpoint, HttpApiGroup } from 'effect/unstable/httpapi';const ApiGroupPlayers = HttpApiGroup.make('Players').add(HttpApiEndpoint.put('replace-player', '/players/:id'),);export const ApiDefinition = HttpApi.make('Api').add(ApiGroupPlayers);import { HttpApi, HttpApiEndpoint, HttpApiGroup } from 'effect/unstable/httpapi';const ApiGroupPlayers = HttpApiGroup.make('Players').add(HttpApiEndpoint.patch('update-player', '/players/:id'),);export const ApiDefinition = HttpApi.make('Api').add(ApiGroupPlayers);import { HttpApi, HttpApiEndpoint, HttpApiGroup } from 'effect/unstable/httpapi';const ApiGroupPlayers = HttpApiGroup.make('Players').add(HttpApiEndpoint.delete('delete-player', '/players/:id'),);export const ApiDefinition = HttpApi.make('Api').add(ApiGroupPlayers);Extend the API Endpoint based on the following snippet:
import {CreatePlayerError,CreatePlayerPayload,CreatePlayerRequestHeaders,CreatePlayerSuccess,} from '@applications/gateway/src/api/players/create-player.schema';import { HttpApi, HttpApiEndpoint, HttpApiGroup } from 'effect/unstable/httpapi';const ApiGroupPlayers = HttpApiGroup.make('Players').add(HttpApiEndpoint.post('create-player', '/players', {headers: CreatePlayerRequestHeaders,payload: CreatePlayerPayload,success: CreatePlayerSuccess,error: CreatePlayerError,}),);export const ApiDefinition = HttpApi.make('Api').add(ApiGroupPlayers);import {GetPlayersError,GetPlayersQuery,GetPlayersRequestHeaders,GetPlayersSuccess,} from '@applications/gateway/src/api/players/get-players.schema';import { HttpApi, HttpApiEndpoint, HttpApiGroup } from 'effect/unstable/httpapi';const ApiGroupPlayers = HttpApiGroup.make('Players').add(HttpApiEndpoint.get('get-players', '/players', {headers: GetPlayersRequestHeaders,query: GetPlayersQuery,success: GetPlayersSuccess,error: GetPlayersError,}),);export const ApiDefinition = HttpApi.make('Api').add(ApiGroupPlayers);import {GetPlayerError,GetPlayerParameters,GetPlayerRequestHeaders,GetPlayerSuccess,} from '@applications/gateway/src/api/players/get-player.schema';import { HttpApi, HttpApiEndpoint, HttpApiGroup } from 'effect/unstable/httpapi';const ApiGroupPlayers = HttpApiGroup.make('Players').add(HttpApiEndpoint.get('get-player', '/players/:id', {headers: GetPlayerRequestHeaders,params: GetPlayerParameters,success: GetPlayerSuccess,error: GetPlayerError,}),);export const ApiDefinition = HttpApi.make('Api').add(ApiGroupPlayers);import {ReplacePlayerError,ReplacePlayerParameters,ReplacePlayerPayload,ReplacePlayerRequestHeaders,ReplacePlayerSuccess,} from '@applications/gateway/src/api/players/replace-player.schema';import { HttpApi, HttpApiEndpoint, HttpApiGroup } from 'effect/unstable/httpapi';const ApiGroupPlayers = HttpApiGroup.make('Players').add(HttpApiEndpoint.put('replace-player', '/players/:id', {headers: ReplacePlayerRequestHeaders,params: ReplacePlayerParameters,payload: ReplacePlayerPayload,success: ReplacePlayerSuccess,error: ReplacePlayerError,}),);export const ApiDefinition = HttpApi.make('Api').add(ApiGroupPlayers);import {UpdatePlayerError,UpdatePlayerParameters,UpdatePlayerPayload,UpdatePlayerRequestHeaders,UpdatePlayerSuccess,} from '@applications/gateway/src/api/players/update-player.schema';import { HttpApi, HttpApiEndpoint, HttpApiGroup } from 'effect/unstable/httpapi';const ApiGroupPlayers = HttpApiGroup.make('Players').add(HttpApiEndpoint.patch('update-player', '/players/:id', {headers: UpdatePlayerRequestHeaders,params: UpdatePlayerParameters,payload: UpdatePlayerPayload,success: UpdatePlayerSuccess,error: UpdatePlayerError,}),);export const ApiDefinition = HttpApi.make('Api').add(ApiGroupPlayers);import {DeletePlayerError,DeletePlayerParameters,DeletePlayerRequestHeaders,DeletePlayerSuccess,} from '@applications/gateway/src/api/players/delete-player.schema';import { HttpApi, HttpApiEndpoint, HttpApiGroup } from 'effect/unstable/httpapi';const ApiGroupPlayers = HttpApiGroup.make('Players').add(HttpApiEndpoint.delete('delete-player', '/players/:id', {headers: DeletePlayerRequestHeaders,params: DeletePlayerParameters,success: DeletePlayerSuccess,error: DeletePlayerError,}),);export const ApiDefinition = HttpApi.make('Api').add(ApiGroupPlayers);
API Handler
Section titled “API Handler”The API Handler fulfills a single API Endpoint — receiving the declared input, executing the logic, and producing the declared output.
// TODO: Add implementation