Skip to content

glisom/HealthQL

Repository files navigation

HealthQL

A SQL-like query language for Apple HealthKit. Query your health data using familiar SQL syntax or a type-safe Swift DSL.

SELECT avg(value), min(value), max(value)
FROM heart_rate
WHERE date > today() - 7d
GROUP BY day

Features

  • SQL-like Syntax - Query HealthKit with familiar SELECT, FROM, WHERE, GROUP BY, ORDER BY, LIMIT
  • Type-safe Swift DSL - Fluent API for building queries programmatically
  • React Native / Expo Support - Use HealthQL in React Native apps with full TypeScript types
  • 33 Quantity Types - Heart rate, steps, calories, VO2 max, swimming, and more
  • 5 Category Types - Sleep analysis, headache, fatigue, appetite, menstrual flow
  • Workouts & Sleep Sessions - Query exercise data and aggregated sleep metrics
  • Date Functions - today(), start_of_week(), start_of_month(), start_of_year()
  • Aggregations - SUM, AVG, MIN, MAX, COUNT with GROUP BY support
  • Full Predicate Support - All comparison operators, AND, IS NULL, IS NOT NULL

Expanding Coverage: We're working toward full HealthKit SDK support. See our Roadmap for nutrition, symptoms, and 70+ additional workout types coming soon.

Installation

React Native / Expo

npm install react-native-healthql

Add the config plugin to your app.json:

{
  "expo": {
    "plugins": [
      [
        "react-native-healthql",
        {
          "healthShareUsageDescription": "Read health data to display insights"
        }
      ]
    ]
  }
}

Then rebuild your app:

npx expo prebuild --clean
npx expo run:ios

Swift Package Manager

Add HealthQL to your Package.swift:

dependencies: [
    .package(url: "https://github.com/glisom/HealthQL.git", from: "1.0.0")
]

Then add the products you need:

.target(
    name: "YourApp",
    dependencies: [
        "HealthQL",        // Core types and execution
        "HealthQLParser",  // SQL string parsing
    ]
)

CocoaPods

pod 'HealthQL', '~> 1.1.0'

Quick Start

React Native / TypeScript

import { HealthQL } from 'react-native-healthql';

// Request authorization first
await HealthQL.requestAuthorization({
  read: ['heart_rate', 'steps', 'sleep_analysis'],
});

// Execute a SQL query
const results = await HealthQL.query(`
  SELECT avg(value) FROM heart_rate
  WHERE date > today() - 7d
  GROUP BY day
`);

results.forEach(row => {
  console.log(`${row.date}: ${row.avg_value} bpm`);
});

Swift - SQL String Queries

import HealthQL
import HealthQLParser

// Parse and execute a query
let result = try await HQL.query("""
    SELECT sum(value) FROM steps
    WHERE date > today() - 7d
    GROUP BY day
""")

for row in result.rows {
    print("\(row["date"]!): \(row["sum_value"]!) steps")
}

Swift DSL

import HealthQL

let result = try await Health.select(.steps, aggregate: .sum)
    .where(.date, .greaterThan, .date(.daysAgo(7)))
    .groupBy(.day)
    .execute()

Supported Health Types

Quantity Types

33 quantity types including:

Type SQL Name Unit
Heart Rate heart_rate bpm
Resting Heart Rate resting_heart_rate bpm
Steps steps count
Active Calories active_calories kcal
Distance distance m
VO2 Max vo2_max mL/(kg·min)
Body Mass body_mass kg
Body Mass Index body_mass_index -
Blood Oxygen oxygen_saturation %
Blood Pressure blood_pressure_systolic mmHg
Blood Glucose blood_glucose mg/dL

See all 33 quantity types →

Category Types

Type SQL Name
Sleep Analysis sleep_analysis
Appetite Changes appetite_changes
Headache headache
Fatigue fatigue
Menstrual Flow menstrual_flow

Special Types

Type SQL Name Description
Workouts workouts Exercise sessions with duration, calories, type
Sleep Sessions sleep Aggregated nightly sleep with stage breakdown

Query Examples

Basic Queries

-- All heart rate readings from today
SELECT * FROM heart_rate WHERE date > today()

-- Latest 10 weight measurements
SELECT value, date FROM body_mass ORDER BY date DESC LIMIT 10

-- Steps with source device info
SELECT value, date, source, device FROM steps WHERE date > today() - 7d

Aggregations

-- Daily step totals for the past month
SELECT sum(value) FROM steps WHERE date > today() - 30d GROUP BY day

-- Weekly average heart rate
SELECT avg(value), min(value), max(value) FROM heart_rate
WHERE date > start_of_month() GROUP BY week

-- Monthly calorie burn
SELECT sum(value) FROM active_calories WHERE date > start_of_year() GROUP BY month

Workouts

-- Recent workouts with details
SELECT duration, total_calories, activity_type FROM workouts
ORDER BY date DESC LIMIT 20

-- Weekly workout summary
SELECT sum(duration), sum(total_calories) FROM workouts
WHERE date > today() - 30d GROUP BY week

Sleep

-- Sleep sessions for the past week
SELECT * FROM sleep WHERE date > today() - 7d ORDER BY date DESC

-- Raw sleep analysis data
SELECT * FROM sleep_analysis WHERE date > today() - 7d

Filtering

-- High heart rate readings
SELECT * FROM heart_rate WHERE value > 100

-- Heart rate in normal range
SELECT * FROM heart_rate WHERE value > 60 AND value < 100

-- Readings with device info
SELECT * FROM heart_rate WHERE device IS NOT NULL

Date Functions

Function Description
today() Start of current day
start_of_week() Start of current week
start_of_month() Start of current month
start_of_year() Start of current year

Duration Syntax

Unit Syntax Example
Days d 7d
Weeks w 4w
Months mo 3mo
Years y 1y
-- Last 7 days
WHERE date > today() - 7d

-- Last 4 weeks
WHERE date > today() - 4w

-- Last 3 months
WHERE date > today() - 3mo

Architecture

HealthQL uses a multi-stage architecture:

SQL String → Lexer → Parser → AST → Compiler → HealthQuery IR → Executor → Results
                                                      ↑
Swift DSL → QueryBuilder ──────────────────────────────┘

Modules

Module Purpose
HealthQL Core types, IR, DSL, HealthKit execution
HealthQLParser SQL lexer, parser, compiler
HealthQLPlayground REPL engine, formatting, autocomplete

Requirements

  • iOS 15.0+ / macOS 13.0+
  • Swift 6.0+
  • HealthKit entitlement

HealthKit Setup

  1. Add HealthKit capability to your app
  2. Add usage descriptions to Info.plist:
<key>NSHealthShareUsageDescription</key>
<string>Read health data to display query results</string>
  1. Request authorization (HealthQL requests automatically on first query, or manually):
let store = HKHealthStore()
try await store.requestAuthorization(toShare: [], read: [
    HKQuantityType(.heartRate),
    HKQuantityType(.stepCount),
    // ... other types
])

Example App

The HealthQLApp directory contains a sample iOS app demonstrating:

  • Query input with syntax highlighting
  • Demo query buttons for common queries
  • Result display with formatting
  • HealthKit authorization flow

License

MIT License - see LICENSE file for details.

Contributing

Contributions welcome! Please read the contributing guidelines before submitting PRs.


Built with Swift and HealthKit.

About

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published