@tryvital/vital-health-react-native 0.1.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.
package/.editorconfig ADDED
@@ -0,0 +1,15 @@
1
+ # EditorConfig helps developers define and maintain consistent
2
+ # coding styles between different editors and IDEs
3
+ # editorconfig.org
4
+
5
+ root = true
6
+
7
+ [*]
8
+
9
+ indent_style = space
10
+ indent_size = 2
11
+
12
+ end_of_line = lf
13
+ charset = utf-8
14
+ trim_trailing_whitespace = true
15
+ insert_final_newline = true
package/.gitattributes ADDED
@@ -0,0 +1,3 @@
1
+ *.pbxproj -text
2
+ # specific for windows script files
3
+ *.bat text eol=crlf
package/.gitignore ADDED
@@ -0,0 +1,70 @@
1
+ # OSX
2
+ #
3
+ .DS_Store
4
+
5
+ # XDE
6
+ .expo/
7
+
8
+ # VSCode
9
+ .vscode/
10
+ jsconfig.json
11
+
12
+ # Xcode
13
+ #
14
+ build/
15
+ *.pbxuser
16
+ !default.pbxuser
17
+ *.mode1v3
18
+ !default.mode1v3
19
+ *.mode2v3
20
+ !default.mode2v3
21
+ *.perspectivev3
22
+ !default.perspectivev3
23
+ xcuserdata
24
+ *.xccheckout
25
+ *.moved-aside
26
+ DerivedData
27
+ *.hmap
28
+ *.ipa
29
+ *.xcuserstate
30
+ project.xcworkspace
31
+
32
+ # Android/IJ
33
+ #
34
+ .classpath
35
+ .cxx
36
+ .gradle
37
+ .idea
38
+ .project
39
+ .settings
40
+ local.properties
41
+ android.iml
42
+
43
+ # Cocoapods
44
+ #
45
+ example/ios/Pods
46
+
47
+ # Ruby
48
+ example/vendor/
49
+
50
+ # node.js
51
+ #
52
+ node_modules/
53
+ npm-debug.log
54
+ yarn-debug.log
55
+ yarn-error.log
56
+
57
+ # BUCK
58
+ buck-out/
59
+ \.buckd/
60
+ android/app/libs
61
+ android/keystores/debug.keystore
62
+
63
+ # Expo
64
+ .expo/
65
+
66
+ # Turborepo
67
+ .turbo/
68
+
69
+ # generated by bob
70
+ lib/
@@ -0,0 +1 @@
1
+ {}
package/.yarnrc ADDED
@@ -0,0 +1,3 @@
1
+ # Override Yarn command so we can automatically setup the repo on running `yarn`
2
+
3
+ yarn-path "scripts/bootstrap.js"
package/LICENSE ADDED
@@ -0,0 +1 @@
1
+ todo
package/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # vital-health-react-native
2
+
3
+ todo
4
+
5
+ ## Installation
6
+
7
+ ```sh
8
+ npm install vital-health-react-native
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```js
14
+ import { multiply } from 'vital-health-react-native';
15
+
16
+ // ...
17
+
18
+ const result = await multiply(3, 7);
19
+ ```
20
+
21
+ ## Contributing
22
+
23
+ See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
24
+
25
+ ## License
26
+
27
+ MIT
28
+
29
+ ---
30
+
31
+ Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
@@ -0,0 +1,146 @@
1
+ buildscript {
2
+ // Buildscript is evaluated before everything else so we can't use getExtOrDefault
3
+ def kotlin_version = rootProject.ext.has('kotlinVersion') ? rootProject.ext.get('kotlinVersion') : project.properties['VitalHealthReactNative_kotlinVersion']
4
+
5
+ repositories {
6
+ google()
7
+ mavenCentral()
8
+ }
9
+
10
+ dependencies {
11
+ classpath 'com.android.tools.build:gradle:3.5.3'
12
+ // noinspection DifferentKotlinGradleVersion
13
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14
+ }
15
+ }
16
+
17
+ def isNewArchitectureEnabled() {
18
+ return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
19
+ }
20
+
21
+ apply plugin: 'com.android.library'
22
+ apply plugin: 'kotlin-android'
23
+
24
+ if (isNewArchitectureEnabled()) {
25
+ apply plugin: 'com.facebook.react'
26
+ }
27
+
28
+ def getExtOrDefault(name) {
29
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['VitalHealthReactNative_' + name]
30
+ }
31
+
32
+ def getExtOrIntegerDefault(name) {
33
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['VitalHealthReactNative_' + name]).toInteger()
34
+ }
35
+
36
+ android {
37
+ compileSdkVersion getExtOrIntegerDefault('compileSdkVersion')
38
+
39
+ defaultConfig {
40
+ minSdkVersion getExtOrIntegerDefault('minSdkVersion')
41
+ targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
42
+ buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
43
+ }
44
+ buildTypes {
45
+ release {
46
+ minifyEnabled false
47
+ }
48
+ }
49
+
50
+ lintOptions {
51
+ disable 'GradleCompatible'
52
+ }
53
+
54
+ compileOptions {
55
+ sourceCompatibility JavaVersion.VERSION_1_8
56
+ targetCompatibility JavaVersion.VERSION_1_8
57
+ }
58
+
59
+ }
60
+
61
+ repositories {
62
+ mavenCentral()
63
+ google()
64
+
65
+ def found = false
66
+ def defaultDir = null
67
+ def androidSourcesName = 'React Native sources'
68
+
69
+ if (rootProject.ext.has('reactNativeAndroidRoot')) {
70
+ defaultDir = rootProject.ext.get('reactNativeAndroidRoot')
71
+ } else {
72
+ defaultDir = new File(
73
+ projectDir,
74
+ '/../../../node_modules/react-native/android'
75
+ )
76
+ }
77
+
78
+ if (defaultDir.exists()) {
79
+ maven {
80
+ url defaultDir.toString()
81
+ name androidSourcesName
82
+ }
83
+
84
+ logger.info(":${project.name}:reactNativeAndroidRoot ${defaultDir.canonicalPath}")
85
+ found = true
86
+ } else {
87
+ def parentDir = rootProject.projectDir
88
+
89
+ 1.upto(5, {
90
+ if (found) return true
91
+ parentDir = parentDir.parentFile
92
+
93
+ def androidSourcesDir = new File(
94
+ parentDir,
95
+ 'node_modules/react-native'
96
+ )
97
+
98
+ def androidPrebuiltBinaryDir = new File(
99
+ parentDir,
100
+ 'node_modules/react-native/android'
101
+ )
102
+
103
+ if (androidPrebuiltBinaryDir.exists()) {
104
+ maven {
105
+ url androidPrebuiltBinaryDir.toString()
106
+ name androidSourcesName
107
+ }
108
+
109
+ logger.info(":${project.name}:reactNativeAndroidRoot ${androidPrebuiltBinaryDir.canonicalPath}")
110
+ found = true
111
+ } else if (androidSourcesDir.exists()) {
112
+ maven {
113
+ url androidSourcesDir.toString()
114
+ name androidSourcesName
115
+ }
116
+
117
+ logger.info(":${project.name}:reactNativeAndroidRoot ${androidSourcesDir.canonicalPath}")
118
+ found = true
119
+ }
120
+ })
121
+ }
122
+
123
+ if (!found) {
124
+ throw new GradleException(
125
+ "${project.name}: unable to locate React Native android sources. " +
126
+ "Ensure you have you installed React Native as a dependency in your project and try again."
127
+ )
128
+ }
129
+ }
130
+
131
+ def kotlin_version = getExtOrDefault('kotlinVersion')
132
+
133
+ dependencies {
134
+ //noinspection GradleDynamicVersion
135
+ implementation "com.facebook.react:react-native:+"
136
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
137
+ // From node_modules
138
+ }
139
+
140
+ if (isNewArchitectureEnabled()) {
141
+ react {
142
+ jsRootDir = file("../src/")
143
+ libraryName = "VitalHealthReactNative"
144
+ codegenJavaPackageName = "com.vitalhealthreactnative"
145
+ }
146
+ }
@@ -0,0 +1,5 @@
1
+ VitalHealthReactNative_kotlinVersion=1.7.0
2
+ VitalHealthReactNative_minSdkVersion=21
3
+ VitalHealthReactNative_targetSdkVersion=31
4
+ VitalHealthReactNative_compileSdkVersion=31
5
+ VitalHealthReactNative_ndkversion=21.4.7075529
@@ -0,0 +1,4 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+ package="com.vitalhealthreactnative">
3
+
4
+ </manifest>
@@ -0,0 +1,25 @@
1
+ package com.vitalhealthreactnative
2
+
3
+ import com.facebook.react.bridge.ReactApplicationContext
4
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
5
+ import com.facebook.react.bridge.ReactMethod
6
+ import com.facebook.react.bridge.Promise
7
+
8
+ class VitalHealthReactNativeModule(reactContext: ReactApplicationContext) :
9
+ ReactContextBaseJavaModule(reactContext) {
10
+
11
+ override fun getName(): String {
12
+ return NAME
13
+ }
14
+
15
+ // Example method
16
+ // See https://reactnative.dev/docs/native-modules-android
17
+ @ReactMethod
18
+ fun multiply(a: Double, b: Double, promise: Promise) {
19
+ promise.resolve(a * b)
20
+ }
21
+
22
+ companion object {
23
+ const val NAME = "VitalHealthReactNative"
24
+ }
25
+ }
@@ -0,0 +1,17 @@
1
+ package com.vitalhealthreactnative
2
+
3
+ import com.facebook.react.ReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.uimanager.ViewManager
7
+
8
+
9
+ class VitalHealthReactNativePackage : ReactPackage {
10
+ override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
11
+ return listOf(VitalHealthReactNativeModule(reactContext))
12
+ }
13
+
14
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
15
+ return emptyList()
16
+ }
17
+ }
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ presets: ['module:metro-react-native-babel-preset'],
3
+ };
@@ -0,0 +1,2 @@
1
+ #import <React/RCTBridgeModule.h>
2
+ #import <React/RCTViewManager.h>
@@ -0,0 +1,31 @@
1
+ #import <React/RCTBridgeModule.h>
2
+
3
+ @interface RCT_EXTERN_MODULE(VitalHealthReactNative, NSObject)
4
+
5
+ RCT_EXTERN_METHOD(configure:(BOOL)backgroundDeliveryEnabled
6
+ numberOfDaysToBackFill:(int)numberOfDaysToBackFill
7
+ enableLogs:(BOOL)enableLogs
8
+ resolver:(RCTPromiseResolveBlock)resolve
9
+ rejecter:(RCTPromiseRejectBlock)reject)
10
+
11
+ RCT_EXTERN_METHOD(askForResources:(NSArray<NSString *> *)resources
12
+ resolver:(RCTPromiseResolveBlock)resolve
13
+ rejecter:(RCTPromiseRejectBlock)reject)
14
+
15
+ RCT_EXTERN_METHOD(cleanUp:(RCTPromiseResolveBlock)resolve
16
+ rejecter:(RCTPromiseRejectBlock)reject)
17
+
18
+ RCT_EXTERN_METHOD(hasAskedForPermission:(NSString *)resource
19
+ resolver:(RCTPromiseResolveBlock)resolve
20
+ rejecter:(RCTPromiseRejectBlock)reject)
21
+
22
+ RCT_EXTERN_METHOD(syncData:(NSArray<NSString *> *)resources
23
+ resolver:(RCTPromiseResolveBlock)resolve
24
+ rejecter:(RCTPromiseRejectBlock)reject)
25
+
26
+ + (BOOL)requiresMainQueueSetup
27
+ {
28
+ return NO;
29
+ }
30
+
31
+ @end
@@ -0,0 +1,138 @@
1
+ import VitalCore
2
+ import VitalHealthKit
3
+
4
+ @objc(VitalHealthReactNative)
5
+ class VitalHealthReactNative: NSObject {
6
+
7
+ @objc(configure:numberOfDaysToBackFill:enableLogs:resolver:rejecter:)
8
+ func configure(
9
+ _ backgroundDeliveryEnabled: Bool,
10
+ numberOfDaysToBackFill: Int,
11
+ enableLogs: Bool,
12
+ resolve: @escaping RCTPromiseResolveBlock,
13
+ reject: RCTPromiseRejectBlock
14
+ ) {
15
+ Task {
16
+ await VitalHealthKitClient.configure(
17
+ .init(
18
+ backgroundDeliveryEnabled: backgroundDeliveryEnabled,
19
+ logsEnabled: enableLogs,
20
+ numberOfDaysToBackFill: numberOfDaysToBackFill
21
+ )
22
+ )
23
+ resolve(())
24
+ }
25
+ }
26
+
27
+
28
+ @objc(askForResources:resolver:rejecter:)
29
+ func askForResources(
30
+ _ resources: [String],
31
+ resolve: @escaping RCTPromiseResolveBlock,
32
+ reject: @escaping RCTPromiseRejectBlock
33
+ ) {
34
+ Task {
35
+ do {
36
+ let outcome = try await VitalHealthKitClient.shared.ask(for: resources.map { try mapResourceToVitalResource($0) })
37
+ switch outcome {
38
+ case .success:
39
+ resolve("success")
40
+ case .failure(let message):
41
+ reject("failure", message, nil)
42
+ case .healthKitNotAvailable:
43
+ reject("healthKitNotAvailable", "healthKitNotAvailable", nil)
44
+ }
45
+ } catch VitalError.UnsupportedResource(let errorMessage) {
46
+ reject("UnsupportedResource", errorMessage, nil)
47
+ } catch {
48
+ reject(nil, "Unknown error", nil)
49
+ }
50
+ }
51
+ }
52
+
53
+ @objc(syncData:resolver:rejecter:)
54
+ func syncData(
55
+ _ resources: [String],
56
+ resolve: RCTPromiseResolveBlock,
57
+ reject: RCTPromiseRejectBlock
58
+ ) {
59
+ do {
60
+ try VitalHealthKitClient.shared.syncData(for: resources.map { try mapResourceToVitalResource($0) })
61
+ resolve(())
62
+ } catch VitalError.UnsupportedResource(let errorMessage) {
63
+ reject("UnsupportedResource", errorMessage, nil)
64
+ } catch {
65
+ reject(nil, "Unknown error", nil)
66
+ }
67
+ }
68
+
69
+ @objc(cleanUp:rejecter:)
70
+ func cleanUp(_ resolve: @escaping RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) {
71
+ Task {
72
+ await VitalHealthKitClient.shared.cleanUp()
73
+ resolve(())
74
+ }
75
+ }
76
+
77
+ @objc(hasAskedForPermission:resolver:rejecter:)
78
+ func hasAskedForPermission(_ resource: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
79
+ do {
80
+ let vitalResource = try mapResourceToVitalResource(resource)
81
+ let value: Bool = VitalHealthKitClient.shared.hasAskedForPermission(resource: vitalResource)
82
+ resolve(value)
83
+ } catch VitalError.UnsupportedResource(let errorMessage) {
84
+ reject("UnsupportedResource", errorMessage, nil)
85
+ } catch {
86
+ reject(nil, "Unknown error", nil)
87
+ }
88
+ }
89
+ }
90
+
91
+ private func mapResourceToVitalResource(_ name: String) throws -> VitalResource {
92
+ switch name {
93
+ case "profile":
94
+ return .profile
95
+ case "body":
96
+ return .body
97
+ case "workout":
98
+ return .workout
99
+ case "activity":
100
+ return .activity
101
+ case "sleep":
102
+ return .sleep
103
+ case "glucose":
104
+ return .vitals(.glucose)
105
+ case "bloodPressure":
106
+ return .vitals(.bloodPressure)
107
+ case "heartRate":
108
+ return .vitals(.hearthRate)
109
+ case "steps":
110
+ return .individual(.steps)
111
+ case "activeEnergyBurned":
112
+ return .individual(.activeEnergyBurned)
113
+ case "basalEnergyBurned":
114
+ return .individual(.basalEnergyBurned)
115
+ case "floorsClimbed":
116
+ return .individual(.floorsClimbed)
117
+ case "distanceWalkingRunning":
118
+ return .individual(.distanceWalkingRunning)
119
+ case "vo2Max":
120
+ return .individual(.vo2Max)
121
+ case "weight":
122
+ return .individual(.weight)
123
+ case "bodyFat":
124
+ return .individual(.bodyFat)
125
+ default:
126
+ throw VitalError.UnsupportedResource(name)
127
+ }
128
+ }
129
+
130
+ enum VitalError: Error {
131
+ case UnsupportedRegion(String)
132
+ case UnsupportedEnvironment(String)
133
+ case UnsupportedResource(String)
134
+ case UnsupportedDataPushMode(String)
135
+ case UnsupportedProvider(String)
136
+ case UnsupportedBrand(String)
137
+ case UnsupportedKind(String)
138
+ }