import { Platform } from 'react-native'; import { getSdkStatus, initialize, insertRecords, readRecords, requestPermission, SdkAvailabilityStatus, type HealthConnectRecord, type ReadRecordsResult, } from 'react-native-health-connect'; import { type HealthPermissions } from './types/permissions'; import { HealthLinkDataType, optionsToAndroidOptions, type ReadOptions, type AndroidType, } from './types/dataTypes'; import type { HealthValue } from 'react-native-health'; import { type HealthLinkDataValue } from './types/results'; import { type WriteDataType, type WriteOptions } from './types/save'; import { serializeWriteOptions, writeIosCallback } from './helpers/save'; import { healthLinkToAndroidType, readDataResultDeserializer, readIosCallback, } from './helpers/results'; import { genericToAndroidPermissions, genericToIosPermissions, } from './helpers/permissions'; const AppleHealthKit = require('react-native-health'); /** * Initializes the health integration for the application by requesting the necessary permissions * based on the platform (iOS or Android). * * @param {HealthPermissions} permissions - The permissions required for accessing health data. * * @returns {Promise} A promise that resolves when the initialization and permission request process is complete. * * @example * ```typescript * const permissions = { * read: [HealthLinkPermissions.StepCount, HealthLinkPermissions.HeartRate], * write: [HealthLinkPermissions.StepCount] * }; * await initializeHealth(permissions); * ``` */ export const initializeHealth = async (permissions: HealthPermissions) => { if (Platform.OS === 'ios') { const iosPermissions = genericToIosPermissions(permissions); AppleHealthKit.initHealthKit(iosPermissions); } else if (Platform.OS === 'android') { const androidPermissions = genericToAndroidPermissions(permissions); await initialize(); await requestPermission(androidPermissions); } }; /** * Checks the availability of the SDK on the current platform. * * On Android, it checks the SDK status and resolves to `true` if the SDK is available, * otherwise logs the reason for unavailability and resolves to `false`. * * On iOS, it uses AppleHealthKit to check availability and resolves to the result. * * @returns {Promise} A promise that resolves to `true` if the SDK is available, otherwise `false`. * * @example * isAvailable().then((available) => { * if (available) { * console.log('SDK is available'); * } else { * console.log('SDK is not available'); * } * }).catch((error) => { * console.error('Error checking SDK availability:', error); * }); */ export const isAvailable = () => { return new Promise(async (resolve, reject) => { if (Platform.OS === 'android') { const status = await getSdkStatus(); if (status === SdkAvailabilityStatus.SDK_AVAILABLE) { resolve(true); } else { if (status === SdkAvailabilityStatus.SDK_UNAVAILABLE) { console.log('SDK is not available'); } if ( status === SdkAvailabilityStatus.SDK_UNAVAILABLE_PROVIDER_UPDATE_REQUIRED ) { console.log('SDK is not available, provider update required'); } resolve(false); } } else if (Platform.OS === 'ios') { AppleHealthKit.isAvailable((err: Object, available: boolean) => { if (err) { console.error('Error checking availability: ', err); reject(err); } else { resolve(available); } }); } }); }; /** * Reads health data of the specified type from the device. * * @param {T} dataType - The type of health data to read. Use the `HealthLinkDataType` enum. * @param {ReadOptions} options - The options for reading the health data. * @returns {Promise>>} A promise that resolves to an array of health data values. */ export const read = async ( dataType: T, options: ReadOptions ): Promise>> => { let data: ReadRecordsResult | HealthValue[] = []; if (Platform.OS === 'ios') { data = (await readIosCallback(dataType, options)) as HealthValue[]; } else if (Platform.OS === 'android') { data = await readRecords( healthLinkToAndroidType(dataType), optionsToAndroidOptions(options) ); } return readDataResultDeserializer(dataType, options, data); }; /** * Writes health data to the appropriate platform's health store. * * @param {T} dataType - The type of data to be written, extending WriteDataType. * @param {WriteOptions} data - The data to be written. * @returns {Promise} A promise that resolves when the data has been written. * * @example * ```typescript * const dataType = 'heartRate'; * const data = { value: 72, timestamp: new Date() }; * await write(dataType, data); * ``` */ export const write = async ( dataType: T, data: WriteOptions ): Promise => { const serializedData = serializeWriteOptions(dataType, data); if (serializedData === null) { return; } if (Platform.OS === 'ios') { await writeIosCallback(dataType, serializedData as WriteOptions); } else if (Platform.OS === 'android') { await insertRecords([serializedData as HealthConnectRecord]).catch((e) => { console.error(e); }); } }; export * from './types/units'; export * from './types/dataTypes'; export * from './types/save'; export * from './types/permissions';