Skip to main content
Glama
monuit
by monuit
validation.ts5.13 kB
import Joi from 'joi'; // Date validation patterns const DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/; const ISO_DATETIME_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z?$/; /** * Schema for date range parameters */ export const dateRangeSchema = Joi.object({ start_date: Joi.string() .pattern(DATE_PATTERN) .required() .messages({ 'string.pattern.base': 'start_date must be in YYYY-MM-DD format', 'any.required': 'start_date is required', }), end_date: Joi.string() .pattern(DATE_PATTERN) .optional() .messages({ 'string.pattern.base': 'end_date must be in YYYY-MM-DD format', }), }); /** * Schema for datetime range parameters */ export const datetimeRangeSchema = Joi.object({ start_datetime: Joi.string() .pattern(ISO_DATETIME_PATTERN) .required() .messages({ 'string.pattern.base': 'start_datetime must be in ISO 8601 format', 'any.required': 'start_datetime is required', }), end_datetime: Joi.string() .pattern(ISO_DATETIME_PATTERN) .optional() .messages({ 'string.pattern.base': 'end_datetime must be in ISO 8601 format', }), }); /** * Schema for sleep summary parameters */ export const sleepSummarySchema = dateRangeSchema.keys({ include_hrv: Joi.boolean().optional(), }); /** * Schema for heart rate parameters */ export const heartRateSchema = datetimeRangeSchema; /** * Schema for health insights parameters */ export const healthInsightsSchema = Joi.object({ days: Joi.number() .integer() .min(1) .max(90) .optional() .default(7) .messages({ 'number.base': 'days must be a number', 'number.integer': 'days must be an integer', 'number.min': 'days must be at least 1', 'number.max': 'days must be at most 90', }), }); /** * Validates parameters against a schema * @param schema - Joi schema to validate against * @param data - Data to validate * @returns Validated and sanitized data * @throws Error if validation fails */ export function validateParams<T>(schema: Joi.Schema, data: any): T { const { error, value } = schema.validate(data, { abortEarly: false, stripUnknown: true, }); if (error) { const messages = error.details.map((detail) => detail.message).join(', '); throw new Error(`Validation error: ${messages}`); } return value as T; } /** * Validates a date string * @param date - Date string to validate * @returns True if valid, false otherwise */ export function isValidDate(date: string): boolean { if (!DATE_PATTERN.test(date)) { return false; } const d = new Date(date); return d instanceof Date && !isNaN(d.getTime()); } /** * Validates an ISO datetime string * @param datetime - Datetime string to validate * @returns True if valid, false otherwise */ export function isValidDatetime(datetime: string): boolean { if (!ISO_DATETIME_PATTERN.test(datetime)) { return false; } const d = new Date(datetime); return d instanceof Date && !isNaN(d.getTime()); } /** * Gets today's date in YYYY-MM-DD format */ export function getTodayDate(): string { return new Date().toISOString().split('T')[0]; } /** * Gets a date N days ago in YYYY-MM-DD format * @param days - Number of days ago */ export function getDaysAgo(days: number): string { const date = new Date(); date.setDate(date.getDate() - days); return date.toISOString().split('T')[0]; } /** * Converts a date string to ISO datetime * @param date - Date in YYYY-MM-DD format * @param endOfDay - If true, returns end of day (23:59:59) */ export function dateToDatetime(date: string, endOfDay: boolean = false): string { const d = new Date(date); if (endOfDay) { d.setHours(23, 59, 59, 999); } else { d.setHours(0, 0, 0, 0); } return d.toISOString(); } /** * Validates that start_date is before end_date * @param startDate - Start date * @param endDate - End date * @throws Error if dates are invalid */ export function validateDateRange(startDate: string, endDate?: string): void { if (!isValidDate(startDate)) { throw new Error('Invalid start_date format'); } if (endDate) { if (!isValidDate(endDate)) { throw new Error('Invalid end_date format'); } const start = new Date(startDate); const end = new Date(endDate); if (start > end) { throw new Error('start_date must be before or equal to end_date'); } } } /** * Validates that start_datetime is before end_datetime * @param startDatetime - Start datetime * @param endDatetime - End datetime * @throws Error if datetimes are invalid */ export function validateDatetimeRange(startDatetime: string, endDatetime?: string): void { if (!isValidDatetime(startDatetime)) { throw new Error('Invalid start_datetime format'); } if (endDatetime) { if (!isValidDatetime(endDatetime)) { throw new Error('Invalid end_datetime format'); } const start = new Date(startDatetime); const end = new Date(endDatetime); if (start > end) { throw new Error('start_datetime must be before or equal to end_datetime'); } } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/monuit/oura-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server