@kingstinct/react-native-healthkit 9.0.6 → 9.0.7

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 (37) hide show
  1. package/ios/CharacteristicTypeModule.swift +36 -21
  2. package/lib/commonjs/healthkit.js +225 -0
  3. package/lib/commonjs/hooks/useStatisticsForQuantity.js +1 -1
  4. package/lib/commonjs/index.js +6 -209
  5. package/lib/module/healthkit.js +203 -0
  6. package/lib/module/hooks/useStatisticsForQuantity.js +1 -1
  7. package/lib/module/index.js +3 -203
  8. package/lib/typescript/healthkit.d.ts +69 -0
  9. package/lib/typescript/{index.ios.d.ts → healthkit.ios.d.ts} +11 -11
  10. package/lib/typescript/hooks/useHealthkitAuthorization.d.ts +1 -1
  11. package/lib/typescript/index.d.ts +3 -69
  12. package/lib/typescript/specs/CategoryTypeModule.nitro.d.ts +1 -1
  13. package/lib/typescript/specs/CharacteristicTypeModule.nitro.d.ts +2 -2
  14. package/lib/typescript/specs/CoreModule.nitro.d.ts +3 -3
  15. package/lib/typescript/types/Shared.d.ts +3 -3
  16. package/nitrogen/generated/ios/ReactNativeHealthkit-Swift-Cxx-Bridge.cpp +4 -4
  17. package/nitrogen/generated/ios/ReactNativeHealthkit-Swift-Cxx-Bridge.hpp +30 -30
  18. package/nitrogen/generated/ios/c++/HybridCharacteristicTypeModuleSpecSwift.hpp +3 -2
  19. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__chrono__system_clock__time_point_.swift +52 -0
  20. package/nitrogen/generated/ios/swift/HybridCharacteristicTypeModuleSpec.swift +2 -2
  21. package/nitrogen/generated/ios/swift/HybridCharacteristicTypeModuleSpec_cxx.swift +23 -11
  22. package/nitrogen/generated/shared/c++/HybridCharacteristicTypeModuleSpec.hpp +3 -2
  23. package/package.json +1 -1
  24. package/src/healthkit.ts +422 -0
  25. package/src/hooks/useHealthkitAuthorization.ts +2 -2
  26. package/src/hooks/useStatisticsForQuantity.ts +1 -3
  27. package/src/index.ts +3 -419
  28. package/src/specs/CategoryTypeModule.nitro.ts +1 -1
  29. package/src/specs/CharacteristicTypeModule.nitro.ts +2 -2
  30. package/src/specs/CoreModule.nitro.ts +5 -5
  31. package/src/test-setup.ts +0 -1
  32. package/src/types/QueryOptions.ts +3 -3
  33. package/src/types/Shared.ts +6 -8
  34. package/nitrogen/generated/ios/swift/Func_void_std__chrono__system_clock__time_point.swift +0 -46
  35. /package/lib/commonjs/{index.ios.js → healthkit.ios.js} +0 -0
  36. /package/lib/module/{index.ios.js → healthkit.ios.js} +0 -0
  37. /package/src/{index.ios.ts → healthkit.ios.ts} +0 -0
@@ -0,0 +1,422 @@
1
+ import { Platform } from 'react-native'
2
+
3
+ // Import types for default values and function signatures.
4
+ // These types are expected to be available via the './types' export.
5
+ // You might need to adjust the import path or ensure these types are correctly exported from './types'
6
+
7
+ // This import is crucial for deriving the type of the default export `HealthkitModule`
8
+ // It assumes that index.ios.ts exports a default object matching the Healthkit native module structure.
9
+ import type ReactNativeHealthkit from './healthkit.ios'
10
+ import type { WorkoutProxy } from './specs/WorkoutProxy.nitro'
11
+ import { AuthorizationRequestStatus, AuthorizationStatus } from './types/Auth'
12
+ import type {
13
+ CategorySamplesWithAnchorResponseTyped,
14
+ CategorySampleTyped,
15
+ } from './types/CategoryType'
16
+ import type { CategoryTypeIdentifier } from './types/CategoryTypeIdentifier'
17
+ import {
18
+ BiologicalSex,
19
+ BloodType,
20
+ FitzpatrickSkinType,
21
+ WheelchairUse,
22
+ } from './types/Characteristics'
23
+ import type { QuantitySample } from './types/QuantitySample'
24
+
25
+ export * from './types'
26
+
27
+ const notAvailableError = `[@kingstinct/react-native-healthkit] Platform "${Platform.OS}" not supported. HealthKit is only available on iOS.`
28
+
29
+ let hasWarned = false
30
+
31
+ // @ts-ignore
32
+ function UnavailableFnFromModule<
33
+ TKey extends keyof typeof ReactNativeHealthkit,
34
+ // @ts-ignore
35
+ // biome-ignore lint/complexity/noBannedTypes: it works
36
+ T extends Function = (typeof ReactNativeHealthkit)[TKey],
37
+ // @ts-ignore
38
+ >(_fn: TKey, defaultValue: ReturnType<T>): T {
39
+ // @ts-ignore
40
+ return () => {
41
+ if (Platform.OS !== 'ios' && !hasWarned) {
42
+ console.warn(notAvailableError)
43
+ hasWarned = true
44
+ }
45
+ return defaultValue
46
+ }
47
+ }
48
+
49
+ // --- Mock Implementations for exported functions ---
50
+
51
+ // CoreModule functions
52
+ export const authorizationStatusFor = UnavailableFnFromModule(
53
+ 'authorizationStatusFor',
54
+ AuthorizationStatus.notDetermined,
55
+ )
56
+ export const disableAllBackgroundDelivery = UnavailableFnFromModule(
57
+ 'disableAllBackgroundDelivery',
58
+ Promise.resolve(false),
59
+ )
60
+ export const disableBackgroundDelivery = UnavailableFnFromModule(
61
+ 'disableBackgroundDelivery',
62
+ Promise.resolve(false),
63
+ )
64
+ export const enableBackgroundDelivery = UnavailableFnFromModule(
65
+ 'enableBackgroundDelivery',
66
+ Promise.resolve(false),
67
+ )
68
+ export const getPreferredUnits = UnavailableFnFromModule(
69
+ 'getPreferredUnits',
70
+ Promise.resolve([]),
71
+ )
72
+ export const getRequestStatusForAuthorization = UnavailableFnFromModule(
73
+ 'getRequestStatusForAuthorization',
74
+ Promise.resolve(AuthorizationRequestStatus.unknown),
75
+ )
76
+ export const isHealthDataAvailable = UnavailableFnFromModule(
77
+ 'isHealthDataAvailable',
78
+ false,
79
+ ) // Original was synchronous
80
+ export const isHealthDataAvailableAsync = UnavailableFnFromModule(
81
+ 'isHealthDataAvailableAsync',
82
+ Promise.resolve(false),
83
+ ) // Added for consistency if needed
84
+ export const querySources = UnavailableFnFromModule(
85
+ 'querySources',
86
+ Promise.resolve([]),
87
+ )
88
+ export const requestAuthorization = UnavailableFnFromModule(
89
+ 'requestAuthorization',
90
+ Promise.resolve(false),
91
+ )
92
+ export const deleteObjects = UnavailableFnFromModule(
93
+ 'deleteObjects',
94
+ Promise.resolve(0),
95
+ )
96
+ export const subscribeToChanges = UnavailableFnFromModule(
97
+ 'subscribeToChanges',
98
+ 'dummy-query-uuid',
99
+ ) // Mocking the observer query UUID
100
+ export const isProtectedDataAvailable = UnavailableFnFromModule(
101
+ 'isProtectedDataAvailable',
102
+ false,
103
+ )
104
+ export const isObjectTypeAvailable = UnavailableFnFromModule(
105
+ 'isObjectTypeAvailable',
106
+ false,
107
+ )
108
+ export const isObjectTypeAvailableAsync = UnavailableFnFromModule(
109
+ 'isObjectTypeAvailableAsync',
110
+ Promise.resolve(false),
111
+ )
112
+ export const areObjectTypesAvailable = UnavailableFnFromModule(
113
+ 'areObjectTypesAvailable',
114
+ {},
115
+ )
116
+ export const areObjectTypesAvailableAsync = UnavailableFnFromModule(
117
+ 'areObjectTypesAvailableAsync',
118
+ Promise.resolve({}),
119
+ )
120
+
121
+ // CharacteristicTypeModule functions
122
+ export const getBiologicalSex = UnavailableFnFromModule(
123
+ 'getBiologicalSex',
124
+ BiologicalSex.notSet,
125
+ )
126
+ export const getBloodType = UnavailableFnFromModule(
127
+ 'getBloodType',
128
+ BloodType.notSet,
129
+ )
130
+ export const getDateOfBirth = UnavailableFnFromModule(
131
+ 'getDateOfBirth',
132
+ new Date(0),
133
+ ) // Assuming string for date
134
+ export const getFitzpatrickSkinType = UnavailableFnFromModule(
135
+ 'getFitzpatrickSkinType',
136
+ FitzpatrickSkinType.notSet,
137
+ )
138
+ export const getWheelchairUse = UnavailableFnFromModule(
139
+ 'getWheelchairUse',
140
+ WheelchairUse.notSet,
141
+ )
142
+
143
+ // QuantityTypeModule functions
144
+ export const queryQuantitySamples = UnavailableFnFromModule(
145
+ 'queryQuantitySamples',
146
+ Promise.resolve([]),
147
+ )
148
+ export const queryQuantitySamplesWithAnchor = UnavailableFnFromModule(
149
+ 'queryQuantitySamplesWithAnchor',
150
+ Promise.resolve({
151
+ samples: [],
152
+ deletedSamples: [],
153
+ newAnchor: '',
154
+ }),
155
+ )
156
+ export const queryStatisticsForQuantity = UnavailableFnFromModule(
157
+ 'queryStatisticsForQuantity',
158
+ Promise.resolve({}),
159
+ )
160
+ export const queryStatisticsCollectionForQuantity = UnavailableFnFromModule(
161
+ 'queryStatisticsCollectionForQuantity',
162
+ Promise.resolve([]),
163
+ )
164
+ export const saveQuantitySample = UnavailableFnFromModule(
165
+ 'saveQuantitySample',
166
+ Promise.resolve(false),
167
+ )
168
+ export const isQuantityCompatibleWithUnit = UnavailableFnFromModule(
169
+ 'isQuantityCompatibleWithUnit',
170
+ false,
171
+ )
172
+
173
+ // CategoryTypeModule functions
174
+ export function queryCategorySamples<T extends CategoryTypeIdentifier>(
175
+ _categoryTypeIdentifier: T,
176
+ ): Promise<CategorySampleTyped<T>[]> {
177
+ if (Platform.OS !== 'ios' && !hasWarned) {
178
+ console.warn(notAvailableError)
179
+ hasWarned = true
180
+ }
181
+ return Promise.resolve([])
182
+ }
183
+
184
+ export function queryCategorySamplesWithAnchor<
185
+ T extends CategoryTypeIdentifier,
186
+ >(
187
+ _categoryTypeIdentifier: T,
188
+ ): Promise<CategorySamplesWithAnchorResponseTyped<T>> {
189
+ if (Platform.OS !== 'ios' && !hasWarned) {
190
+ console.warn(notAvailableError)
191
+ hasWarned = true
192
+ }
193
+ return Promise.resolve({
194
+ samples: [],
195
+ deletedSamples: [],
196
+ newAnchor: '',
197
+ })
198
+ }
199
+ export const saveCategorySample = UnavailableFnFromModule(
200
+ 'saveCategorySample',
201
+ Promise.resolve(false),
202
+ )
203
+
204
+ // CorrelationTypeModule functions
205
+ export const queryCorrelationSamples = UnavailableFnFromModule(
206
+ 'queryCorrelationSamples',
207
+ Promise.resolve([]),
208
+ )
209
+ export const saveCorrelationSample = UnavailableFnFromModule(
210
+ 'saveCorrelationSample',
211
+ Promise.resolve(false),
212
+ )
213
+
214
+ // HeartbeatSeriesModule functions
215
+ export const queryHeartbeatSeriesSamples = UnavailableFnFromModule(
216
+ 'queryHeartbeatSeriesSamples',
217
+ Promise.resolve([]),
218
+ )
219
+ export const queryHeartbeatSeriesSamplesWithAnchor = UnavailableFnFromModule(
220
+ 'queryHeartbeatSeriesSamplesWithAnchor',
221
+ Promise.resolve({
222
+ samples: [],
223
+ deletedSamples: [],
224
+ newAnchor: '',
225
+ }),
226
+ )
227
+
228
+ // WorkoutsModule functions
229
+ export const queryWorkoutSamples = UnavailableFnFromModule(
230
+ 'queryWorkoutSamples',
231
+ Promise.resolve([]),
232
+ )
233
+ export const queryWorkoutSamplesWithAnchor = UnavailableFnFromModule(
234
+ 'queryWorkoutSamplesWithAnchor',
235
+ Promise.resolve({
236
+ workouts: [],
237
+ deletedSamples: [],
238
+ newAnchor: '',
239
+ }),
240
+ )
241
+ export const saveWorkoutSample = UnavailableFnFromModule(
242
+ 'saveWorkoutSample',
243
+ Promise.resolve(''),
244
+ )
245
+ export const startWatchApp = UnavailableFnFromModule(
246
+ 'startWatchApp',
247
+ Promise.resolve(false),
248
+ )
249
+
250
+ // StateOfMindModule functions
251
+ export const queryStateOfMindSamples = UnavailableFnFromModule(
252
+ 'queryStateOfMindSamples',
253
+ Promise.resolve([]),
254
+ )
255
+ export const saveStateOfMindSample = UnavailableFnFromModule(
256
+ 'saveStateOfMindSample',
257
+ Promise.resolve(false),
258
+ )
259
+
260
+ // Utility functions (from original export list)
261
+ export function getMostRecentCategorySample<T extends CategoryTypeIdentifier>(
262
+ _identifier: T,
263
+ ): Promise<CategorySampleTyped<T> | undefined> {
264
+ if (Platform.OS !== 'ios' && !hasWarned) {
265
+ console.warn(notAvailableError)
266
+ hasWarned = true
267
+ }
268
+ return Promise.resolve(undefined)
269
+ }
270
+
271
+ export const getMostRecentQuantitySample = UnavailableFnFromModule(
272
+ 'getMostRecentQuantitySample',
273
+ // biome-ignore lint/suspicious/noExplicitAny: it works
274
+ Promise.resolve(undefined as any as QuantitySample),
275
+ )
276
+ export const getMostRecentWorkout = UnavailableFnFromModule(
277
+ 'getMostRecentWorkout',
278
+ // biome-ignore lint/suspicious/noExplicitAny: it works
279
+ Promise.resolve(undefined as any as WorkoutProxy),
280
+ )
281
+ export const getPreferredUnit = UnavailableFnFromModule(
282
+ 'getPreferredUnit',
283
+ Promise.resolve('count'),
284
+ ) // Defaulting to 'count'
285
+
286
+ // Hooks (from original export list)
287
+ export function useMostRecentCategorySample<T extends CategoryTypeIdentifier>(
288
+ _categoryTypeIdentifier: T,
289
+ ): CategorySampleTyped<T> | undefined {
290
+ if (Platform.OS !== 'ios' && !hasWarned) {
291
+ console.warn(notAvailableError)
292
+ hasWarned = true
293
+ }
294
+ return undefined
295
+ }
296
+
297
+ export const useMostRecentQuantitySample = UnavailableFnFromModule(
298
+ 'useMostRecentQuantitySample',
299
+ undefined,
300
+ )
301
+ export const useMostRecentWorkout = UnavailableFnFromModule(
302
+ 'useMostRecentWorkout',
303
+ undefined,
304
+ )
305
+ export const useSubscribeToChanges = UnavailableFnFromModule(
306
+ 'useSubscribeToChanges',
307
+ undefined,
308
+ ) // Mocking callback structure
309
+ export const useHealthkitAuthorization = UnavailableFnFromModule(
310
+ 'useHealthkitAuthorization',
311
+ [
312
+ AuthorizationRequestStatus.unknown,
313
+ () => Promise.resolve(AuthorizationRequestStatus.unknown),
314
+ ] as const,
315
+ )
316
+ export const useIsHealthDataAvailable = UnavailableFnFromModule(
317
+ 'useIsHealthDataAvailable',
318
+ false,
319
+ )
320
+ export const useSources = UnavailableFnFromModule('useSources', null)
321
+ export const useStatisticsForQuantity = UnavailableFnFromModule(
322
+ 'useStatisticsForQuantity',
323
+ null,
324
+ )
325
+
326
+ export const getBiologicalSexAsync = UnavailableFnFromModule(
327
+ 'getBiologicalSexAsync',
328
+ Promise.resolve(BiologicalSex.notSet),
329
+ )
330
+ export const getBloodTypeAsync = UnavailableFnFromModule(
331
+ 'getBloodTypeAsync',
332
+ Promise.resolve(BloodType.notSet),
333
+ )
334
+ export const getDateOfBirthAsync = UnavailableFnFromModule(
335
+ 'getDateOfBirthAsync',
336
+ Promise.resolve(new Date(0)),
337
+ ) // Assuming string for date
338
+ export const getFitzpatrickSkinTypeAsync = UnavailableFnFromModule(
339
+ 'getFitzpatrickSkinTypeAsync',
340
+ Promise.resolve(FitzpatrickSkinType.notSet),
341
+ )
342
+ export const getWheelchairUseAsync = UnavailableFnFromModule(
343
+ 'getWheelchairUseAsync',
344
+ Promise.resolve(WheelchairUse.notSet),
345
+ )
346
+
347
+ export const unsubscribeQueries = UnavailableFnFromModule(
348
+ 'unsubscribeQueries',
349
+ 0,
350
+ )
351
+
352
+ // --- Default Export ---
353
+ // This attempts to match the structure of the default export from index.ios.ts
354
+ const HealthkitModule = {
355
+ // All named exports are also part of the default export object
356
+ authorizationStatusFor,
357
+ isObjectTypeAvailable,
358
+ unsubscribeQueries,
359
+ isObjectTypeAvailableAsync,
360
+ areObjectTypesAvailable,
361
+ areObjectTypesAvailableAsync,
362
+ isQuantityCompatibleWithUnit,
363
+ disableAllBackgroundDelivery,
364
+ disableBackgroundDelivery,
365
+ enableBackgroundDelivery,
366
+ getBiologicalSex,
367
+ getBloodType,
368
+ getDateOfBirth,
369
+ getFitzpatrickSkinType,
370
+ getMostRecentCategorySample,
371
+ getMostRecentQuantitySample,
372
+ getMostRecentWorkout,
373
+ getPreferredUnits,
374
+ getPreferredUnit,
375
+ getRequestStatusForAuthorization,
376
+ getWheelchairUse,
377
+ isHealthDataAvailable,
378
+ isHealthDataAvailableAsync,
379
+ queryCategorySamples,
380
+ queryCategorySamplesWithAnchor,
381
+ queryCorrelationSamples,
382
+ queryHeartbeatSeriesSamples,
383
+ queryHeartbeatSeriesSamplesWithAnchor,
384
+ queryQuantitySamples,
385
+ queryQuantitySamplesWithAnchor,
386
+ queryStatisticsForQuantity,
387
+ queryStatisticsCollectionForQuantity,
388
+ queryWorkoutSamples,
389
+ queryWorkoutSamplesWithAnchor,
390
+ querySources,
391
+ requestAuthorization,
392
+ deleteObjects,
393
+ saveCategorySample,
394
+ saveCorrelationSample,
395
+ saveQuantitySample,
396
+ saveWorkoutSample,
397
+ subscribeToChanges,
398
+ startWatchApp,
399
+ isProtectedDataAvailable,
400
+ queryStateOfMindSamples,
401
+ saveStateOfMindSample,
402
+
403
+ // Hooks
404
+ useMostRecentCategorySample,
405
+ useMostRecentQuantitySample,
406
+ useMostRecentWorkout,
407
+ useSubscribeToChanges,
408
+ useHealthkitAuthorization,
409
+ useIsHealthDataAvailable,
410
+ useSources,
411
+ useStatisticsForQuantity,
412
+ getBiologicalSexAsync,
413
+ getBloodTypeAsync,
414
+ getDateOfBirthAsync,
415
+ getFitzpatrickSkinTypeAsync,
416
+ getWheelchairUseAsync,
417
+ } as Omit<typeof ReactNativeHealthkit, 'default'>
418
+
419
+ export default {
420
+ ...HealthkitModule,
421
+ default: HealthkitModule,
422
+ } as typeof ReactNativeHealthkit
@@ -13,8 +13,8 @@ import type {
13
13
  * @see {@link https://developer.apple.com/documentation/healthkit/authorizing_access_to_health_data Apple Docs - Authorizing access to health data}
14
14
  */
15
15
  export const useHealthkitAuthorization = (
16
- read: ObjectTypeIdentifier[],
17
- write?: SampleTypeIdentifierWriteable[],
16
+ read: readonly ObjectTypeIdentifier[],
17
+ write?: readonly SampleTypeIdentifierWriteable[],
18
18
  ) => {
19
19
  const [status, setStatus] = useState<AuthorizationRequestStatus | null>(null)
20
20
 
@@ -1,13 +1,11 @@
1
1
  import { useCallback, useEffect, useRef, useState } from 'react'
2
-
3
- import useSubscribeToChanges from './useSubscribeToChanges'
4
-
5
2
  import { QuantityTypes } from '../modules'
6
3
  import type {
7
4
  QueryStatisticsResponse,
8
5
  StatisticsOptions,
9
6
  } from '../types/QuantityType'
10
7
  import type { QuantityTypeIdentifier } from '../types/QuantityTypeIdentifier'
8
+ import useSubscribeToChanges from './useSubscribeToChanges'
11
9
 
12
10
  export function useStatisticsForQuantity<
13
11
  TIdentifier extends QuantityTypeIdentifier,