UNPKG

diabetic-utils

Version:

Zero-bloat TypeScript utilities for diabetes data: glucose, A1C, conversions, time-in-range, and more.

395 lines (386 loc) 16.1 kB
/** * Formats an A1C value with % sign. * @param val - A1C number * @returns A1C as string with percent */ declare function formatA1C(val: number): string; /** * Validates if a value is a plausible A1C percentage. * @param value - Value to check * @returns True if valid A1C */ declare function isValidA1C(value: unknown): boolean; /** * Returns a clinical category for an A1C value. * @param a1c - A1C value * @returns 'normal' | 'prediabetes' | 'diabetes' | 'invalid' */ declare function getA1CCategory(a1c: number): 'normal' | 'prediabetes' | 'diabetes' | 'invalid'; /** * Checks if an A1C value is within a target range. * @param a1c - A1C value * @param target - [min, max] range (default: [6.5, 7.0]) * @returns True if in target range */ declare function isA1CInTarget(a1c: number, target?: [number, number]): boolean; /** * Calculates the change (delta) between two A1C values. * @param current - Current A1C * @param previous - Previous A1C * @returns Delta (current - previous) * @throws If either value is invalid */ declare function a1cDelta(current: number, previous: number): number; /** * Determines the trend of A1C values over time. * @param readings - Array of A1C values (chronological order) * @returns 'increasing' | 'decreasing' | 'stable' | 'insufficient data' */ declare function a1cTrend(readings: number[]): 'increasing' | 'decreasing' | 'stable' | 'insufficient data'; /** * Hypoglycemia threshold in mg/dL. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-level-ranges.html */ declare const HYPO_THRESHOLD_MGDL = 70; /** * Hyperglycemia threshold in mg/dL. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-level-ranges.html */ declare const HYPER_THRESHOLD_MGDL = 180; /** * Hypoglycemia threshold in mmol/L. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-level-ranges.html */ declare const HYPO_THRESHOLD_MMOLL = 3.9; /** * Hyperglycemia threshold in mmol/L. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-level-ranges.html */ declare const HYPER_THRESHOLD_MMOLL = 10; /** * Multiplier for converting A1C to estimated average glucose (eAG). * @see https://www.cdc.gov/diabetes/managing/managing-blood-sugar/a1c.html */ declare const A1C_TO_EAG_MULTIPLIER = 28.7; /** * Constant for converting A1C to estimated average glucose (eAG). * @see https://www.cdc.gov/diabetes/managing/managing-blood-sugar/a1c.html */ declare const A1C_TO_EAG_CONSTANT = 46.7; /** * Conversion factor between mg/dL and mmol/L. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-conversion.html */ declare const MGDL_MMOLL_CONVERSION = 18.0182; /** * String literal for mg/dL unit. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-conversion.html */ declare const MG_DL: "mg/dL"; /** * String literal for mmol/L unit. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-conversion.html */ declare const MMOL_L: "mmol/L"; /** * Color codes for glucose zones. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-level-ranges.html */ declare const GLUCOSE_COLOR_LOW = "#D32F2F"; declare const GLUCOSE_COLOR_NORMAL = "#388E3C"; declare const GLUCOSE_COLOR_NORMAL_UP = "#4CAF50"; declare const GLUCOSE_COLOR_NORMAL_DOWN = "#2E7D32"; declare const GLUCOSE_COLOR_ELEVATED = "#FBC02D"; declare const GLUCOSE_COLOR_HIGH = "#F57C00"; /** * Glucose zone color mapping for different statuses and trends. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-level-ranges.html */ declare const GLUCOSE_ZONE_COLORS: { LOW: string; NORMAL: string; ELEVATED: string; HIGH: string; NORMAL_UP: string; NORMAL_DOWN: string; }; /** * Unicode arrows for glucose trend indication. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-level-ranges.html */ declare const TREND_ARROWS: { STEADY: string; RISING: string; FALLING: string; RAPIDRISE: string; RAPIDFALL: string; }; /** * Supported glucose units. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-conversion.html */ type GlucoseUnit = typeof MG_DL | typeof MMOL_L; /** * All allowed glucose units. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-conversion.html */ declare const AllowedGlucoseUnits: GlucoseUnit[]; /** * Represents a single glucose reading with value, unit, and timestamp. * @see https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7445493/ */ interface GlucoseReading { readonly value: number; readonly unit: GlucoseUnit; readonly timestamp: string; } /** * Result of a Time-in-Range (TIR) calculation. * @see https://care.diabetesjournals.org/content/42/8/1593 */ interface TIRResult { inRange: number; belowRange: number; aboveRange: number; } /** * Options for estimating GMI (Glucose Management Indicator). * @see https://diatribe.org/glucose-management-indicator-gmi */ interface EstimateGMIOptions { value: number; unit: GlucoseUnit; } /** * Options for Time-in-Range (TIR) calculations. */ interface TIROptions { readings: GlucoseReading[]; unit: GlucoseUnit; range: [number, number]; } /** * Represents a single A1C reading with value and date. */ interface A1CReading { value: number; date: string; } /** * Options for calculating glucose statistics. */ interface GlucoseStatsOptions { readings: GlucoseReading[]; unit: GlucoseUnit; range: [number, number]; gmi?: boolean; a1c?: boolean; tir?: boolean; tirRange?: [number, number]; tirPercent?: boolean; tirPercentBelow?: boolean; tirPercentAbove?: boolean; tirPercentInRange?: boolean; tirPercentBelowRounded?: boolean; tirPercentAboveRounded?: boolean; tirPercentInRangeRounded?: boolean; } /** * Converts average glucose (mg/dL) to estimated A1C. * @param avgMgDl - Average glucose in mg/dL * @returns Estimated A1C value * @see https://www.cdc.gov/diabetes/managing/managing-blood-sugar/a1c.html */ declare function estimateA1CFromAvgGlucose(avgMgDl: number): number; /** * Converts A1C value to estimated average glucose (mg/dL). * @param a1c - A1C value * @returns Estimated average glucose in mg/dL * @see https://www.cdc.gov/diabetes/managing/managing-blood-sugar/a1c.html */ declare function estimateAvgGlucoseFromA1C(a1c: number): number; /** * Estimates eAG (estimated average glucose) from A1C. * @param a1c - A1C value * @returns Estimated average glucose (eAG) in mg/dL * @throws {Error} If a1c is negative. * @see https://www.cdc.gov/diabetes/managing/managing-blood-sugar/a1c.html */ declare function estimateEAG(a1c: number): number; /** * Estimates A1C from average glucose. * @param avgGlucose - Average glucose value * @param unit - Glucose unit (mg/dL or mmol/L) * @returns Estimated A1C * @see https://www.cdc.gov/diabetes/managing/managing-blood-sugar/a1c.html */ declare function estimateA1CFromAverage(avgGlucose: number, unit?: GlucoseUnit): number; /** * Converts A1C to Glucose Management Indicator (GMI). * @param a1c - A1C value * @returns GMI value * @see https://diatribe.org/glucose-management-indicator-gmi */ declare function a1cToGMI(a1c: number): number; /** * Estimate Glucose Management Indicator (GMI) from average glucose. * @param valueOrOptions - Glucose value, string, or options object * @param unit - Glucose unit (if value is a number) * @returns GMI value * @throws {Error} If unit is required but not provided when input is a number. * @throws {Error} If the glucose unit is unsupported. * @throws {Error} If the glucose value is not a positive number. * @see https://diatribe.org/glucose-management-indicator-gmi */ declare function estimateGMI(valueOrOptions: number | string | EstimateGMIOptions, unit?: GlucoseUnit): number; /** * Converts mg/dL to mmol/L. * @param val - Glucose value in mg/dL * @returns Value in mmol/L * @throws {Error} If val is not a finite number or is negative/zero. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-conversion.html */ declare function mgDlToMmolL(val: number): number; /** * Converts mmol/L to mg/dL. * @param val - Glucose value in mmol/L * @returns Value in mg/dL * @throws {Error} If val is not a finite number or is negative/zero. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-conversion.html */ declare function mmolLToMgDl(val: number): number; /** * Converts glucose value between mg/dL and mmol/L. * @param value - Glucose value * @param unit - Current glucose unit * @returns Object with converted value and new unit * @throws {Error} If value is not a finite number or is negative/zero. * @throws {Error} If unit is not a supported glucose unit. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-conversion.html */ declare function convertGlucoseUnit({ value, unit, }: { value: number; unit: GlucoseUnit; }): { value: number; unit: GlucoseUnit; }; /** * Formats a glucose value with its unit and optional rounding. * @param val - Glucose value to format. * @param unit - Unit of measurement (mg/dL or mmol/L). * @param options - Formatting options: number of digits and whether to include the unit suffix (default: { digits: 0, suffix: true }). * @returns Formatted glucose string, e.g., '5.5 mmol/L' or '120 mg/dL'. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-conversion.html */ declare function formatGlucose(val: number, unit: GlucoseUnit, options?: { digits?: number; suffix?: boolean; }): string; /** * Formats a number as a percentage string. * @param val - Value to format as a percentage (e.g., 0.85 or 85). * @param digits - Number of decimal places (default: 1). * @returns Formatted percentage string, e.g., '85.0%'. * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed */ declare function formatPercentage(val: number, digits?: number): string; /** * Formats a UTC ISO timestamp to a local-readable string. * @param iso - ISO 8601 timestamp string (e.g., '2024-03-20T10:00:00Z'). * @param timeZone - Optional IANA time zone name (e.g., 'America/New_York'). * @returns Localized date and time string, e.g., 'Mar 20, 2024, 06:00 AM'. * @throws {RangeError} If the ISO string is invalid or cannot be parsed by Date. * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString * @see https://en.wikipedia.org/wiki/ISO_8601 */ declare function formatDate(iso: string, timeZone?: string): string; /** * Determines if a glucose value is below the hypoglycemia threshold for the given unit. * @param val - Glucose value to check. * @param unit - Unit of measurement (mg/dL or mmol/L). Defaults to mg/dL. * @returns True if the value is below the hypoglycemia threshold, otherwise false. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-level-ranges.html */ declare function isHypo(val: number, unit?: GlucoseUnit): boolean; /** * Determines if a glucose value is above the hyperglycemia threshold for the given unit. * @param val - Glucose value to check. * @param unit - Unit of measurement (mg/dL or mmol/L). Defaults to mg/dL. * @returns True if the value is above the hyperglycemia threshold, otherwise false. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-level-ranges.html */ declare function isHyper(val: number, unit?: GlucoseUnit): boolean; /** * Returns a glucose status label ('low', 'normal', or 'high') based on thresholds for the given unit. * @param val - Glucose value to label. * @param unit - Unit of measurement (mg/dL or mmol/L). Defaults to mg/dL. * @returns 'low' if below hypo threshold, 'high' if above hyper threshold, otherwise 'normal'. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-level-ranges.html */ declare function getGlucoseLabel(val: number, unit?: GlucoseUnit): 'low' | 'normal' | 'high'; /** * Parses a glucose string like "100 mg/dL" or "5.5 mmol/L" into a value and unit. * @param input - A string in the format "value unit" (e.g., "100 mg/dL"). * @returns An object with numeric `value` and validated `unit`. * @throws {Error} If the input string is invalid or not in the expected format. * @example * parseGlucoseString("100 mg/dL") // { value: 100, unit: "mg/dL" } * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-conversion.html */ declare function parseGlucoseString(input: string): { value: number; unit: GlucoseUnit; }; /** * Checks if a glucose value and unit are valid. * @param value - Glucose value to validate. * @param unit - Glucose unit to validate. * @returns True if the value is a positive finite number and the unit is supported, otherwise false. */ declare function isValidGlucoseValue(value: unknown, unit: unknown): boolean; /** * Type guard to check if a value is a valid EstimateGMIOptions object. * @param input - The value to check for EstimateGMIOptions shape. * @returns True if the input is an object with numeric 'value' and string 'unit' properties, otherwise false. */ declare function isEstimateGMIOptions(input: unknown): input is EstimateGMIOptions; /** * Checks if a string is in the format "100 mg/dL" or "5.5 mmol/L". * @param input - The value to validate as a glucose string. * @returns True if the input is a string matching the glucose value and unit format, otherwise false. * @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-conversion.html */ declare function isValidGlucoseString(input: unknown): input is string; /** * Calculates the percentage of time glucose readings are in, below, and above a target range. * @param readings - Array of glucose readings to analyze. * @param target - Object specifying the target range with { min, max } values. * @returns An object with the percentage of readings in range, below range, and above range. * @see https://care.diabetesjournals.org/content/42/8/1593 */ declare function calculateTIR(readings: GlucoseReading[], target: { min: number; max: number; }): TIRResult; /** * Generates a human-readable summary string from a TIRResult object. * @param result - The TIR result breakdown to summarize. * @returns A string summarizing the in-range, below-range, and above-range percentages (e.g., 'In Range: 70%, Below: 10%, Above: 20%'). */ declare function getTIRSummary(result: TIRResult): string; /** * Groups glucose readings by date (YYYY-MM-DD). * @param readings - Array of glucose readings to group. * @returns An object mapping each date string to an array of readings for that day. */ declare function groupByDay(readings: GlucoseReading[]): Record<string, GlucoseReading[]>; /** * Calculates the percentage of readings within a specified numeric range. * @param readings - Array of glucose values (numbers) to analyze. * @param lower - Lower bound of the target range (inclusive). * @param upper - Upper bound of the target range (inclusive). * @returns The percentage of readings within the specified range (0-100). */ declare function calculateTimeInRange(readings: number[], lower: number, upper: number): number; export { type A1CReading, A1C_TO_EAG_CONSTANT, A1C_TO_EAG_MULTIPLIER, AllowedGlucoseUnits, type EstimateGMIOptions, GLUCOSE_COLOR_ELEVATED, GLUCOSE_COLOR_HIGH, GLUCOSE_COLOR_LOW, GLUCOSE_COLOR_NORMAL, GLUCOSE_COLOR_NORMAL_DOWN, GLUCOSE_COLOR_NORMAL_UP, GLUCOSE_ZONE_COLORS, type GlucoseReading, type GlucoseStatsOptions, type GlucoseUnit, HYPER_THRESHOLD_MGDL, HYPER_THRESHOLD_MMOLL, HYPO_THRESHOLD_MGDL, HYPO_THRESHOLD_MMOLL, MGDL_MMOLL_CONVERSION, MG_DL, MMOL_L, type TIROptions, type TIRResult, TREND_ARROWS, a1cDelta, a1cToGMI, a1cTrend, calculateTIR, calculateTimeInRange, convertGlucoseUnit, estimateA1CFromAverage, estimateA1CFromAvgGlucose, estimateAvgGlucoseFromA1C, estimateEAG, estimateGMI, formatA1C, formatDate, formatGlucose, formatPercentage, getA1CCategory, getGlucoseLabel, getTIRSummary, groupByDay, isA1CInTarget, isEstimateGMIOptions, isHyper, isHypo, isValidA1C, isValidGlucoseString, isValidGlucoseValue, mgDlToMmolL, mmolLToMgDl, parseGlucoseString };