mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 00:32:12 +02:00
371 lines
10 KiB
TypeScript
371 lines
10 KiB
TypeScript
import {
|
|
OpenAPIRegistry,
|
|
OpenApiGeneratorV3,
|
|
} from "@asteasolutions/zod-to-openapi";
|
|
import DatabaseBaseModel from "../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
import Models from "../../Models/DatabaseModels/Index";
|
|
import { JSONObject } from "../../Types/JSON";
|
|
|
|
export default class OpenAPIUtil {
|
|
public static generateOpenAPISpec(): JSONObject {
|
|
const registry: OpenAPIRegistry = new OpenAPIRegistry();
|
|
|
|
// Register schemas and paths for all models
|
|
for (const ModelClass of Models) {
|
|
const model: DatabaseBaseModel = new ModelClass();
|
|
const modelName: string = model.constructor.name;
|
|
const basePath: string = `/api/${modelName.toLowerCase()}`;
|
|
// Use a plain object for paths
|
|
const paths: Record<string, Record<string, any>> = {};
|
|
|
|
// List endpoints (POST and GET)
|
|
paths[`${basePath}/get-list`] = {
|
|
post: this.generateListApiSpec({ modelType: ModelClass }),
|
|
get: this.generateListApiSpec({ modelType: ModelClass }),
|
|
};
|
|
// Count endpoint
|
|
paths[`${basePath}/count`] = {
|
|
post: this.generateCountApiSpec({ modelType: ModelClass }),
|
|
};
|
|
// Create endpoint
|
|
paths[basePath] = {
|
|
post: this.generateCreateApiSpec({ modelType: ModelClass }),
|
|
};
|
|
// Get item endpoints (POST and GET)
|
|
paths[`${basePath}/{id}/get-item`] = {
|
|
post: this.generateGetApiSpec({ modelType: ModelClass }),
|
|
get: this.generateGetApiSpec({ modelType: ModelClass }),
|
|
};
|
|
// Update endpoints (PUT, POST, GET)
|
|
if (!paths[`${basePath}/{id}`]) {
|
|
paths[`${basePath}/{id}`] = {};
|
|
}
|
|
|
|
paths[`${basePath}/{id}`]!["put"] = this.generateUpdateApiSpec({
|
|
modelType: ModelClass,
|
|
});
|
|
paths[`${basePath}/{id}/update-item`] = {
|
|
post: this.generateUpdateApiSpec({ modelType: ModelClass }),
|
|
get: this.generateUpdateApiSpec({ modelType: ModelClass }),
|
|
};
|
|
// Delete endpoints (DELETE, POST, GET)
|
|
if (!paths[`${basePath}/{id}`]) {
|
|
paths[`${basePath}/{id}`] = {};
|
|
}
|
|
paths[`${basePath}/{id}`]!["delete"] = this.generateDeleteApiSpec({
|
|
modelType: ModelClass,
|
|
});
|
|
paths[`${basePath}/{id}/delete-item`] = {
|
|
post: this.generateDeleteApiSpec({ modelType: ModelClass }),
|
|
get: this.generateDeleteApiSpec({ modelType: ModelClass }),
|
|
};
|
|
|
|
// Register the paths in the registry
|
|
for (const path in paths) {
|
|
if (paths[path]) {
|
|
const methods: Record<string, any> | undefined = paths[path];
|
|
if (typeof methods === "object" && methods !== null) {
|
|
for (const method in methods) {
|
|
if (methods[method]) {
|
|
const spec: any = methods[method];
|
|
registry.registerPath({
|
|
method: method as any,
|
|
path,
|
|
...spec,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const generator: OpenApiGeneratorV3 = new OpenApiGeneratorV3(
|
|
registry.definitions,
|
|
);
|
|
|
|
const components: Pick<any, "components"> = generator.generateComponents();
|
|
|
|
return {
|
|
openapi: "3.0.0",
|
|
info: {
|
|
title: "API Documentation",
|
|
version: "1.0.0",
|
|
description: "API documentation generated from models",
|
|
},
|
|
components: components,
|
|
} as unknown as JSONObject;
|
|
}
|
|
|
|
public static generateListApiSpec(data: {
|
|
modelType: new () => DatabaseBaseModel;
|
|
}): JSONObject {
|
|
const modelType: new () => DatabaseBaseModel = data.modelType;
|
|
const model: DatabaseBaseModel = new modelType();
|
|
return {
|
|
summary: `List ${model.constructor.name}`,
|
|
description: `Endpoint to list all ${model.constructor.name} items`,
|
|
requestBody: {
|
|
required: false,
|
|
content: {
|
|
"application/json": {
|
|
schema: {
|
|
type: "object",
|
|
properties: {
|
|
query: { type: "object" },
|
|
select: { type: "object" },
|
|
sort: { type: "object" },
|
|
groupBy: { type: "object" },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
responses: {
|
|
"200": {
|
|
description: "Successful response",
|
|
content: {
|
|
"application/json": {
|
|
schema: {
|
|
type: "object",
|
|
properties: {
|
|
data: {
|
|
type: "array",
|
|
items: {
|
|
$ref: `#/components/schemas/${model.constructor.name}`,
|
|
},
|
|
},
|
|
count: { type: "number" },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
public static generateCountApiSpec(data: {
|
|
modelType: new () => DatabaseBaseModel;
|
|
}): JSONObject {
|
|
const modelType: new () => DatabaseBaseModel = data.modelType;
|
|
const model: DatabaseBaseModel = new modelType();
|
|
return {
|
|
summary: `Count ${model.constructor.name}`,
|
|
description: `Endpoint to count ${model.constructor.name} items`,
|
|
requestBody: {
|
|
required: false,
|
|
content: {
|
|
"application/json": {
|
|
schema: {
|
|
type: "object",
|
|
properties: {
|
|
query: { type: "object" },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
responses: {
|
|
"200": {
|
|
description: "Successful response",
|
|
content: {
|
|
"application/json": {
|
|
schema: {
|
|
type: "object",
|
|
properties: {
|
|
count: { type: "number" },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
public static generateCreateApiSpec(data: {
|
|
modelType: new () => DatabaseBaseModel;
|
|
}): JSONObject {
|
|
const modelType: new () => DatabaseBaseModel = data.modelType;
|
|
const model: DatabaseBaseModel = new modelType();
|
|
return {
|
|
summary: `Create ${model.constructor.name}`,
|
|
description: `Endpoint to create a new ${model.constructor.name}`,
|
|
requestBody: {
|
|
required: true,
|
|
content: {
|
|
"application/json": {
|
|
schema: {
|
|
type: "object",
|
|
properties: {
|
|
data: {
|
|
$ref: `#/components/schemas/${model.constructor.name}Input`,
|
|
},
|
|
miscDataProps: { type: "object" },
|
|
},
|
|
required: ["data"],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
responses: {
|
|
"201": {
|
|
description: "Created successfully",
|
|
content: {
|
|
"application/json": {
|
|
schema: {
|
|
type: "object",
|
|
properties: {
|
|
data: {
|
|
$ref: `#/components/schemas/${model.constructor.name}`,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"400": {
|
|
description: "Bad request",
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
public static generateGetApiSpec(data: {
|
|
modelType: new () => DatabaseBaseModel;
|
|
}): JSONObject {
|
|
const modelType: new () => DatabaseBaseModel = data.modelType;
|
|
const model: DatabaseBaseModel = new modelType();
|
|
return {
|
|
summary: `Get ${model.constructor.name}`,
|
|
description: `Endpoint to retrieve a single ${model.constructor.name} by ID`,
|
|
parameters: [
|
|
{
|
|
name: "id",
|
|
in: "path",
|
|
required: true,
|
|
schema: {
|
|
type: "string",
|
|
format: "uuid",
|
|
},
|
|
description: `ID of the ${model.constructor.name} to retrieve`,
|
|
},
|
|
],
|
|
responses: {
|
|
"200": {
|
|
description: "Successful response",
|
|
content: {
|
|
"application/json": {
|
|
schema: {
|
|
type: "object",
|
|
properties: {
|
|
data: {
|
|
$ref: `#/components/schemas/${model.constructor.name}`,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"404": {
|
|
description: "Resource not found",
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
public static generateUpdateApiSpec(data: {
|
|
modelType: new () => DatabaseBaseModel;
|
|
}): JSONObject {
|
|
const modelType: new () => DatabaseBaseModel = data.modelType;
|
|
const model: DatabaseBaseModel = new modelType();
|
|
return {
|
|
summary: `Update ${model.constructor.name}`,
|
|
description: `Endpoint to update an existing ${model.constructor.name}`,
|
|
parameters: [
|
|
{
|
|
name: "id",
|
|
in: "path",
|
|
required: true,
|
|
schema: {
|
|
type: "string",
|
|
format: "uuid",
|
|
},
|
|
description: `ID of the ${model.constructor.name} to update`,
|
|
},
|
|
],
|
|
requestBody: {
|
|
required: true,
|
|
content: {
|
|
"application/json": {
|
|
schema: {
|
|
type: "object",
|
|
properties: {
|
|
data: {
|
|
$ref: `#/components/schemas/${model.constructor.name}UpdateInput`,
|
|
},
|
|
},
|
|
required: ["data"],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
responses: {
|
|
"200": {
|
|
description: "Updated successfully",
|
|
content: {
|
|
"application/json": {
|
|
schema: {
|
|
type: "object",
|
|
properties: {
|
|
data: {
|
|
$ref: `#/components/schemas/${model.constructor.name}`,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"404": {
|
|
description: "Resource not found",
|
|
},
|
|
"400": {
|
|
description: "Bad request",
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
public static generateDeleteApiSpec(data: {
|
|
modelType: new () => DatabaseBaseModel;
|
|
}): JSONObject {
|
|
const modelType: new () => DatabaseBaseModel = data.modelType;
|
|
const model: DatabaseBaseModel = new modelType();
|
|
return {
|
|
summary: `Delete ${model.constructor.name}`,
|
|
description: `Endpoint to delete a ${model.constructor.name}`,
|
|
parameters: [
|
|
{
|
|
name: "id",
|
|
in: "path",
|
|
required: true,
|
|
schema: {
|
|
type: "string",
|
|
format: "uuid",
|
|
},
|
|
description: `ID of the ${model.constructor.name} to delete`,
|
|
},
|
|
],
|
|
responses: {
|
|
"204": {
|
|
description: "Deleted successfully",
|
|
},
|
|
"404": {
|
|
description: "Resource not found",
|
|
},
|
|
},
|
|
};
|
|
}
|
|
}
|