in packages/better-auth/src/plugins/open-api/generator.ts [274:468]
export async function generator(ctx: AuthContext, options: BetterAuthOptions) {
const baseEndpoints = getEndpoints(ctx, {
...options,
plugins: [],
});
const tables = getAuthTables(options);
const models = Object.entries(tables).reduce((acc, [key, value]) => {
const modelName = key.charAt(0).toUpperCase() + key.slice(1);
// @ts-ignore
acc[modelName] = {
type: "object",
properties: Object.entries(value.fields).reduce(
(acc, [key, value]) => {
acc[key] = {
type: value.type,
};
return acc;
},
{ id: { type: "string" } } as Record<string, any>,
),
};
return acc;
}, {});
const components = {
schemas: {
...models,
},
};
Object.entries(baseEndpoints.api).forEach(([_, value]) => {
if (ctx.options.disabledPaths?.includes(value.path)) return;
const options = value.options as EndpointOptions;
if (options.metadata?.SERVER_ONLY) return;
const path = toOpenApiPath(value.path);
if (options.method === "GET") {
paths[path] = {
get: {
tags: ["Default", ...(options.metadata?.openapi?.tags || [])],
description: options.metadata?.openapi?.description,
operationId: options.metadata?.openapi?.operationId,
security: [
{
bearerAuth: [],
},
],
parameters: getParameters(options),
responses: getResponse(options.metadata?.openapi?.responses),
},
};
}
if (options.method === "POST") {
const body = getRequestBody(options);
paths[path] = {
post: {
tags: ["Default", ...(options.metadata?.openapi?.tags || [])],
description: options.metadata?.openapi?.description,
operationId: options.metadata?.openapi?.operationId,
security: [
{
bearerAuth: [],
},
],
parameters: getParameters(options),
...(body
? { requestBody: body }
: {
requestBody: {
//set body none
content: {
"application/json": {
schema: {
type: "object",
properties: {},
},
},
},
},
}),
responses: getResponse(options.metadata?.openapi?.responses),
},
};
}
});
for (const plugin of options.plugins || []) {
if (plugin.id === "open-api") {
continue;
}
const pluginEndpoints = getEndpoints(ctx, {
...options,
plugins: [plugin],
});
const api = Object.keys(pluginEndpoints.api)
.map((key) => {
if (
baseEndpoints.api[key as keyof typeof baseEndpoints.api] === undefined
) {
return pluginEndpoints.api[key as keyof typeof pluginEndpoints.api];
}
return null;
})
.filter((x) => x !== null) as Endpoint[];
Object.entries(api).forEach(([key, value]) => {
if (ctx.options.disabledPaths?.includes(value.path)) return;
const options = value.options as EndpointOptions;
if (options.metadata?.SERVER_ONLY) return;
const path = toOpenApiPath(value.path);
if (options.method === "GET") {
paths[path] = {
get: {
tags: options.metadata?.openapi?.tags || [
plugin.id.charAt(0).toUpperCase() + plugin.id.slice(1),
],
description: options.metadata?.openapi?.description,
operationId: options.metadata?.openapi?.operationId,
security: [
{
bearerAuth: [],
},
],
parameters: getParameters(options),
responses: getResponse(options.metadata?.openapi?.responses),
},
};
}
if (options.method === "POST") {
paths[path] = {
post: {
tags: options.metadata?.openapi?.tags || [
plugin.id.charAt(0).toUpperCase() + plugin.id.slice(1),
],
description: options.metadata?.openapi?.description,
operationId: options.metadata?.openapi?.operationId,
security: [
{
bearerAuth: [],
},
],
parameters: getParameters(options),
requestBody: getRequestBody(options),
responses: getResponse(options.metadata?.openapi?.responses),
},
};
}
});
}
const res = {
openapi: "3.1.1",
info: {
title: "Better Auth",
description: "API Reference for your Better Auth Instance",
version: "1.1.0",
},
components: {
...components,
securitySchemes: {
apiKeyCookie: {
type: "apiKey",
in: "cookie",
name: "apiKeyCookie",
description: "API Key authentication via cookie",
},
bearerAuth: {
type: "http",
scheme: "bearer",
description: "Bearer token authentication",
},
},
},
security: [
{
apiKeyCookie: [],
bearerAuth: [],
},
],
servers: [
{
url: ctx.baseURL,
},
],
tags: [
{
name: "Default",
description:
"Default endpoints that are included with Better Auth by default. These endpoints are not part of any plugin.",
},
],
paths,
};
return res;
}