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
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 myApi.prefix("my-subpath")
.
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