const { AppError } = require("../utils/appError"); const { parseDateInput } = require("../utils/time"); const INTERVAL_SHORTCUTS = { "1m": "1 minute", "5m": "5 minutes", "10m": "10 minutes", "15m": "15 minutes", "30m": "30 minutes", "1h": "1 hour", "3h": "3 hours", "6h": "6 hours", "12h": "12 hours", "1d": "1 day", }; const INTERVAL_PATTERN = /^\d+\s*(second|minute|hour|day)s?$/i; function normalizeInterval(raw) { if (!raw) { return null; } const lower = String(raw).trim().toLowerCase(); if (INTERVAL_SHORTCUTS[lower]) { return INTERVAL_SHORTCUTS[lower]; } if (INTERVAL_PATTERN.test(lower)) { return lower; } throw new AppError( "Invalid interval. Use values like 5m, 15m, 1h, or '5 minutes'.", 400 ); } function normalizeBucketMinutes(raw) { if (raw === undefined || raw === null || raw === "") { return null; } const parsed = Number(raw); if (!Number.isFinite(parsed) || parsed <= 0) { throw new AppError("bucketMinutes must be a positive number", 400); } const rounded = Math.floor(parsed); if (rounded > 24 * 60) { throw new AppError("bucketMinutes cannot exceed 1440 (24 hours)", 400); } return rounded; } function parseHistoryQuery(query, config) { const from = parseDateInput(query.from); const to = parseDateInput(query.to); if (query.from && !from) { throw new AppError("Invalid 'from' timestamp", 400); } if (query.to && !to) { throw new AppError("Invalid 'to' timestamp", 400); } if (from && to && from > to) { throw new AppError("'from' must be earlier than or equal to 'to'", 400); } const requestedLimit = Number(query.limit || config.query.historyDefaultLimit); if (!Number.isFinite(requestedLimit) || requestedLimit <= 0) { throw new AppError("limit must be a positive number", 400); } const limit = Math.min(Math.floor(requestedLimit), config.query.historyMaxLimit); const bucketMinutes = normalizeBucketMinutes(query.bucketMinutes); const interval = normalizeInterval(query.interval) || (bucketMinutes ? `${bucketMinutes} minutes` : null); return { from: from ? from.toISOString() : null, to: to ? to.toISOString() : null, limit, bucketMinutes, interval, }; } module.exports = { parseHistoryQuery, };