🧁
Confect
GitHubnpm
  • Introduction
  • Getting started
  • HTTP APIs
  • Schema restrictions
Powered by GitBook
On this page
  • Usage
  • 1. Define your HTTP API
  • 2. Make a Convex HTTP router
  • OpenAPI Documentation
  • Read more

HTTP APIs

PreviousGetting startedNextSchema restrictions

Last updated 6 months ago

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

Usage

1. Define your HTTP API

2. Make a Convex HTTP router

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

If you'd like to mount an Effect HTTP API to a subpath, you must be sure that your API is prefixed with the same subpath, as this will not (yet) be done automatically for you. The easiest way to do this right now is .

OpenAPI Documentation

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

Read more

See the for detailed information on how to build an HTTP API with Effect.

Convex site URL
myApi.prefix("my-subpath")
Scalar
@effect/platform HTTP API docs
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),
  },
});
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),
);