diff --git a/src/app.ts b/src/app.ts index d680d93..bf53750 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,10 +1,12 @@ import express from "express" -import { Application, Request, Response, NextFunction } from "express" +import { Express, Request, Response, NextFunction } from "express" import cors from "cors" import router from "./routes" import { authMiddleware } from "./middleware" +import setupSwagger from "./utils/swagger" +import { StatusCodes } from "http-status-codes" -const app: Application = express() +const app: Express = express() app.use(cors()) app.use(express.urlencoded({ extended: true })) @@ -15,6 +17,10 @@ app.use((req: Request, res: Response, next) => { next() }) +app.get("/", (req: Request, res: Response) => { + return res.sendStatus(StatusCodes.OK) +}) app.use("/api/store", authMiddleware, router) +setupSwagger(app) export default app diff --git a/src/routes/index.ts b/src/routes/index.ts index 5788c0d..b331e5b 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -9,12 +9,196 @@ const upload = multer({ }) // Set Data +/** + * @swagger + * /set-data: + * post: + * summary: Set data + * tags: + * requestBody: + * required: true + * content: + * multipart/form-data: + * schema: + * type: object + * properties: + * dataset: + * type: string + * description: Name of the dataset + * id: + * type: string + * description: ID for the data + * name: + * type: string + * description: Name of the data + * replace: + * type: boolean + * description: Whether to replace existing data + * data: + * type: string + * format: binary + * description: Data file + * application/json: + * schema: + * type: object + * properties: + * dataset: + * type: string + * description: Name of the dataset + * id: + * type: string + * description: ID for the data + * name: + * type: string + * description: Name of the data + * replace: + * type: boolean + * description: Whether to replace existing data + * data: + * type: string + * description: Data in JSON format + * responses: + * '200': + * description: Data saved successfully + * content: + * application/json: + * schema: + * type: object + * properties: + * version: + * type: integer + * description: Version of the data + * '400': + * description: Bad request + * content: + * application/json: + * schema: + * type: object + * properties: + * error: + * type: string + * description: Error message + * '500': + * description: Internal server error + * content: + * application/json: + * schema: + * type: object + * properties: + * error: + * type: string + * description: Error message + */ router.post("/set-data", upload.single("data"), handlers.setData) // Get Data +/** + * @swagger + * /get-data: + * post: + * summary: Get data + * tags: + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * dataset: + * type: string + * description: Name of the dataset + * id: + * type: string + * description: ID for the data + * name: + * type: string + * description: Name of the data + * version: + * type: integer + * description: Version of the data + * required: false + * responses: + * '302': + * description: Redirect to the requested data + * '400': + * description: Bad request + * content: + * application/json: + * schema: + * type: object + * properties: + * error: + * type: string + * description: Error message + * '404': + * description: Data not found + * content: + * application/json: + * schema: + * type: object + * properties: + * error: + * type: string + * description: Error message + */ router.post("/get-data", handlers.getData) // Has Data +/** + * @swagger + * /has-data: + * post: + * summary: Check if data exists + * tags: + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * dataset: + * type: string + * description: Name of the dataset + * id: + * type: string + * description: ID for the data + * name: + * type: string + * description: Name of the data + * responses: + * '200': + * description: Check for data completed + * content: + * application/json: + * schema: + * type: object + * properties: + * data: + * type: boolean + * description: Indicates whether the data exists + * '400': + * description: Bad request + * content: + * application/json: + * schema: + * type: object + * properties: + * error: + * type: string + * description: Error message + * '500': + * description: Internal server error + * content: + * application/json: + * schema: + * type: object + * properties: + * error: + * type: string + * description: Error message + */ router.post("/has-data", handlers.hasData) export default router diff --git a/src/utils/swagger.ts b/src/utils/swagger.ts new file mode 100644 index 0000000..13420cb --- /dev/null +++ b/src/utils/swagger.ts @@ -0,0 +1,40 @@ +import swaggerUi from "swagger-ui-express" +import swaggerJsdoc from "swagger-jsdoc" +import { Express } from "express" +import { version } from "../../package.json" + +const options = { + definition: { + openapi: "3.0.0", + info: { + title: "STORE API Docs", + version: version ?? "1.0.0", + }, + security: [ + { + apiKeyAuth: [] as string[], + }, + ], + components: { + securitySchemes: { + apiKeyAuth: { + type: "apiKey", + in: "header", + name: "x-api-key", + }, + }, + }, + servers: [ + { + url: "https://data.storybrain.io/api/store", + }, + ], + }, + apis: ["./src/routes/*.ts"], +} + +const specs = swaggerJsdoc(options) + +export default function setupSwagger(app: Express) { + app.use("/store-docs", swaggerUi.serve, swaggerUi.setup(specs)) +}