HTTP APIs

Confect allows you to use Effect to build your Convex HTTP API(s).

Usage

1. Define your HTTP API

https://github.com/rjdellecese/confect/blob/main/example/convex/http/api.ts
import {
  HttpApi,
  HttpApiBuilder,
  HttpApiEndpoint,
  HttpApiGroup,
  OpenApi,
} from "@effect/platform";
import type { HttpApiDecodeError } from "@effect/platform/HttpApiError";
import { Effect, Layer, Option, Schema } from "effect";
import { api } from "../_generated/api";
import { ConfectActionCtx } from "../confect";
import { GetFirstResult } from "../functions.schemas";
import { confectSchema } from "../schema";

class ApiGroup extends HttpApiGroup.make("notes")
  .add(
    HttpApiEndpoint.get("getFirst", "/get-first")
      .annotate(OpenApi.Description, "Get the first note, if there is one.")
      .addSuccess(
        Schema.NullOr(confectSchema.tableSchemas.notes.withSystemFields),
      ),
  )
  .annotate(OpenApi.Title, "Notes")
  .annotate(OpenApi.Description, "Operations on notes.") {}

export class Api extends HttpApi.make("Api")
  .annotate(OpenApi.Title, "Confect Example")
  .annotate(
    OpenApi.Description,
    `
An example API built with Confect and powered by [Scalar](https://github.com/scalar/scalar). 

# Learn More

See Scalar's documentation on [markdown support](https://github.com/scalar/scalar/blob/main/documentation/markdown.md) and [OpenAPI spec extensions](https://github.com/scalar/scalar/blob/main/documentation/openapi.md).
	`,
  )
  .add(ApiGroup)
  .prefix("/path-prefix") {}

const ApiGroupLive = HttpApiBuilder.group(Api, "notes", (handlers) =>
  handlers.handle(
    "getFirst",
    (): Effect.Effect<
      (typeof confectSchema.tableSchemas.notes.withSystemFields)["Type"] | null,
      HttpApiDecodeError,
      ConfectActionCtx
    > =>
      Effect.gen(function* () {
        const { runQuery } = yield* ConfectActionCtx;

        const firstNote = yield* runQuery(api.functions.getFirst, {}).pipe(
          Effect.andThen(Schema.decode(GetFirstResult)),
          Effect.map(Option.getOrNull),
          Effect.orDie,
        );

        return firstNote;
      }),
  ),
);

export const ApiLive = HttpApiBuilder.api(Api).pipe(
  Layer.provide(ApiGroupLive),
);

2. Make a Convex HTTP router

You can mount your Effect HTTP API to the root path of your Convex site URL, or to any subpath. You can even mount multiple Effect HTTP APIs to different subpaths!

https://github.com/rjdellecese/confect/blob/main/example/convex/http.ts
import { makeHttpRouter } from "@rjdellecese/confect/server";

import { HttpMiddleware } from "@effect/platform";
import { flow } from "effect";
import { ApiLive } from "./http/api";

export default makeHttpRouter({
  "/path-prefix/": {
    apiLive: ApiLive,
    middleware: flow(HttpMiddleware.cors(), HttpMiddleware.logger),
  },
});

OpenAPI Documentation

Each Effect HTTP API will be accompanied by its own live OpenAPI documentation page, powered by Scalar. This can be configured via the scalar property.

Read more

See the @effect/platform HTTP API docs for detailed information on how to build an HTTP API with Effect.

Last updated