{"_id":"@appeeky/expo-healthkit","_rev":"7-0ffe013d3ea95ef02807d00b2efffe2d","name":"@appeeky/expo-healthkit","dist-tags":{"latest":"0.4.1"},"versions":{"0.1.0":{"name":"@appeeky/expo-healthkit","version":"0.1.0","keywords":["react-native","expo","expo-module","healthkit","apple-health","apple-healthkit","health-connect","google-health-connect","ios","android","health","fitness"],"author":{"url":"https://github.com/Eronred","name":"Erencan Arica","email":"erencan_arica@hotmail.com"},"license":"SEE LICENSE IN LICENSE","_id":"@appeeky/expo-healthkit@0.1.0","maintainers":[{"name":"erencan","email":"erencan_arica@hotmail.com"}],"homepage":"https://github.com/appeeky/expo-healthkit#readme","bugs":{"url":"https://github.com/appeeky/expo-healthkit/issues"},"dist":{"shasum":"22854e5ecbc5e21e4527cac67d0dff6c9c8e4847","tarball":"https://registry.npmjs.org/@appeeky/expo-healthkit/-/expo-healthkit-0.1.0.tgz","fileCount":62,"integrity":"sha512-6PYyvcL2GF5vjfGsvPzxN6zeBcCuuIIHA3+s8i6Jbky78TdioqqzMmw4hqUM0qfDE5kSdi/uzNXwSEtExOC8Gg==","signatures":[{"sig":"MEUCIQCcfBeS5eIvIZmpZpTp2vqlY0wNDcUWYwLAvAC8Kzkl3AIgTIKsiKSQMa69SOQXARjfeFCjpv6+HQu88zH9lDly7i8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":517991},"jest":{"roots":["<rootDir>/src"],"transform":{"^.+\\.(js|ts|tsx)$":"babel-jest"},"testEnvironment":"node","coverageDirectory":"coverage","coverageThreshold":{"global":{"lines":90,"branches":80,"functions":90,"statements":90}},"collectCoverageFrom":["src/identifiers.ts","src/errors.ts","src/dates.ts"],"moduleFileExtensions":["ts","tsx","js"]},"main":"build/index.js","types":"build/index.d.ts","engines":{"node":">=18.18"},"exports":{".":{"types":"./build/index.d.ts","default":"./build/index.js"},"./app.plugin":"./app.plugin.js","./package.json":"./package.json","./app.plugin.js":"./app.plugin.js"},"gitHead":"6e954698fb2d9d0f904fec178614dc35beb99c58","scripts":{"lint":"eslint src plugin/src","test":"node internal/module_scripts/test.js","build":"node internal/module_scripts/build.js","clean":"node internal/module_scripts/clean.js","prepare":"node internal/module_scripts/prepare.js","open:ios":"node internal/module_scripts/open-ios.js","typecheck":"tsc --noEmit && tsc --noEmit -p plugin","open:android":"node internal/module_scripts/open-android.js","test:coverage":"node internal/module_scripts/test.js --coverage --watchAll=false","prepublishOnly":"node internal/module_scripts/prepare.js"},"_npmUser":{"name":"erencan","email":"erencan_arica@hotmail.com"},"repository":{"url":"git+https://github.com/appeeky/expo-healthkit.git","type":"git"},"_npmVersion":"10.9.8","description":"Apple HealthKit and Android Health Connect for Expo. One identifier-based JavaScript API on iOS and Android.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"expo":"^57.0.19","jest":"^29.7.0","eslint":"~9.39.4","prettier":"^3.0.0","typescript":"^5.9.2","@babel/core":"^7.26.0","@types/jest":"^29.2.1","@types/react":"~19.1.1","react-native":"0.82.1","babel-preset-expo":"~57.0.10","eslint-config-universe":"^15.0.3"},"peerDependencies":{"expo":">=53.0.0","react":"*","react-native":"*"},"_npmOperationalInternal":{"tmp":"tmp/expo-healthkit_0.1.0_1788628535086_0.26215693903861514","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@appeeky/expo-healthkit","version":"0.1.1","keywords":["react-native","expo","expo-module","healthkit","apple-health","apple-healthkit","health-connect","google-health-connect","ios","android","health","fitness"],"author":{"url":"https://github.com/Eronred","name":"Erencan Arica","email":"erencan_arica@hotmail.com"},"license":"SEE LICENSE IN LICENSE","_id":"@appeeky/expo-healthkit@0.1.1","maintainers":[{"name":"erencan","email":"erencan_arica@hotmail.com"}],"homepage":"https://github.com/appeeky/expo-healthkit#readme","bugs":{"url":"https://github.com/appeeky/expo-healthkit/issues"},"dist":{"shasum":"6e2a419314e8958445a335bac14e52b456cb462d","tarball":"https://registry.npmjs.org/@appeeky/expo-healthkit/-/expo-healthkit-0.1.1.tgz","fileCount":63,"integrity":"sha512-LfREzE9nEzLBHMhXtq8WEXxcRsNi2Avu9TBNYJRy7oNsj1xAqioEr2ssehjPXAtOXOgL7xP9BVpsw2muz3eD4A==","signatures":[{"sig":"MEUCIFOJuKakRz0UlZqM9nLiCFLYswRuwf1h9BqwZrIjlym6AiEAu0AmnOAj/xpRTXh3U1/8wb7qr8nXWlyO4MbHhgqksKQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@appeeky%2fexpo-healthkit@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":520801},"jest":{"roots":["<rootDir>/src"],"transform":{"^.+\\.(js|ts|tsx)$":"babel-jest"},"testEnvironment":"node","coverageDirectory":"coverage","coverageThreshold":{"global":{"lines":90,"branches":80,"functions":90,"statements":90}},"collectCoverageFrom":["src/identifiers.ts","src/errors.ts","src/dates.ts"],"moduleFileExtensions":["ts","tsx","js"]},"main":"build/index.js","types":"build/index.d.ts","engines":{"node":">=18.18"},"exports":{".":{"types":"./build/index.d.ts","default":"./build/index.js"},"./app.plugin":"./app.plugin.js","./package.json":"./package.json","./app.plugin.js":"./app.plugin.js"},"gitHead":"dd50903092fafbe14ae0444dc12ae665a1a90df3","scripts":{"lint":"eslint src plugin/src","test":"node internal/module_scripts/test.js","build":"node internal/module_scripts/build.js","clean":"node internal/module_scripts/clean.js","prepare":"node internal/module_scripts/prepare.js","release":"semantic-release","open:ios":"node internal/module_scripts/open-ios.js","typecheck":"tsc --noEmit && tsc --noEmit -p plugin","open:android":"node internal/module_scripts/open-android.js","test:coverage":"node internal/module_scripts/test.js --coverage --watchAll=false","prepublishOnly":"node internal/module_scripts/prepare.js"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:1d8ba55b-5c7b-4b1e-8a4e-39febedeb25d"}},"repository":{"url":"git+https://github.com/appeeky/expo-healthkit.git","type":"git"},"_npmVersion":"11.19.1","description":"Apple HealthKit and Android Health Connect for Expo. One identifier-based JavaScript API on iOS and Android.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"expo":"^57.0.19","jest":"^29.7.0","eslint":"~9.39.4","prettier":"^3.0.0","typescript":"^5.9.2","@babel/core":"^7.26.0","@types/jest":"^29.2.1","@types/react":"~19.1.1","react-native":"0.82.1","semantic-release":"^25.0.9","babel-preset-expo":"~57.0.10","@semantic-release/git":"^11.0.1","eslint-config-universe":"^15.0.3","@semantic-release/changelog":"^7.0.0"},"peerDependencies":{"expo":">=53.0.0","react":"*","react-native":"*"},"_npmOperationalInternal":{"tmp":"tmp/expo-healthkit_0.1.1_1788636361570_0.8898672553005471","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@appeeky/expo-healthkit","version":"0.2.0","keywords":["react-native","expo","expo-module","healthkit","apple-health","apple-healthkit","health-connect","google-health-connect","ios","android","health","fitness"],"author":{"url":"https://github.com/Eronred","name":"Erencan Arica","email":"erencan_arica@hotmail.com"},"license":"SEE LICENSE IN LICENSE","_id":"@appeeky/expo-healthkit@0.2.0","maintainers":[{"name":"erencan","email":"erencan_arica@hotmail.com"}],"homepage":"https://github.com/appeeky/expo-healthkit#readme","bugs":{"url":"https://github.com/appeeky/expo-healthkit/issues"},"dist":{"shasum":"74cefd25e6e184e078b000df0c82e0b3e31a3d4d","tarball":"https://registry.npmjs.org/@appeeky/expo-healthkit/-/expo-healthkit-0.2.0.tgz","fileCount":65,"integrity":"sha512-iOukWIhos/ETjBOoYI49zJ6sT4ZWhJ4aS1jH7uTb97yKc8yYaThvrHK+NyKD3wT3E9HobWCLrPo6xLG+FKmE2g==","signatures":[{"sig":"MEUCIDIIdIn4oBizqBYhNl9e91c5mhJW/5ID+NvlhBt6J/sOAiEAvsXvukt1eV35jaqaqlMQB2zRiTRD5IeCxnvJaMMRNBI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@appeeky%2fexpo-healthkit@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":541246},"jest":{"roots":["<rootDir>/src"],"transform":{"^.+\\.(js|ts|tsx)$":"babel-jest"},"testEnvironment":"node","coverageDirectory":"coverage","coverageThreshold":{"global":{"lines":90,"branches":80,"functions":90,"statements":90}},"collectCoverageFrom":["src/identifiers.ts","src/errors.ts","src/dates.ts"],"moduleFileExtensions":["ts","tsx","js"]},"main":"build/index.js","types":"build/index.d.ts","engines":{"node":">=18.18"},"exports":{".":{"types":"./build/index.d.ts","default":"./build/index.js"},"./app.plugin":"./app.plugin.js","./package.json":"./package.json","./app.plugin.js":"./app.plugin.js"},"gitHead":"e0c6d6aaf8f7e96d048e4b854dec46455d162167","scripts":{"lint":"eslint src plugin/src","test":"node internal/module_scripts/test.js","build":"node internal/module_scripts/build.js","clean":"node internal/module_scripts/clean.js","prepare":"node internal/module_scripts/prepare.js","release":"semantic-release","open:ios":"node internal/module_scripts/open-ios.js","typecheck":"tsc --noEmit && tsc --noEmit -p plugin","open:android":"node internal/module_scripts/open-android.js","test:coverage":"node internal/module_scripts/test.js --coverage --watchAll=false","prepublishOnly":"node internal/module_scripts/prepare.js"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:1d8ba55b-5c7b-4b1e-8a4e-39febedeb25d"}},"repository":{"url":"git+https://github.com/appeeky/expo-healthkit.git","type":"git"},"_npmVersion":"11.19.1","description":"Apple HealthKit and Android Health Connect for Expo. One identifier-based JavaScript API on iOS and Android.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"expo":"^57.0.19","jest":"^29.7.0","eslint":"~9.39.4","prettier":"^3.0.0","typescript":"^5.9.2","@babel/core":"^7.26.0","@types/jest":"^29.2.1","@types/react":"~19.1.1","react-native":"0.82.1","semantic-release":"^25.0.9","babel-preset-expo":"~57.0.10","@semantic-release/git":"^11.0.1","eslint-config-universe":"^15.0.3","@semantic-release/changelog":"^7.0.0"},"peerDependencies":{"expo":">=53.0.0","react":"*","react-native":"*"},"_npmOperationalInternal":{"tmp":"tmp/expo-healthkit_0.2.0_1788968970642_0.7017593126625137","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@appeeky/expo-healthkit","version":"0.2.1","keywords":["react-native","expo","expo-module","healthkit","apple-health","apple-healthkit","health-connect","google-health-connect","ios","android","health","fitness"],"author":{"url":"https://github.com/Eronred","name":"Erencan Arica","email":"erencan_arica@hotmail.com"},"license":"SEE LICENSE IN LICENSE","_id":"@appeeky/expo-healthkit@0.2.1","maintainers":[{"name":"erencan","email":"erencan_arica@hotmail.com"}],"homepage":"https://github.com/appeeky/expo-healthkit#readme","bugs":{"url":"https://github.com/appeeky/expo-healthkit/issues"},"dist":{"shasum":"47f30f41c7c7e4deb42178c3189313d4cea473bd","tarball":"https://registry.npmjs.org/@appeeky/expo-healthkit/-/expo-healthkit-0.2.1.tgz","fileCount":65,"integrity":"sha512-EjpwGMtL2wqDcVDunPCqdiWPc6thffqHWvae9ZXNZHTOjBrhZFdkrumem0IMkhDBDtnFsnRs3ZZbrCqVdc1zvQ==","signatures":[{"sig":"MEYCIQDLrYn+IxSYN1lxZbjE/k3j67WSckPu7clFkrJ4G1DGGQIhAIlwccgSAKWNrYcRWBsgsRXzS8swQa+f5pcXBqQohA3d","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDXSfQsy7jiDhGPAE902A+O6faJq1IY66PLXj9CpYCJYAIgBqqDSJYwZMM8pZJ+5FPtQdj+xyfVd3ux/Ouxt5Qhkfk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@appeeky%2fexpo-healthkit@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":541072},"jest":{"roots":["<rootDir>/src"],"transform":{"^.+\\.(js|ts|tsx)$":"babel-jest"},"testEnvironment":"node","coverageDirectory":"coverage","coverageThreshold":{"global":{"lines":90,"branches":80,"functions":90,"statements":90}},"collectCoverageFrom":["src/identifiers.ts","src/errors.ts","src/dates.ts"],"moduleFileExtensions":["ts","tsx","js"]},"main":"build/index.js","types":"build/index.d.ts","engines":{"node":">=18.18"},"exports":{".":{"types":"./build/index.d.ts","default":"./build/index.js"},"./app.plugin":"./app.plugin.js","./package.json":"./package.json","./app.plugin.js":"./app.plugin.js"},"gitHead":"6d54bbe3bbd82ee7ae2d3c6f864bf3be6a8c9944","scripts":{"lint":"eslint src plugin/src","test":"node internal/module_scripts/test.js","build":"node internal/module_scripts/build.js","clean":"node internal/module_scripts/clean.js","prepare":"node internal/module_scripts/prepare.js","release":"semantic-release","open:ios":"node internal/module_scripts/open-ios.js","typecheck":"tsc --noEmit && tsc --noEmit -p plugin","open:android":"node internal/module_scripts/open-android.js","test:coverage":"node internal/module_scripts/test.js --coverage --watchAll=false","prepublishOnly":"node internal/module_scripts/prepare.js"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"1d8ba55b-5c7b-4b1e-8a4e-39febedeb25d"}},"repository":{"url":"git+https://github.com/appeeky/expo-healthkit.git","type":"git"},"_npmVersion":"11.19.1","description":"Apple HealthKit and Android Health Connect for Expo. One identifier-based JavaScript API on iOS and Android.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"expo":"^57.0.19","jest":"^29.7.0","eslint":"~9.39.4","prettier":"^3.0.0","typescript":"^5.9.2","@babel/core":"^7.26.0","@types/jest":"^29.2.1","@types/react":"~19.1.1","react-native":"0.82.1","semantic-release":"^25.0.9","babel-preset-expo":"~57.0.10","@semantic-release/git":"^11.0.1","eslint-config-universe":"^15.0.3","@semantic-release/changelog":"^7.0.0"},"peerDependencies":{"expo":">=53.0.0","react":"*","react-native":"*"},"_npmOperationalInternal":{"tmp":"tmp/expo-healthkit_0.2.1_1790897107316_0.6545833026536385","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@appeeky/expo-healthkit","version":"0.3.0","keywords":["react-native","expo","expo-module","healthkit","apple-health","apple-healthkit","health-connect","google-health-connect","ios","android","health","fitness"],"author":{"url":"https://github.com/Eronred","name":"Erencan Arica","email":"erencan_arica@hotmail.com"},"license":"SEE LICENSE IN LICENSE","_id":"@appeeky/expo-healthkit@0.3.0","maintainers":[{"name":"erencan","email":"erencan_arica@hotmail.com"}],"homepage":"https://github.com/appeeky/expo-healthkit#readme","bugs":{"url":"https://github.com/appeeky/expo-healthkit/issues"},"dist":{"shasum":"5c80a07a3b21bb5df2a579b75eda691ac1e3f984","tarball":"https://registry.npmjs.org/@appeeky/expo-healthkit/-/expo-healthkit-0.3.0.tgz","fileCount":65,"integrity":"sha512-kgFD96vluuUxNSaZr0QTwEzVgkxKPnVpaiQXLEt8yOnwRl/lwkZoq0IeYFsp9KGa4UI70SYdz98dAaVfzazTDQ==","signatures":[{"sig":"MEUCIBKdTpTXIx2ZNPdISCY38PvsDTklqjeLA3h3HDkMMZ+eAiEA6eZHmK9TgNCO2dqmYQrfcMcrEsC96nMyJUnEZattQPw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDe9UUV0XufunFspXk900IW6MCLOmmR9PGeykW+eE9ePwIhALsVZD9jUieB/Jct0EIA0n+EeMj6Sc/QPNmbW8tvdlZX","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@appeeky%2fexpo-healthkit@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":581014},"jest":{"roots":["<rootDir>/src"],"transform":{"^.+\\.(js|ts|tsx)$":"babel-jest"},"testEnvironment":"node","coverageDirectory":"coverage","coverageThreshold":{"global":{"lines":90,"branches":80,"functions":90,"statements":90}},"collectCoverageFrom":["src/identifiers.ts","src/errors.ts","src/dates.ts"],"moduleFileExtensions":["ts","tsx","js"]},"main":"build/index.js","types":"build/index.d.ts","engines":{"node":">=18.18"},"exports":{".":{"types":"./build/index.d.ts","default":"./build/index.js"},"./app.plugin":"./app.plugin.js","./package.json":"./package.json","./app.plugin.js":"./app.plugin.js"},"gitHead":"12df33557fc8773e1835eb2c78bc6aeb9758eb8f","scripts":{"lint":"eslint src plugin/src","test":"node internal/module_scripts/test.js","build":"node internal/module_scripts/build.js","clean":"node internal/module_scripts/clean.js","prepare":"node internal/module_scripts/prepare.js","release":"semantic-release","open:ios":"node internal/module_scripts/open-ios.js","typecheck":"tsc --noEmit && tsc --noEmit -p plugin","open:android":"node internal/module_scripts/open-android.js","test:coverage":"node internal/module_scripts/test.js --coverage --watchAll=false","prepublishOnly":"node internal/module_scripts/prepare.js"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"1d8ba55b-5c7b-4b1e-8a4e-39febedeb25d"}},"repository":{"url":"git+https://github.com/appeeky/expo-healthkit.git","type":"git"},"_npmVersion":"11.19.1","description":"Apple HealthKit and Android Health Connect for Expo. One identifier-based JavaScript API on iOS and Android.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"expo":"^57.0.19","jest":"^29.7.0","eslint":"~9.39.4","prettier":"^3.0.0","typescript":"^5.9.2","@babel/core":"^7.26.0","@types/jest":"^29.2.1","@types/react":"~19.1.1","react-native":"0.82.1","semantic-release":"^25.0.9","babel-preset-expo":"~57.0.10","@semantic-release/git":"^11.0.1","eslint-config-universe":"^15.0.3","@semantic-release/changelog":"^7.0.0"},"peerDependencies":{"expo":">=53.0.0","react":"*","react-native":"*"},"_npmOperationalInternal":{"tmp":"tmp/expo-healthkit_0.3.0_1790897172683_0.35096345457153677","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@appeeky/expo-healthkit","version":"0.4.0","keywords":["react-native","expo","expo-module","healthkit","apple-health","apple-healthkit","health-connect","google-health-connect","ios","android","health","fitness"],"author":{"url":"https://github.com/Eronred","name":"Erencan Arica","email":"erencan_arica@hotmail.com"},"license":"SEE LICENSE IN LICENSE","_id":"@appeeky/expo-healthkit@0.4.0","maintainers":[{"name":"erencan","email":"erencan_arica@hotmail.com"}],"homepage":"https://github.com/appeeky/expo-healthkit#readme","bugs":{"url":"https://github.com/appeeky/expo-healthkit/issues"},"dist":{"shasum":"7579b95fd0c2e5015ea102e806ed3a0bff030ce5","tarball":"https://registry.npmjs.org/@appeeky/expo-healthkit/-/expo-healthkit-0.4.0.tgz","fileCount":65,"integrity":"sha512-4KUKXCstrBTfZxDPGn5I5Uej5eMrwTsHgHr/Opxy10/wFqWzgiXQnt5lNzCxYdyUHJEEBnmRhID+9FyPAYy8lQ==","signatures":[{"sig":"MEUCIE1iWQQ6YjSzW0rR2gz1MkcMhH++gXODpkBwH4yodFFOAiEAl7cJTpM50JLtayjjBE8abeOJxZJZ1IcmrZhwJE6ZL1Y=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIFCDtE9KcSbgTwNbZD0PuUG23d6Pf/UN+KwP4Vymb4G4AiARIQFhp2CN8Fm2xovlLYo6J0taBpYCBNhGqleuCYbX/Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@appeeky%2fexpo-healthkit@0.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":574275},"jest":{"roots":["<rootDir>/src"],"transform":{"^.+\\.(js|ts|tsx)$":"babel-jest"},"testEnvironment":"node","coverageDirectory":"coverage","coverageThreshold":{"global":{"lines":90,"branches":80,"functions":90,"statements":90}},"collectCoverageFrom":["src/identifiers.ts","src/errors.ts","src/dates.ts"],"moduleFileExtensions":["ts","tsx","js"]},"main":"build/index.js","types":"build/index.d.ts","engines":{"node":">=18.18"},"exports":{".":{"types":"./build/index.d.ts","default":"./build/index.js"},"./app.plugin":"./app.plugin.js","./package.json":"./package.json","./app.plugin.js":"./app.plugin.js"},"gitHead":"317f7e8e4db8d075de89cc770a18a6b9e70bdf85","scripts":{"lint":"eslint src plugin/src","test":"node internal/module_scripts/test.js","build":"node internal/module_scripts/build.js","clean":"node internal/module_scripts/clean.js","prepare":"node internal/module_scripts/prepare.js","release":"semantic-release","open:ios":"node internal/module_scripts/open-ios.js","typecheck":"tsc --noEmit && tsc --noEmit -p plugin","open:android":"node internal/module_scripts/open-android.js","test:coverage":"node internal/module_scripts/test.js --coverage --watchAll=false","prepublishOnly":"node internal/module_scripts/prepare.js"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"1d8ba55b-5c7b-4b1e-8a4e-39febedeb25d"}},"repository":{"url":"git+https://github.com/appeeky/expo-healthkit.git","type":"git"},"_npmVersion":"11.19.1","description":"Apple HealthKit and Android Health Connect for Expo. One identifier-based JavaScript API on iOS and Android.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"expo":"^57.0.19","jest":"^29.7.0","eslint":"~9.39.4","prettier":"^3.0.0","typescript":"^5.9.2","@babel/core":"^7.26.0","@types/jest":"^29.2.1","@types/react":"~19.1.1","react-native":"0.82.1","semantic-release":"^25.0.9","babel-preset-expo":"~57.0.10","@semantic-release/git":"^11.0.1","eslint-config-universe":"^15.0.3","@semantic-release/changelog":"^7.0.0"},"peerDependencies":{"expo":">=53.0.0","react":"*","react-native":"*"},"_npmOperationalInternal":{"tmp":"tmp/expo-healthkit_0.4.0_1790897646726_0.7080984077962293","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"_id":"@appeeky/expo-healthkit@0.4.1","bugs":{"url":"https://github.com/appeeky/expo-healthkit/issues"},"dist":{"shasum":"dcea0053956337ff728c0111f841266bd202459f","tarball":"https://registry.npmjs.org/@appeeky/expo-healthkit/-/expo-healthkit-0.4.1.tgz","fileCount":65,"integrity":"sha512-v/jQprDuP+pQj60b67Mmq8Dqe6Oj3sU/3wntl0bj/g/6AEv0RB5NGmVDKH8KvzxpQQD1qSPbSZxtJqP0sVVmuQ==","signatures":[{"sig":"MEYCIQDd0kuRKw156UOyKH7uvnqitelDuDEbngcFbd1TtmR4AgIhALRl57BZl73osf98vk4FTLq9barV4kds3OJJLqHNuOXK","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQC3POiyDDpUGFPAujW1GE3BtnvNg7vzEiz4oD/77wzf5gIgKDqvWbbcn7vJaVMlgKQaOpCo6+GRCTSjNIFh2+Mutak="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@appeeky%2fexpo-healthkit@0.4.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":587246},"jest":{"roots":["<rootDir>/src"],"transform":{"^.+\\.(js|ts|tsx)$":"babel-jest"},"testEnvironment":"node","coverageDirectory":"coverage","coverageThreshold":{"global":{"lines":90,"branches":80,"functions":90,"statements":90}},"collectCoverageFrom":["src/identifiers.ts","src/errors.ts","src/dates.ts"],"moduleFileExtensions":["ts","tsx","js"]},"main":"build/index.js","name":"@appeeky/expo-healthkit","types":"build/index.d.ts","author":{"url":"https://github.com/Eronred","name":"Erencan Arica","email":"erencan_arica@hotmail.com"},"engines":{"node":">=18.18"},"exports":{".":{"types":"./build/index.d.ts","default":"./build/index.js"},"./app.plugin":"./app.plugin.js","./package.json":"./package.json","./app.plugin.js":"./app.plugin.js"},"gitHead":"28432825ce895c2b3d60503b63ec7b862be9c417","license":"SEE LICENSE IN LICENSE","scripts":{"lint":"eslint src plugin/src","test":"node internal/module_scripts/test.js","build":"node internal/module_scripts/build.js","clean":"node internal/module_scripts/clean.js","prepare":"node internal/module_scripts/prepare.js","release":"semantic-release","open:ios":"node internal/module_scripts/open-ios.js","typecheck":"tsc --noEmit && tsc --noEmit -p plugin","open:android":"node internal/module_scripts/open-android.js","test:coverage":"node internal/module_scripts/test.js --coverage --watchAll=false","prepublishOnly":"node internal/module_scripts/prepare.js"},"version":"0.4.1","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"1d8ba55b-5c7b-4b1e-8a4e-39febedeb25d"}},"homepage":"https://github.com/appeeky/expo-healthkit#readme","keywords":["react-native","expo","expo-module","healthkit","apple-health","apple-healthkit","health-connect","google-health-connect","ios","android","health","fitness"],"repository":{"url":"git+https://github.com/appeeky/expo-healthkit.git","type":"git"},"_npmVersion":"11.19.1","description":"Apple HealthKit and Android Health Connect for Expo. One identifier-based JavaScript API on iOS and Android.","directories":{},"maintainers":[{"name":"erencan","email":"erencan_arica@hotmail.com"}],"sideEffects":false,"_nodeVersion":"22.23.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"expo":"^57.0.19","jest":"^29.7.0","eslint":"~9.39.4","prettier":"^3.0.0","typescript":"^5.9.2","@babel/core":"^7.26.0","@types/jest":"^29.2.1","@types/react":"~19.1.1","react-native":"0.82.1","semantic-release":"^25.0.9","babel-preset-expo":"~57.0.10","@semantic-release/git":"^11.0.1","eslint-config-universe":"^15.0.3","@semantic-release/changelog":"^7.0.0"},"peerDependencies":{"expo":">=53.0.0","react":"*","react-native":"*"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/expo-healthkit_0.4.1_1790898688945_0.6911065239107264"}}},"time":{"created":"2026-09-05T17:15:34.900Z","modified":"2026-10-01T23:51:29.457Z","0.1.0":"2026-09-05T17:15:35.211Z","0.1.1":"2026-09-05T19:26:01.745Z","0.2.0":"2026-09-09T15:49:30.787Z","0.2.1":"2026-10-01T23:25:07.448Z","0.3.0":"2026-10-01T23:26:12.797Z","0.4.0":"2026-10-01T23:34:06.845Z","0.4.1":"2026-10-01T23:51:29.101Z"},"bugs":{"url":"https://github.com/appeeky/expo-healthkit/issues"},"author":{"url":"https://github.com/Eronred","name":"Erencan Arica","email":"erencan_arica@hotmail.com"},"license":"SEE LICENSE IN LICENSE","homepage":"https://github.com/appeeky/expo-healthkit#readme","keywords":["react-native","expo","expo-module","healthkit","apple-health","apple-healthkit","health-connect","google-health-connect","ios","android","health","fitness"],"repository":{"url":"git+https://github.com/appeeky/expo-healthkit.git","type":"git"},"description":"Apple HealthKit and Android Health Connect for Expo. One identifier-based JavaScript API on iOS and Android.","maintainers":[{"name":"erencan","email":"erencan_arica@hotmail.com"}],"readme":"<img width=\"1024\" height=\"725\" alt=\"image\" src=\"https://github.com/user-attachments/assets/fadcd831-4187-42b1-b03b-3228ab2d8f32\" />\n\n\n# @appeeky/expo-healthkit\n\nApple [HealthKit](https://developer.apple.com/documentation/healthkit) and Android [Health Connect](https://developer.android.com/health-and-fitness/guides/health-connect) for [Expo](https://expo.dev) and React Native, built on the [Expo Modules API](https://docs.expo.dev/modules/overview/).\n\nOne JavaScript API on both platforms. You pass Apple HealthKit type identifiers (`HKQuantityTypeIdentifierStepCount`, …), query or save samples, and the native layer talks to HealthKit on iOS and Health Connect on Android.\n\n\n|              | iOS                                       | Android                                          |\n| ------------ | ----------------------------------------- | ------------------------------------------------ |\n| Backend      | HealthKit                                 | Health Connect                                   |\n| App code     | Same identifiers and methods              | Same identifiers and methods                     |\n| Availability | `isAvailable()` when HealthKit is present | `isAvailable()` when Health Connect is installed |\n\n\n- Expo SDK 53+ / New Architecture (tested on SDK 57)\n- Promise-based TypeScript API\n- Config plugin for HealthKit entitlements **and** Health Connect permissions (`minSdk` 26)\n- iOS 16.4+, Android 8+ (API 26+). Web reports `isAvailable() === false`\n\n> Health data APIs cannot run in Expo Go. Use a development build (`npx expo run:ios` or `npx expo run:android`).\n\n\n\n## 📋 Requirements\n\n- Expo SDK 53 or later and a **development build** (not Expo Go)\n- iOS 16.4+, physical iPhone or Simulator, with the HealthKit capability enabled on the App ID in the [Apple Developer portal](https://developer.apple.com/account)\n- Android 8+ with [Health Connect](https://play.google.com/store/apps/details?id=com.google.android.apps.healthdata) (built-in on Android 14+)\n\n\n\n## 📦 Install\n\n```sh\nnpx expo install @appeeky/expo-healthkit\n```\n\nFrom GitHub, if you are tracking `main` before a release:\n\n```sh\nnpx expo install github:appeeky/expo-healthkit\n```\n\nAdd the config plugin in `app.json` / `app.config.ts`:\n\n```json\n{\n  \"expo\": {\n    \"plugins\": [\n      [\n        \"@appeeky/expo-healthkit\",\n        {\n          \"healthSharePermission\": \"Allow $(PRODUCT_NAME) to read your health data\",\n          \"healthUpdatePermission\": \"Allow $(PRODUCT_NAME) to write health data\",\n          \"isBackgroundDeliveryEnabled\": true\n        }\n      ]\n    ],\n    \"ios\": {\n      \"bundleIdentifier\": \"com.example.app\"\n    }\n  }\n}\n```\n\nThen rebuild native code:\n\n```sh\nnpx expo prebuild --clean\nnpx expo run:ios\n# or\nnpx expo run:android\n```\n\nEnable the **HealthKit** capability on the App ID in the Apple Developer portal. The plugin writes the entitlement into the generated Xcode project; the capability still has to be allowed for that bundle ID.\n\nOn Android, install [Health Connect](https://play.google.com/store/apps/details?id=com.google.android.apps.healthdata) if the OS does not already include it (built-in on Android 14+). The plugin declares the Health Connect permissions (all mapped types by default; narrow with `healthConnectPermissions`) and raises `minSdk` to 26. The module's own manifest declares none, so a bare React Native app that does not run the config plugin must add the `android.permission.health.*` `uses-permission` entries it needs to `AndroidManifest.xml` itself.\n\n## ⚡️ Quick start\n\n```ts\nimport * as HealthKit from '@appeeky/expo-healthkit';\n\nif (!HealthKit.isAvailable()) {\n  return;\n}\n\nawait HealthKit.requestAuthorization({\n  toRead: [\n    HealthKit.QuantityType.stepCount,\n    HealthKit.QuantityType.heartRate,\n    HealthKit.CategoryType.sleepAnalysis,\n    HealthKit.WorkoutType.workout,\n  ],\n  toShare: [HealthKit.QuantityType.stepCount],\n});\n\nconst today = new Date();\ntoday.setHours(0, 0, 0, 0);\n\nconst steps = await HealthKit.queryStatistics({\n  type: HealthKit.QuantityType.stepCount,\n  unit: HealthKit.Unit.count,\n  from: today,\n  to: new Date(),\n  options: HealthKit.StatisticsOption.cumulativeSum,\n});\n\nconst heartRate = await HealthKit.queryQuantitySamples({\n  type: HealthKit.QuantityType.heartRate,\n  unit: HealthKit.Unit.countPerMinute,\n  from: today,\n  to: new Date(),\n  limit: 20,\n  ascending: false,\n});\n```\n\n\n\n## 📚 API\n\n\n\n### 🔐 Availability and permissions\n\n\n| Method                                                  | Notes                                                                                            |\n| ------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |\n| `isAvailable()`                                         | `true` on iOS when HealthKit is present, and on Android when Health Connect is installed         |\n| `getSupportedTypes()`                                   | Identifiers this platform can provide. Static, no prompt. iOS: what HealthKit resolves on this OS; Android: the Health Connect mapping; web: `[]` |\n| `getUnsupportedTypes(identifiers)`                      | The subset of `identifiers` this platform cannot provide                                          |\n| `requestAuthorization({ toRead, toShare, includeBackgroundRead })` | Shows the system permission sheet (HealthKit or Health Connect). `includeBackgroundRead` adds Health Connect's `READ_HEALTH_DATA_IN_BACKGROUND` (Android only; needs the plugin's `isHealthConnectBackgroundReadEnabled`) |\n| `getAuthorizationStatus(type)`                          | iOS: reliable for **write** types. Android: reflects granted Health Connect read or write access |\n| `getRequestStatusForAuthorization({ toRead, toShare })` | Whether you still need to prompt                                                                 |\n| `getGrantedPermissions()`                               | Android: granted `android.permission.health.*` strings. iOS: identifiers this app may **write** — HealthKit does not disclose read grants |\n| `requestPermissions(permissions)`                       | Android: request raw `android.permission.health.*` strings, resolves with the granted subset. iOS: throws `ERR_HEALTHKIT_UNSUPPORTED` |\n| `revokeAllPermissions()`                                | Android: in-app \"disconnect Health Connect\". The revoke takes effect when the app process ends, and Android may end it right away; until then `getGrantedPermissions()` still lists the grants. iOS: throws `ERR_HEALTHKIT_UNSUPPORTED` (HealthKit has no revoke) |\n\n\nOn iOS, read authorization is intentionally opaque: `getAuthorizationStatus` returning `notDetermined` / `sharingDenied` does **not** mean the user blocked reads.\n\n`ERR_HEALTHKIT_UNSUPPORTED` is the iOS mirror of `ERR_HEALTH_CONNECT_UNSUPPORTED`: the method exists on both platforms so app code needs no `Platform.OS` fork, and the one backend that cannot do it says so.\n\n### 📊 Samples and statistics\n\n\n|     | Method                                                                    | Use for                                                       |\n| --- | ------------------------------------------------------------------------- | ------------------------------------------------------------- |\n| ❤️  | `queryQuantitySamples({ type, unit, from, to, limit, ascending })`        | Heart rate, weight, glucose, …                                |\n| 😴  | `queryCategorySamples({ type, from, to, limit, ascending })`              | Sleep, mindful sessions, …                                    |\n| 🏃  | `queryWorkouts({ from, to, limit, ascending, activityType })`             | Workouts                                                      |\n| 🫀  | `queryElectrocardiograms({ from, to, limit, ascending, includeVoltage })` | ECG samples. Voltage is omitted unless `includeVoltage: true` |\n| 🔴  | `queryActivitySummaries({ from, to })`                                    | Move / Exercise / Stand rings                                 |\n| 🏥  | `queryClinicalRecords({ type, from, to, limit, ascending })`              | FHIR clinical records. Needs `isClinicalDataEnabled`          |\n| 👂  | `queryAudiograms({ from, to, limit, ascending })`                         | Hearing-test audiograms                                       |\n| 📍  | `queryWorkoutRoute({ workoutUUID })`                                      | GPS locations for a workout                                   |\n| 🩺  | `queryCorrelations({ type, from, to, limit, ascending })`                 | Blood pressure and food correlations                          |\n| 💓  | `queryHeartbeatSeries({ from, to, limit, ascending, includeBeats })`      | Beat-to-beat series used for HRV                              |\n| 📈  | `queryStatistics({ type, unit, from, to, options })`                      | Totals / min / max / average for a range                      |\n| 📅  | `queryStatisticsCollection({ type, unit, from, to, interval, options })`  | Daily (or hourly) buckets                                     |\n| 🔄  | `queryAnchored({ type, unit, from, to, limit, anchor })`                  | Incremental sync. Store `anchor`, pass it back while `hasMore` |\n\n\n`limit` defaults to HealthKit's unlimited query. Dates accept `Date` or ISO-8601 strings. Units are HealthKit unit strings (`count`, `count/min`, `kcal`, `kg`, `m`, `%`, …) also exported as `Unit`.\n\n#### Source filters\n\nEvery query above (except activity summaries and workout routes) accepts `sources` and `excludeSources`. Both take iOS bundle identifiers / Android package names; `'self'` in `excludeSources` is this app. Use it to skip your own writes when you sync:\n\n```ts\nconst heartRate = await HealthKit.queryQuantitySamples({\n  type: HealthKit.QuantityType.heartRate,\n  unit: HealthKit.Unit.countPerMinute,\n  from: today,\n  limit: 100,\n  excludeSources: ['self'],\n});\n\nconst watchOnly = await HealthKit.queryWorkouts({\n  sources: ['com.apple.health'],\n});\n```\n\nThe filters run natively, **before `limit`**, on both platforms: `limit: 100` with `excludeSources: ['self']` returns the 100 newest samples that other apps wrote, not 100 rows minus yours. On iOS they compile to an `HKQuery.predicateForObjects(from:)` predicate; on Android `sources` is the request's `dataOriginFilter` and `excludeSources` is applied to each page before the limit is counted. `queryStatistics` / `queryStatisticsCollection` on Android support `sources` only; `excludeSources` there throws `ERR_HEALTH_CONNECT_UNSUPPORTED`. `queryAnchored` filters added samples; deletions carry no source and are always returned.\n\n#### Anchored sync\n\n`queryAnchored` returns `{ added, deleted, anchor, hasMore }`. Apply the page, persist `anchor`, and call again while `hasMore` is true. Treat `added` as upserts keyed by `uuid`: a sample can arrive twice.\n\n```ts\nlet anchor = await loadAnchor(); // null on first sync\nlet hasMore = true;\nwhile (hasMore) {\n  const page = await HealthKit.queryAnchored({ type, unit, limit: 500, anchor });\n  await applyPage(page.added, page.deleted);\n  anchor = page.anchor;\n  hasMore = page.hasMore;\n  await saveAnchor(anchor);\n}\n```\n\n- **The anchor is an opaque token, not a timestamp.** On iOS it is an archived `HKQueryAnchor`; on Android it wraps a Health Connect changes token (plus a page token during the first sync). It is not portable between platforms, between apps, or from another library — an anchor saved by `@kingstinct/react-native-healthkit` or `react-native-health-connect`, or an ISO date from a timestamp-based cursor, is not a valid token here. Persist it per platform and per type, and when migrating from another cursor start with `anchor: null` and dedupe by `uuid`.\n- **Android, first sync.** With no anchor, the existing records are read in pages of `limit` records (a heart-rate record can expand to many samples; no `limit` reads everything in one call). The changes token is taken before the first page, so records written or deleted meanwhile arrive as changes afterwards — `hasMore` stays true until those are read.\n- **Android, expired or rejected anchor.** Health Connect keeps its change log for 30 days, so a token unused for longer expires. `queryAnchored` then throws `ERR_HEALTH_CONNECT_ANCHOR_EXPIRED` instead of returning a delta: deletions made during the gap are lost, so restart with `anchor: null` and reconcile your copy against the full read. Health Connect reports a token it does not recognise (for example one from another library) the same way. A malformed anchor throws `ERR_INVALID_ANCHOR`, and other Health Connect errors are thrown as-is. The restart's read is limited to the last 30 days unless the user granted `READ_HEALTH_DATA_HISTORY` (requested with every `toRead`).\n- **iOS.** HealthKit does not say whether more results remain, so `hasMore` is true whenever a page is full; the next call may come back empty. A string that is not base64 is treated as \"no anchor\" and runs the initial fetch again (only a base64 string that is not an `HKQueryAnchor` archive rejects).\n\nECG, activity rings, clinical records, audiograms, workout GPS routes, heartbeat series, and correlations are not quantity/category/workout samples. Request the matching identifier in `toRead`:\n\n```ts\nawait HealthKit.requestAuthorization({\n  toRead: [\n    HealthKit.ElectrocardiogramType.electrocardiogram,\n    HealthKit.ActivitySummaryType.activitySummary,\n    HealthKit.ClinicalType.allergyRecord,\n    HealthKit.AudiogramType.audiogram,\n    HealthKit.WorkoutType.workout,\n    HealthKit.SeriesType.workoutRoute,\n    HealthKit.SeriesType.heartbeat,\n    HealthKit.CorrelationType.bloodPressure,\n    HealthKit.CorrelationType.food,\n  ],\n});\n\nconst rings = await HealthKit.queryActivitySummaries({ from: today });\nconst [workout] = await HealthKit.queryWorkouts({ limit: 1 });\nconst routes = workout\n  ? await HealthKit.queryWorkoutRoute({ workoutUUID: workout.uuid })\n  : [];\nconst pressure = await HealthKit.queryCorrelations({\n  type: HealthKit.CorrelationType.bloodPressure,\n  limit: 20,\n});\n```\n\nClinical reads also need `isClinicalDataEnabled: true` on the config plugin.\n\n### ✍️ Write / delete\n\n```ts\nawait HealthKit.saveQuantitySample({\n  type: HealthKit.QuantityType.stepCount,\n  unit: HealthKit.Unit.count,\n  value: 100,\n  startDate: new Date(Date.now() - 60_000),\n  endDate: new Date(),\n});\n\nawait HealthKit.saveCategorySample({\n  type: HealthKit.CategoryType.sleepAnalysis,\n  value: HealthKit.SleepAnalysisValue.asleepCore,\n  startDate,\n  endDate,\n});\n\nawait HealthKit.saveWorkout({\n  activityType: HealthKit.WorkoutActivityType.running,\n  startDate,\n  endDate,\n  energyBurned: 400,\n  energyBurnedUnit: HealthKit.Unit.kilocalorie,\n  distance: 5000,\n  distanceUnit: HealthKit.Unit.meter,\n});\n\nawait HealthKit.saveCorrelation({\n  type: HealthKit.CorrelationType.bloodPressure,\n  startDate: new Date(),\n  objects: [\n    {\n      type: HealthKit.QuantityType.bloodPressureSystolic,\n      unit: HealthKit.Unit.millimeterOfMercury,\n      value: 120,\n    },\n    {\n      type: HealthKit.QuantityType.bloodPressureDiastolic,\n      unit: HealthKit.Unit.millimeterOfMercury,\n      value: 80,\n    },\n  ],\n});\n\nawait HealthKit.deleteObjects({\n  type: HealthKit.QuantityType.stepCount,\n  uuid,\n});\n```\n\n\n\n### 👤 Characteristics\n\n`getBiologicalSex()`, `getBloodType()`, `getDateOfBirth()`, `getFitzpatrickSkinType()`, `getWheelchairUse()`. These are read-only HealthKit characteristics; include the matching `CharacteristicType` in `toRead`.\n\n### 🔔 Background updates\n\n```ts\nawait HealthKit.observe([HealthKit.QuantityType.stepCount]);\n\nconst subscription = HealthKit.addUpdateListener(async ({ type }) => {\n  // Re-query that type. Return a promise: iOS keeps the app alive and holds\n  // the HealthKit completion handler until it settles (~25s cap).\n  await syncSteps();\n});\n\nawait HealthKit.enableBackgroundDelivery(\n  HealthKit.QuantityType.stepCount,\n  HealthKit.UpdateFrequency.hourly\n);\n```\n\n`useHealthKitUpdates()` is a React hook around the same event.\n\nBackground delivery needs `isBackgroundDeliveryEnabled: true` on the config plugin and the HealthKit background mode.\n\n**Killed-app relaunch.** Types passed to `observe` are persisted natively. When iOS relaunches the app in the background for a HealthKit delivery, the observer queries are re-registered in `didFinishLaunching` (via an Expo AppDelegate subscriber), before the JS runtime boots. The delivery is queued until JS calls `addUpdateListener`, then dispatched. Register your listener at module scope (or early in the root component) so it exists on cold start; `getObservedTypes()` tells you what is already being observed. `clearObservers()` stops and forgets them.\n\n**Apple limits.** Step count, distance, energy, exercise/stand time and similar activity types are delivered at most **once per hour** regardless of `UpdateFrequency`; heart rate, sleep, workouts and body measurements are not capped. Each delivery gets ~30 s of background time; the library completes at 25 s if your listener hasn't. The Simulator never relaunches a killed app for HealthKit — test on a device.\n\n**Debugging.** Native logs are under the `expo-healthkit` `os_log` subsystem (`restore`, `delivery`, `complete reason=js|timeout`). Full guide with a device test recipe: [`.cursor/skills/expo-healthkit/background-delivery.md`](.cursor/skills/expo-healthkit/background-delivery.md).\n\n## 🏷️ Identifiers\n\nPass Apple's raw identifier strings. Named constants are provided for autocomplete; unknown identifiers still work if HealthKit knows them.\n\n```ts\nHealthKit.QuantityType.stepCount\n// 'HKQuantityTypeIdentifierStepCount'\n\nHealthKit.queryQuantitySamples({\n  type: 'HKQuantityTypeIdentifierStepCount',\n  unit: 'count',\n});\n```\n\nApp code should keep using Apple identifier strings on both platforms. See [Cross-platform](#cross-platform) for what Health Connect maps, what stays iOS-only, and how to handle those APIs without `Platform.OS` forks.\n\n## 🌍 Cross-platform\n\nJavaScript always speaks HealthKit. You never pass Health Connect record class names from app code. The native layer chooses the backend:\n\n```mermaid\nflowchart LR\n  App[\"App JS<br/>QuantityType.stepCount\"] --> API[\"@appeeky/expo-healthkit\"]\n  API --> iOS[\"iOS<br/>HealthKit\"]\n  API --> Android[\"Android<br/>Health Connect\"]\n```\n\nMapped types (steps, heart rate, sleep, workouts, weight, blood pressure, nutrition, …) use the **same method and identifier** on both platforms. Unmapped identifiers are skipped in Android `requestAuthorization`, so an unsupported type and an empty one look alike; ask first:\n\n```ts\nconst missing = HealthKit.getUnsupportedTypes([\n  HealthKit.QuantityType.vo2Max,\n  HealthKit.QuantityType.appleExerciseTime,\n]);\n// Android: ['HKQuantityTypeIdentifierAppleExerciseTime'] — say \"not on this phone\", not \"no data\"\n```\n\nCalling an Apple-only method on Android throws `ERR_HEALTH_CONNECT_UNSUPPORTED` instead of requiring `if (Platform.OS === 'ios')` on every query.\n\nHide Apple-only UI by catching that code:\n\n```ts\ntry {\n  const rings = await HealthKit.queryActivitySummaries({ from: today });\n} catch (error) {\n  if (error instanceof Error && 'code' in error && error.code === 'ERR_HEALTH_CONNECT_UNSUPPORTED') {\n    return;\n  }\n  throw error;\n}\n```\n\n### What works on both\n\n| Area | Identifiers / methods |\n| --- | --- |\n| Activity | `QuantityType.stepCount`, walking/running/cycling/swimming/wheelchair distance, `flightsClimbed`, `pushCount`, `activeEnergyBurned`, `basalEnergyBurned` |\n| Heart | `heartRate`, `restingHeartRate`, `heartRateVariabilitySDNN`, `vo2Max`, `oxygenSaturation`, `respiratoryRate` |\n| Body | `bodyMass`, `height`, `bodyFatPercentage`, `leanBodyMass`, `bodyTemperature`, `bloodGlucose` |\n| Blood pressure | `CorrelationType.bloodPressure` plus systolic / diastolic quantities |\n| Nutrition | `CorrelationType.food`, `dietaryWater`, other `HKQuantityTypeIdentifierDietary*` types |\n| Sleep | `CategoryType.sleepAnalysis` |\n| Workouts | `queryWorkouts` / `saveWorkout` (`WorkoutActivityType` mapped onto Health Connect exercise types) |\n| Aggregates | `queryStatistics`, `queryStatisticsCollection`, `queryAnchored` |\n| Writes | `saveQuantitySample`, `saveCategorySample`, `saveCorrelation`, `deleteObjects` |\n\n### iOS-only\n\nThese throw `ERR_HEALTH_CONNECT_UNSUPPORTED` on Android. Health Connect has no equivalent (or no stable mapping yet):\n\n| API | Why |\n| --- | --- |\n| `queryElectrocardiograms` | Apple Watch ECG |\n| `queryActivitySummaries` | Move / Exercise / Stand rings |\n| `queryClinicalRecords` | FHIR health records |\n| `queryAudiograms` | Hearing-test charts |\n| `queryWorkoutRoute` | Workout GPS polylines |\n| `queryHeartbeatSeries` | Beat-to-beat series |\n| `getBiologicalSex`, `getBloodType`, `getDateOfBirth`, `getFitzpatrickSkinType`, `getWheelchairUse` | HealthKit characteristics |\n| `observe`, `getObservedTypes`, `enableBackgroundDelivery` | HealthKit observer queries / background delivery |\n\n### Behavioral differences\n\n| | iOS | Android |\n| --- | --- | --- |\n| Backend | HealthKit | Health Connect (`connect-client` 1.1) |\n| `isAvailable()` | HealthKit present | Health Connect installed (built-in on Android 14+; otherwise the Health Connect app) |\n| Read permission | Apple does **not** disclose read grants; `getGrantedPermissions` lists write grants only | `getAuthorizationStatus` reflects granted Health Connect read or write; `getGrantedPermissions` returns the raw permission strings |\n| Revoke | None (`revokeAllPermissions` throws `ERR_HEALTHKIT_UNSUPPORTED`) | `revokeAllPermissions()` |\n| Background reads | Observer queries / background delivery | `requestAuthorization({ includeBackgroundRead: true })` plus the plugin's `isHealthConnectBackgroundReadEnabled` |\n| Unmapped types in `requestAuthorization` | Forwarded if HealthKit knows them | Skipped |\n| History window | Granted samples, any age | Often last **30 days** unless the user also grants history access (the SDK requests it) |\n| Anchored sync | `HKQueryAnchor` (opaque string) | Paged first sync, then Health Connect changes (opaque string). Expired tokens throw `ERR_HEALTH_CONNECT_ANCHOR_EXPIRED` — see [Anchored sync](#anchored-sync). Do not reuse an iOS anchor on Android |\n| HRV | SDNN. Samples carry `statistic: 'sdnn'` | Mapped to Health Connect RMSSD on the same `heartRateVariabilitySDNN` identifier — not the same statistic. Samples carry `statistic: 'rmssd'`; branch on it before charting the two together |\n| Workout GPS | `queryWorkoutRoute` | Unsupported |\n| `minSdk` | iOS 16.4 | API 26 (plugin raises it) |\n\nDo **not** fork mapped queries per platform. Fork only when you need different UI for an Apple-only feature.\n\n## 🔌 Config plugin\n\n\n| Prop                              | Default                                            | Purpose                                                         |\n| --------------------------------- | -------------------------------------------------- | --------------------------------------------------------------- |\n| `healthSharePermission`           | `\"Allow $(PRODUCT_NAME) to read your health data\"` | `NSHealthShareUsageDescription`                                 |\n| `healthUpdatePermission`          | `\"Allow $(PRODUCT_NAME) to write health data\"`     | `NSHealthUpdateUsageDescription`                                |\n| `healthClinicalRecordsPermission` | clinical default                                   | Used when `isClinicalDataEnabled` is true                       |\n| `isBackgroundDeliveryEnabled`     | `false`                                            | HealthKit background delivery entitlement |\n| `isClinicalDataEnabled`           | `false`                                            | `health-records` access                                         |\n| `healthConnectPrivacyPolicyUrl`   | —                                                  | Shown on the Health Connect permission rationale screen         |\n| `healthConnectPermissions`        | every permission the module maps (47, incl. `READ_HEALTH_DATA_HISTORY`) | Health Connect `uses-permission` entries to declare. `READ_STEPS` or `android.permission.health.READ_STEPS`. When set, **only** these are declared |\n| `isHealthConnectBackgroundReadEnabled` | `false`                                       | Declares `READ_HEALTH_DATA_IN_BACKGROUND` for `requestAuthorization({ includeBackgroundRead: true })` |\n\n\nThe plugin also sets `android.minSdkVersion` to 26 (Health Connect’s floor) unless the project already uses a higher value.\n\nThe plugin is the **only** place Health Connect permissions are declared; the module's own `AndroidManifest.xml` declares none. Play Console asks you to justify every declared Health Connect data type and the permission sheet shows the user the full list, so narrow it to what you query:\n\n```json\n[\"@appeeky/expo-healthkit\", { \"healthConnectPermissions\": [\"READ_STEPS\", \"READ_HEART_RATE\", \"READ_SLEEP\", \"READ_HEALTH_DATA_HISTORY\"] }]\n```\n\nA type you query without declaring its permission is skipped at `requestAuthorization` and reads as empty. `HEALTH_CONNECT_PERMISSIONS` (exported from the plugin) is the default list.\n\nSet a permission string to `false` to skip writing that Info.plist key (if you manage it yourself).\n\n## 📱 Example app\n\n```sh\ncd example\nnpm install\nnpx expo run:ios\n# or\nnpx expo run:android\n```\n\nThe example is an Expo SDK 57 app that autolinks this module on **iOS and Android**. It will not work in Expo Go.\n\n## 🤖 Agent skills\n\nCoding agents (Cursor, Claude Code, Copilot, and similar) should load the bundled skill.\n\nCopy [`.cursor/skills/expo-healthkit/`](https://github.com/appeeky/expo-healthkit/tree/main/.cursor/skills/expo-healthkit) into your app’s `.cursor/skills/expo-healthkit/` (or the agent’s skills folder):\n\n| File | What agents get |\n| --- | --- |\n| [`SKILL.md`](https://github.com/appeeky/expo-healthkit/blob/main/.cursor/skills/expo-healthkit/SKILL.md) | When to use which query, auth rules, and plugin flags |\n| [`reference.md`](https://github.com/appeeky/expo-healthkit/blob/main/.cursor/skills/expo-healthkit/reference.md) | Method signatures, units, identifiers |\n| [`examples.md`](https://github.com/appeeky/expo-healthkit/blob/main/.cursor/skills/expo-healthkit/examples.md) | Copy-paste flows (steps, sleep, rings, blood pressure, food) |\n\nThe skill tells the agent to pass Apple identifier strings through one query/save API on iOS and Android, request every type in `toRead`, and rebuild native code after Swift, Kotlin, or plugin changes.\n\n## 🚀 Releases\n\nVersions follow [semver](https://semver.org/). Pushing to `main` with a [Conventional Commit](https://www.conventionalcommits.org/) runs `.github/workflows/release.yml`: bump `package.json`, update `CHANGELOG.md`, GitHub Release, and `npm publish`.\n\n| Commit | npm bump |\n| --- | --- |\n| `fix: …` | patch (`0.1.0` → `0.1.1`) |\n| `feat: …` | minor (`0.1.0` → `0.2.0`) |\n| `feat!: …` or `BREAKING CHANGE:` in the body | major (`0.1.0` → `1.0.0`) |\n| `docs:`, `chore:`, `ci:`, `test:` | no release |\n\nSquash-merge PRs so the merge commit (or PR title) starts with `fix:` / `feat:`. `chore:` and `ci:` do not publish.\n\nnpm publishes from GitHub Actions via [trusted publishing](https://docs.npmjs.com/trusted-publishers) (no `NPM_TOKEN`). One-time setup: package Settings → Trusted Publisher → GitHub Actions, repository `appeeky/expo-healthkit`, workflow filename `release.yml`, and allow **`npm publish`** (not only staged publish).\n\n## 🤝 Contributing\n\nIssues and pull requests are welcome. Contributions are licensed under [PolyForm Shield 1.0.0](./LICENSE).\n\n### Checks\n\nCI on `main` and every PR runs lint, typecheck, Jest, and an `npm pack` contents check (`.github/workflows/ci.yml`). Run the same locally before opening a PR:\n\n```sh\nnpm ci\nnpm run lint\nnpm run typecheck\nnpm test -- --watchAll=false\nnpm run test:coverage\n```\n\n`npm test` opens Jest watch mode on a TTY. Pass `--watchAll=false` (as CI does) for a single run. `test:coverage` writes an HTML report to `coverage/` and must stay green for the JavaScript that tests already cover (`src/identifiers.ts`, `src/errors.ts`, `src/dates.ts`).\n\n### What to test\n\n| Change | Expected coverage |\n| --- | --- |\n| Identifiers, errors, date helpers, public JS types | Add or extend Jest in `src/__tests__/`. Keep `npm run test:coverage` passing |\n| Config plugin | Typecheck `plugin/`; if you add pure helpers, put Jest next to them |\n| Kotlin Health Connect mapping | Update the [Cross-platform](#cross-platform) tables **and** `.cursor/skills/expo-healthkit/`. Run the example on an Android device with Health Connect |\n| Swift HealthKit | Same skill/README update. Run the example on Simulator or a device with the HealthKit capability |\n| Example UI | `cd example && npx expo run:ios` / `npx expo run:android`. Health APIs do not run in Expo Go |\n\nNative HealthKit / Health Connect cannot run in Node. Device or Simulator verification is the coverage for Swift and Kotlin. Do not add `Platform.OS` branches in `example/` for types that already map.\n\n### Native rebuild\n\nMetro reload is not enough after Swift, Kotlin, or plugin edits:\n\n```sh\nnpx expo prebuild --clean\nnpx expo run:ios\n# or\nnpx expo run:android\n```\n\n### Docs\n\nIf the public API or Android mapping changes, update `README.md` and `.cursor/skills/expo-healthkit/` (`SKILL.md`, `reference.md`, `examples.md`) in the same PR. `CHANGELOG.md` is generated on release from conventional commits.\n\n## 🔒 Privacy\n\nHealth data stays on-device unless your app uploads it. Request only the types you need, explain why in the iOS usage strings, declare the matching Health Connect data types in Play Console, and follow Apple HealthKit and Google Health Connect review guidelines. Android reads are often limited to the last 30 days unless the user also grants history access.\n\n## 📄 License\n\n[PolyForm Shield 1.0.0](./LICENSE). See [`LICENSE`](./LICENSE) for the full terms.\n\nYou **can** install and use this SDK inside your own Expo / React Native apps, including commercial products.\n\nYou **cannot** copy this SDK and sell, publish, or otherwise offer a competing HealthKit / Health Connect library based on it.\n","readmeFilename":"README.md"}