Skip to main content

src/oaisp.erl

-module(oaisp).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/oaisp.gleam").
-export([type_ref/2, info/2, add_openapi/3]).

-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.

?MODULEDOC(
    " oaisp — a code-first OpenAPI 3.1 generator for Wisp applications on the BEAM.\n"
    "\n"
    " You declare your API as a list of [`Route`](./oaisp/route.html)s — each\n"
    " binding a path + method to a handler and carrying its OpenAPI annotations.\n"
    " That single list drives both your running server (`route.match`) and the\n"
    " emitted document, so the two can't drift. One CLI command\n"
    " (`gleam run -m oaisp/cli generate`) writes a truthful OpenAPI 3.1 document\n"
    " at build time.\n"
    "\n"
    " This module is the public surface. The route builders live in\n"
    " [`oaisp/route`](./oaisp/route.html), scalar param helpers in\n"
    " [`oaisp/param`](./oaisp/param.html), and the CLI in\n"
    " [`oaisp/cli`](./oaisp/cli.html).\n"
).

-file("src/oaisp.gleam", 39).
?DOC(
    " A schema referring to a public Gleam type, resolved at merge time from the\n"
    " package interface.\n"
).
-spec type_ref(binary(), binary()) -> oaisp@schema:schema().
type_ref(Module, Name) ->
    oaisp@schema:type_ref(Module, Name).

-file("src/oaisp.gleam", 44).
?DOC(" Document metadata with no description and no servers; spread to override.\n").
-spec info(binary(), binary()) -> oaisp@info:info().
info(Title, Version) ->
    oaisp@info:info(Title, Version).

-file("src/oaisp.gleam", 63).
?DOC(
    " The build-time hook. Drop it into your server builder pipeline alongside the\n"
    " same `routes` you dispatch with `route.match`:\n"
    "\n"
    " ```gleam\n"
    " wisp_mist.handler(handle(routes), secret_key_base)\n"
    " |> mist.new\n"
    " |> oaisp.add_openapi(routes, info)\n"
    " |> mist.port(8080)\n"
    " |> mist.start\n"
    " ```\n"
    "\n"
    " Run with `--emit-endpoints` (as the CLI does internally) it prints the\n"
    " declarations and exits; otherwise it returns `builder` untouched. It is\n"
    " generic in the builder and never inspects it, so oaisp needs no dependency\n"
    " on `mist` or any server library.\n"
).
-spec add_openapi(EPQ, list(oaisp@route:route(any())), oaisp@info:info()) -> EPQ.
add_openapi(Builder, Routes, Info) ->
    case gleam@list:contains(
        erlang:element(4, argv:load()),
        <<"--emit-endpoints"/utf8>>
    ) of
        true ->
            gleam_stdlib:println(
                oaisp@internal@emit:to_string(
                    {document, Info, oaisp@route:to_endpoints(Routes)}
                )
            ),
            erlang:halt(0);

        false ->
            Builder
    end.