349 lines
9.2 KiB
JavaScript
349 lines
9.2 KiB
JavaScript
const swaggerJsdoc = require('swagger-jsdoc');
|
|
|
|
const options = {
|
|
definition: {
|
|
openapi: '3.0.0',
|
|
info: {
|
|
title: 'Interview Quiz Application API',
|
|
version: '1.0.0',
|
|
description: 'Comprehensive API documentation for the Interview Quiz Application. This API provides endpoints for user authentication, quiz management, guest sessions, bookmarks, and admin operations.',
|
|
contact: {
|
|
name: 'API Support',
|
|
email: 'support@interviewquiz.com'
|
|
},
|
|
license: {
|
|
name: 'MIT',
|
|
url: 'https://opensource.org/licenses/MIT'
|
|
}
|
|
},
|
|
servers: [
|
|
{
|
|
url: 'http://localhost:3000/api',
|
|
description: 'Development server'
|
|
},
|
|
{
|
|
url: 'https://api.interviewquiz.com/api',
|
|
description: 'Production server'
|
|
}
|
|
],
|
|
components: {
|
|
securitySchemes: {
|
|
bearerAuth: {
|
|
type: 'http',
|
|
scheme: 'bearer',
|
|
bearerFormat: 'JWT',
|
|
description: 'Enter your JWT token in the format: Bearer {token}'
|
|
}
|
|
},
|
|
schemas: {
|
|
Error: {
|
|
type: 'object',
|
|
properties: {
|
|
message: {
|
|
type: 'string',
|
|
description: 'Error message'
|
|
},
|
|
error: {
|
|
type: 'string',
|
|
description: 'Detailed error information'
|
|
}
|
|
}
|
|
},
|
|
User: {
|
|
type: 'object',
|
|
properties: {
|
|
id: {
|
|
type: 'integer',
|
|
description: 'User ID'
|
|
},
|
|
username: {
|
|
type: 'string',
|
|
description: 'Unique username'
|
|
},
|
|
email: {
|
|
type: 'string',
|
|
format: 'email',
|
|
description: 'User email address'
|
|
},
|
|
role: {
|
|
type: 'string',
|
|
enum: ['user', 'admin'],
|
|
description: 'User role'
|
|
},
|
|
isActive: {
|
|
type: 'boolean',
|
|
description: 'Account activation status'
|
|
},
|
|
createdAt: {
|
|
type: 'string',
|
|
format: 'date-time',
|
|
description: 'Account creation timestamp'
|
|
},
|
|
updatedAt: {
|
|
type: 'string',
|
|
format: 'date-time',
|
|
description: 'Last update timestamp'
|
|
}
|
|
}
|
|
},
|
|
Category: {
|
|
type: 'object',
|
|
properties: {
|
|
id: {
|
|
type: 'integer',
|
|
description: 'Category ID'
|
|
},
|
|
name: {
|
|
type: 'string',
|
|
description: 'Category name'
|
|
},
|
|
description: {
|
|
type: 'string',
|
|
description: 'Category description'
|
|
},
|
|
questionCount: {
|
|
type: 'integer',
|
|
description: 'Number of questions in category'
|
|
},
|
|
createdAt: {
|
|
type: 'string',
|
|
format: 'date-time'
|
|
}
|
|
}
|
|
},
|
|
Question: {
|
|
type: 'object',
|
|
properties: {
|
|
id: {
|
|
type: 'integer',
|
|
description: 'Question ID'
|
|
},
|
|
categoryId: {
|
|
type: 'integer',
|
|
description: 'Associated category ID'
|
|
},
|
|
questionText: {
|
|
type: 'string',
|
|
description: 'Question content'
|
|
},
|
|
difficulty: {
|
|
type: 'string',
|
|
enum: ['easy', 'medium', 'hard'],
|
|
description: 'Question difficulty level'
|
|
},
|
|
options: {
|
|
type: 'array',
|
|
items: {
|
|
type: 'string'
|
|
},
|
|
description: 'Answer options'
|
|
},
|
|
correctAnswer: {
|
|
type: 'string',
|
|
description: 'Correct answer (admin only)'
|
|
}
|
|
}
|
|
},
|
|
QuizSession: {
|
|
type: 'object',
|
|
properties: {
|
|
id: {
|
|
type: 'integer',
|
|
description: 'Quiz session ID'
|
|
},
|
|
userId: {
|
|
type: 'integer',
|
|
description: 'User ID (null for guest)'
|
|
},
|
|
guestSessionId: {
|
|
type: 'string',
|
|
format: 'uuid',
|
|
description: 'Guest session ID (null for authenticated user)'
|
|
},
|
|
categoryId: {
|
|
type: 'integer',
|
|
description: 'Quiz category ID'
|
|
},
|
|
totalQuestions: {
|
|
type: 'integer',
|
|
description: 'Total questions in quiz'
|
|
},
|
|
currentQuestionIndex: {
|
|
type: 'integer',
|
|
description: 'Current question position'
|
|
},
|
|
score: {
|
|
type: 'integer',
|
|
description: 'Current score'
|
|
},
|
|
isCompleted: {
|
|
type: 'boolean',
|
|
description: 'Quiz completion status'
|
|
},
|
|
completedAt: {
|
|
type: 'string',
|
|
format: 'date-time',
|
|
description: 'Completion timestamp'
|
|
},
|
|
startedAt: {
|
|
type: 'string',
|
|
format: 'date-time',
|
|
description: 'Start timestamp'
|
|
}
|
|
}
|
|
},
|
|
Bookmark: {
|
|
type: 'object',
|
|
properties: {
|
|
id: {
|
|
type: 'integer',
|
|
description: 'Bookmark ID'
|
|
},
|
|
userId: {
|
|
type: 'integer',
|
|
description: 'User ID'
|
|
},
|
|
questionId: {
|
|
type: 'integer',
|
|
description: 'Bookmarked question ID'
|
|
},
|
|
notes: {
|
|
type: 'string',
|
|
description: 'Optional user notes'
|
|
},
|
|
createdAt: {
|
|
type: 'string',
|
|
format: 'date-time'
|
|
},
|
|
Question: {
|
|
$ref: '#/components/schemas/Question'
|
|
}
|
|
}
|
|
},
|
|
GuestSession: {
|
|
type: 'object',
|
|
properties: {
|
|
guestSessionId: {
|
|
type: 'string',
|
|
format: 'uuid',
|
|
description: 'Unique guest session identifier'
|
|
},
|
|
convertedUserId: {
|
|
type: 'integer',
|
|
description: 'User ID after conversion (null if not converted)'
|
|
},
|
|
expiresAt: {
|
|
type: 'string',
|
|
format: 'date-time',
|
|
description: 'Session expiration timestamp'
|
|
},
|
|
createdAt: {
|
|
type: 'string',
|
|
format: 'date-time'
|
|
}
|
|
}
|
|
}
|
|
},
|
|
responses: {
|
|
UnauthorizedError: {
|
|
description: 'Authentication token is missing or invalid',
|
|
content: {
|
|
'application/json': {
|
|
schema: {
|
|
$ref: '#/components/schemas/Error'
|
|
},
|
|
example: {
|
|
message: 'No token provided'
|
|
}
|
|
}
|
|
}
|
|
},
|
|
ForbiddenError: {
|
|
description: 'User does not have permission to access this resource',
|
|
content: {
|
|
'application/json': {
|
|
schema: {
|
|
$ref: '#/components/schemas/Error'
|
|
},
|
|
example: {
|
|
message: 'Access denied. Admin only.'
|
|
}
|
|
}
|
|
}
|
|
},
|
|
NotFoundError: {
|
|
description: 'The requested resource was not found',
|
|
content: {
|
|
'application/json': {
|
|
schema: {
|
|
$ref: '#/components/schemas/Error'
|
|
},
|
|
example: {
|
|
message: 'Resource not found'
|
|
}
|
|
}
|
|
}
|
|
},
|
|
ValidationError: {
|
|
description: 'Request validation failed',
|
|
content: {
|
|
'application/json': {
|
|
schema: {
|
|
$ref: '#/components/schemas/Error'
|
|
},
|
|
example: {
|
|
message: 'Validation error',
|
|
error: 'Invalid input data'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
security: [
|
|
{
|
|
bearerAuth: []
|
|
}
|
|
],
|
|
tags: [
|
|
{
|
|
name: 'Authentication',
|
|
description: 'User authentication and authorization endpoints'
|
|
},
|
|
{
|
|
name: 'Users',
|
|
description: 'User profile and account management'
|
|
},
|
|
{
|
|
name: 'Categories',
|
|
description: 'Quiz category management'
|
|
},
|
|
{
|
|
name: 'Questions',
|
|
description: 'Question management and retrieval'
|
|
},
|
|
{
|
|
name: 'Quiz',
|
|
description: 'Quiz session lifecycle and answer submission'
|
|
},
|
|
{
|
|
name: 'Bookmarks',
|
|
description: 'User question bookmarks'
|
|
},
|
|
{
|
|
name: 'Guest',
|
|
description: 'Guest user session management'
|
|
},
|
|
{
|
|
name: 'Admin',
|
|
description: 'Administrative operations (admin only)'
|
|
}
|
|
]
|
|
},
|
|
apis: ['./routes/*.js'] // Path to the API routes
|
|
};
|
|
|
|
const swaggerSpec = swaggerJsdoc(options);
|
|
|
|
module.exports = swaggerSpec;
|