UNPKG

qbo-mcp-ts

Version:

TypeScript QuickBooks Online MCP Server with enhanced features and dual transport support

273 lines 11.8 kB
"use strict"; /** * Natural language date parser for accounting queries */ Object.defineProperty(exports, "__esModule", { value: true }); exports.DateParser = void 0; const date_fns_1 = require("date-fns"); class DateParser { /** * Parse natural language date string to ISO date */ static parse(input) { if (!input) { return (0, date_fns_1.format)(new Date(), 'yyyy-MM-dd'); } const normalized = input.toLowerCase().trim(); const today = new Date(); // Check for relative dates if (normalized === 'today') { return (0, date_fns_1.format)(today, 'yyyy-MM-dd'); } if (normalized === 'yesterday') { return (0, date_fns_1.format)((0, date_fns_1.addDays)(today, -1), 'yyyy-MM-dd'); } if (normalized === 'tomorrow') { return (0, date_fns_1.format)((0, date_fns_1.addDays)(today, 1), 'yyyy-MM-dd'); } // Month-based patterns if (normalized === 'this month' || normalized === 'current month') { return (0, date_fns_1.format)((0, date_fns_1.startOfMonth)(today), 'yyyy-MM-dd'); } if (normalized === 'last month' || normalized === 'previous month') { return (0, date_fns_1.format)((0, date_fns_1.startOfMonth)((0, date_fns_1.subMonths)(today, 1)), 'yyyy-MM-dd'); } if (normalized === 'next month') { return (0, date_fns_1.format)((0, date_fns_1.startOfMonth)((0, date_fns_1.addDays)(today, 30)), 'yyyy-MM-dd'); } // Quarter-based patterns const quarterMatch = normalized.match(/q([1-4])\s*(\d{4})?/); if (quarterMatch) { const quarter = parseInt(quarterMatch[1]); const year = quarterMatch[2] ? parseInt(quarterMatch[2]) : today.getFullYear(); const date = new Date(year, (quarter - 1) * 3, 1); return (0, date_fns_1.format)((0, date_fns_1.startOfQuarter)(date), 'yyyy-MM-dd'); } if (normalized === 'this quarter' || normalized === 'current quarter') { return (0, date_fns_1.format)((0, date_fns_1.startOfQuarter)(today), 'yyyy-MM-dd'); } if (normalized === 'last quarter' || normalized === 'previous quarter') { return (0, date_fns_1.format)((0, date_fns_1.startOfQuarter)((0, date_fns_1.subQuarters)(today, 1)), 'yyyy-MM-dd'); } // Year-based patterns if (normalized === 'this year' || normalized === 'current year') { return (0, date_fns_1.format)((0, date_fns_1.startOfYear)(today), 'yyyy-MM-dd'); } if (normalized === 'last year' || normalized === 'previous year') { return (0, date_fns_1.format)((0, date_fns_1.startOfYear)((0, date_fns_1.subYears)(today, 1)), 'yyyy-MM-dd'); } if (normalized === 'year to date' || normalized === 'ytd') { return (0, date_fns_1.format)((0, date_fns_1.startOfYear)(today), 'yyyy-MM-dd'); } // Fiscal year patterns (assuming fiscal year = calendar year for now) if (normalized.includes('fiscal year') || normalized.includes('fy')) { const fyMatch = normalized.match(/(?:fiscal year|fy)\s*(\d{4})/); if (fyMatch) { const year = parseInt(fyMatch[1]); return (0, date_fns_1.format)(new Date(year, 0, 1), 'yyyy-MM-dd'); } return (0, date_fns_1.format)((0, date_fns_1.startOfYear)(today), 'yyyy-MM-dd'); } // Month name patterns const monthNames = [ 'january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december', ]; for (let i = 0; i < monthNames.length; i++) { if (normalized.includes(monthNames[i])) { const yearMatch = normalized.match(/(\d{4})/); const year = yearMatch ? parseInt(yearMatch[1]) : today.getFullYear(); return (0, date_fns_1.format)(new Date(year, i, 1), 'yyyy-MM-dd'); } } // Try standard date formats const formats = [ 'yyyy-MM-dd', 'MM/dd/yyyy', 'MM-dd-yyyy', 'dd/MM/yyyy', 'dd-MM-yyyy', 'MMM dd, yyyy', 'MMMM dd, yyyy', ]; for (const fmt of formats) { try { const parsed = (0, date_fns_1.parse)(input, fmt, new Date()); if ((0, date_fns_1.isValid)(parsed)) { return (0, date_fns_1.format)(parsed, 'yyyy-MM-dd'); } } catch { // Continue to next format } } // If nothing matches, return the original input // QuickBooks might understand it better return input; } /** * Parse date range from natural language */ static parseRange(input) { const normalized = input.toLowerCase().trim(); const today = new Date(); // Common ranges if (normalized === 'this month' || normalized === 'current month') { return { start: (0, date_fns_1.format)((0, date_fns_1.startOfMonth)(today), 'yyyy-MM-dd'), end: (0, date_fns_1.format)((0, date_fns_1.endOfMonth)(today), 'yyyy-MM-dd'), }; } if (normalized === 'last month' || normalized === 'previous month') { const lastMonth = (0, date_fns_1.subMonths)(today, 1); return { start: (0, date_fns_1.format)((0, date_fns_1.startOfMonth)(lastMonth), 'yyyy-MM-dd'), end: (0, date_fns_1.format)((0, date_fns_1.endOfMonth)(lastMonth), 'yyyy-MM-dd'), }; } if (normalized === 'this quarter' || normalized === 'current quarter') { return { start: (0, date_fns_1.format)((0, date_fns_1.startOfQuarter)(today), 'yyyy-MM-dd'), end: (0, date_fns_1.format)((0, date_fns_1.endOfQuarter)(today), 'yyyy-MM-dd'), }; } if (normalized === 'last quarter' || normalized === 'previous quarter') { const lastQuarter = (0, date_fns_1.subQuarters)(today, 1); return { start: (0, date_fns_1.format)((0, date_fns_1.startOfQuarter)(lastQuarter), 'yyyy-MM-dd'), end: (0, date_fns_1.format)((0, date_fns_1.endOfQuarter)(lastQuarter), 'yyyy-MM-dd'), }; } if (normalized === 'this year' || normalized === 'current year') { return { start: (0, date_fns_1.format)((0, date_fns_1.startOfYear)(today), 'yyyy-MM-dd'), end: (0, date_fns_1.format)((0, date_fns_1.endOfYear)(today), 'yyyy-MM-dd'), }; } if (normalized === 'last year' || normalized === 'previous year') { const lastYear = (0, date_fns_1.subYears)(today, 1); return { start: (0, date_fns_1.format)((0, date_fns_1.startOfYear)(lastYear), 'yyyy-MM-dd'), end: (0, date_fns_1.format)((0, date_fns_1.endOfYear)(lastYear), 'yyyy-MM-dd'), }; } if (normalized === 'year to date' || normalized === 'ytd') { return { start: (0, date_fns_1.format)((0, date_fns_1.startOfYear)(today), 'yyyy-MM-dd'), end: (0, date_fns_1.format)(today, 'yyyy-MM-dd'), }; } if (normalized === 'month to date' || normalized === 'mtd') { return { start: (0, date_fns_1.format)((0, date_fns_1.startOfMonth)(today), 'yyyy-MM-dd'), end: (0, date_fns_1.format)(today, 'yyyy-MM-dd'), }; } if (normalized === 'quarter to date' || normalized === 'qtd') { return { start: (0, date_fns_1.format)((0, date_fns_1.startOfQuarter)(today), 'yyyy-MM-dd'), end: (0, date_fns_1.format)(today, 'yyyy-MM-dd'), }; } // Last N days/months/years const lastNMatch = normalized.match(/last (\d+) (days?|months?|years?)/); if (lastNMatch) { const n = parseInt(lastNMatch[1]); const unit = lastNMatch[2]; let start; if (unit.startsWith('day')) { start = (0, date_fns_1.addDays)(today, -n); } else if (unit.startsWith('month')) { start = (0, date_fns_1.subMonths)(today, n); } else { start = (0, date_fns_1.subYears)(today, n); } return { start: (0, date_fns_1.format)(start, 'yyyy-MM-dd'), end: (0, date_fns_1.format)(today, 'yyyy-MM-dd'), }; } // Quarter patterns (e.g., "Q1 2024") const quarterMatch = normalized.match(/q([1-4])\s*(\d{4})?/); if (quarterMatch) { const quarter = parseInt(quarterMatch[1]); const year = quarterMatch[2] ? parseInt(quarterMatch[2]) : today.getFullYear(); const date = new Date(year, (quarter - 1) * 3, 1); return { start: (0, date_fns_1.format)((0, date_fns_1.startOfQuarter)(date), 'yyyy-MM-dd'), end: (0, date_fns_1.format)((0, date_fns_1.endOfQuarter)(date), 'yyyy-MM-dd'), }; } // Default to current month return { start: (0, date_fns_1.format)((0, date_fns_1.startOfMonth)(today), 'yyyy-MM-dd'), end: (0, date_fns_1.format)((0, date_fns_1.endOfMonth)(today), 'yyyy-MM-dd'), }; } /** * Get fiscal year dates (customize based on company settings) */ static getFiscalYear(year, fiscalYearStart = 1) { const targetYear = year || new Date().getFullYear(); const start = new Date(targetYear, fiscalYearStart - 1, 1); const end = new Date(targetYear + 1, fiscalYearStart - 1, 0); return { start: (0, date_fns_1.format)(start, 'yyyy-MM-dd'), end: (0, date_fns_1.format)(end, 'yyyy-MM-dd'), }; } /** * Format date for display */ static formatDisplay(date, formatStr = 'MMM dd, yyyy') { const d = typeof date === 'string' ? new Date(date) : date; return (0, date_fns_1.isValid)(d) ? (0, date_fns_1.format)(d, formatStr) : String(date); } /** * Calculate days between dates */ static daysBetween(start, end) { const startDate = typeof start === 'string' ? new Date(start) : start; const endDate = typeof end === 'string' ? new Date(end) : end; const diffTime = Math.abs(endDate.getTime() - startDate.getTime()); return Math.ceil(diffTime / (1000 * 60 * 60 * 24)); } /** * Check if date is overdue */ static isOverdue(date) { const d = typeof date === 'string' ? new Date(date) : date; return d < new Date(); } /** * Add business days to a date (excluding weekends) */ static addBusinessDays(date, days) { let current = typeof date === 'string' ? new Date(date) : new Date(date); let remaining = Math.abs(days); const direction = days > 0 ? 1 : -1; while (remaining > 0) { current = (0, date_fns_1.addDays)(current, direction); const dayOfWeek = current.getDay(); // Skip weekends if (dayOfWeek !== 0 && dayOfWeek !== 6) { remaining--; } } return (0, date_fns_1.format)(current, 'yyyy-MM-dd'); } } exports.DateParser = DateParser; //# sourceMappingURL=date-parser.js.map