@kingstinct/react-native-healthkit 8.5.0 → 8.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/ios/Helpers.swift +145 -0
  2. package/ios/ReactNativeHealthkit.m +14 -0
  3. package/ios/ReactNativeHealthkit.swift +194 -24
  4. package/lib/commonjs/index.ios.js +19 -1
  5. package/lib/commonjs/index.ios.js.map +1 -1
  6. package/lib/commonjs/index.native.js +7 -1
  7. package/lib/commonjs/index.native.js.map +1 -1
  8. package/lib/commonjs/native-types.js +16 -1
  9. package/lib/commonjs/native-types.js.map +1 -1
  10. package/lib/commonjs/test-setup.js +3 -1
  11. package/lib/commonjs/test-setup.js.map +1 -1
  12. package/lib/commonjs/utils/saveStateOfMindSample.js +17 -0
  13. package/lib/commonjs/utils/saveStateOfMindSample.js.map +1 -0
  14. package/lib/commonjs/utils/subscribeToChanges.js.map +1 -1
  15. package/lib/commonjs/utils/workoutSessionMirroringStartHandler.js +17 -0
  16. package/lib/commonjs/utils/workoutSessionMirroringStartHandler.js.map +1 -0
  17. package/lib/module/index.ios.js +5 -1
  18. package/lib/module/index.ios.js.map +1 -1
  19. package/lib/module/index.native.js +5 -1
  20. package/lib/module/index.native.js.map +1 -1
  21. package/lib/module/native-types.js +16 -0
  22. package/lib/module/native-types.js.map +1 -1
  23. package/lib/module/test-setup.js +3 -1
  24. package/lib/module/test-setup.js.map +1 -1
  25. package/lib/module/utils/saveStateOfMindSample.js +10 -0
  26. package/lib/module/utils/saveStateOfMindSample.js.map +1 -0
  27. package/lib/module/utils/subscribeToChanges.js.map +1 -1
  28. package/lib/module/utils/workoutSessionMirroringStartHandler.js +11 -0
  29. package/lib/module/utils/workoutSessionMirroringStartHandler.js.map +1 -0
  30. package/lib/typescript/src/index.ios.d.ts +5 -1
  31. package/lib/typescript/src/index.native.d.ts +2 -2
  32. package/lib/typescript/src/native-types.d.ts +43 -2
  33. package/lib/typescript/src/utils/saveStateOfMindSample.d.ts +11 -0
  34. package/lib/typescript/src/utils/workoutSessionMirroringStartHandler.d.ts +8 -0
  35. package/package.json +1 -1
  36. package/src/index.ios.tsx +6 -0
  37. package/src/index.native.tsx +6 -0
  38. package/src/native-types.ts +58 -3
  39. package/src/test-setup.ts +2 -0
  40. package/src/utils/saveStateOfMindSample.ts +38 -0
  41. package/src/utils/subscribeToChanges.ts +1 -1
  42. package/src/utils/workoutSessionMirroringStartHandler.ts +11 -0
@@ -1 +1 @@
1
- {"version":3,"names":["mock","jest","beforeAll","mockModule","queryWorkoutSamplesWithAnchor","fn","isHealthDataAvailable","isProtectedDataAvailable","authorizationStatusFor","requestAuthorization","saveQuantitySample","deleteQuantitySample","deleteSamples","disableAllBackgroundDelivery","disableBackgroundDelivery","enableBackgroundDelivery","queryCategorySamplesWithAnchor","queryQuantitySamplesWithAnchor","getBiologicalSex","getBloodType","getDateOfBirth","getFitzpatrickSkinType","getPreferredUnits","getRequestStatusForAuthorization","getWheelchairUse","getWorkoutRoutes","queryCategorySamples","queryCorrelationSamples","queryHeartbeatSeriesSamples","queryHeartbeatSeriesSamplesWithAnchor","queryQuantitySamples","querySources","queryStatisticsForQuantity","queryStatisticsCollectionForQuantity","queryWorkoutSamples","saveCategorySample","saveCorrelationSample","saveWorkoutSample","subscribeToObserverQuery","unsubscribeQuery","saveWorkoutRoute","getWorkoutPlanById","startWatchAppWithWorkoutConfiguration","queryStateOfMindSamples","module","NativeModules","ReactNativeHealthkit","NativeEventEmitter"],"sources":["test-setup.ts"],"sourcesContent":["// eslint-disable-next-line import/no-unresolved\nimport { mock, jest, beforeAll } from 'bun:test'\n\nimport type Native from './native-types'\n\nbeforeAll(async () => {\n const mockModule: typeof Native = {\n queryWorkoutSamplesWithAnchor: jest.fn(),\n isHealthDataAvailable: jest.fn(),\n isProtectedDataAvailable: jest.fn(),\n authorizationStatusFor: jest.fn(),\n requestAuthorization: jest.fn(),\n saveQuantitySample: jest.fn(),\n deleteQuantitySample: jest.fn(),\n deleteSamples: jest.fn(),\n disableAllBackgroundDelivery: jest.fn(),\n disableBackgroundDelivery: jest.fn(),\n enableBackgroundDelivery: jest.fn(),\n queryCategorySamplesWithAnchor: jest.fn(),\n queryQuantitySamplesWithAnchor: jest.fn(),\n getBiologicalSex: jest.fn(),\n getBloodType: jest.fn(),\n getDateOfBirth: jest.fn(),\n getFitzpatrickSkinType: jest.fn(),\n getPreferredUnits: jest.fn(),\n getRequestStatusForAuthorization: jest.fn(),\n getWheelchairUse: jest.fn(),\n getWorkoutRoutes: jest.fn(),\n queryCategorySamples: jest.fn(),\n queryCorrelationSamples: jest.fn(),\n queryHeartbeatSeriesSamples: jest.fn(),\n queryHeartbeatSeriesSamplesWithAnchor: jest.fn(),\n queryQuantitySamples: jest.fn(),\n querySources: jest.fn(),\n queryStatisticsForQuantity: jest.fn(),\n queryStatisticsCollectionForQuantity: jest.fn(),\n queryWorkoutSamples: jest.fn(),\n saveCategorySample: jest.fn(),\n saveCorrelationSample: jest.fn(),\n saveWorkoutSample: jest.fn(),\n subscribeToObserverQuery: jest.fn(),\n unsubscribeQuery: jest.fn(),\n saveWorkoutRoute: jest.fn(),\n getWorkoutPlanById: jest.fn(),\n startWatchAppWithWorkoutConfiguration: jest.fn(),\n queryStateOfMindSamples: jest.fn(),\n }\n\n await mock.module('react-native', () => ({\n NativeModules: {\n ReactNativeHealthkit: mockModule,\n },\n NativeEventEmitter: jest.fn(),\n }))\n})\n"],"mappings":"AAAA;AACA,SAASA,IAAI,EAAEC,IAAI,EAAEC,SAAS,QAAQ,UAAU;AAIhDA,SAAS,CAAC,YAAY;EACpB,MAAMC,UAAyB,GAAG;IAChCC,6BAA6B,EAAEH,IAAI,CAACI,EAAE,CAAC,CAAC;IACxCC,qBAAqB,EAAEL,IAAI,CAACI,EAAE,CAAC,CAAC;IAChCE,wBAAwB,EAAEN,IAAI,CAACI,EAAE,CAAC,CAAC;IACnCG,sBAAsB,EAAEP,IAAI,CAACI,EAAE,CAAC,CAAC;IACjCI,oBAAoB,EAAER,IAAI,CAACI,EAAE,CAAC,CAAC;IAC/BK,kBAAkB,EAAET,IAAI,CAACI,EAAE,CAAC,CAAC;IAC7BM,oBAAoB,EAAEV,IAAI,CAACI,EAAE,CAAC,CAAC;IAC/BO,aAAa,EAAEX,IAAI,CAACI,EAAE,CAAC,CAAC;IACxBQ,4BAA4B,EAAEZ,IAAI,CAACI,EAAE,CAAC,CAAC;IACvCS,yBAAyB,EAAEb,IAAI,CAACI,EAAE,CAAC,CAAC;IACpCU,wBAAwB,EAAEd,IAAI,CAACI,EAAE,CAAC,CAAC;IACnCW,8BAA8B,EAAEf,IAAI,CAACI,EAAE,CAAC,CAAC;IACzCY,8BAA8B,EAAEhB,IAAI,CAACI,EAAE,CAAC,CAAC;IACzCa,gBAAgB,EAAEjB,IAAI,CAACI,EAAE,CAAC,CAAC;IAC3Bc,YAAY,EAAElB,IAAI,CAACI,EAAE,CAAC,CAAC;IACvBe,cAAc,EAAEnB,IAAI,CAACI,EAAE,CAAC,CAAC;IACzBgB,sBAAsB,EAAEpB,IAAI,CAACI,EAAE,CAAC,CAAC;IACjCiB,iBAAiB,EAAErB,IAAI,CAACI,EAAE,CAAC,CAAC;IAC5BkB,gCAAgC,EAAEtB,IAAI,CAACI,EAAE,CAAC,CAAC;IAC3CmB,gBAAgB,EAAEvB,IAAI,CAACI,EAAE,CAAC,CAAC;IAC3BoB,gBAAgB,EAAExB,IAAI,CAACI,EAAE,CAAC,CAAC;IAC3BqB,oBAAoB,EAAEzB,IAAI,CAACI,EAAE,CAAC,CAAC;IAC/BsB,uBAAuB,EAAE1B,IAAI,CAACI,EAAE,CAAC,CAAC;IAClCuB,2BAA2B,EAAE3B,IAAI,CAACI,EAAE,CAAC,CAAC;IACtCwB,qCAAqC,EAAE5B,IAAI,CAACI,EAAE,CAAC,CAAC;IAChDyB,oBAAoB,EAAE7B,IAAI,CAACI,EAAE,CAAC,CAAC;IAC/B0B,YAAY,EAAE9B,IAAI,CAACI,EAAE,CAAC,CAAC;IACvB2B,0BAA0B,EAAE/B,IAAI,CAACI,EAAE,CAAC,CAAC;IACrC4B,oCAAoC,EAAEhC,IAAI,CAACI,EAAE,CAAC,CAAC;IAC/C6B,mBAAmB,EAAEjC,IAAI,CAACI,EAAE,CAAC,CAAC;IAC9B8B,kBAAkB,EAAElC,IAAI,CAACI,EAAE,CAAC,CAAC;IAC7B+B,qBAAqB,EAAEnC,IAAI,CAACI,EAAE,CAAC,CAAC;IAChCgC,iBAAiB,EAAEpC,IAAI,CAACI,EAAE,CAAC,CAAC;IAC5BiC,wBAAwB,EAAErC,IAAI,CAACI,EAAE,CAAC,CAAC;IACnCkC,gBAAgB,EAAEtC,IAAI,CAACI,EAAE,CAAC,CAAC;IAC3BmC,gBAAgB,EAAEvC,IAAI,CAACI,EAAE,CAAC,CAAC;IAC3BoC,kBAAkB,EAAExC,IAAI,CAACI,EAAE,CAAC,CAAC;IAC7BqC,qCAAqC,EAAEzC,IAAI,CAACI,EAAE,CAAC,CAAC;IAChDsC,uBAAuB,EAAE1C,IAAI,CAACI,EAAE,CAAC;EACnC,CAAC;EAED,MAAML,IAAI,CAAC4C,MAAM,CAAC,cAAc,EAAE,OAAO;IACvCC,aAAa,EAAE;MACbC,oBAAoB,EAAE3C;IACxB,CAAC;IACD4C,kBAAkB,EAAE9C,IAAI,CAACI,EAAE,CAAC;EAC9B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["mock","jest","beforeAll","mockModule","queryWorkoutSamplesWithAnchor","fn","isHealthDataAvailable","isProtectedDataAvailable","authorizationStatusFor","requestAuthorization","saveQuantitySample","deleteQuantitySample","deleteSamples","disableAllBackgroundDelivery","disableBackgroundDelivery","enableBackgroundDelivery","queryCategorySamplesWithAnchor","queryQuantitySamplesWithAnchor","getBiologicalSex","getBloodType","getDateOfBirth","getFitzpatrickSkinType","getPreferredUnits","getRequestStatusForAuthorization","getWheelchairUse","getWorkoutRoutes","queryCategorySamples","queryCorrelationSamples","queryHeartbeatSeriesSamples","queryHeartbeatSeriesSamplesWithAnchor","queryQuantitySamples","querySources","queryStatisticsForQuantity","queryStatisticsCollectionForQuantity","queryWorkoutSamples","saveStateOfMindSample","saveCategorySample","saveCorrelationSample","saveWorkoutSample","subscribeToObserverQuery","unsubscribeQuery","saveWorkoutRoute","getWorkoutPlanById","startWatchAppWithWorkoutConfiguration","queryStateOfMindSamples","workoutSessionMirroringStartHandler","module","NativeModules","ReactNativeHealthkit","NativeEventEmitter"],"sources":["test-setup.ts"],"sourcesContent":["// eslint-disable-next-line import/no-unresolved\nimport { mock, jest, beforeAll } from 'bun:test'\n\nimport type Native from './native-types'\n\nbeforeAll(async () => {\n const mockModule: typeof Native = {\n queryWorkoutSamplesWithAnchor: jest.fn(),\n isHealthDataAvailable: jest.fn(),\n isProtectedDataAvailable: jest.fn(),\n authorizationStatusFor: jest.fn(),\n requestAuthorization: jest.fn(),\n saveQuantitySample: jest.fn(),\n deleteQuantitySample: jest.fn(),\n deleteSamples: jest.fn(),\n disableAllBackgroundDelivery: jest.fn(),\n disableBackgroundDelivery: jest.fn(),\n enableBackgroundDelivery: jest.fn(),\n queryCategorySamplesWithAnchor: jest.fn(),\n queryQuantitySamplesWithAnchor: jest.fn(),\n getBiologicalSex: jest.fn(),\n getBloodType: jest.fn(),\n getDateOfBirth: jest.fn(),\n getFitzpatrickSkinType: jest.fn(),\n getPreferredUnits: jest.fn(),\n getRequestStatusForAuthorization: jest.fn(),\n getWheelchairUse: jest.fn(),\n getWorkoutRoutes: jest.fn(),\n queryCategorySamples: jest.fn(),\n queryCorrelationSamples: jest.fn(),\n queryHeartbeatSeriesSamples: jest.fn(),\n queryHeartbeatSeriesSamplesWithAnchor: jest.fn(),\n queryQuantitySamples: jest.fn(),\n querySources: jest.fn(),\n queryStatisticsForQuantity: jest.fn(),\n queryStatisticsCollectionForQuantity: jest.fn(),\n queryWorkoutSamples: jest.fn(),\n saveStateOfMindSample: jest.fn(),\n saveCategorySample: jest.fn(),\n saveCorrelationSample: jest.fn(),\n saveWorkoutSample: jest.fn(),\n subscribeToObserverQuery: jest.fn(),\n unsubscribeQuery: jest.fn(),\n saveWorkoutRoute: jest.fn(),\n getWorkoutPlanById: jest.fn(),\n startWatchAppWithWorkoutConfiguration: jest.fn(),\n queryStateOfMindSamples: jest.fn(),\n workoutSessionMirroringStartHandler: jest.fn(),\n }\n\n await mock.module('react-native', () => ({\n NativeModules: {\n ReactNativeHealthkit: mockModule,\n },\n NativeEventEmitter: jest.fn(),\n }))\n})\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,10 @@
1
+ import Native from '../native-types';
2
+ /**
3
+ * @see {@link https://developer.apple.com/documentation/healthkit/hkstateofmind Saving state of mind samples (Apple Docs)}
4
+ * @description Saves a state of mind sample to HealthKit, including kind, mood, valence, labels (optional), and associations (optional).
5
+ */
6
+ async function saveStateOfMindSample(options) {
7
+ return Native.saveStateOfMindSample(options.date.toISOString(), options.kind, options.valence, options.labels || [], options.associations || [], options.metadata || {});
8
+ }
9
+ export default saveStateOfMindSample;
10
+ //# sourceMappingURL=saveStateOfMindSample.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Native","saveStateOfMindSample","options","date","toISOString","kind","valence","labels","associations","metadata"],"sources":["saveStateOfMindSample.ts"],"sourcesContent":["import Native from '../native-types'\n\nimport type { HKStateOfMindSampleRaw } from '../native-types'\n\n/**\n * @see {@link https://developer.apple.com/documentation/healthkit/hkstateofmind Saving state of mind samples (Apple Docs)}\n * @description Saves a state of mind sample to HealthKit, including kind, mood, valence, labels (optional), and associations (optional).\n */\nasync function saveStateOfMindSample(\n options: Omit<\n HKStateOfMindSampleRaw,\n | 'uuid'\n | 'valenceClassification'\n | 'startDate'\n | 'endDate'\n | 'labels'\n | 'associations'\n | 'device'\n | 'sourceRevision'\n > & {\n // allow the user to provide a Date instead of expecting them to provide date.toISOString()\n readonly date: Date\n // omitting then redeclaring these in order to make them optional\n readonly associations?: HKStateOfMindSampleRaw['associations']\n readonly labels?: HKStateOfMindSampleRaw['labels']\n },\n) {\n return Native.saveStateOfMindSample(\n options.date.toISOString(),\n options.kind,\n options.valence,\n options.labels || [],\n options.associations || [],\n options.metadata || {},\n )\n}\n\nexport default saveStateOfMindSample\n"],"mappings":"AAAA,OAAOA,MAAM,MAAM,iBAAiB;AAIpC;AACA;AACA;AACA;AACA,eAAeC,qBAAqBA,CAClCC,OAgBC,EACD;EACA,OAAOF,MAAM,CAACC,qBAAqB,CACjCC,OAAO,CAACC,IAAI,CAACC,WAAW,CAAC,CAAC,EAC1BF,OAAO,CAACG,IAAI,EACZH,OAAO,CAACI,OAAO,EACfJ,OAAO,CAACK,MAAM,IAAI,EAAE,EACpBL,OAAO,CAACM,YAAY,IAAI,EAAE,EAC1BN,OAAO,CAACO,QAAQ,IAAI,CAAC,CACvB,CAAC;AACH;AAEA,eAAeR,qBAAqB","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"names":["Native","EventEmitter","subscribeToChanges","identifier","callback","subscription","addListener","typeIdentifier","queryId","subscribeToObserverQuery","catch","error","remove","Promise","reject","unsubscribeQuery"],"sources":["subscribeToChanges.ts"],"sourcesContent":["import Native, { EventEmitter } from '../native-types'\n\nimport type { HKSampleTypeIdentifier } from '..'\n\nconst subscribeToChanges = async (\n identifier: HKSampleTypeIdentifier,\n callback: () => void,\n) => {\n const subscription = EventEmitter.addListener(\n 'onChange',\n ({ typeIdentifier }) => {\n if (typeIdentifier === identifier) {\n callback()\n }\n },\n )\n\n const queryId = await Native.subscribeToObserverQuery(identifier).catch(\n async (error) => {\n subscription.remove()\n return Promise.reject(error)\n },\n )\n\n return async () => {\n subscription.remove()\n return Native.unsubscribeQuery(queryId)\n }\n}\n\nexport default subscribeToChanges\n"],"mappings":"AAAA,OAAOA,MAAM,IAAIC,YAAY,QAAQ,iBAAiB;AAItD,MAAMC,kBAAkB,GAAG,MAAAA,CACzBC,UAAkC,EAClCC,QAAoB,KACjB;EACH,MAAMC,YAAY,GAAGJ,YAAY,CAACK,WAAW,CAC3C,UAAU,EACV,CAAC;IAAEC;EAAe,CAAC,KAAK;IACtB,IAAIA,cAAc,KAAKJ,UAAU,EAAE;MACjCC,QAAQ,CAAC,CAAC;IACZ;EACF,CACF,CAAC;EAED,MAAMI,OAAO,GAAG,MAAMR,MAAM,CAACS,wBAAwB,CAACN,UAAU,CAAC,CAACO,KAAK,CACrE,MAAOC,KAAK,IAAK;IACfN,YAAY,CAACO,MAAM,CAAC,CAAC;IACrB,OAAOC,OAAO,CAACC,MAAM,CAACH,KAAK,CAAC;EAC9B,CACF,CAAC;EAED,OAAO,YAAY;IACjBN,YAAY,CAACO,MAAM,CAAC,CAAC;IACrB,OAAOZ,MAAM,CAACe,gBAAgB,CAACP,OAAO,CAAC;EACzC,CAAC;AACH,CAAC;AAED,eAAeN,kBAAkB","ignoreList":[]}
1
+ {"version":3,"names":["Native","EventEmitter","subscribeToChanges","identifier","callback","subscription","addListener","typeIdentifier","queryId","subscribeToObserverQuery","catch","error","remove","Promise","reject","unsubscribeQuery"],"sources":["subscribeToChanges.ts"],"sourcesContent":["import Native, { EventEmitter } from '../native-types'\n\nimport type { HKSampleTypeIdentifier } from '..'\n\nconst subscribeToChanges = async (\n identifier: HKSampleTypeIdentifier,\n callback: () => void,\n) => {\n const subscription = EventEmitter.addListener(\n 'onChange',\n ({ typeIdentifier }: { readonly typeIdentifier: HKSampleTypeIdentifier }) => {\n if (typeIdentifier === identifier) {\n callback()\n }\n },\n )\n\n const queryId = await Native.subscribeToObserverQuery(identifier).catch(\n async (error) => {\n subscription.remove()\n return Promise.reject(error)\n },\n )\n\n return async () => {\n subscription.remove()\n return Native.unsubscribeQuery(queryId)\n }\n}\n\nexport default subscribeToChanges\n"],"mappings":"AAAA,OAAOA,MAAM,IAAIC,YAAY,QAAQ,iBAAiB;AAItD,MAAMC,kBAAkB,GAAG,MAAAA,CACzBC,UAAkC,EAClCC,QAAoB,KACjB;EACH,MAAMC,YAAY,GAAGJ,YAAY,CAACK,WAAW,CAC3C,UAAU,EACV,CAAC;IAAEC;EAAoE,CAAC,KAAK;IAC3E,IAAIA,cAAc,KAAKJ,UAAU,EAAE;MACjCC,QAAQ,CAAC,CAAC;IACZ;EACF,CACF,CAAC;EAED,MAAMI,OAAO,GAAG,MAAMR,MAAM,CAACS,wBAAwB,CAACN,UAAU,CAAC,CAACO,KAAK,CACrE,MAAOC,KAAK,IAAK;IACfN,YAAY,CAACO,MAAM,CAAC,CAAC;IACrB,OAAOC,OAAO,CAACC,MAAM,CAACH,KAAK,CAAC;EAC9B,CACF,CAAC;EAED,OAAO,YAAY;IACjBN,YAAY,CAACO,MAAM,CAAC,CAAC;IACrB,OAAOZ,MAAM,CAACe,gBAAgB,CAACP,OAAO,CAAC;EACzC,CAAC;AACH,CAAC;AAED,eAAeN,kBAAkB","ignoreList":[]}
@@ -0,0 +1,11 @@
1
+ import Native from '../native-types';
2
+
3
+ /**
4
+ * A block that the system calls when it starts a mirrored workout session between iOS and watchOS apps.
5
+ * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/4172878-workoutsessionmirroringstarthand workoutSessionMirroringStartHandler (Apple Docs)}
6
+ * @returns {Promise<boolean>} A promise that resolves to true if mirroring started successfully, false otherwise.
7
+ * @throws {Error} If there's an error starting the mirroring session.
8
+ */
9
+ const workoutSessionMirroringStartHandler = async () => Native.workoutSessionMirroringStartHandler();
10
+ export default workoutSessionMirroringStartHandler;
11
+ //# sourceMappingURL=workoutSessionMirroringStartHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Native","workoutSessionMirroringStartHandler"],"sources":["workoutSessionMirroringStartHandler.ts"],"sourcesContent":["import Native from '../native-types'\n\n/**\n* A block that the system calls when it starts a mirrored workout session between iOS and watchOS apps.\n* @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/4172878-workoutsessionmirroringstarthand workoutSessionMirroringStartHandler (Apple Docs)}\n* @returns {Promise<boolean>} A promise that resolves to true if mirroring started successfully, false otherwise.\n* @throws {Error} If there's an error starting the mirroring session.\n*/\nconst workoutSessionMirroringStartHandler: () => Promise<boolean> = async () => Native.workoutSessionMirroringStartHandler()\n\nexport default workoutSessionMirroringStartHandler\n"],"mappings":"AAAA,OAAOA,MAAM,MAAM,iBAAiB;;AAEpC;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,mCAA2D,GAAG,MAAAA,CAAA,KAAYD,MAAM,CAACC,mCAAmC,CAAC,CAAC;AAE5H,eAAeA,mCAAmC","ignoreList":[]}
@@ -34,10 +34,12 @@ import requestAuthorization from './utils/requestAuthorization';
34
34
  import saveCategorySample from './utils/saveCategorySample';
35
35
  import saveCorrelationSample from './utils/saveCorrelationSample';
36
36
  import saveQuantitySample from './utils/saveQuantitySample';
37
+ import saveStateOfMindSample from './utils/saveStateOfMindSample';
37
38
  import saveWorkoutRoute from './utils/saveWorkoutRoute';
38
39
  import saveWorkoutSample from './utils/saveWorkoutSample';
39
40
  import startWatchApp from './utils/startWatchApp';
40
41
  import subscribeToChanges from './utils/subscribeToChanges';
42
+ import workoutSessionMirroringStartHandler from './utils/workoutSessionMirroringStartHandler';
41
43
  declare const availableQuantityTypes: (majorVersionIOS?: number) => HKQuantityTypeIdentifier[];
42
44
  declare const authorizationStatusFor: (type: import("./native-types").HealthkitReadAuthorization) => Promise<import("./native-types").HKAuthorizationStatus>;
43
45
  declare const isHealthDataAvailable: () => Promise<boolean>;
@@ -148,8 +150,10 @@ declare const _default: {
148
150
  saveQuantitySample: typeof saveQuantitySample;
149
151
  saveWorkoutSample: typeof saveWorkoutSample;
150
152
  saveWorkoutRoute: typeof saveWorkoutRoute;
153
+ saveStateOfMindSample: typeof saveStateOfMindSample;
151
154
  subscribeToChanges: (identifier: import("./native-types").HKSampleTypeIdentifier, callback: () => void) => Promise<() => Promise<boolean>>;
152
155
  startWatchApp: (configuration: import("./native-types").HKWorkoutConfiguration) => () => Promise<boolean>;
156
+ workoutSessionMirroringStartHandler: () => Promise<boolean>;
153
157
  /**
154
158
  * @returns the most recent sample for the given category type.
155
159
  */
@@ -190,5 +194,5 @@ export { authorizationStatusFor, availableQuantityTypes, disableAllBackgroundDel
190
194
  /**
191
195
  * @deprecated Use queryWorkoutSamples instead
192
196
  */
193
- queryWorkouts, queryWorkoutSamples, queryWorkoutSamplesWithAnchor, querySources, requestAuthorization, deleteQuantitySample, deleteSamples, getWorkoutPlanById, saveCategorySample, saveCorrelationSample, saveQuantitySample, saveWorkoutSample, saveWorkoutRoute, subscribeToChanges, startWatchApp, useMostRecentCategorySample, useMostRecentQuantitySample, useMostRecentWorkout, useSubscribeToChanges, useHealthkitAuthorization, useIsHealthDataAvailable, useSources, useStatisticsForQuantity, isProtectedDataAvailable, queryStateOfMindSamples, };
197
+ queryWorkouts, queryWorkoutSamples, queryWorkoutSamplesWithAnchor, querySources, requestAuthorization, deleteQuantitySample, deleteSamples, getWorkoutPlanById, saveCategorySample, saveStateOfMindSample, saveCorrelationSample, saveQuantitySample, saveWorkoutSample, saveWorkoutRoute, subscribeToChanges, startWatchApp, workoutSessionMirroringStartHandler, useMostRecentCategorySample, useMostRecentQuantitySample, useMostRecentWorkout, useSubscribeToChanges, useHealthkitAuthorization, useIsHealthDataAvailable, useSources, useStatisticsForQuantity, isProtectedDataAvailable, queryStateOfMindSamples, };
194
198
  export * from './types';
@@ -34,8 +34,8 @@ declare const authorizationStatusFor: () => Promise<HKAuthorizationStatus>, avai
34
34
  samples: never[];
35
35
  deletedSamples: never[];
36
36
  newAnchor: string;
37
- }>, querySources: () => Promise<never[]>, requestAuthorization: () => Promise<boolean>, deleteQuantitySample: () => Promise<boolean>, deleteSamples: () => Promise<boolean>, getWorkoutPlanById: () => Promise<null>, saveCategorySample: () => Promise<boolean>, saveCorrelationSample: () => Promise<boolean>, saveQuantitySample: () => Promise<boolean>, saveWorkoutSample: () => Promise<null>, saveWorkoutRoute: () => Promise<boolean>, subscribeToChanges: () => Promise<() => Promise<boolean>>, startWatchApp: () => () => Promise<boolean>, useMostRecentCategorySample: () => null, useMostRecentQuantitySample: () => null, useMostRecentWorkout: () => null, useSubscribeToChanges: () => ((() => null) | null)[], useHealthkitAuthorization: () => readonly [null, () => Promise<HKAuthorizationRequestStatus>], useIsHealthDataAvailable: () => boolean, isProtectedDataAvailable: () => Promise<boolean>, queryStateOfMindSamples: () => Promise<never[]>;
37
+ }>, querySources: () => Promise<never[]>, requestAuthorization: () => Promise<boolean>, deleteQuantitySample: () => Promise<boolean>, deleteSamples: () => Promise<boolean>, getWorkoutPlanById: () => Promise<null>, saveCategorySample: () => Promise<boolean>, saveStateOfMindSample: () => Promise<boolean>, saveCorrelationSample: () => Promise<boolean>, saveQuantitySample: () => Promise<boolean>, saveWorkoutSample: () => Promise<null>, saveWorkoutRoute: () => Promise<boolean>, subscribeToChanges: () => Promise<() => Promise<boolean>>, startWatchApp: () => () => Promise<boolean>, workoutSessionMirroringStartHandler: () => Promise<boolean>, useMostRecentCategorySample: () => null, useMostRecentQuantitySample: () => null, useMostRecentWorkout: () => null, useSubscribeToChanges: () => ((() => null) | null)[], useHealthkitAuthorization: () => readonly [null, () => Promise<HKAuthorizationRequestStatus>], useIsHealthDataAvailable: () => boolean, isProtectedDataAvailable: () => Promise<boolean>, queryStateOfMindSamples: () => Promise<never[]>;
38
38
  declare const Healthkit: typeof ReactNativeHealthkit;
39
- export { authorizationStatusFor, availableQuantityTypes, deleteQuantitySample, deleteSamples, disableAllBackgroundDelivery, disableBackgroundDelivery, enableBackgroundDelivery, getBiologicalSex, getBloodType, getDateOfBirth, getFitzpatrickSkinType, getMostRecentCategorySample, getMostRecentQuantitySample, getMostRecentWorkout, getPreferredUnit, getPreferredUnits, getRequestStatusForAuthorization, getWheelchairUse, getWorkoutPlanById, getWorkoutRoutes, isHealthDataAvailable, isProtectedDataAvailable, queryCategorySamples, queryCategorySamplesWithAnchor, queryCorrelationSamples, queryHeartbeatSeriesSamples, queryHeartbeatSeriesSamplesWithAnchor, queryQuantitySamples, queryQuantitySamplesWithAnchor, querySources, queryStatisticsForQuantity, queryStatisticsCollectionForQuantity, queryWorkouts, queryWorkoutSamples, queryWorkoutSamplesWithAnchor, requestAuthorization, saveCategorySample, saveCorrelationSample, saveQuantitySample, saveWorkoutRoute, saveWorkoutSample, subscribeToChanges, startWatchApp, useHealthkitAuthorization, useIsHealthDataAvailable, useMostRecentCategorySample, useMostRecentQuantitySample, useMostRecentWorkout, useSources, useStatisticsForQuantity, useSubscribeToChanges, queryStateOfMindSamples, };
39
+ export { authorizationStatusFor, availableQuantityTypes, deleteQuantitySample, deleteSamples, disableAllBackgroundDelivery, disableBackgroundDelivery, enableBackgroundDelivery, getBiologicalSex, getBloodType, getDateOfBirth, getFitzpatrickSkinType, getMostRecentCategorySample, getMostRecentQuantitySample, getMostRecentWorkout, getPreferredUnit, getPreferredUnits, getRequestStatusForAuthorization, getWheelchairUse, getWorkoutPlanById, getWorkoutRoutes, isHealthDataAvailable, isProtectedDataAvailable, queryCategorySamples, queryCategorySamplesWithAnchor, queryCorrelationSamples, queryHeartbeatSeriesSamples, queryHeartbeatSeriesSamplesWithAnchor, queryQuantitySamples, queryQuantitySamplesWithAnchor, querySources, queryStatisticsForQuantity, queryStatisticsCollectionForQuantity, queryWorkouts, queryWorkoutSamples, queryWorkoutSamplesWithAnchor, requestAuthorization, saveCategorySample, saveStateOfMindSample, saveCorrelationSample, saveQuantitySample, saveWorkoutRoute, saveWorkoutSample, subscribeToChanges, startWatchApp, workoutSessionMirroringStartHandler, useHealthkitAuthorization, useIsHealthDataAvailable, useMostRecentCategorySample, useMostRecentQuantitySample, useMostRecentWorkout, useSources, useStatisticsForQuantity, useSubscribeToChanges, queryStateOfMindSamples, };
40
40
  export * from './types';
41
41
  export default Healthkit;
@@ -1393,6 +1393,9 @@ export interface HKWorkoutEvent {
1393
1393
  readonly startDate: string;
1394
1394
  readonly endDate: string;
1395
1395
  }
1396
+ /**
1397
+ * @see {@link https://developer.apple.com/documentation/healthkit/hkworkouteventtype Apple Docs }
1398
+ */
1396
1399
  export declare enum HKWorkoutEventType {
1397
1400
  pause = 1,
1398
1401
  resume = 2,
@@ -1534,6 +1537,35 @@ export declare enum HKWorkoutSessionLocationType {
1534
1537
  indoor = 2,
1535
1538
  outdoor = 3
1536
1539
  }
1540
+ /**
1541
+ * @see {@link https://developer.apple.com/documentation/healthkit/hkworkoutsessionstate Apple Docs }
1542
+ */
1543
+ export declare enum WorkoutSessionState {
1544
+ NotStarted = 1,
1545
+ Running = 2,
1546
+ Ended = 3,
1547
+ Paused = 4,
1548
+ Prepared = 5,
1549
+ Stopped = 6
1550
+ }
1551
+ export interface WorkoutStateChangeEvent {
1552
+ readonly toState: WorkoutSessionState;
1553
+ readonly fromState: WorkoutSessionState;
1554
+ readonly date: string;
1555
+ }
1556
+ export interface WorkoutErrorEvent {
1557
+ readonly error: string;
1558
+ }
1559
+ export type RemoteSessionSharableData = {
1560
+ readonly type: string;
1561
+ readonly payload: Record<string, unknown>;
1562
+ };
1563
+ export type WorkoutDataReceivedEvent = {
1564
+ readonly data: readonly RemoteSessionSharableData[];
1565
+ };
1566
+ export type WorkoutEventReceivedEvent = {
1567
+ readonly type: HKWorkoutEventType;
1568
+ };
1537
1569
  type ReactNativeHealthkitTypeNative = {
1538
1570
  /**
1539
1571
  * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614180-ishealthdataavailable Apple Docs }
@@ -1591,6 +1623,7 @@ type ReactNativeHealthkitTypeNative = {
1591
1623
  readonly queryHeartbeatSeriesSamplesWithAnchor: (from: string, to: string, limit: number, anchor: string) => Promise<QueryHeartbeatSeriesSamplesResponseRaw>;
1592
1624
  readonly querySources: <TIdentifier extends HKCategoryTypeIdentifier | HKQuantityTypeIdentifier>(identifier: TIdentifier) => Promise<readonly HKSource[]>;
1593
1625
  readonly saveCategorySample: <T extends HKCategoryTypeIdentifier>(identifier: T, value: HKCategoryValueForIdentifier<T>, start: string, end: string, metadata: unknown) => Promise<boolean>;
1626
+ readonly saveStateOfMindSample: (startDate: HKStateOfMindSampleRaw['startDate'], kind: HKStateOfMindSampleRaw['kind'], valence: HKStateOfMindSampleRaw['valence'], labels: HKStateOfMindSampleRaw['labels'], associations: HKStateOfMindSampleRaw['associations'], metadata: HKStateOfMindSampleRaw['metadata']) => Promise<boolean>;
1594
1627
  readonly queryStatisticsForQuantity: <TIdentifier extends HKQuantityTypeIdentifier, TUnit extends UnitForIdentifier<TIdentifier>>(identifier: HKQuantityTypeIdentifier, unit: TUnit, from: string, to: string, options: readonly HKStatisticsOptions[]) => Promise<QueryStatisticsResponseRaw<TIdentifier, TUnit>>;
1595
1628
  readonly queryStatisticsCollectionForQuantity: <TIdentifier extends HKQuantityTypeIdentifier, TUnit extends UnitForIdentifier<TIdentifier>>(identifier: TIdentifier, unit: TUnit, options: readonly HKStatisticsOptions[], anchorDate: string, intervalComponents: IntervalComponents, startDate: string, endDate: string) => Promise<readonly QueryStatisticsResponseRaw<TIdentifier, TUnit>[]>;
1596
1629
  readonly getPreferredUnits: (identifiers: readonly HKQuantityTypeIdentifier[]) => Promise<TypeToUnitMapping>;
@@ -1614,6 +1647,10 @@ type ReactNativeHealthkitTypeNative = {
1614
1647
  * @requires iOS 17.0+
1615
1648
  */
1616
1649
  readonly queryStateOfMindSamples: (from: string | null, to: string | null, limit: number, ascending: boolean) => Promise<readonly HKStateOfMindSampleRaw[]>;
1650
+ /**
1651
+ * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/4172878-workoutsessionmirroringstarthand Apple Docs }
1652
+ */
1653
+ readonly workoutSessionMirroringStartHandler: () => Promise<boolean>;
1617
1654
  };
1618
1655
  export declare enum HKStateOfMindValenceClassification {
1619
1656
  veryUnpleasant = 1,
@@ -1629,7 +1666,7 @@ export type HKStateOfMindSampleRaw = {
1629
1666
  readonly device?: HKDevice;
1630
1667
  readonly startDate: string;
1631
1668
  readonly endDate: string;
1632
- readonly metadata?: HKHeartbeatSeriesSampleMetadata;
1669
+ readonly metadata?: HKGenericMetadata;
1633
1670
  readonly sourceRevision?: HKSourceRevision;
1634
1671
  /**
1635
1672
  * @see {@link https://developer.apple.com/documentation/healthkit/hkstateofmind/4337998-valence Apple Docs }
@@ -1645,8 +1682,12 @@ declare const Native: ReactNativeHealthkitTypeNative;
1645
1682
  type OnChangeCallback = ({ typeIdentifier, }: {
1646
1683
  readonly typeIdentifier: HKSampleTypeIdentifier;
1647
1684
  }) => void;
1685
+ type OnRemoteWorkoutStateChangeCallback = (event: WorkoutStateChangeEvent) => void;
1686
+ type OnRemoteWorkoutErrorCallback = (event: WorkoutErrorEvent) => void;
1687
+ type OnRemoteWorkoutDataCallback = (event: WorkoutDataReceivedEvent) => void;
1688
+ type OnRemoteWorkoutEventReceivedCallback = (event: WorkoutEventReceivedEvent) => void;
1648
1689
  interface HealthkitEventEmitter extends NativeEventEmitter {
1649
- readonly addListener: (eventType: 'onChange', callback: OnChangeCallback) => EmitterSubscription;
1690
+ readonly addListener: (eventType: 'onChange' | 'onRemoteWorkoutStateChange' | 'onRemoteWorkoutError' | 'onRemoteWorkoutDataReceived' | 'onRemoteWorkoutEventReceived', callback: OnChangeCallback | OnRemoteWorkoutStateChangeCallback | OnRemoteWorkoutErrorCallback | OnRemoteWorkoutDataCallback | OnRemoteWorkoutEventReceivedCallback) => EmitterSubscription;
1650
1691
  }
1651
1692
  export declare const EventEmitter: HealthkitEventEmitter;
1652
1693
  export default Native;
@@ -0,0 +1,11 @@
1
+ import type { HKStateOfMindSampleRaw } from '../native-types';
2
+ /**
3
+ * @see {@link https://developer.apple.com/documentation/healthkit/hkstateofmind Saving state of mind samples (Apple Docs)}
4
+ * @description Saves a state of mind sample to HealthKit, including kind, mood, valence, labels (optional), and associations (optional).
5
+ */
6
+ declare function saveStateOfMindSample(options: Omit<HKStateOfMindSampleRaw, 'uuid' | 'valenceClassification' | 'startDate' | 'endDate' | 'labels' | 'associations' | 'device' | 'sourceRevision'> & {
7
+ readonly date: Date;
8
+ readonly associations?: HKStateOfMindSampleRaw['associations'];
9
+ readonly labels?: HKStateOfMindSampleRaw['labels'];
10
+ }): Promise<boolean>;
11
+ export default saveStateOfMindSample;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * A block that the system calls when it starts a mirrored workout session between iOS and watchOS apps.
3
+ * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/4172878-workoutsessionmirroringstarthand workoutSessionMirroringStartHandler (Apple Docs)}
4
+ * @returns {Promise<boolean>} A promise that resolves to true if mirroring started successfully, false otherwise.
5
+ * @throws {Error} If there's an error starting the mirroring session.
6
+ */
7
+ declare const workoutSessionMirroringStartHandler: () => Promise<boolean>;
8
+ export default workoutSessionMirroringStartHandler;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kingstinct/react-native-healthkit",
3
- "version": "8.5.0",
3
+ "version": "8.6.0",
4
4
  "description": "React Native bindings for HealthKit",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
package/src/index.ios.tsx CHANGED
@@ -36,10 +36,12 @@ import requestAuthorization from './utils/requestAuthorization'
36
36
  import saveCategorySample from './utils/saveCategorySample'
37
37
  import saveCorrelationSample from './utils/saveCorrelationSample'
38
38
  import saveQuantitySample from './utils/saveQuantitySample'
39
+ import saveStateOfMindSample from './utils/saveStateOfMindSample'
39
40
  import saveWorkoutRoute from './utils/saveWorkoutRoute'
40
41
  import saveWorkoutSample from './utils/saveWorkoutSample'
41
42
  import startWatchApp from './utils/startWatchApp'
42
43
  import subscribeToChanges from './utils/subscribeToChanges'
44
+ import workoutSessionMirroringStartHandler from './utils/workoutSessionMirroringStartHandler'
43
45
 
44
46
  const currentMajorVersionIOS = Platform.OS === 'ios' ? parseInt(Platform.Version, 10) : 0
45
47
 
@@ -187,11 +189,13 @@ export default {
187
189
  saveQuantitySample,
188
190
  saveWorkoutSample,
189
191
  saveWorkoutRoute,
192
+ saveStateOfMindSample,
190
193
 
191
194
  // subscriptions
192
195
  subscribeToChanges,
193
196
 
194
197
  startWatchApp,
198
+ workoutSessionMirroringStartHandler,
195
199
 
196
200
  /**
197
201
  * @returns the most recent sample for the given category type.
@@ -265,12 +269,14 @@ export {
265
269
  deleteSamples,
266
270
  getWorkoutPlanById,
267
271
  saveCategorySample,
272
+ saveStateOfMindSample,
268
273
  saveCorrelationSample,
269
274
  saveQuantitySample,
270
275
  saveWorkoutSample,
271
276
  saveWorkoutRoute,
272
277
  subscribeToChanges,
273
278
  startWatchApp,
279
+ workoutSessionMirroringStartHandler,
274
280
  useMostRecentCategorySample,
275
281
  useMostRecentQuantitySample,
276
282
  useMostRecentWorkout,
@@ -97,12 +97,14 @@ const authorizationStatusFor = UnavailableFn(Promise.resolve(HKAuthorizationStat
97
97
  deleteSamples = UnavailableFn(Promise.resolve(false)),
98
98
  getWorkoutPlanById = UnavailableFn(Promise.resolve(null)),
99
99
  saveCategorySample = UnavailableFn(Promise.resolve(false)),
100
+ saveStateOfMindSample = UnavailableFn(Promise.resolve(false)),
100
101
  saveCorrelationSample = UnavailableFn(Promise.resolve(false)),
101
102
  saveQuantitySample = UnavailableFn(Promise.resolve(false)),
102
103
  saveWorkoutSample = UnavailableFn(Promise.resolve(null)),
103
104
  saveWorkoutRoute = UnavailableFn(Promise.resolve(false)),
104
105
  subscribeToChanges = UnavailableFn(Promise.resolve(async () => Promise.resolve(false))),
105
106
  startWatchApp = UnavailableFn(async () => Promise.resolve(false)),
107
+ workoutSessionMirroringStartHandler = UnavailableFn(Promise.resolve(false)),
106
108
  useMostRecentCategorySample = UnavailableFn(null),
107
109
  useMostRecentQuantitySample = UnavailableFn(null),
108
110
  useMostRecentWorkout = UnavailableFn(null),
@@ -149,6 +151,7 @@ const Healthkit: typeof ReactNativeHealthkit = {
149
151
  queryWorkoutSamples,
150
152
  queryWorkoutSamplesWithAnchor,
151
153
  requestAuthorization,
154
+ saveStateOfMindSample,
152
155
  saveCategorySample,
153
156
  saveCorrelationSample,
154
157
  saveQuantitySample,
@@ -156,6 +159,7 @@ const Healthkit: typeof ReactNativeHealthkit = {
156
159
  saveWorkoutSample,
157
160
  subscribeToChanges,
158
161
  startWatchApp,
162
+ workoutSessionMirroringStartHandler,
159
163
  useHealthkitAuthorization,
160
164
  useIsHealthDataAvailable,
161
165
  useMostRecentCategorySample,
@@ -205,12 +209,14 @@ export {
205
209
  queryWorkoutSamplesWithAnchor,
206
210
  requestAuthorization,
207
211
  saveCategorySample,
212
+ saveStateOfMindSample,
208
213
  saveCorrelationSample,
209
214
  saveQuantitySample,
210
215
  saveWorkoutRoute,
211
216
  saveWorkoutSample,
212
217
  subscribeToChanges,
213
218
  startWatchApp,
219
+ workoutSessionMirroringStartHandler,
214
220
  useHealthkitAuthorization,
215
221
  useIsHealthDataAvailable,
216
222
  useMostRecentCategorySample,
@@ -1851,6 +1851,9 @@ export interface HKWorkoutEvent {
1851
1851
  readonly endDate: string;
1852
1852
  }
1853
1853
 
1854
+ /**
1855
+ * @see {@link https://developer.apple.com/documentation/healthkit/hkworkouteventtype Apple Docs }
1856
+ */
1854
1857
  export enum HKWorkoutEventType {
1855
1858
  pause = 1,
1856
1859
  resume = 2,
@@ -2040,6 +2043,41 @@ export enum HKWorkoutSessionLocationType {
2040
2043
  outdoor = 3
2041
2044
  }
2042
2045
 
2046
+ /**
2047
+ * @see {@link https://developer.apple.com/documentation/healthkit/hkworkoutsessionstate Apple Docs }
2048
+ */
2049
+ export enum WorkoutSessionState {
2050
+ NotStarted = 1,
2051
+ Running = 2,
2052
+ Ended = 3,
2053
+ Paused = 4,
2054
+ Prepared = 5,
2055
+ Stopped = 6,
2056
+ }
2057
+
2058
+ export interface WorkoutStateChangeEvent {
2059
+ readonly toState: WorkoutSessionState;
2060
+ readonly fromState: WorkoutSessionState;
2061
+ readonly date: string;
2062
+ }
2063
+
2064
+ export interface WorkoutErrorEvent {
2065
+ readonly error: string;
2066
+ }
2067
+
2068
+ export type RemoteSessionSharableData = {
2069
+ readonly type: string;
2070
+ readonly payload: Record<string, unknown>;
2071
+ }
2072
+
2073
+ export type WorkoutDataReceivedEvent = {
2074
+ readonly data: readonly RemoteSessionSharableData[];
2075
+ };
2076
+
2077
+ export type WorkoutEventReceivedEvent = {
2078
+ readonly type: HKWorkoutEventType;
2079
+ };
2080
+
2043
2081
  type ReactNativeHealthkitTypeNative = {
2044
2082
  /**
2045
2083
  * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614180-ishealthdataavailable Apple Docs }
@@ -2234,6 +2272,14 @@ type ReactNativeHealthkitTypeNative = {
2234
2272
  end: string,
2235
2273
  metadata: unknown
2236
2274
  ) => Promise<boolean>;
2275
+ readonly saveStateOfMindSample: (
2276
+ startDate: HKStateOfMindSampleRaw['startDate'],
2277
+ kind: HKStateOfMindSampleRaw['kind'],
2278
+ valence: HKStateOfMindSampleRaw['valence'],
2279
+ labels: HKStateOfMindSampleRaw['labels'],
2280
+ associations: HKStateOfMindSampleRaw['associations'],
2281
+ metadata: HKStateOfMindSampleRaw['metadata']
2282
+ ) => Promise<boolean>;
2237
2283
  readonly queryStatisticsForQuantity: <
2238
2284
  TIdentifier extends HKQuantityTypeIdentifier,
2239
2285
  TUnit extends UnitForIdentifier<TIdentifier>
@@ -2287,6 +2333,11 @@ type ReactNativeHealthkitTypeNative = {
2287
2333
  limit: number,
2288
2334
  ascending: boolean
2289
2335
  ) => Promise<readonly HKStateOfMindSampleRaw[]>;
2336
+
2337
+ /**
2338
+ * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/4172878-workoutsessionmirroringstarthand Apple Docs }
2339
+ */
2340
+ readonly workoutSessionMirroringStartHandler: () => Promise<boolean>;
2290
2341
  };
2291
2342
 
2292
2343
  export enum HKStateOfMindValenceClassification {
@@ -2304,7 +2355,7 @@ export type HKStateOfMindSampleRaw = {
2304
2355
  readonly device?: HKDevice;
2305
2356
  readonly startDate: string;
2306
2357
  readonly endDate: string;
2307
- readonly metadata?: HKHeartbeatSeriesSampleMetadata;
2358
+ readonly metadata?: HKGenericMetadata;
2308
2359
  readonly sourceRevision?: HKSourceRevision;
2309
2360
  // State of mind sample properties
2310
2361
  /**
@@ -2325,11 +2376,15 @@ type OnChangeCallback = ({
2325
2376
  }: {
2326
2377
  readonly typeIdentifier: HKSampleTypeIdentifier;
2327
2378
  }) => void;
2379
+ type OnRemoteWorkoutStateChangeCallback = (event: WorkoutStateChangeEvent) => void;
2380
+ type OnRemoteWorkoutErrorCallback = (event: WorkoutErrorEvent) => void;
2381
+ type OnRemoteWorkoutDataCallback = (event: WorkoutDataReceivedEvent) => void;
2382
+ type OnRemoteWorkoutEventReceivedCallback = (event: WorkoutEventReceivedEvent) => void;
2328
2383
 
2329
2384
  interface HealthkitEventEmitter extends NativeEventEmitter {
2330
2385
  readonly addListener: (
2331
- eventType: 'onChange',
2332
- callback: OnChangeCallback
2386
+ eventType: 'onChange' | 'onRemoteWorkoutStateChange' | 'onRemoteWorkoutError' | 'onRemoteWorkoutDataReceived' | 'onRemoteWorkoutEventReceived',
2387
+ callback: OnChangeCallback | OnRemoteWorkoutStateChangeCallback | OnRemoteWorkoutErrorCallback | OnRemoteWorkoutDataCallback | OnRemoteWorkoutEventReceivedCallback
2333
2388
  ) => EmitterSubscription;
2334
2389
  }
2335
2390
 
package/src/test-setup.ts CHANGED
@@ -35,6 +35,7 @@ beforeAll(async () => {
35
35
  queryStatisticsForQuantity: jest.fn(),
36
36
  queryStatisticsCollectionForQuantity: jest.fn(),
37
37
  queryWorkoutSamples: jest.fn(),
38
+ saveStateOfMindSample: jest.fn(),
38
39
  saveCategorySample: jest.fn(),
39
40
  saveCorrelationSample: jest.fn(),
40
41
  saveWorkoutSample: jest.fn(),
@@ -44,6 +45,7 @@ beforeAll(async () => {
44
45
  getWorkoutPlanById: jest.fn(),
45
46
  startWatchAppWithWorkoutConfiguration: jest.fn(),
46
47
  queryStateOfMindSamples: jest.fn(),
48
+ workoutSessionMirroringStartHandler: jest.fn(),
47
49
  }
48
50
 
49
51
  await mock.module('react-native', () => ({
@@ -0,0 +1,38 @@
1
+ import Native from '../native-types'
2
+
3
+ import type { HKStateOfMindSampleRaw } from '../native-types'
4
+
5
+ /**
6
+ * @see {@link https://developer.apple.com/documentation/healthkit/hkstateofmind Saving state of mind samples (Apple Docs)}
7
+ * @description Saves a state of mind sample to HealthKit, including kind, mood, valence, labels (optional), and associations (optional).
8
+ */
9
+ async function saveStateOfMindSample(
10
+ options: Omit<
11
+ HKStateOfMindSampleRaw,
12
+ | 'uuid'
13
+ | 'valenceClassification'
14
+ | 'startDate'
15
+ | 'endDate'
16
+ | 'labels'
17
+ | 'associations'
18
+ | 'device'
19
+ | 'sourceRevision'
20
+ > & {
21
+ // allow the user to provide a Date instead of expecting them to provide date.toISOString()
22
+ readonly date: Date
23
+ // omitting then redeclaring these in order to make them optional
24
+ readonly associations?: HKStateOfMindSampleRaw['associations']
25
+ readonly labels?: HKStateOfMindSampleRaw['labels']
26
+ },
27
+ ) {
28
+ return Native.saveStateOfMindSample(
29
+ options.date.toISOString(),
30
+ options.kind,
31
+ options.valence,
32
+ options.labels || [],
33
+ options.associations || [],
34
+ options.metadata || {},
35
+ )
36
+ }
37
+
38
+ export default saveStateOfMindSample
@@ -8,7 +8,7 @@ const subscribeToChanges = async (
8
8
  ) => {
9
9
  const subscription = EventEmitter.addListener(
10
10
  'onChange',
11
- ({ typeIdentifier }) => {
11
+ ({ typeIdentifier }: { readonly typeIdentifier: HKSampleTypeIdentifier }) => {
12
12
  if (typeIdentifier === identifier) {
13
13
  callback()
14
14
  }
@@ -0,0 +1,11 @@
1
+ import Native from '../native-types'
2
+
3
+ /**
4
+ * A block that the system calls when it starts a mirrored workout session between iOS and watchOS apps.
5
+ * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/4172878-workoutsessionmirroringstarthand workoutSessionMirroringStartHandler (Apple Docs)}
6
+ * @returns {Promise<boolean>} A promise that resolves to true if mirroring started successfully, false otherwise.
7
+ * @throws {Error} If there's an error starting the mirroring session.
8
+ */
9
+ const workoutSessionMirroringStartHandler: () => Promise<boolean> = async () => Native.workoutSessionMirroringStartHandler()
10
+
11
+ export default workoutSessionMirroringStartHandler