diabetic-utils
Version:
Zero-bloat TypeScript utilities for diabetes data: glucose, A1C, conversions, time-in-range, and more.
1,226 lines (1,207 loc) • 71.7 kB
TypeScript
/**
* Formats a clinical A1C value as a percent string (e.g., "7.2%").
* Used for clinical reporting and display.
* @param val - A1C value (percentage)
* @returns A1C as string with percent sign
*/
declare function formatA1C(val: number): string;
/**
* Validates a clinical A1C value (percentage).
* Ensures value is within physiologically plausible range for clinical analytics.
* @param value - Candidate A1C value
* @returns True if value is a valid A1C percentage
*/
declare function isValidA1C(value: unknown): boolean;
/**
* Returns the clinical category for an A1C value (normal, prediabetes, diabetes, or invalid).
* Uses ADA thresholds by default, but allows custom cutoffs for research or population-specific use.
* @param a1c - A1C value (percentage)
* @returns 'normal' | 'prediabetes' | 'diabetes' | 'invalid'
*/
/**
* Returns the clinical category for an A1C value (normal, prediabetes, diabetes, or invalid).
* Uses ADA thresholds by default, but allows custom cutoffs for research or population-specific use.
* @param a1c - A1C value (percentage)
* @param thresholds - Optional custom thresholds: { normalMax?: number; prediabetesMax?: number }
* @returns 'normal' | 'prediabetes' | 'diabetes' | 'invalid'
*/
declare function getA1CCategory(a1c: number, thresholds?: {
normalMax?: number;
prediabetesMax?: 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])
* @param thresholds - Optional custom thresholds: { min?: number; max?: number }
* @returns True if in target range
*/
declare function isA1CInTarget(a1c: number, target?: [number, number], thresholds?: {
min?: number;
max?: 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';
/**
* Calculates HOMA-IR (Homeostatic Model Assessment for Insulin Resistance) from fasting glucose and insulin.
*
* Formula: HOMA-IR = (fasting glucose [mg/dL] × fasting insulin [µIU/mL]) / 405
*
* Used for estimating insulin resistance. Not a diagnostic tool.
*
* @param glucose - Fasting glucose value in mg/dL. Must be a positive finite number.
* @param insulin - Fasting insulin value in µIU/mL. Must be a positive finite number.
* @returns Object with numeric HOMA-IR value and interpretation label.
* @throws {Error} If glucose or insulin are invalid (non-finite, zero, or negative).
* @see https://pubmed.ncbi.nlm.nih.gov/3899825/ (Original HOMA-IR publication)
* @see https://diabetesjournals.org/care/article/26/1/118/22567/Prevalence-and-Concomitants-of-Glucose-Intolerance (ADA: Glucose Intolerance and HOMA-IR context)
*/
declare function calculateHOMAIR(glucose: number, insulin: number): {
value: number;
interpretation: string;
};
/**
* Checks consistency among A1C, fasting glucose, and fasting insulin markers.
*
* Returns:
* - Estimated average glucose (mg/dL), calculated per CDC formula
* - HOMA-IR result (value and interpretation)
* - Flags for potential inconsistencies
* - Informational note and disclaimer
*
* Used for high-level insight and trend alignment, not for diagnosis.
*
* @param a1c - A1C value (percentage). Must be a positive finite number.
* @param glucose - Fasting glucose value in mg/dL. Must be a positive finite number.
* @param insulin - Fasting insulin value in µIU/mL. Must be a positive finite number.
* @returns Object with estimated average glucose (mg/dL), HOMA-IR result object, flags array, recommendation string, and disclaimer.
* @throws {Error} If any input value is invalid (non-finite, zero, or negative).
* @see https://www.cdc.gov/diabetes/diabetes-testing/prediabetes-a1c-test.html (CDC: eAG formula)
*/
declare function checkGlycemicAlignment(a1c: number, glucose: number, insulin: number): {
estimatedAverageGlucose: number;
homaIR: {
value: number;
interpretation: string;
};
flags: string[];
recommendation: string;
disclaimer: string;
};
/**
* Denominator constant for HOMA-IR calculation.
* HOMA-IR = (glucose [mg/dL] × insulin [µIU/mL]) / HOMA_IR_DENOMINATOR
* @see https://www.ncbi.nlm.nih.gov/books/NBK279396/
*/
declare const HOMA_IR_DENOMINATOR = 405;
/**
* Interpretation cutoffs for HOMA-IR (insulin resistance assessment).
* These are general categories, not diagnostic.
*/
declare const HOMA_IR_CUTOFFS: {
readonly VERY_SENSITIVE: 1;
readonly NORMAL: 2;
readonly EARLY_RESISTANCE: 2.9;
};
/**
* Hypoglycemia threshold (mg/dL).
* Used for detecting low glucose events.
* @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-level-ranges.html
*/
declare const HYPO_THRESHOLD_MGDL = 70;
/**
* Hyperglycemia threshold (mg/dL).
* Used for detecting high glucose events.
* @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-level-ranges.html
*/
declare const HYPER_THRESHOLD_MGDL = 180;
/**
* Hypoglycemia threshold (mmol/L).
* Used for low glucose detection in international/metric contexts.
* @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-level-ranges.html
*/
declare const HYPO_THRESHOLD_MMOLL = 3.9;
/**
* Hyperglycemia threshold (mmol/L).
* Used for high glucose detection in international/metric contexts.
* @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).
* Used in eAG calculation per CDC/ADA guidelines.
* @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).
* Used in eAG calculation per CDC/ADA guidelines.
* @see https://www.cdc.gov/diabetes/managing/managing-blood-sugar/a1c.html
*/
declare const A1C_TO_EAG_CONSTANT = 46.7;
/**
* GMI (Glucose Management Indicator) calculation coefficients.
* Used for estimating GMI from average glucose values.
* @see https://diatribe.org/glucose-management-indicator-gmi
*/
declare const GMI_COEFFICIENTS: {
/** Slope for mmol/L to GMI conversion */
readonly MMOL_L_SLOPE: 1.57;
/** Intercept for mmol/L to GMI conversion */
readonly MMOL_L_INTERCEPT: 3.5;
/** Slope for mg/dL to GMI conversion */
readonly MG_DL_SLOPE: 0.03;
/** Intercept for mg/dL to GMI conversion */
readonly MG_DL_INTERCEPT: 2.4;
/** Slope for A1C to GMI conversion */
readonly A1C_SLOPE: 0.02392;
/** Intercept for A1C to GMI conversion */
readonly A1C_INTERCEPT: 3.31;
};
/**
* Conversion factor between mg/dL and mmol/L.
* Used for unit conversion.
* @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-conversion.html
*/
declare const MGDL_MMOLL_CONVERSION = 18.0182;
/**
* String literal for mg/dL glucose unit.
* Used for data interoperability and formatting.
* @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: {
readonly LOW: "#D32F2F";
readonly NORMAL: "#388E3C";
readonly ELEVATED: "#FBC02D";
readonly HIGH: "#F57C00";
readonly NORMAL_UP: "#4CAF50";
readonly NORMAL_DOWN: "#2E7D32";
};
/**
* Unicode arrows for glucose trend indication.
* @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-level-ranges.html
*/
declare const TREND_ARROWS: {
readonly STEADY: "→";
readonly RISING: "↗";
readonly FALLING: "↘";
readonly RAPIDRISE: "↑";
readonly RAPIDFALL: "↓";
};
/**
* Level 2 hypoglycemia threshold (mg/dL).
* Readings below this value indicate significant hypoglycemia.
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
declare const TIR_VERY_LOW_THRESHOLD_MGDL = 54;
/**
* Level 1 hypoglycemia threshold (mg/dL).
* Target range begins at this value.
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
declare const TIR_LOW_THRESHOLD_MGDL = 70;
/**
* Level 1 hyperglycemia threshold (mg/dL).
* Target range ends at this value.
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
declare const TIR_HIGH_THRESHOLD_MGDL = 180;
/**
* Level 2 hyperglycemia threshold (mg/dL).
* Readings above this value indicate significant hyperglycemia.
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
declare const TIR_VERY_HIGH_THRESHOLD_MGDL = 250;
/**
* Level 2 hypoglycemia threshold (mmol/L).
* Readings below this value indicate significant hypoglycemia.
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
declare const TIR_VERY_LOW_THRESHOLD_MMOLL = 3;
/**
* Level 1 hypoglycemia threshold (mmol/L).
* Target range begins at this value.
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
declare const TIR_LOW_THRESHOLD_MMOLL = 3.9;
/**
* Level 1 hyperglycemia threshold (mmol/L).
* Target range ends at this value.
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
declare const TIR_HIGH_THRESHOLD_MMOLL = 10;
/**
* Level 2 hyperglycemia threshold (mmol/L).
* Readings above this value indicate significant hyperglycemia.
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
declare const TIR_VERY_HIGH_THRESHOLD_MMOLL = 13.9;
/**
* Lower bound of target glucose range during pregnancy (mg/dL).
* Applies to Type 1, Type 2, and gestational diabetes.
* @see {@link https://diabetesjournals.org/care/article/47/Supplement_1/S282 | ADA Standards of Care (2024)}
*/
declare const PREGNANCY_TARGET_LOW_MGDL = 63;
/**
* Upper bound of target glucose range during pregnancy (mg/dL).
* Applies to Type 1, Type 2, and gestational diabetes.
* @see {@link https://diabetesjournals.org/care/article/47/Supplement_1/S282 | ADA Standards of Care (2024)}
*/
declare const PREGNANCY_TARGET_HIGH_MGDL = 140;
/**
* Lower bound of target glucose range during pregnancy (mmol/L).
* Applies to Type 1, Type 2, and gestational diabetes.
* @see {@link https://diabetesjournals.org/care/article/47/Supplement_1/S282 | ADA Standards of Care (2024)}
*/
declare const PREGNANCY_TARGET_LOW_MMOLL = 3.5;
/**
* Upper bound of target glucose range during pregnancy (mmol/L).
* Applies to Type 1, Type 2, and gestational diabetes.
* @see {@link https://diabetesjournals.org/care/article/47/Supplement_1/S282 | ADA Standards of Care (2024)}
*/
declare const PREGNANCY_TARGET_HIGH_MMOLL = 7.8;
/**
* Target percentage for time-in-range (70-180 mg/dL).
* Clinical goal: ≥70% of readings in target range.
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
declare const TIR_GOAL_STANDARD = 70;
/**
* Maximum acceptable percentage for Level 1 hypoglycemia (54-69 mg/dL).
* Clinical goal: <4% of readings in this range.
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
declare const TBR_LEVEL1_GOAL = 4;
/**
* Maximum acceptable percentage for Level 2 hypoglycemia (<54 mg/dL).
* Clinical goal: <1% of readings in this range.
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
declare const TBR_LEVEL2_GOAL = 1;
/**
* Maximum acceptable percentage for Level 1 hyperglycemia (181-250 mg/dL).
* Clinical goal: <25% of readings in this range.
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
declare const TAR_LEVEL1_GOAL = 25;
/**
* Maximum acceptable percentage for Level 2 hyperglycemia (>250 mg/dL).
* Clinical goal: <5% of readings in this range.
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
declare const TAR_LEVEL2_GOAL = 5;
/**
* Target percentage for time-in-range for older/high-risk adults.
* More lenient goal: ≥50% of readings in target range.
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
declare const TIR_GOAL_OLDER_ADULTS = 50;
/**
* Maximum acceptable percentage for Level 1 hypoglycemia for older/high-risk adults.
* More stringent goal: <1% of readings in this range.
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
declare const TBR_LEVEL1_GOAL_OLDER_ADULTS = 1;
/**
* Maximum acceptable percentage for Level 2 hypoglycemia for older/high-risk adults.
* More stringent goal: <0.5% of readings in this range.
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
declare const TBR_LEVEL2_GOAL_OLDER_ADULTS = 0.5;
/**
* Supported clinical glucose units.
* Used for all clinical analytics and conversions.
* @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-conversion.html
*/
type GlucoseUnit = typeof MG_DL | typeof MMOL_L;
/**
* List of allowed clinical glucose units.
* Used for input validation and unit conversion.
* @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-conversion.html
*/
declare const AllowedGlucoseUnits: GlucoseUnit[];
/**
* Single clinical glucose reading.
* Includes value, unit, and ISO 8601 timestamp for clinical analytics.
* @see https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7445493/
*/
interface GlucoseReading {
readonly value: number;
readonly unit: GlucoseUnit;
readonly timestamp: string;
}
/**
* Result object for clinical Time-in-Range (TIR) analytics.
* Percentages for in-range, below-range, and above-range readings.
* @see https://care.diabetesjournals.org/content/42/8/1593
*/
interface TIRResult {
inRange: number;
belowRange: number;
aboveRange: number;
}
/**
* Options for clinical GMI (Glucose Management Indicator) estimation.
* Used to standardize GMI calculation input.
* @see https://diatribe.org/glucose-management-indicator-gmi
*/
interface EstimateGMIOptions {
value: number;
unit: GlucoseUnit;
}
/**
* Result of glucose unit conversion.
* Provides converted value and new unit for clinical interoperability.
* @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-conversion.html
*/
interface ConversionResult {
/** Converted glucose value */
readonly value: number;
/** New glucose unit after conversion */
readonly unit: GlucoseUnit;
}
/**
* Options for clinical Time-in-Range (TIR) analytics.
*/
interface TIROptions {
readings: GlucoseReading[];
unit: GlucoseUnit;
range: [number, number];
}
/**
* Single clinical A1C reading (value and ISO date).
*/
interface A1CReading {
value: number;
date: string;
}
/**
* Options for clinical glucose statistics analytics.
* Controls which metrics are calculated and reported.
*/
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;
}
/**
* Population type for TIR target assessment.
* Different populations have different clinical goals.
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
type TIRPopulation = 'standard' | 'older-adults' | 'high-risk';
/**
* Overall glycemic control assessment based on TIR metrics.
*/
type TIRAssessment = 'excellent' | 'good' | 'needs improvement' | 'concerning';
/**
* Detailed metrics for a single glucose range.
* Provides percentage, duration, count, and average value for clinical analysis.
*/
interface RangeMetrics {
/** Percentage of readings in this range (0-100) */
readonly percentage: number;
/** Total duration in this range (minutes) */
readonly duration: number;
/** Count of readings in this range */
readonly readingCount: number;
/** Average glucose value in this range (mg/dL or mmol/L) */
readonly averageValue: number | null;
}
/**
* Assessment of whether TIR metrics meet clinical targets.
* Based on International Consensus on Time in Range (2019).
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
interface TargetAssessment {
/** TIR ≥70% for standard population, ≥50% for older adults */
readonly tirMeetsGoal: boolean;
/** TBR Level 1 <4% for standard, <1% for older adults */
readonly tbrLevel1Safe: boolean;
/** TBR Level 2 <1% for standard, <0.5% for older adults */
readonly tbrLevel2Safe: boolean;
/** TAR Level 1 <25% (all populations) */
readonly tarLevel1Acceptable: boolean;
/** TAR Level 2 <5% (all populations) */
readonly tarLevel2Acceptable: boolean;
/** Overall assessment of glycemic control */
readonly overallAssessment: TIRAssessment;
/** Clinical recommendations based on metrics */
readonly recommendations: readonly string[];
}
/**
* Summary statistics for TIR calculation.
*/
interface TIRSummary {
/** Total number of glucose readings analyzed */
readonly totalReadings: number;
/** Total duration of data analyzed (minutes) */
readonly totalDuration: number;
/** Data quality assessment */
readonly dataQuality: 'excellent' | 'good' | 'fair' | 'poor';
}
/**
* Complete Enhanced Time-in-Range result.
* Provides detailed breakdown across five clinical glucose ranges per International Consensus 2019.
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*/
interface EnhancedTIRResult {
/** Very Low: <54 mg/dL (3.0 mmol/L) - Level 2 Hypoglycemia */
readonly veryLow: RangeMetrics;
/** Low: 54-69 mg/dL (3.0-3.8 mmol/L) - Level 1 Hypoglycemia */
readonly low: RangeMetrics;
/** In Range: 70-180 mg/dL (3.9-10.0 mmol/L) - Target Range */
readonly inRange: RangeMetrics;
/** High: 181-250 mg/dL (10.1-13.9 mmol/L) - Level 1 Hyperglycemia */
readonly high: RangeMetrics;
/** Very High: >250 mg/dL (>13.9 mmol/L) - Level 2 Hyperglycemia */
readonly veryHigh: RangeMetrics;
/** Assessment against clinical targets */
readonly meetsTargets: TargetAssessment;
/** Summary statistics */
readonly summary: TIRSummary;
}
/**
* Options for Enhanced TIR calculation.
* Allows customization for different clinical populations and use cases.
*/
interface EnhancedTIROptions {
/** Population type for target assessment (default: 'standard') */
readonly population?: TIRPopulation;
/** Glucose unit for input validation (default: 'mg/dL') */
readonly unit?: GlucoseUnit;
/** Override for the very low threshold (<54 mg/dL). Value must be provided in mg/dL. */
readonly veryLowThreshold?: number;
/** Override for the low threshold (54-69 mg/dL). Value must be provided in mg/dL. */
readonly lowThreshold?: number;
/** Override for the high threshold (181-250 mg/dL). Value must be provided in mg/dL. */
readonly highThreshold?: number;
/** Override for the very high threshold (>250 mg/dL). Value must be provided in mg/dL. */
readonly veryHighThreshold?: number;
}
/**
* Pregnancy-specific Time-in-Range result.
* Uses tighter target range per ADA 2024 guidelines for pregnancy.
* @see {@link https://diabetesjournals.org/care/article/47/Supplement_1/S282 | ADA Standards of Care (2024)}
*/
interface PregnancyTIRResult {
/** In Range: 63-140 mg/dL (3.5-7.8 mmol/L) */
readonly inRange: RangeMetrics;
/** Below Range: <63 mg/dL (3.5 mmol/L) */
readonly belowRange: RangeMetrics;
/** Above Range: >140 mg/dL (7.8 mmol/L) */
readonly aboveRange: RangeMetrics;
/** Whether metrics meet pregnancy-specific targets (TIR >70%, TBR <4%, TAR <25%) */
readonly meetsPregnancyTargets: boolean;
/** Clinical recommendations */
readonly recommendations: readonly string[];
/** Summary statistics */
readonly summary: TIRSummary;
}
/**
* Options for Pregnancy TIR calculation.
*/
interface PregnancyTIROptions {
/** Glucose unit for input validation (default: 'mg/dL') */
readonly unit?: GlucoseUnit;
}
/**
* Converts clinical average glucose (mg/dL) to estimated A1C (percentage).
* Used for clinical analytics and patient reporting.
* @param avgMgDl - Average glucose in mg/dL
* @returns Estimated A1C value (percentage)
* @see https://www.cdc.gov/diabetes/managing/managing-blood-sugar/a1c.html
*/
declare function estimateA1CFromAvgGlucose(avgMgDl: number): number;
/**
* Converts clinical A1C value (percentage) to estimated average glucose (mg/dL).
* Used for clinical analytics and patient reporting.
* @param a1c - A1C value (percentage)
* @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, mg/dL) from clinical A1C value.
* Throws if input is negative. Used for clinical and research reporting.
* @param a1c - A1C value (percentage)
* @returns Estimated average glucose (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 clinical glucose value from mg/dL to mmol/L.
* Used for international interoperability and reporting.
* @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
*
* @example
* ```typescript
* const result = mgDlToMmolL(180)
* console.log(result) // 10.0
* ```
*/
declare function mgDlToMmolL(val: number): number;
/**
* Converts clinical glucose value from mmol/L to mg/dL.
* Used for international interoperability and reporting.
* @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
*
* @example
* ```typescript
* const result = mmolLToMgDl(5.5)
* console.log(result) // 99
* ```
*/
declare function mmolLToMgDl(val: number): number;
/**
* Converts clinical glucose value between mg/dL and mmol/L.
* Used for clinical interoperability and analytics.
* @param value - Glucose value (number)
* @param unit - Current glucose unit ('mg/dL' or 'mmol/L')
* @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;
}): ConversionResult;
/**
* Formats a clinical glucose value with unit and optional rounding.
* Used for clinical reporting, charting, and data export.
* @param val - Glucose value (number)
* @param unit - Glucose unit ('mg/dL' or 'mmol/L')
* @param options - Formatting options: { digits?: number; suffix?: boolean } (default: { digits: 0, suffix: true })
* @returns Formatted glucose string (e.g., '5.5 mmol/L', '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 value as a clinical percentage string (e.g., '85.0%').
* Used for reporting TIR, CV, and other clinical metrics.
* @param val - Value to format (fraction or percent)
* @param digits - Number of decimal places (default: 1)
* @returns Formatted percentage string (e.g., '85.0%')
*/
declare function formatPercentage(val: number, digits?: number): string;
/**
* Formats a UTC ISO 8601 timestamp to a local-readable date/time string.
* Used for clinical charting, logs, and reports. Supports optional IANA time zone.
* @param iso - ISO 8601 timestamp string (e.g., '2024-03-20T10:00:00Z')
* @param timeZone - Optional IANA time zone (e.g., 'America/New_York')
* @returns Localized date/time string (e.g., 'Mar 20, 2024, 06:00 AM')
* @throws {RangeError} If the ISO string is invalid or cannot be parsed
*/
declare function formatDate(iso: string, timeZone?: string): string;
/**
* Checks if a glucose value is below the hypoglycemia threshold for the given unit.
* Used for detecting low glucose events.
* @param val - Glucose value (number)
* @param unit - Glucose unit ('mg/dL' or 'mmol/L'), default: 'mg/dL'
* @param thresholds - Optional custom thresholds ({ mgdl?: number; mmoll?: number })
* @returns True if value is below the hypoglycemia threshold
* @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-level-ranges.html
*/
declare function isHypo(val: number, unit?: GlucoseUnit, thresholds?: {
mgdl?: number;
mmoll?: number;
}): boolean;
/**
* Checks if a glucose value is above the hyperglycemia threshold for the given unit.
* Used for detecting high glucose events.
* @param val - Glucose value (number)
* @param unit - Glucose unit ('mg/dL' or 'mmol/L'), default: 'mg/dL'
* @param thresholds - Optional custom thresholds ({ mgdl?: number; mmoll?: number })
* @returns True if value is above the hyperglycemia threshold
* @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-level-ranges.html
*/
declare function isHyper(val: number, unit?: GlucoseUnit, thresholds?: {
mgdl?: number;
mmoll?: number;
}): boolean;
/**
* Returns a glucose status label ('low', 'normal', or 'high') based on thresholds for the given unit.
* Used for charting, alerts, and reporting.
* @param val - Glucose value (number)
* @param unit - Glucose unit ('mg/dL' or 'mmol/L'), default: 'mg/dL'
* @param thresholds - Optional custom thresholds for hypo/hyper ({ hypo?: { mgdl?: number; mmoll?: number }, hyper?: { mgdl?: number; mmoll?: number } })
* @returns 'low', 'normal', or 'high' based on configured thresholds
* @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-level-ranges.html
*/
declare function getGlucoseLabel(val: number, unit?: GlucoseUnit, thresholds?: {
hypo?: {
mgdl?: number;
mmoll?: number;
};
hyper?: {
mgdl?: number;
mmoll?: number;
};
}): 'low' | 'normal' | 'high';
/**
* Parses a glucose string (e.g., "100 mg/dL", "5.5 mmol/L") into value and unit.
* Used for robust input validation and data ingestion.
* @param input - String in the format "value unit" (e.g., "100 mg/dL")
* @returns Object with numeric value and validated unit
* @throws {Error} If input string is invalid or not in 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;
};
/**
* Validates a glucose value and unit.
* Ensures value is a positive finite number and unit is supported.
* @param value - Glucose value to validate
* @param unit - Glucose unit to validate
* @returns True if value and unit are valid
*/
declare function isValidGlucoseValue(value: unknown, unit: unknown): boolean;
/**
* Clinical type guard for EstimateGMIOptions.
* Validates that the input matches the required shape for GMI estimation options (numeric value, string unit).
* Useful for ensuring safe handling of clinical glucose data and interoperability with analytics functions.
* @param input - Candidate value to validate.
* @returns True if input is a valid EstimateGMIOptions object.
*/
declare function isEstimateGMIOptions(input: unknown): input is EstimateGMIOptions;
/**
* Validates a clinical glucose string (e.g., "100 mg/dL", "5.5 mmol/L").
* Ensures the string is in a recognized clinical format for glucose values, supporting safe parsing and conversion.
* @param input - Value to check as a clinical glucose string.
* @returns True if input is a valid glucose string for clinical use.
* @see https://www.diabetes.co.uk/diabetes_care/blood-sugar-conversion.html
*/
declare function isValidGlucoseString(input: unknown): input is string;
/**
* Validates a clinical fasting insulin value (µIU/mL).
* Ensures value is a positive finite number and within plausible physiological range.
* @param value - Candidate insulin value
* @returns True if value is a valid fasting insulin (µIU/mL)
* @see https://www.ncbi.nlm.nih.gov/books/NBK279396/ (normal fasting insulin: ~2-25 µIU/mL, but allow wider plausible range for outliers)
*/
declare function isValidInsulin(value: unknown): value is number;
/**
* Calculates clinical Time in Range (TIR) metrics for glucose readings.
* Returns the percentage of readings in, below, and above the specified clinical target range.
* @param readings - Array of glucose readings to analyze
* @param target - Object specifying the target range ({ min, max })
* @returns Object with in-range, below-range, and above-range percentages
* @see https://care.diabetesjournals.org/content/42/8/1593
*/
declare function calculateTIR(readings: GlucoseReading[], target: {
min: number;
max: number;
}): TIRResult;
/**
* Generates a clinical summary string from a TIRResult object.
* Used for reporting and visualization of TIR analytics.
* @param result - TIR result breakdown to summarize
* @returns String summarizing 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 glucose readings within a specified numeric range.
* Used for clinical TIR analytics and custom range assessments.
* @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 Percentage of readings within the specified range (0-100)
*/
declare function calculateTimeInRange(readings: number[], lower: number, upper: number): number;
/**
* Calculates Mean Amplitude of Glycemic Excursions (MAGE).
* Implements Service FJ et al. (1970) methodology.
* @param readings - Array of glucose values (mg/dL or mmol/L)
* @param options - Configuration options for MAGE calculation
* @returns MAGE value, or NaN if insufficient data or no valid excursions
* @see https://pubmed.ncbi.nlm.nih.gov/5469118/ (Service FJ, et al. 1970)
* @see https://journals.sagepub.com/doi/10.1177/19322968211061165 (Fernandes NJ, et al. 2022)
* @see https://care.diabetesjournals.org/content/42/8/1593 (ADA 2019)
* @example
* // Basic usage
* glucoseMAGE([100, 120, 80, 160, 90, 140, 70, 180])
* // Advanced usage
* glucoseMAGE(readings, { shortWindow: 5, longWindow: 32, direction: 'auto' })
* @remarks
* - Minimum 24 data points recommended (1 day of hourly readings)
* - Best suited for continuous glucose monitoring (CGM) data
* - Not recommended for sparse or irregular measurements
* - Uses dual moving averages, three-point excursion definition, and prevents double-counting.
*/
declare function glucoseMAGE$1(readings: number[], options?: MAGEOptions): number;
/**
* Configuration options for MAGE calculation.
* @property shortWindow - Short moving average window (default: 5)
* @property longWindow - Long moving average window (default: 32)
* @property direction - Excursion direction: 'auto', 'ascending', or 'descending'
*/
interface MAGEOptions {
/** Short moving average window size (default: 5, recommended range: 1-7) */
shortWindow?: number;
/** Long moving average window size (default: 32, recommended range: 16-38) */
longWindow?: number;
/**
* Direction of excursions to count:
* - 'auto': Use first excursion type that exceeds SD threshold (Service 1970 default)
* - 'ascending': Count only ascending excursions (MAGE+)
* - 'descending': Count only descending excursions (MAGE-)
*/
direction?: 'auto' | 'ascending' | 'descending';
}
/**
* Calculates the unbiased sample standard deviation (SD) of glucose values.
* Uses n-1 in the denominator (sample SD), as recommended in research guidelines.
*
* @param readings Array of glucose values (numbers)
* @returns Standard deviation, or NaN if fewer than 2 values
* @throws {TypeError} If readings is not an array
* @see {@link https://care.diabetesjournals.org/content/42/8/1593 ADA 2019: Glycemic Targets}
* @see {@link https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7445493/ ISPAD 2019}
* @example
* ```ts
* glucoseStandardDeviation([100, 120, 140]) // 20
* glucoseStandardDeviation([]) // NaN
* ```
* @remarks
* - If readings contains <2 values, returns NaN (not enough data for SD).
* - Handles NaN/Infinity values by propagating them in the result.
*/
declare function glucoseStandardDeviation(readings: number[]): number;
/**
* Calculates the coefficient of variation (CV) for glucose values.
* CV = (SD / mean) × 100. Used to assess glycemic variability.
*
* @param readings Array of glucose values (numbers)
* @returns Coefficient of variation as a percentage, or NaN if <2 values or mean is 0
* @throws {TypeError} If readings is not an array
* @see {@link https://care.diabetesjournals.org/content/42/8/1593 ADA 2019: Glycemic Targets}
* @example
* ```ts
* glucoseCoefficientOfVariation([100, 120, 140]) // 18.26
* glucoseCoefficientOfVariation([100]) // NaN
* glucoseCoefficientOfVariation([]) // NaN
* ```
* @remarks
* - If readings contains <2 values or mean is 0, returns NaN.
* - Handles NaN/Infinity values by propagating them in the result.
*/
declare function glucoseCoefficientOfVariation(readings: number[]): number;
/**
* Calculates specified percentiles from an array of glucose values using the nearest-rank method.
* Used for glucose variability assessment.
* @param readings - Array of glucose values (numbers)
* @param percentiles - Array of percentiles to calculate (e.g., [10, 25, 50, 75, 90])
* @returns Object mapping percentile to value, or {} if input is empty
* @throws {TypeError} If readings or percentiles is not an array
* @see https://en.wikipedia.org/wiki/Percentile
* @see https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7445493/ (ISPAD 2019)
* @example
* glucosePercentiles([100, 120, 140, 160, 180], [10, 50, 90]) // { 10: 100, 50: 140, 90: 180 }
* glucosePercentiles([], [10, 50, 90]) // {}
* @remarks
* - Returns the value at the nearest-rank for each percentile.
* - If readings is empty, returns an empty object.
* - Percentiles outside [0, 100] are ignored.
*/
declare function glucosePercentiles(readings: number[], percentiles: number[]): Record<number, number>;
/**
* Calculates Mean Amplitude of Glycemic Excursions (MAGE) for glucose values.
* Implements Service FJ et al. (1970) methodology.
* @param readings - Array of glucose values (mg/dL or mmol/L)
* @param options - Optional configuration for MAGE calculation
* @returns MAGE value, or NaN if insufficient data or no valid excursions
* @see https://pubmed.ncbi.nlm.nih.gov/5469118/ (Service FJ, et al. 1970)
* @see https://journals.sagepub.com/doi/10.1177/19322968211061165 (Fernandes NJ, et al. 2022)
* @see https://care.diabetesjournals.org/content/42/8/1593 (ADA 2019)
* @example
* glucoseMAGE([100, 120, 80, 160, 90, 140, 70, 180])
* glucoseMAGE(readings, { direction: 'ascending', shortWindow: 5, longWindow: 32 })
* @remarks
* - Minimum 24 data points recommended (1 day of hourly readings)
* - Best suited for continuous glucose monitoring (CGM) data
* - Not recommended for sparse or irregular measurements
* - Uses dual moving averages, three-point excursion definition, and prevents double-counting.
*/
declare function glucoseMAGE(readings: number[], options?: MAGEOptions): number;
/**
* Calculates Enhanced Time-in-Range metrics per International Consensus 2019.
*
* Provides detailed breakdown of glucose readings across five clinical ranges:
* - Very Low (<54 mg/dL / 3.0 mmol/L): Level 2 Hypoglycemia
* - Low (54-69 mg/dL / 3.0-3.8 mmol/L): Level 1 Hypoglycemia
* - In Range (70-180 mg/dL / 3.9-10.0 mmol/L): Target Range
* - High (181-250 mg/dL / 10.1-13.9 mmol/L): Level 1 Hyperglycemia
* - Very High (>250 mg/dL / >13.9 mmol/L): Level 2 Hyperglycemia
*
* @param readings - Array of glucose readings with timestamp, value, and unit
* @param options - Optional configuration for thresholds and population type
* @returns Enhanced TIR result with detailed metrics and target assessment
*
* @example
* ```typescript
* const readings: GlucoseReading[] = [
* { value: 120, unit: 'mg/dL', timestamp: '2024-01-01T08:00:00Z' },
* { value: 95, unit: 'mg/dL', timestamp: '2024-01-01T08:05:00Z' },
* // ... more readings
* ];
* const result = calculateEnhancedTIR(readings);
* console.log(`TIR: ${result.inRange.percentage}%`);
* console.log(`Meets targets: ${result.meetsTargets.tirMeetsGoal}`);
* ```
*
* @throws {Error} If readings array is empty
* @throws {Error} If readings contain invalid glucose values
*
* @see {@link https://diabetesjournals.org/care/article/42/8/1593 | International Consensus on Time in Range (2019)}
*
* @remarks
* - Requires minimum 24 hours of data for meaningful results
* - Consensus targets: TIR ≥70%, TBR Level 1 <4%, TBR Level 2 <1%, TAR Level 1 <25%, TAR Level 2 <5%
* - Verify data quality and sensor accuracy before drawing conclusions
* - Readings are assumed to be evenly distributed for duration calculations
*
* @category Enhanced TIR
* @public
*/
declare function calculateEnhancedTIR(readings: GlucoseReading[], options?: EnhancedTIROptions): EnhancedTIRResult;
/**
* Calculates Pregnancy-specific Time-in-Range metrics per ADA 2024 guidelines.
*
* Uses tighter target range for pregnancy: 63-140 mg/dL (3.5-7.8 mmol/L).
* Consensus targets: TIR >70%, TBR <4% (Level 1) and <1% (Level 2), TAR <25%.
*
* @param readings - Array of glucose readings with timestamp, value, and unit
* @param options - Optional configuration for glucose unit
* @returns Pregnancy TIR result with target assessment and recommendations
*
* @example
* ```typescript
* const readings: GlucoseReading[] = [
* { value: 100, unit: 'mg/dL', timestamp: '2024-01-01T08:00:00Z' },
* // ... more readings
* ];
* const result = calculatePregnancyTIR(readings);
* console.log(`TIR: ${result.inRange.percentage}%`);
* console.log(`Meets pregnancy targets: ${result.meetsPregnancyTargets}`);
* ```
*
* @throws {Error} If readings array is empty
* @throws {Error} If readings contain invalid glucose values
*
* @see {@link https://diabetesjournals.org/care/article/47/Supplement_1/S282 | ADA Standards of Care (2024)}
*
* @remarks
* - Target range: 63-140 mg/dL (3.5-7.8 mmol/L)
* - Tighter targets per published guidelines
* - This is informational only and does not constitute medical advice
* - Applies to Type 1, Type 2, and gestational diabetes during pregnancy
*
* @category Pregnancy TIR
* @public
*/
declare function calculatePregnancyTIR(readings: GlucoseReading[], options?: PregnancyTIROptions): PregnancyTIRResult;
/**
* @file src/metrics/bgi.ts
*
* Low Blood Glucose Index (LBGI) and High Blood Glucose Index (HBGI).
*
* These risk indices quantify the risk of hypo- and hyperglycemia from a
* series of glucose readings. They are asymmetric transforms that weight
* low values more heavily (LBGI) or high values more heavily (HBGI).
*
* Formula (Kovatchev et al. 2006):
* f(G) = 1.509 * (ln(G)^1.084 - 5.381)
* rl(G) = 10 * f(G)^2 if f(G) < 0, else 0 (low risk)
* rh(G) = 10 * f(G)^2 if f(G) > 0, else 0 (high risk)
* LBGI = mean(rl)
* HBGI = mean(rh)
*
* Input values must be in mg/dL. Values <= 0 are skipped.
*
* @see https://doi.org/10.2337/dc06-1085 Kovatchev et al. (2006)
*/
/**
* Computes the blood glucose symmetry function f(G).
* Used by LBGI, HBGI, and ADRR calculations.
* @internal
*/
declare function fbg(glucoseMgDl: number): number;
/**
* Calculates the Low Blood Glucose Index (LBGI).
*
* Quantifies the risk and extent of hypoglycemia from a glucose trace.
* Higher values indicate greater hypoglycemia risk.
*
* Risk categories (Kovatchev 2006):
* - < 1.1: low risk
* - 1.1 - 2.5: moderate risk
* - > 2.5: high risk
*
* @param readings - Array of glucose values in mg/dL
* @returns LBGI value, or NaN if no valid readings
* @see https://doi.org/10.2337/dc06-1085
*/
declare function glucoseLBGI(readings: number[]): number;
/**
* Calculates the High Blood Glucose Index (HBGI).
*
* Quantifies the risk and extent of hyperglycemia from a glucose trace.
* Higher values indicate greater hyperglycemia risk.
*
* Risk categories (Kovatchev 2006):
* - < 4.5: low risk
* - 4.5 - 9.0: moderate risk
* - > 9.0: high risk
*
* @param readings - Array of glucose values in mg/dL
* @returns HBGI value, or NaN if no valid readings
* @see https://doi.org/10.2337/dc06-1085
*/
declare function glucoseHBGI(readings: number[]): number;
/**
* @file src/metrics/adrr.ts
*
* Average Daily Risk Range (ADRR).
*
* ADRR combines the maximum daily hypo and hyper risk values to produce
* a single composite risk score. It captures the amplitude of extreme
* glucose excursions on each day and averages them.
*
* Formula (Kovatchev et al. 2006):
* For each day d: DR(d) = max(rl over day d) + max(rh over day d)
* ADRR = mean(DR) across all days
*
* Risk categories:
* - < 20: low risk
* - 20 - 40: moderate risk
* - > 40: high risk
*
* @see https://doi.org/10.2337/dc06-1085 Kovatchev et al. (2006)
*/
/**
* Calculates the Average Daily Risk Range (ADRR).
*
* @param readings - Array of GlucoseReading objects with timestamps
* @returns ADRR value, or NaN if no valid readings
* @see https://doi.org/10.2337/dc06-1085
*/
declare function calculateADRR(readings: GlucoseReading[]): number;
/**
* @file src/metrics/grade.ts
*
* Glycemic Risk Assessment Diabetes Equation (GRADE).
*
* GRADE produces a single risk score from a glucose value, and its
* partitioned variants break down what percentage of the total GRADE
* score comes from euglycemic, hyperglycemic, and hypoglycemic readings.
*
* Formula (Hill et al. 2007):
* GRADE(G) = 425 * (log10(log10(G_mmol)) + 0.16)^2
* where G_mmol = G_mgdl / 18.0182
*
* Input values must be in mg/dL. Values <= 0 are skipped.
*
* @see https://doi.org/10.1111/j.1464-5491.2007.02119.x Hill et al. (2007)
*/
/** Result of the partitioned GRADE calculation. */
interface GRADEResult {
/** Mean GRADE score across all valid readings */
readonly grade: number;
/** % of total GRADE contributed by euglycemic readings (70-140 mg/dL) */
readonly gradeEuglycemia: number;
/** % of total GRADE contributed by hyperglycemic readings (>140 mg/dL) */
readonly gradeHyperglycemia: number;
/** % of total GRADE contributed by hypoglycemic readings (<70 mg/dL) */
readonly gradeHypoglycemia: number;
}
/**
* Calculates the GRADE score and its partitioned components.
*
* @param readings - Array of glucose values in mg/dL
* @param hypoThreshold - Upper bound for hypoglycemia (default: 70 mg/dL)
* @param hyperThreshold - Lower bound for hyperglycemia (default: 140 mg/dL)
* @returns GRADE result with overall score and percentage breakdown, or NaN fields if no valid data
* @see https://doi.org/10.1111/j.1464-5491.2007.02119.x
*/
declare function calculateGRADE(readings: number[], hypoThreshold?: number, hyperThreshold?: number): GRADEResult;
/**
* @file src/metrics/gri.ts
*
* Glycemia Risk Index (GRI).
*
* The GRI is a composite CGM metric that captures both hypo- and
* hyperglycemia risk in a single 0-100 score. It is derived from four
* TIR zone percentages using the formula from Klonoff et al. (2023).
*
* Formula:
* GRI = (3.0 * VLow) + (2.4 * Low) + (1.6 * VHigh) + (0.8 * High)
* clamped to [0, 100]
*
* Where:
* VLow = % time < 54 mg/dL (TBR Level 2)
* Low = % time 54-69 mg/dL (TBR Level 1)
* VHigh = % time > 250 mg/dL (TAR Level 2)
* High = % time 181-250 mg/dL (TAR Level 1)
*
* Risk zones:
* A (lowest risk): GRI <= 20
* B: 20 < GRI <= 40
* C: 40 < GRI <= 60
* D: 60 < GRI <= 80
* E (highest risk): GRI > 80
*
* @see https://doi.org/10.1177/19322968221085273 Klonoff et al. (2023)
*/
/** Input percentages for GRI calculation. */
interface GRIInput {
/** % time < 54 mg/dL */
readonly veryLowPercent: number;
/** % time 54-69 mg/dL */
readonly lowPercent: number;
/** % time 181-250 mg/dL */
readonly highPercent: number;
/** % time > 250 mg/dL */
readonly veryHighPercent: number;
}
/** GRI result with numeric score and risk zone. */
interface GRIResult {
readonly score: number;
readonly zone: 'A' | 'B' | 'C' | 'D' | 'E';
readonly hypoComponent: number;
readonly hyperComponent: number;
}
/**
* Calculates the Glycemia Risk Index (GRI) from TIR zone percentages.
*
* @param input - Percentages for each out-of-range zone
* @returns GRI result with composite score and risk zone
* @see https://doi.org/10.1177/19322968221085273
*/
declare function calculateGRI(input: GRIInput): GRIResult;
/**
* @file src/metrics/jindex.ts
*
* J-Index: a composite measure of both mean glucose and variability.
*
* Formula (Wojcicki 1995):
* J = 0.001 * (mean + SD)^2
*
* Input values must be in mg/dL.
*
* @see https://doi.org/10.1055/s-2007-979906 Wojcicki (1995)
*/
/**
* Calculates the J-Index for a glucose trace.
*
* The J-Index captures both central tendency and variability in a
* single score. Higher values indicate worse glycemic control.
*
* @param readings - Array of glucose values in mg/dL
* @returns J-Index value, or NaN if fewer than 2 valid readings
* @see https://doi.org/10.1055/s-2007-979906
*/
declare function calculateJIndex(readings: number[]): number;
/**
* @file src/metrics/modd.ts
*
* Mean of Daily Differences (MODD).
*
* MODD quantifies day-to-day glucose variability by comparing glucose values
* at matching times on consecutive days. It measures how consistently glucose
* behaves across days — lower values indicate more predictable patterns.
*
* Formula (Service & Nelson, 1980):
* MODD = mean(|G(t) - G(t - 24h)|) for all t where both values exist
*
* Readings are matched across days by finding the closest timestamp within
* a configurable tolera