UNPKG

mcp-quiz-server

Version:

🧠 AI-Powered Quiz Management via Model Context Protocol (MCP) - Create, manage, and take quizzes directly from VS Code, Claude, and other AI agents.

152 lines (151 loc) • 5.11 kB
"use strict"; /** * @fileoverview List Quizzes Query - Clean Architecture Application Layer * @version 1.0.0 * @since 2025-07-30 * @module ListQuizzesQuery * @description Query for listing quizzes with filtering and pagination * * @architecture * Layer: Application (Query) * Pattern: Query Pattern + Pagination * Dependencies: Domain value objects * * @relationships * USED_BY: * - ListQuizzesQueryHandler (Application Layer) * - MCP list-quizzes tool (Infrastructure) * - HTTP list endpoints (Infrastructure) * * @contributors Claude Code Agent * @testCoverage Query validation tests, integration tests */ Object.defineProperty(exports, "__esModule", { value: true }); exports.ListQuizzesQuery = void 0; /** * List Quizzes Query * * @description Represents a request to list quizzes with optional filtering, * pagination, and permission checking. * * @example * ```typescript * const query = new ListQuizzesQuery({ * limit: 10, * category: 'math', * difficulty: 'medium', * includeQuestions: false * }); * ``` * * @since 2025-07-30 * @author Claude Code Agent */ class ListQuizzesQuery { constructor(data = {}) { var _a; // Validate and set pagination this.limit = Math.min(Math.max(data.limit || 10, 1), 100); // Limit between 1 and 100 this.offset = Math.max(data.offset || 0, 0); // Non-negative offset // Set filtering options this.category = data.category; this.difficulty = data.difficulty; this.isActive = data.isActive !== false; // Default to true (only active quizzes) this.searchTerm = (_a = data.searchTerm) === null || _a === void 0 ? void 0 : _a.trim(); // Set inclusion options this.includeQuestions = data.includeQuestions === true; this.includeStatistics = data.includeStatistics === true; // Set sorting options this.sortBy = data.sortBy || 'createdAt'; this.sortOrder = data.sortOrder || 'desc'; // Set user context this.userId = data.userId; this.metadata = { ...data.metadata, timestamp: new Date().toISOString(), }; // Validate sort options this.validateSortOptions(); } /** * Validate sorting options */ validateSortOptions() { const validSortFields = ['title', 'createdAt', 'updatedAt', 'questionCount', 'difficulty']; const validSortOrders = ['asc', 'desc']; if (!validSortFields.includes(this.sortBy)) { throw new Error(`Invalid sortBy field: ${this.sortBy}. Must be one of: ${validSortFields.join(', ')}`); } if (!validSortOrders.includes(this.sortOrder)) { throw new Error(`Invalid sortOrder: ${this.sortOrder}. Must be 'asc' or 'desc'`); } if (this.difficulty && !['easy', 'medium', 'hard', 'expert'].includes(this.difficulty)) { throw new Error(`Invalid difficulty: ${this.difficulty}. Must be one of: easy, medium, hard, expert`); } } /** * Check if this is a search query */ isSearchQuery() { return !!this.searchTerm && this.searchTerm.length > 0; } /** * Check if this query has filters applied */ hasFilters() { return !!(this.category || this.difficulty || this.searchTerm || this.isActive === false); } /** * Get pagination info for response metadata */ getPaginationInfo() { return { limit: this.limit, offset: this.offset, page: Math.floor(this.offset / this.limit) + 1, pageSize: this.limit, }; } /** * Convert to repository search criteria */ toSearchCriteria() { return { category: this.category, difficulty: this.difficulty, isActive: this.isActive, titleContains: this.searchTerm, hasQuestions: true, // Only return quizzes with questions }; } /** * Convert to repository search options */ toSearchOptions() { return { limit: this.limit, offset: this.offset, sortBy: this.sortBy, sortOrder: this.sortOrder, includeQuestions: this.includeQuestions, includeResults: this.includeStatistics, }; } /** * Convert to string representation for logging */ toString() { const filters = []; if (this.category) filters.push(`category=${this.category}`); if (this.difficulty) filters.push(`difficulty=${this.difficulty}`); if (this.searchTerm) filters.push(`search="${this.searchTerm}"`); if (this.isActive === false) filters.push('includeInactive=true'); const filterStr = filters.length > 0 ? ` with filters: ${filters.join(', ')}` : ''; return `ListQuizzesQuery(limit=${this.limit}, offset=${this.offset}, sortBy=${this.sortBy}${filterStr})`; } } exports.ListQuizzesQuery = ListQuizzesQuery;