From 785cfc71f536d39223dda5d5dd315ec585b157d0 Mon Sep 17 00:00:00 2001 From: andwati Date: Tue, 13 Jan 2026 02:47:50 +0300 Subject: [PATCH] swagger ui --- package.json | 3 +- src/config/swagger.ts | 14 ++++++ src/models/order.model.ts | 40 ++++++++++++++++ src/models/product.model.ts | 28 +++++++++++ src/models/user.model.ts | 26 ++++++++++ src/routes/auth.routes.ts | 55 +++++++++++++++++++++ src/routes/docs.routes.ts | 7 ++- src/routes/order.routes.ts | 92 ++++++++++++++++++++++++++++++++++++ src/routes/product.routes.ts | 65 +++++++++++++++++++++++++ tsconfig.json | 3 +- 10 files changed, 329 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 04bc73c..cbd57d8 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,6 @@ "main": "index.js", "scripts": { "start": "node dist/server.js", - "dev": "ts-node --transpile-only src/server.ts", "build": "tsc", "lint": "eslint . --ext .ts", "lint:fix": "eslint . --ext .ts --fix", @@ -51,4 +50,4 @@ "typescript": "^5.9.3", "typescript-eslint": "^8.52.0" } -} +} \ No newline at end of file diff --git a/src/config/swagger.ts b/src/config/swagger.ts index 4a91b6e..69b5072 100644 --- a/src/config/swagger.ts +++ b/src/config/swagger.ts @@ -13,6 +13,20 @@ const options = { url: `http://localhost:${process.env.PORT || 3000}`, }, ], + components: { + securitySchemes: { + BearerAuth: { + type: "http", + scheme: "bearer", + bearerFormat: "JWT", + }, + }, + }, + security: [ + { + BearerAuth: [], + }, + ], }, apis: ["./src/routes/*.ts", "./src/controllers/*.ts", "./src/models/*.ts"], }; diff --git a/src/models/order.model.ts b/src/models/order.model.ts index fd4cd51..c9358bc 100644 --- a/src/models/order.model.ts +++ b/src/models/order.model.ts @@ -75,4 +75,44 @@ const orderSchema = new Schema( }, ); +/** + * @openapi + * components: + * schemas: + * Order: + * type: object + * properties: + * _id: + * type: string + * description: The order ID + * userId: + * type: string + * description: The user ID who placed the order + * items: + * type: array + * items: + * type: object + * properties: + * productId: + * type: string + * quantity: + * type: number + * unitPrice: + * type: number + * total: + * type: number + * description: The total order amount in cents + * status: + * type: string + * enum: [created, paid, cancelled] + * description: The order status + * createdAt: + * type: string + * format: date-time + * description: The date the order was created + * updatedAt: + * type: string + * format: date-time + * description: The date the order was updated + */ export const OrderModel = model("Order", orderSchema); diff --git a/src/models/product.model.ts b/src/models/product.model.ts index 7558208..5393749 100644 --- a/src/models/product.model.ts +++ b/src/models/product.model.ts @@ -37,4 +37,32 @@ const productSchema = new Schema( }, ); +/** + * @openapi + * components: + * schemas: + * Product: + * type: object + * properties: + * _id: + * type: string + * description: The product ID + * name: + * type: string + * description: The product name + * price: + * type: number + * description: The product price in cents + * stock: + * type: number + * description: The product stock quantity + * createdAt: + * type: string + * format: date-time + * description: The date the product was created + * updatedAt: + * type: string + * format: date-time + * description: The date the product was updated + */ export const ProductModel = model("Product", productSchema); diff --git a/src/models/user.model.ts b/src/models/user.model.ts index 022bcc0..d7f626f 100644 --- a/src/models/user.model.ts +++ b/src/models/user.model.ts @@ -40,4 +40,30 @@ const userSchema = new Schema( }, ); +/** + * @openapi + * components: + * schemas: + * User: + * type: object + * properties: + * _id: + * type: string + * description: The user ID + * email: + * type: string + * description: The user's email + * role: + * type: string + * enum: [admin, customer] + * description: The user's role + * createdAt: + * type: string + * format: date-time + * description: The date the user was created + * updatedAt: + * type: string + * format: date-time + * description: The date the user was updated + */ export const UserModel = model("User", userSchema); diff --git a/src/routes/auth.routes.ts b/src/routes/auth.routes.ts index 3ee7f42..26d3e37 100644 --- a/src/routes/auth.routes.ts +++ b/src/routes/auth.routes.ts @@ -6,6 +6,30 @@ import { registerSchema, loginSchema } from "../validation/auth.schema.js"; const router: Router = Router(); +/** + * @openapi + * /auth/register: + * post: + * tags: + * - Auth + * summary: Register a new user + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * email: + * type: string + * password: + * type: string + * responses: + * 201: + * description: User created + * 400: + * description: Invalid input + */ router.post( "/register", authRateLimiter, @@ -13,6 +37,37 @@ router.post( AuthController.register, ); +/** + * @openapi + * /auth/login: + * post: + * tags: + * - Auth + * summary: Login a user + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * email: + * type: string + * password: + * type: string + * responses: + * 200: + * description: Login successful + * content: + * application/json: + * schema: + * type: object + * properties: + * token: + * type: string + * 401: + * description: Invalid credentials + */ router.post( "/login", authRateLimiter, diff --git a/src/routes/docs.routes.ts b/src/routes/docs.routes.ts index 2c7eb6e..ae0fac8 100644 --- a/src/routes/docs.routes.ts +++ b/src/routes/docs.routes.ts @@ -1,10 +1,15 @@ import express from "express"; -import swaggerUi from "swagger-ui-express"; +import * as swaggerUi from "swagger-ui-express"; import swaggerSpec from "../config/swagger.js"; import { Router } from "express"; const router: Router = express.Router(); +router.use("/", (req, res, next) => { + console.log("Serving Swagger UI at", req.originalUrl); + next(); +}); + router.use("/", swaggerUi.serve, swaggerUi.setup(swaggerSpec)); export default router; diff --git a/src/routes/order.routes.ts b/src/routes/order.routes.ts index 90abc68..9ee1db6 100644 --- a/src/routes/order.routes.ts +++ b/src/routes/order.routes.ts @@ -10,6 +10,37 @@ import { const router: Router = Router(); +/** + * @openapi + * /orders: + * post: + * tags: + * - Orders + * summary: Create a new order + * security: + * - BearerAuth: [] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * items: + * type: array + * items: + * type: object + * properties: + * productId: + * type: string + * quantity: + * type: number + * responses: + * 201: + * description: Order created + * 400: + * description: Invalid input + */ router.post( "/", authMiddleware, @@ -18,8 +49,48 @@ router.post( OrderController.create, ); +/** + * @openapi + * /orders: + * get: + * tags: + * - Orders + * summary: List my orders + * security: + * - BearerAuth: [] + * responses: + * 200: + * description: List of orders + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Order' + */ router.get("/", authMiddleware, OrderController.list); +/** + * @openapi + * /orders/{id}/pay: + * post: + * tags: + * - Orders + * summary: Pay for an order + * security: + * - BearerAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * responses: + * 200: + * description: Order paid + * 404: + * description: Order not found + */ router.post( "/:id/pay", authMiddleware, @@ -27,6 +98,27 @@ router.post( OrderController.pay, ); +/** + * @openapi + * /orders/{id}/cancel: + * post: + * tags: + * - Orders + * summary: Cancel an order + * security: + * - BearerAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * responses: + * 200: + * description: Order cancelled + * 404: + * description: Order not found + */ router.post( "/:id/cancel", authMiddleware, diff --git a/src/routes/product.routes.ts b/src/routes/product.routes.ts index 6c60c20..e64e763 100644 --- a/src/routes/product.routes.ts +++ b/src/routes/product.routes.ts @@ -10,6 +10,27 @@ import { const router: Router = Router(); +/** + * @openapi + * /products: + * post: + * tags: + * - Products + * summary: Create a product + * security: + * - BearerAuth: [] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Product' + * responses: + * 201: + * description: Product created + * 403: + * description: Not authorized + */ router.post( "/", authMiddleware, @@ -18,6 +39,33 @@ router.post( ProductController.create, ); +/** + * @openapi + * /products/{id}: + * patch: + * tags: + * - Products + * summary: Update a product + * security: + * - BearerAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * requestBody: + * required: true + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Product' + * responses: + * 200: + * description: Product updated + * 404: + * description: Product not found + */ router.patch( "/:id", authMiddleware, @@ -26,6 +74,23 @@ router.patch( ProductController.update, ); +/** + * @openapi + * /products: + * get: + * tags: + * - Products + * summary: List all products + * responses: + * 200: + * description: List of products + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Product' + */ router.get("/", ProductController.list); export default router; diff --git a/tsconfig.json b/tsconfig.json index f39be98..4341121 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -39,7 +39,8 @@ "isolatedModules": true, "noUncheckedSideEffectImports": true, "moduleDetection": "force", - "skipLibCheck": true + "skipLibCheck": true, + "esModuleInterop": true }, "include": ["src/**/*"],