Files
bknd/app/src/modules/server/openapi.ts

313 lines
8.3 KiB
TypeScript

import { Type } from "core/utils";
import type { ModuleConfigs } from "modules/ModuleManager";
import type { OpenAPIV3 as OAS } from "openapi-types";
function prefixPaths(paths: OAS.PathsObject, prefix: string): OAS.PathsObject {
const result: OAS.PathsObject = {};
for (const [path, pathItem] of Object.entries(paths)) {
result[`${prefix}${path}`] = pathItem;
}
return result;
}
function systemRoutes(config: ModuleConfigs): { paths: OAS.Document["paths"] } {
const tags = ["system"];
const paths: OAS.PathsObject = {
"/ping": {
get: {
summary: "Ping",
responses: {
"200": {
description: "Pong",
content: {
"application/json": {
schema: Type.Object({
pong: Type.Boolean({ default: true }),
}),
},
},
},
},
tags,
},
},
"/config": {
get: {
summary: "Get config",
responses: {
"200": {
description: "Config",
content: {
"application/json": {
schema: Type.Object({
version: Type.Number() as any,
server: Type.Object({}),
data: Type.Object({}),
auth: Type.Object({}),
flows: Type.Object({}),
media: Type.Object({}),
}),
},
},
},
},
tags,
},
},
"/schema": {
get: {
summary: "Get config",
responses: {
"200": {
description: "Config",
content: {
"application/json": {
schema: Type.Object({
version: Type.Number() as any,
schema: Type.Object({
server: Type.Object({}),
data: Type.Object({}),
auth: Type.Object({}),
flows: Type.Object({}),
media: Type.Object({}),
}),
}),
},
},
},
},
tags,
},
},
};
return { paths: prefixPaths(paths, "/api/system") };
}
function dataRoutes(config: ModuleConfigs): { paths: OAS.Document["paths"] } {
const schemas = {
entityData: Type.Object({
id: Type.Number() as any,
}),
};
const repoManyResponses: OAS.ResponsesObject = {
"200": {
description: "List of entities",
content: {
"application/json": {
schema: Type.Array(schemas.entityData),
},
},
},
};
const repoSingleResponses: OAS.ResponsesObject = {
"200": {
description: "Entity",
content: {
"application/json": {
schema: schemas.entityData,
},
},
},
};
const params = {
entity: {
name: "entity",
in: "path",
required: true,
schema: Type.String(),
},
entityId: {
name: "id",
in: "path",
required: true,
schema: Type.Number() as any,
},
};
const tags = ["data"];
const paths: OAS.PathsObject = {
"/entity/{entity}": {
get: {
summary: "List entities",
parameters: [params.entity],
responses: repoManyResponses,
tags,
},
post: {
summary: "Create entity",
parameters: [params.entity],
requestBody: {
content: {
"application/json": {
schema: Type.Object({}),
},
},
},
responses: repoSingleResponses,
tags,
},
},
"/entity/{entity}/{id}": {
get: {
summary: "Get entity",
parameters: [params.entity, params.entityId],
responses: repoSingleResponses,
tags,
},
patch: {
summary: "Update entity",
parameters: [params.entity, params.entityId],
requestBody: {
content: {
"application/json": {
schema: Type.Object({}),
},
},
},
responses: repoSingleResponses,
tags,
},
delete: {
summary: "Delete entity",
parameters: [params.entity, params.entityId],
responses: {
"200": {
description: "Entity deleted",
},
},
tags,
},
},
};
return { paths: prefixPaths(paths, config.data.basepath!) };
}
function authRoutes(config: ModuleConfigs): { paths: OAS.Document["paths"] } {
const schemas = {
user: Type.Object({
id: Type.String(),
email: Type.String(),
name: Type.String(),
}),
};
const tags = ["auth"];
const paths: OAS.PathsObject = {
"/password/login": {
post: {
summary: "Login",
requestBody: {
content: {
"application/json": {
schema: Type.Object({
email: Type.String(),
password: Type.String(),
}),
},
},
},
responses: {
"200": {
description: "User",
content: {
"application/json": {
schema: Type.Object({
user: schemas.user,
}),
},
},
},
},
tags,
},
},
"/password/register": {
post: {
summary: "Register",
requestBody: {
content: {
"application/json": {
schema: Type.Object({
email: Type.String(),
password: Type.String(),
}),
},
},
},
responses: {
"200": {
description: "User",
content: {
"application/json": {
schema: Type.Object({
user: schemas.user,
}),
},
},
},
},
tags,
},
},
"/me": {
get: {
summary: "Get me",
responses: {
"200": {
description: "User",
content: {
"application/json": {
schema: Type.Object({
user: schemas.user,
}),
},
},
},
},
tags,
},
},
"/strategies": {
get: {
summary: "Get auth strategies",
responses: {
"200": {
description: "Strategies",
content: {
"application/json": {
schema: Type.Object({
strategies: Type.Object({}),
}),
},
},
},
},
tags,
},
},
};
return { paths: prefixPaths(paths, config.auth.basepath!) };
}
export function generateOpenAPI(config: ModuleConfigs): OAS.Document {
const system = systemRoutes(config);
const data = dataRoutes(config);
const auth = authRoutes(config);
return {
openapi: "3.1.0",
info: {
title: "bknd API",
version: "0.0.0",
},
paths: {
...system.paths,
...data.paths,
...auth.paths,
},
};
}