airborne-react-native 0.1.0 → 0.3.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/AirborneReact.podspec +4 -1
- package/README.md +6 -6
- package/android/build.gradle +30 -1
- package/android/gradle.properties +1 -1
- package/android/src/latest/java/in/juspay/airborneplugin/AirborneReactHostDelegate.kt +65 -0
- package/android/src/main/AndroidManifest.xml +4 -2
- package/android/src/main/java/in/juspay/airborneplugin/Airborne.kt +53 -19
- package/android/src/main/java/in/juspay/airborneplugin/AirborneInterface.kt +2 -6
- package/android/src/main/java/in/juspay/airborneplugin/AirborneModule.kt +6 -6
- package/android/src/main/java/in/juspay/airborneplugin/AirborneModuleImpl.kt +6 -6
- package/android/src/main/java/in/juspay/airborneplugin/AirbornePackage.kt +25 -25
- package/android/src/main/java/in/juspay/airborneplugin/AirborneReactActivityDelegate.kt +81 -0
- package/android/src/main/java/in/juspay/airborneplugin/AirborneReactNativeHost.kt +49 -0
- package/android/src/main/java/in/juspay/airborneplugin/AirborneTurboModule.kt +7 -7
- package/android/src/main/res/raw/juspay_airborne_react_res.xml +1 -0
- package/android/src/rn77/java/in/juspay/airborneplugin/AirborneReactHostDelegate.kt +71 -0
- package/ios/Airborne.h +13 -5
- package/ios/Airborne.mm +27 -22
- package/ios/AirborneiOS.h +72 -9
- package/ios/AirborneiOS.m +90 -98
- package/lib/module/index.js +6 -6
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/NativeAirborne.d.ts +3 -3
- package/lib/typescript/src/NativeAirborne.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +3 -3
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +4 -1
- package/src/NativeAirborne.ts +3 -3
- package/src/index.tsx +6 -6
- package/lib/typescript/ExampleOldArch/App.d.ts +0 -4
- package/lib/typescript/ExampleOldArch/App.d.ts.map +0 -1
package/AirborneReact.podspec
CHANGED
|
@@ -33,7 +33,10 @@ Pod::Spec.new do |s|
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
s.source_files = "ios/**/*.{h,m,mm,cpp}"
|
|
36
|
-
s.
|
|
36
|
+
s.public_header_files = "ios/**/*.h"
|
|
37
|
+
s.static_framework = false
|
|
38
|
+
|
|
39
|
+
s.dependency "Airborne", "0.0.4"
|
|
37
40
|
|
|
38
41
|
install_modules_dependencies(s)
|
|
39
42
|
end
|
package/README.md
CHANGED
|
@@ -53,9 +53,9 @@ This implementation provides a React Native module for Airborne that:
|
|
|
53
53
|
|
|
54
54
|
## API Methods
|
|
55
55
|
|
|
56
|
-
1. **readReleaseConfig()** - Returns the release configuration as a stringified JSON
|
|
57
|
-
2. **getFileContent(filePath)** - Reads content from a file in the OTA bundle
|
|
58
|
-
3. **getBundlePath()** - Returns the path to the JavaScript bundle
|
|
56
|
+
1. **readReleaseConfig(namespace/appId)** - Returns the release configuration as a stringified JSON
|
|
57
|
+
2. **getFileContent(namespace/appId, filePath)** - Reads content from a file in the OTA bundle
|
|
58
|
+
3. **getBundlePath(namespace/appId)** - Returns the path to the JavaScript bundle
|
|
59
59
|
|
|
60
60
|
## Usage
|
|
61
61
|
|
|
@@ -68,13 +68,13 @@ This implementation provides a React Native module for Airborne that:
|
|
|
68
68
|
import { readReleaseConfig, getFileContent, getBundlePath } from 'airborne-react-native';
|
|
69
69
|
|
|
70
70
|
// Read configuration
|
|
71
|
-
const config = await readReleaseConfig();
|
|
71
|
+
const config = await readReleaseConfig(namespace/appId);
|
|
72
72
|
|
|
73
73
|
// Get file content
|
|
74
|
-
const content = await getFileContent('path/to/file.json');
|
|
74
|
+
const content = await getFileContent(namespace/appId, 'path/to/file.json');
|
|
75
75
|
|
|
76
76
|
// Get bundle path
|
|
77
|
-
const bundlePath = await getBundlePath();
|
|
77
|
+
const bundlePath = await getBundlePath(namespace/appId);
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
## Implementation Notes
|
package/android/build.gradle
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
// limitations under the License.
|
|
14
14
|
|
|
15
15
|
import com.android.Version
|
|
16
|
+
import groovy.json.JsonSlurper
|
|
16
17
|
|
|
17
18
|
buildscript {
|
|
18
19
|
ext.getExtOrDefault = { name ->
|
|
@@ -35,6 +36,22 @@ def isNewArchitectureEnabled() {
|
|
|
35
36
|
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
|
|
36
37
|
}
|
|
37
38
|
|
|
39
|
+
def findReactNativeVersion() {
|
|
40
|
+
// Locate app's node_modules/react-native/package.json
|
|
41
|
+
def packageJson = file("${rootProject.projectDir}/../node_modules/react-native/package.json")
|
|
42
|
+
if (!packageJson.exists()) {
|
|
43
|
+
packageJson = file("${rootProject.projectDir}/node_modules/react-native/package.json")
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!packageJson.exists()) {
|
|
47
|
+
println("[AirborneReact] Could not find react-native/package.json. Defaulting to latest.")
|
|
48
|
+
return "999.0.0"
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
def json = new JsonSlurper().parseText(packageJson.text)
|
|
52
|
+
return json.version
|
|
53
|
+
}
|
|
54
|
+
|
|
38
55
|
apply plugin: "com.android.library"
|
|
39
56
|
apply plugin: "kotlin-android"
|
|
40
57
|
|
|
@@ -67,6 +84,18 @@ android {
|
|
|
67
84
|
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
68
85
|
}
|
|
69
86
|
|
|
87
|
+
sourceSets {
|
|
88
|
+
main {
|
|
89
|
+
java.srcDirs = ["src/main/java"]
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (findReactNativeVersion().tokenize('.')[1].toInteger() >= 78) {
|
|
94
|
+
sourceSets.main.java.srcDirs += "src/latest/java"
|
|
95
|
+
} else {
|
|
96
|
+
sourceSets.main.java.srcDirs += "src/rn77/java"
|
|
97
|
+
}
|
|
98
|
+
|
|
70
99
|
buildFeatures {
|
|
71
100
|
buildConfig true
|
|
72
101
|
}
|
|
@@ -114,7 +143,7 @@ dependencies {
|
|
|
114
143
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
115
144
|
|
|
116
145
|
// Airborne SDK dependency
|
|
117
|
-
api "in.juspay:airborne:
|
|
146
|
+
api "in.juspay:airborne:2.2.5-xota.03"
|
|
118
147
|
}
|
|
119
148
|
|
|
120
149
|
react {
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
package `in`.juspay.airborneplugin
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import com.facebook.react.JSEngineResolutionAlgorithm
|
|
6
|
+
import com.facebook.react.ReactNativeHost
|
|
7
|
+
import com.facebook.react.ReactPackage
|
|
8
|
+
import com.facebook.react.ReactPackageTurboModuleManagerDelegate
|
|
9
|
+
import com.facebook.react.bridge.JSBundleLoader
|
|
10
|
+
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
|
11
|
+
import com.facebook.react.defaults.DefaultTurboModuleManagerDelegate
|
|
12
|
+
import com.facebook.react.runtime.BindingsInstaller
|
|
13
|
+
import com.facebook.react.runtime.JSCInstance
|
|
14
|
+
import com.facebook.react.runtime.JSRuntimeFactory
|
|
15
|
+
import com.facebook.react.runtime.ReactHostDelegate
|
|
16
|
+
import com.facebook.react.runtime.hermes.HermesInstance
|
|
17
|
+
import java.lang.ref.WeakReference
|
|
18
|
+
|
|
19
|
+
@OptIn(UnstableReactNativeAPI::class)
|
|
20
|
+
class AirborneReactHostDelegate(
|
|
21
|
+
private val weakContext: WeakReference<Context>,
|
|
22
|
+
private val reactNativeHostWrapper: ReactNativeHost,
|
|
23
|
+
override val bindingsInstaller: BindingsInstaller? = null,
|
|
24
|
+
override val turboModuleManagerDelegateBuilder: ReactPackageTurboModuleManagerDelegate.Builder =
|
|
25
|
+
DefaultTurboModuleManagerDelegate.Builder()
|
|
26
|
+
) : ReactHostDelegate {
|
|
27
|
+
|
|
28
|
+
override val jsBundleLoader: JSBundleLoader
|
|
29
|
+
get() {
|
|
30
|
+
val bundleName =
|
|
31
|
+
(reactNativeHostWrapper as AirborneReactNativeHost).jsBundleFile
|
|
32
|
+
bundleName?.let {
|
|
33
|
+
return if (bundleName.startsWith("assets://")) {
|
|
34
|
+
JSBundleLoader.createAssetLoader(
|
|
35
|
+
weakContext.get(),
|
|
36
|
+
bundleName,
|
|
37
|
+
false
|
|
38
|
+
)
|
|
39
|
+
} else {
|
|
40
|
+
JSBundleLoader.createFileLoader(bundleName)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return JSBundleLoader.createAssetLoader(
|
|
44
|
+
weakContext.get(),
|
|
45
|
+
"assets://index.android.bundle",
|
|
46
|
+
false
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
override val jsMainModulePath: String
|
|
51
|
+
get() = (reactNativeHostWrapper as AirborneReactNativeHost).jsMainModuleName
|
|
52
|
+
|
|
53
|
+
override val jsRuntimeFactory: JSRuntimeFactory
|
|
54
|
+
get() = if ((reactNativeHostWrapper as AirborneReactNativeHost).jsEngineResolutionAlgorithm == JSEngineResolutionAlgorithm.HERMES) {
|
|
55
|
+
HermesInstance()
|
|
56
|
+
} else {
|
|
57
|
+
JSCInstance()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
override val reactPackages: List<ReactPackage>
|
|
61
|
+
get() = (reactNativeHostWrapper as AirborneReactNativeHost).packages
|
|
62
|
+
|
|
63
|
+
override fun handleInstanceException(error: Exception) {
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -5,11 +5,11 @@ import androidx.annotation.Keep
|
|
|
5
5
|
import `in`.juspay.airborne.HyperOTAServices
|
|
6
6
|
import `in`.juspay.airborne.LazyDownloadCallback
|
|
7
7
|
import `in`.juspay.airborne.TrackerCallback
|
|
8
|
-
import `in`.juspay.
|
|
8
|
+
import `in`.juspay.hyperutil.constants.LogLevel
|
|
9
9
|
import org.json.JSONObject
|
|
10
10
|
|
|
11
11
|
@Keep
|
|
12
|
-
class Airborne
|
|
12
|
+
class Airborne(
|
|
13
13
|
context: Context,
|
|
14
14
|
releaseConfigUrl: String,
|
|
15
15
|
private val airborneInterface: AirborneInterface
|
|
@@ -50,23 +50,27 @@ class Airborne (
|
|
|
50
50
|
"",
|
|
51
51
|
releaseConfigUrl,
|
|
52
52
|
trackerCallback,
|
|
53
|
-
|
|
53
|
+
this::bootComplete
|
|
54
54
|
)
|
|
55
55
|
|
|
56
56
|
private val applicationManager = hyperOTAServices.createApplicationManager(airborneInterface.getDimensions())
|
|
57
57
|
|
|
58
58
|
init {
|
|
59
|
-
|
|
59
|
+
airborneObjectMap.put(airborneInterface.getNamespace(), this)
|
|
60
60
|
applicationManager.loadApplication(airborneInterface.getNamespace(), airborneInterface.getLazyDownloadCallback())
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
private fun bootComplete(filePath: String) {
|
|
64
|
+
airborneInterface.startApp(filePath.ifEmpty { "assets://${applicationManager.getBundledIndexPath().ifEmpty { "index.android.bundle" }}" })
|
|
65
|
+
}
|
|
66
|
+
|
|
63
67
|
/**
|
|
64
68
|
* @return The path of the index bundle, or asset path fallback if empty.
|
|
65
69
|
*/
|
|
66
70
|
@Keep
|
|
67
71
|
fun getBundlePath(): String {
|
|
68
72
|
val filePath = applicationManager.getIndexBundlePath()
|
|
69
|
-
return filePath.ifEmpty { "assets://${
|
|
73
|
+
return filePath.ifEmpty { "assets://${applicationManager.getBundledIndexPath().ifEmpty { "index.android.bundle" }}" }
|
|
70
74
|
}
|
|
71
75
|
|
|
72
76
|
/**
|
|
@@ -88,16 +92,46 @@ class Airborne (
|
|
|
88
92
|
}
|
|
89
93
|
|
|
90
94
|
companion object {
|
|
91
|
-
private var initializer: (() -> Airborne)? = null
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Lazily initialized singleton instance.
|
|
95
|
-
*/
|
|
96
|
-
@JvmStatic
|
|
97
|
-
val instance: Airborne by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
|
|
98
|
-
initializer?.invoke()
|
|
99
|
-
?: throw IllegalStateException("
|
|
100
|
-
}
|
|
95
|
+
// private var initializer: (() -> Airborne)? = null
|
|
96
|
+
//
|
|
97
|
+
// /**
|
|
98
|
+
// * Lazily initialized singleton instance.
|
|
99
|
+
// */
|
|
100
|
+
// @JvmStatic
|
|
101
|
+
// val instance: Airborne by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
|
|
102
|
+
// initializer?.invoke()
|
|
103
|
+
// ?: throw IllegalStateException("AirborneReact initializer not set. Call init() first.")
|
|
104
|
+
// }
|
|
105
|
+
//
|
|
106
|
+
// /**
|
|
107
|
+
// * Initializes the AirborneReact singleton.
|
|
108
|
+
// */
|
|
109
|
+
// @JvmStatic
|
|
110
|
+
// fun init(
|
|
111
|
+
// context: Context,
|
|
112
|
+
// appId: String,
|
|
113
|
+
// indexFileName: String,
|
|
114
|
+
// appVersion: String,
|
|
115
|
+
// releaseConfigTemplateUrl: String,
|
|
116
|
+
// headers: Map<String, String>? = null,
|
|
117
|
+
// lazyDownloadCallback: LazyDownloadCallback? = null,
|
|
118
|
+
// trackerCallback: TrackerCallback? = null
|
|
119
|
+
// ) {
|
|
120
|
+
// initializer = {
|
|
121
|
+
// Airborne(
|
|
122
|
+
// context,
|
|
123
|
+
// appId,
|
|
124
|
+
// indexFileName,
|
|
125
|
+
// appVersion,
|
|
126
|
+
// releaseConfigTemplateUrl,
|
|
127
|
+
// headers,
|
|
128
|
+
// lazyDownloadCallback ?: defaultLazyCallback,
|
|
129
|
+
// trackerCallback ?: defaultTrackerCallback
|
|
130
|
+
// )
|
|
131
|
+
// }
|
|
132
|
+
// }
|
|
133
|
+
|
|
134
|
+
public val airborneObjectMap: MutableMap<String, Airborne> = mutableMapOf()
|
|
101
135
|
|
|
102
136
|
/**
|
|
103
137
|
* Default LazyDownloadCallback implementation.
|
|
@@ -106,18 +140,18 @@ class Airborne (
|
|
|
106
140
|
override fun fileInstalled(filePath: String, success: Boolean) {
|
|
107
141
|
// Default implementation: log the file installation status
|
|
108
142
|
if (success) {
|
|
109
|
-
println("
|
|
143
|
+
println("AirborneReact: File installed successfully: $filePath")
|
|
110
144
|
} else {
|
|
111
|
-
println("
|
|
145
|
+
println("AirborneReact: File installation failed: $filePath")
|
|
112
146
|
}
|
|
113
147
|
}
|
|
114
148
|
|
|
115
149
|
override fun lazySplitsInstalled(success: Boolean) {
|
|
116
150
|
// Default implementation: log the lazy splits installation status
|
|
117
151
|
if (success) {
|
|
118
|
-
println("
|
|
152
|
+
println("AirborneReact: Lazy splits installed successfully")
|
|
119
153
|
} else {
|
|
120
|
-
println("
|
|
154
|
+
println("AirborneReact: Lazy splits installation failed")
|
|
121
155
|
}
|
|
122
156
|
}
|
|
123
157
|
}
|
|
@@ -6,18 +6,14 @@ import org.json.JSONObject
|
|
|
6
6
|
|
|
7
7
|
abstract class AirborneInterface {
|
|
8
8
|
open fun getNamespace(): String {
|
|
9
|
-
return "
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
open fun getIndexBundlePath(): String {
|
|
13
|
-
return "index.android.bundle"
|
|
9
|
+
return "airborne-example"
|
|
14
10
|
}
|
|
15
11
|
|
|
16
12
|
open fun getDimensions(): HashMap<String, String> {
|
|
17
13
|
return hashMapOf()
|
|
18
14
|
}
|
|
19
15
|
|
|
20
|
-
open fun
|
|
16
|
+
open fun startApp(indexPath: String) {
|
|
21
17
|
}
|
|
22
18
|
|
|
23
19
|
open fun onEvent(level: String, label: String, key: String, value: JSONObject, category: String, subCategory: String) {
|
|
@@ -17,18 +17,18 @@ class AirborneModule(reactContext: ReactApplicationContext) :
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
@ReactMethod
|
|
20
|
-
fun readReleaseConfig(promise: Promise) {
|
|
21
|
-
implementation.readReleaseConfig(promise)
|
|
20
|
+
fun readReleaseConfig(namespace: String, promise: Promise) {
|
|
21
|
+
implementation.readReleaseConfig(namespace, promise)
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
@ReactMethod
|
|
25
|
-
fun getFileContent(filePath: String, promise: Promise) {
|
|
26
|
-
implementation.getFileContent(filePath, promise)
|
|
25
|
+
fun getFileContent(namespace: String, filePath: String, promise: Promise) {
|
|
26
|
+
implementation.getFileContent(namespace, filePath, promise)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
@ReactMethod
|
|
30
|
-
fun getBundlePath(promise: Promise) {
|
|
31
|
-
implementation.getBundlePath(promise)
|
|
30
|
+
fun getBundlePath(namespace: String, promise: Promise) {
|
|
31
|
+
implementation.getBundlePath(namespace, promise)
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
companion object {
|
|
@@ -42,27 +42,27 @@ class AirborneModuleImpl(private val reactContext: ReactApplicationContext) {
|
|
|
42
42
|
// }
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
fun readReleaseConfig(promise: Promise) {
|
|
45
|
+
fun readReleaseConfig(namespace: String, promise: Promise) {
|
|
46
46
|
try {
|
|
47
|
-
val config = Airborne.
|
|
47
|
+
val config = Airborne.airborneObjectMap[namespace]?.getReleaseConfig()
|
|
48
48
|
promise.resolve(config)
|
|
49
49
|
} catch (e: Exception) {
|
|
50
50
|
promise.reject("AIRBORNE_ERROR", "Failed to read release config: ${e.message}", e)
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
fun getFileContent(filePath: String, promise: Promise) {
|
|
54
|
+
fun getFileContent(namespace: String, filePath: String, promise: Promise) {
|
|
55
55
|
try {
|
|
56
|
-
val content = Airborne.
|
|
56
|
+
val content = Airborne.airborneObjectMap[namespace]?.getFileContent(filePath)
|
|
57
57
|
promise.resolve(content)
|
|
58
58
|
} catch (e: Exception) {
|
|
59
59
|
promise.reject("AIRBORNE_ERROR", "Failed to read file content: ${e.message}", e)
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
fun getBundlePath(promise: Promise) {
|
|
63
|
+
fun getBundlePath(namespace: String, promise: Promise) {
|
|
64
64
|
try {
|
|
65
|
-
val path = Airborne.
|
|
65
|
+
val path = Airborne.airborneObjectMap[namespace]?.getBundlePath()
|
|
66
66
|
promise.resolve(path)
|
|
67
67
|
} catch (e: Exception) {
|
|
68
68
|
promise.reject("AIRBORNE_ERROR", "Failed to get bundle path: ${e.message}", e)
|
|
@@ -8,32 +8,32 @@ import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
|
8
8
|
import java.util.HashMap
|
|
9
9
|
|
|
10
10
|
class AirbornePackage : TurboReactPackage() {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
|
|
12
|
+
return if (name == AirborneModule.NAME) {
|
|
13
|
+
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
|
14
|
+
AirborneTurboModule(reactContext)
|
|
15
|
+
} else {
|
|
16
|
+
AirborneModule(reactContext)
|
|
17
|
+
}
|
|
18
|
+
} else {
|
|
19
|
+
null
|
|
20
|
+
}
|
|
20
21
|
}
|
|
21
|
-
}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
23
|
+
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
|
|
24
|
+
return ReactModuleInfoProvider {
|
|
25
|
+
val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
|
|
26
|
+
val isTurboModule: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
|
|
27
|
+
moduleInfos[AirborneModule.NAME] = ReactModuleInfo(
|
|
28
|
+
AirborneModule.NAME,
|
|
29
|
+
if (isTurboModule) AirborneTurboModule::class.java.name else AirborneModule::class.java.name,
|
|
30
|
+
false, // canOverrideExistingModule
|
|
31
|
+
false, // needsEagerInit
|
|
32
|
+
true, // hasConstants
|
|
33
|
+
false, // isCxxModule
|
|
34
|
+
isTurboModule // isTurboModule
|
|
35
|
+
)
|
|
36
|
+
moduleInfos
|
|
37
|
+
}
|
|
37
38
|
}
|
|
38
|
-
}
|
|
39
39
|
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
package `in`.juspay.airborneplugin
|
|
2
|
+
|
|
3
|
+
import android.util.Log
|
|
4
|
+
import com.facebook.react.ReactActivity
|
|
5
|
+
import com.facebook.react.defaults.DefaultReactActivityDelegate
|
|
6
|
+
import kotlinx.coroutines.CoroutineScope
|
|
7
|
+
import kotlinx.coroutines.Dispatchers
|
|
8
|
+
import kotlinx.coroutines.launch
|
|
9
|
+
|
|
10
|
+
class AirborneReactActivityDelegate(
|
|
11
|
+
activity: ReactActivity,
|
|
12
|
+
mainComponentName: String,
|
|
13
|
+
fabricEnabled: Boolean
|
|
14
|
+
) : DefaultReactActivityDelegate(activity, mainComponentName, fabricEnabled) {
|
|
15
|
+
|
|
16
|
+
private var appState = AppState.BEFORE_APPLOAD;
|
|
17
|
+
override fun loadApp(appKey: String) {
|
|
18
|
+
if (reactNativeHost is AirborneReactNativeHost) {
|
|
19
|
+
CoroutineScope(Dispatchers.Default).launch {
|
|
20
|
+
|
|
21
|
+
// The wait for bundle update
|
|
22
|
+
(reactNativeHost as AirborneReactNativeHost).jsBundleFile
|
|
23
|
+
|
|
24
|
+
CoroutineScope(Dispatchers.Main).launch {
|
|
25
|
+
callLoadApp(appKey)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
callLoadApp(appKey)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private fun callLoadApp(appKey: String) {
|
|
34
|
+
super.loadApp(appKey)
|
|
35
|
+
appState = AppState.APP_LOADED
|
|
36
|
+
onResume()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
override fun onPause() {
|
|
40
|
+
try {
|
|
41
|
+
if (appState == AppState.ONRESUME_CALLED) {
|
|
42
|
+
super.onPause()
|
|
43
|
+
} else {
|
|
44
|
+
Log.d(AirborneReactNativeHost.toString(), "skipping onPause as onResume is not yet called")
|
|
45
|
+
}
|
|
46
|
+
} catch (e: Exception) {
|
|
47
|
+
Log.e( AirborneReactNativeHost.toString(), "Exception in onPause: ${e.message}")
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
override fun onResume() {
|
|
52
|
+
try {
|
|
53
|
+
if (appState == AppState.APP_LOADED) {
|
|
54
|
+
super.onResume()
|
|
55
|
+
appState = AppState.ONRESUME_CALLED
|
|
56
|
+
} else {
|
|
57
|
+
Log.d(AirborneReactNativeHost.toString(), "skipping onResume as app is not yet loaded")
|
|
58
|
+
}
|
|
59
|
+
} catch (e: Exception) {
|
|
60
|
+
Log.e(AirborneReactNativeHost.toString(), "Exception in onResume: ${e.message}")
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
override fun onDestroy() {
|
|
65
|
+
try {
|
|
66
|
+
if (appState == AppState.ONRESUME_CALLED) {
|
|
67
|
+
super.onDestroy()
|
|
68
|
+
} else {
|
|
69
|
+
Log.d(AirborneReactNativeHost.toString(), "skipping onDestroy as onResume is not yet called")
|
|
70
|
+
}
|
|
71
|
+
} catch (e: Exception) {
|
|
72
|
+
Log.e(AirborneReactNativeHost.toString(), "Exception in onDestroy: ${e.message}")
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
enum class AppState {
|
|
77
|
+
BEFORE_APPLOAD,
|
|
78
|
+
APP_LOADED,
|
|
79
|
+
ONRESUME_CALLED
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
package `in`.juspay.airborneplugin
|
|
2
|
+
|
|
3
|
+
import android.app.Application
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.util.Log
|
|
6
|
+
import com.facebook.react.JSEngineResolutionAlgorithm
|
|
7
|
+
import com.facebook.react.ReactHost
|
|
8
|
+
import com.facebook.react.ReactNativeHost
|
|
9
|
+
import com.facebook.react.ReactPackage
|
|
10
|
+
import com.facebook.react.bridge.JSExceptionHandler
|
|
11
|
+
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
|
12
|
+
import com.facebook.react.defaults.DefaultComponentsRegistry
|
|
13
|
+
import com.facebook.react.defaults.DefaultReactNativeHost
|
|
14
|
+
import com.facebook.react.fabric.ComponentFactory
|
|
15
|
+
import com.facebook.react.runtime.ReactHostImpl
|
|
16
|
+
import java.lang.ref.WeakReference
|
|
17
|
+
|
|
18
|
+
abstract class AirborneReactNativeHost(application: Application) :
|
|
19
|
+
DefaultReactNativeHost(application) {
|
|
20
|
+
|
|
21
|
+
public override fun getPackages(): List<ReactPackage> {
|
|
22
|
+
return this.packages
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public override fun getJSBundleFile(): String? {
|
|
26
|
+
return super.getJSBundleFile()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public override fun getJSEngineResolutionAlgorithm(): JSEngineResolutionAlgorithm? {
|
|
30
|
+
return super.getJSEngineResolutionAlgorithm()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public override fun getJSMainModuleName(): String {
|
|
34
|
+
return super.getJSMainModuleName()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
companion object {
|
|
38
|
+
@OptIn(UnstableReactNativeAPI::class)
|
|
39
|
+
fun getReactHost(context: Context, reactNativeHost: ReactNativeHost): ReactHost {
|
|
40
|
+
val reactHostDelegate =
|
|
41
|
+
AirborneReactHostDelegate(WeakReference(context), reactNativeHost)
|
|
42
|
+
val componentFactory = ComponentFactory()
|
|
43
|
+
DefaultComponentsRegistry.register(componentFactory)
|
|
44
|
+
val reactHostImpl =
|
|
45
|
+
ReactHostImpl(context, reactHostDelegate, componentFactory, true, true)
|
|
46
|
+
return reactHostImpl
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -14,19 +14,19 @@ class AirborneTurboModule(reactContext: ReactApplicationContext) :
|
|
|
14
14
|
return NAME
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
override fun readReleaseConfig(promise: Promise) {
|
|
18
|
-
implementation.readReleaseConfig(promise)
|
|
17
|
+
override fun readReleaseConfig(nameSpace: String, promise: Promise) {
|
|
18
|
+
implementation.readReleaseConfig(nameSpace, promise)
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
override fun getFileContent(filePath: String, promise: Promise) {
|
|
22
|
-
implementation.getFileContent(filePath, promise)
|
|
21
|
+
override fun getFileContent(nameSpace: String, filePath: String, promise: Promise) {
|
|
22
|
+
implementation.getFileContent(nameSpace, filePath, promise)
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
override fun getBundlePath(promise: Promise) {
|
|
26
|
-
implementation.getBundlePath(promise)
|
|
25
|
+
override fun getBundlePath(nameSpace: String, promise: Promise) {
|
|
26
|
+
implementation.getBundlePath(nameSpace, promise)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
companion object {
|
|
30
|
-
const val NAME = "
|
|
30
|
+
const val NAME = "AirborneReact"
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?><resources xmlns:tools="http://schemas.android.com/tools" tools:keep="@string/airborne_react_version,@string/airborne_react_build_version" />
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
package `in`.juspay.airborneplugin
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import com.facebook.react.JSEngineResolutionAlgorithm
|
|
6
|
+
import com.facebook.react.ReactNativeHost
|
|
7
|
+
import com.facebook.react.ReactPackage
|
|
8
|
+
import com.facebook.react.ReactPackageTurboModuleManagerDelegate
|
|
9
|
+
import com.facebook.react.bridge.JSBundleLoader
|
|
10
|
+
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
|
11
|
+
import com.facebook.react.defaults.DefaultTurboModuleManagerDelegate
|
|
12
|
+
import com.facebook.react.fabric.ReactNativeConfig
|
|
13
|
+
import com.facebook.react.runtime.BindingsInstaller
|
|
14
|
+
import com.facebook.react.runtime.JSCInstance
|
|
15
|
+
import com.facebook.react.runtime.JSRuntimeFactory
|
|
16
|
+
import com.facebook.react.runtime.ReactHostDelegate
|
|
17
|
+
import com.facebook.react.runtime.hermes.HermesInstance
|
|
18
|
+
import java.lang.ref.WeakReference
|
|
19
|
+
|
|
20
|
+
@OptIn(UnstableReactNativeAPI::class)
|
|
21
|
+
class AirborneReactHostDelegate(
|
|
22
|
+
private val weakContext: WeakReference<Context>,
|
|
23
|
+
private val reactNativeHostWrapper: ReactNativeHost,
|
|
24
|
+
override val bindingsInstaller: BindingsInstaller? = null,
|
|
25
|
+
private val reactNativeConfig: ReactNativeConfig = ReactNativeConfig.DEFAULT_CONFIG,
|
|
26
|
+
override val turboModuleManagerDelegateBuilder: ReactPackageTurboModuleManagerDelegate.Builder =
|
|
27
|
+
DefaultTurboModuleManagerDelegate.Builder()
|
|
28
|
+
) : ReactHostDelegate {
|
|
29
|
+
|
|
30
|
+
override val jsBundleLoader: JSBundleLoader
|
|
31
|
+
get() {
|
|
32
|
+
val bundleName =
|
|
33
|
+
(reactNativeHostWrapper as AirborneReactNativeHost).jsBundleFile
|
|
34
|
+
bundleName?.let {
|
|
35
|
+
return if (bundleName.startsWith("assets://")) {
|
|
36
|
+
JSBundleLoader.createAssetLoader(
|
|
37
|
+
weakContext.get(),
|
|
38
|
+
bundleName,
|
|
39
|
+
false
|
|
40
|
+
)
|
|
41
|
+
} else {
|
|
42
|
+
JSBundleLoader.createFileLoader(bundleName)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return JSBundleLoader.createAssetLoader(
|
|
46
|
+
weakContext.get(),
|
|
47
|
+
"assets://index.android.bundle",
|
|
48
|
+
false
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
override val jsMainModulePath: String
|
|
53
|
+
get() = (reactNativeHostWrapper as AirborneReactNativeHost).jsMainModuleName
|
|
54
|
+
|
|
55
|
+
override val jsRuntimeFactory: JSRuntimeFactory
|
|
56
|
+
get() = if ((reactNativeHostWrapper as AirborneReactNativeHost).jsEngineResolutionAlgorithm == JSEngineResolutionAlgorithm.HERMES) {
|
|
57
|
+
HermesInstance()
|
|
58
|
+
} else {
|
|
59
|
+
JSCInstance()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
override val reactPackages: List<ReactPackage>
|
|
63
|
+
get() = (reactNativeHostWrapper as AirborneReactNativeHost).packages
|
|
64
|
+
|
|
65
|
+
override fun getReactNativeConfig(): ReactNativeConfig {
|
|
66
|
+
return reactNativeConfig
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
override fun handleInstanceException(error: Exception) {
|
|
70
|
+
}
|
|
71
|
+
}
|
package/ios/Airborne.h
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#import "AirborneiOS.h"
|
|
1
2
|
#ifdef RCT_NEW_ARCH_ENABLED
|
|
2
3
|
#import <AirborneSpec/AirborneSpec.h>
|
|
3
4
|
|
|
@@ -5,13 +6,20 @@
|
|
|
5
6
|
#else
|
|
6
7
|
#import <React/RCTBridgeModule.h>
|
|
7
8
|
|
|
9
|
+
|
|
8
10
|
@interface Airborne : NSObject <RCTBridgeModule>
|
|
9
11
|
#endif
|
|
10
12
|
|
|
11
|
-
+ (void)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
+ (void)initializeAirborneWithReleaseConfigUrl:(NSString *) releaseConfigUrl;
|
|
14
|
+
|
|
15
|
+
+ (void)initializeAirborneWithReleaseConfigUrl:(NSString *) releaseConfigUrl
|
|
16
|
+
inNamespace:(NSString *) ns;
|
|
17
|
+
|
|
18
|
+
+ (void)initializeAirborneWithReleaseConfigUrl:(NSString *)releaseConfigUrl
|
|
19
|
+
delegate:delegate;
|
|
20
|
+
|
|
21
|
+
+ (void)initializeAirborneWithReleaseConfigUrl:(NSString *) releaseConfigUrl
|
|
22
|
+
inNamespace:(NSString *) ns
|
|
23
|
+
delegate:(id<AirborneReactDelegate>) delegate;
|
|
16
24
|
|
|
17
25
|
@end
|
package/ios/Airborne.mm
CHANGED
|
@@ -1,34 +1,39 @@
|
|
|
1
1
|
#import "Airborne.h"
|
|
2
2
|
#import "AirborneiOS.h"
|
|
3
3
|
#import <React/RCTLog.h>
|
|
4
|
+
#import <Airborne/Airborne.h>
|
|
5
|
+
#import <Airborne/Airborne-Swift.h>
|
|
4
6
|
|
|
5
7
|
@implementation Airborne
|
|
6
8
|
|
|
7
9
|
RCT_EXPORT_MODULE(Airborne)
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
11
|
+
static NSString * const defaultNamespace = @"default";
|
|
12
|
+
|
|
13
|
+
+ (void)initializeAirborneWithReleaseConfigUrl:(NSString *)releaseConfigUrl {
|
|
14
|
+
[self initializeAirborneWithReleaseConfigUrl:releaseConfigUrl inNamespace:defaultNamespace];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
+ (void)initializeAirborneWithReleaseConfigUrl:(NSString *)releaseConfigUrl inNamespace:ns {
|
|
18
|
+
AirborneiOS* air = [AirborneiOS sharedInstanceWithNamespace:ns];
|
|
19
|
+
[air loadWithReleaseConfig:releaseConfigUrl delegate:nil];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
+ (void)initializeAirborneWithReleaseConfigUrl:(NSString *)releaseConfigUrl delegate:delegate {
|
|
23
|
+
AirborneiOS* air = [AirborneiOS sharedInstanceWithNamespace:defaultNamespace];
|
|
24
|
+
[air loadWithReleaseConfig:releaseConfigUrl delegate:delegate];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
+ (void)initializeAirborneWithReleaseConfigUrl:(NSString *)releaseConfigUrl inNamespace:ns delegate:delegate {
|
|
28
|
+
AirborneiOS* air = [AirborneiOS sharedInstanceWithNamespace:ns];
|
|
29
|
+
[air loadWithReleaseConfig:releaseConfigUrl delegate:delegate];
|
|
25
30
|
}
|
|
26
31
|
|
|
27
32
|
#ifdef RCT_NEW_ARCH_ENABLED
|
|
28
33
|
- (void)readReleaseConfig:(RCTPromiseResolveBlock)resolve
|
|
29
34
|
reject:(RCTPromiseRejectBlock)reject {
|
|
30
35
|
@try {
|
|
31
|
-
NSString *config = [[AirborneiOS
|
|
36
|
+
NSString *config = [[AirborneiOS sharedInstanceWithNamespace:defaultNamespace] getReleaseConfig];
|
|
32
37
|
resolve(config);
|
|
33
38
|
} @catch (NSException *exception) {
|
|
34
39
|
reject(@"AIRBORNE_ERROR", exception.reason, nil);
|
|
@@ -39,7 +44,7 @@ RCT_EXPORT_MODULE(Airborne)
|
|
|
39
44
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
40
45
|
reject:(RCTPromiseRejectBlock)reject {
|
|
41
46
|
@try {
|
|
42
|
-
NSString *content = [[AirborneiOS
|
|
47
|
+
NSString *content = [[AirborneiOS sharedInstanceWithNamespace:defaultNamespace] getFileContent:filePath];
|
|
43
48
|
resolve(content);
|
|
44
49
|
} @catch (NSException *exception) {
|
|
45
50
|
reject(@"AIRBORNE_ERROR", exception.reason, nil);
|
|
@@ -49,7 +54,7 @@ RCT_EXPORT_MODULE(Airborne)
|
|
|
49
54
|
- (void)getBundlePath:(RCTPromiseResolveBlock)resolve
|
|
50
55
|
reject:(RCTPromiseRejectBlock)reject {
|
|
51
56
|
@try {
|
|
52
|
-
NSString *bundlePath = [[AirborneiOS
|
|
57
|
+
NSString *bundlePath = [[AirborneiOS sharedInstanceWithNamespace:defaultNamespace] getBundlePath];
|
|
53
58
|
resolve(bundlePath);
|
|
54
59
|
} @catch (NSException *exception) {
|
|
55
60
|
reject(@"AIRBORNE_ERROR", exception.reason, nil);
|
|
@@ -59,7 +64,7 @@ RCT_EXPORT_MODULE(Airborne)
|
|
|
59
64
|
RCT_EXPORT_METHOD(readReleaseConfig:(RCTPromiseResolveBlock)resolve
|
|
60
65
|
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
61
66
|
@try {
|
|
62
|
-
NSString *config = [[AirborneiOS
|
|
67
|
+
NSString *config = [[AirborneiOS sharedInstanceWithNamespace:defaultNamespace] getReleaseConfig];
|
|
63
68
|
resolve(config);
|
|
64
69
|
} @catch (NSException *exception) {
|
|
65
70
|
reject(@"AIRBORNE_ERROR", exception.reason, nil);
|
|
@@ -70,7 +75,7 @@ RCT_EXPORT_METHOD(getFileContent:(NSString *)filePath
|
|
|
70
75
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
71
76
|
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
72
77
|
@try {
|
|
73
|
-
NSString *content = [[AirborneiOS
|
|
78
|
+
NSString *content = [[AirborneiOS sharedInstanceWithNamespace:defaultNamespace] getFileContent:filePath];
|
|
74
79
|
resolve(content);
|
|
75
80
|
} @catch (NSException *exception) {
|
|
76
81
|
reject(@"AIRBORNE_ERROR", exception.reason, nil);
|
|
@@ -80,7 +85,7 @@ RCT_EXPORT_METHOD(getFileContent:(NSString *)filePath
|
|
|
80
85
|
RCT_EXPORT_METHOD(getBundlePath:(RCTPromiseResolveBlock)resolve
|
|
81
86
|
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
82
87
|
@try {
|
|
83
|
-
NSString *bundlePath = [[AirborneiOS
|
|
88
|
+
NSString *bundlePath = [[AirborneiOS sharedInstanceWithNamespace:defaultNamespace] getBundlePath];
|
|
84
89
|
resolve(bundlePath);
|
|
85
90
|
} @catch (NSException *exception) {
|
|
86
91
|
reject(@"AIRBORNE_ERROR", exception.reason, nil);
|
package/ios/AirborneiOS.h
CHANGED
|
@@ -2,21 +2,84 @@
|
|
|
2
2
|
|
|
3
3
|
NS_ASSUME_NONNULL_BEGIN
|
|
4
4
|
|
|
5
|
+
@protocol AirborneReactDelegate <NSObject>
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Returns custom dimensions/metadata to include with release configuration requests.
|
|
9
|
+
*
|
|
10
|
+
* These dimensions are sent as HTTP headers when fetching the release configuration
|
|
11
|
+
* and can be used for:
|
|
12
|
+
* - A/B testing and feature flags
|
|
13
|
+
* - Device-specific configurations
|
|
14
|
+
* - User segmentation
|
|
15
|
+
* - Analytics and debugging context
|
|
16
|
+
*
|
|
17
|
+
* @return A dictionary of header field names and values to include in network requests.
|
|
18
|
+
* If not implemented, defaults to an empty dictionary.
|
|
19
|
+
*/
|
|
20
|
+
- (NSDictionary<NSString *, NSString *> *)getDimensions;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Returns the namespace, an unique identifier of the app/sdk.
|
|
24
|
+
*
|
|
25
|
+
* This namespace is used to store the files in the internal storage.
|
|
26
|
+
* and also to read the bundled release config.
|
|
27
|
+
*
|
|
28
|
+
* @return the namespace, an unique identifier of the app/sdk.
|
|
29
|
+
* If not implemented, defaults to an default.
|
|
30
|
+
*/
|
|
31
|
+
- (NSString *)getNamespace;
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
- (NSBundle *)getBundle;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Called when the OTA boot process has completed successfully.
|
|
38
|
+
*
|
|
39
|
+
* This callback indicates that the application is ready to load the packages & resources
|
|
40
|
+
*
|
|
41
|
+
* @note This method is called on a background queue. Dispatch UI updates
|
|
42
|
+
* to the main queue if needed.
|
|
43
|
+
* @note Boot completion occurs even if some downloads failed or timed out.
|
|
44
|
+
* Check the release configuration for actual status.
|
|
45
|
+
*/
|
|
46
|
+
- (void)startApp:(NSString *) bundlePath;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Called when significant events occur during the OTA update process.
|
|
50
|
+
*
|
|
51
|
+
* This callback provides detailed information about:
|
|
52
|
+
* - Download progress and completion
|
|
53
|
+
* - Error conditions and failures
|
|
54
|
+
* - Performance metrics and timing
|
|
55
|
+
* - State transitions in the update process
|
|
56
|
+
*
|
|
57
|
+
* @param level The severity level of the event ("info", "error", "warning")
|
|
58
|
+
* @param label A category label for the event (e.g., "ota_update")
|
|
59
|
+
* @param key A specific identifier for the event type
|
|
60
|
+
* @param value Additional structured data about the event
|
|
61
|
+
* @param category The broad category of the event (e.g., "lifecycle")
|
|
62
|
+
* @param subcategory The specific subcategory (e.g., "hyperota")
|
|
63
|
+
*
|
|
64
|
+
* @note Use this for logging, analytics, debugging, and monitoring OTA performance.
|
|
65
|
+
*/
|
|
66
|
+
- (void)onEventWithLevel:(NSString *)level
|
|
67
|
+
label:(NSString *)label
|
|
68
|
+
key:(NSString *)key
|
|
69
|
+
value:(NSDictionary<NSString *, id> *)value
|
|
70
|
+
category:(NSString *)category
|
|
71
|
+
subcategory:(NSString *)subcategory;
|
|
72
|
+
|
|
73
|
+
@end
|
|
74
|
+
|
|
5
75
|
typedef void (^HyperOTALazyDownloadCallback)(NSString *filePath, BOOL success);
|
|
6
76
|
typedef void (^HyperOTALazySplitsCallback)(BOOL success);
|
|
7
77
|
|
|
8
78
|
@interface AirborneiOS : NSObject
|
|
9
79
|
|
|
10
|
-
+ (instancetype)
|
|
11
|
-
|
|
12
|
-
- (void)initializeWithAppId:(NSString *)appId
|
|
13
|
-
indexFileName:(NSString *)indexFileName
|
|
14
|
-
appVersion:(NSString *)appVersion
|
|
15
|
-
releaseConfigTemplateUrl:(NSString *)releaseConfigTemplateUrl
|
|
16
|
-
headers:(nullable NSDictionary<NSString *, NSString *> *)headers
|
|
17
|
-
lazyDownloadCallback:(nullable HyperOTALazyDownloadCallback)lazyDownloadCallback
|
|
18
|
-
lazySplitsCallback:(nullable HyperOTALazySplitsCallback)lazySplitsCallback;
|
|
80
|
+
+ (instancetype)sharedInstanceWithNamespace:(NSString *)ns;
|
|
19
81
|
|
|
82
|
+
- (void) loadWithReleaseConfig:(NSString *) rcurl delegate:(id<AirborneReactDelegate>) delegate;
|
|
20
83
|
- (NSString *)getBundlePath;
|
|
21
84
|
- (NSString *)getFileContent:(NSString *)filePath;
|
|
22
85
|
- (NSString *)getReleaseConfig;
|
package/ios/AirborneiOS.m
CHANGED
|
@@ -1,128 +1,120 @@
|
|
|
1
1
|
#import "AirborneiOS.h"
|
|
2
|
+
#import "Airborne/Airborne.h"
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@interface AirborneLocalDelegate : NSObject<AirborneDelegate>
|
|
6
|
+
@property (nonatomic, weak) NSString* ns;
|
|
7
|
+
@property (nonatomic, weak) id<AirborneReactDelegate> delegate;
|
|
8
|
+
-(instancetype)initWithNamespace:(NSString*) ns
|
|
9
|
+
delegate:(id<AirborneReactDelegate>) delegate;
|
|
10
|
+
@end
|
|
11
|
+
|
|
12
|
+
@implementation AirborneLocalDelegate
|
|
13
|
+
|
|
14
|
+
-(instancetype)initWithNamespace:(NSString*) ns delegate:(id<AirborneReactDelegate>) del {
|
|
15
|
+
self = [super init];
|
|
16
|
+
if (self) {
|
|
17
|
+
_ns = ns;
|
|
18
|
+
_delegate = del;
|
|
19
|
+
}
|
|
20
|
+
return self;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
- (NSString *)namespace{
|
|
24
|
+
if(_delegate == nil) return @"default";
|
|
25
|
+
return [_delegate getNamespace];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
- (NSBundle *)bundle{
|
|
29
|
+
if(_delegate == nil) return NSBundle.mainBundle;
|
|
30
|
+
return [_delegate getBundle];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
- (NSDictionary *)dimensions{
|
|
34
|
+
if(_delegate == nil) return @{};
|
|
35
|
+
return [_delegate getDimensions];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
- (void)onBootCompleteWithIndexBundlePath:(NSString *)indexBundlePath{
|
|
39
|
+
if (_delegate == nil) return;
|
|
40
|
+
[_delegate startApp:indexBundlePath];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
-(void)onEventWithLevel:(NSString *)level label:(NSString *)label key:(NSString *)key value:(NSDictionary<NSString *,id> *)value category:(NSString *)category subcategory:(NSString *)subcategory{
|
|
44
|
+
if (_delegate == nil) return;
|
|
45
|
+
[_delegate onEventWithLevel:level label:label key:key value:value category:category subcategory:subcategory];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@end
|
|
49
|
+
|
|
2
50
|
|
|
3
51
|
@interface AirborneiOS ()
|
|
4
|
-
@property (nonatomic,
|
|
5
|
-
@property (nonatomic, strong)
|
|
6
|
-
|
|
52
|
+
@property (nonatomic, strong) NSString* ns;
|
|
53
|
+
@property (nonatomic, strong) AirborneServices* air;
|
|
54
|
+
@property (nonatomic, strong) id<AirborneDelegate> delegate;
|
|
55
|
+
@property (nonatomic, strong) AirborneLocalDelegate* delegateproxy;
|
|
56
|
+
|
|
7
57
|
@end
|
|
8
58
|
|
|
9
59
|
@implementation AirborneiOS
|
|
10
60
|
|
|
11
|
-
+ (instancetype)
|
|
12
|
-
static AirborneiOS *
|
|
61
|
+
+ (instancetype)sharedInstanceWithNamespace:(NSString *)namespace{
|
|
62
|
+
static NSMutableDictionary<NSString *, AirborneiOS *> *instances = nil;
|
|
63
|
+
static dispatch_queue_t syncQueue;
|
|
13
64
|
static dispatch_once_t onceToken;
|
|
65
|
+
|
|
66
|
+
// Initialize dictionary and queue once
|
|
14
67
|
dispatch_once(&onceToken, ^{
|
|
15
|
-
|
|
68
|
+
instances = [NSMutableDictionary dictionary];
|
|
69
|
+
syncQueue = dispatch_queue_create("in.juspay.Airborne.singleton", DISPATCH_QUEUE_CONCURRENT);
|
|
16
70
|
});
|
|
17
|
-
|
|
71
|
+
|
|
72
|
+
__block AirborneiOS *instance = nil;
|
|
73
|
+
|
|
74
|
+
// Read existing instance (concurrent)
|
|
75
|
+
dispatch_sync(syncQueue, ^{
|
|
76
|
+
instance = instances[namespace];
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
if (instance == nil) {
|
|
80
|
+
// Write new instance (barrier to prevent concurrent writes)
|
|
81
|
+
dispatch_barrier_sync(syncQueue, ^{
|
|
82
|
+
if (!instances[namespace]) {
|
|
83
|
+
instances[namespace] = [[self alloc] initWithNamespace:namespace];
|
|
84
|
+
}
|
|
85
|
+
instance = instances[namespace];
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return instance;
|
|
18
90
|
}
|
|
19
91
|
|
|
20
|
-
|
|
92
|
+
|
|
93
|
+
- (instancetype)initWithNamespace:(NSString *) ns{
|
|
21
94
|
self = [super init];
|
|
22
95
|
if (self) {
|
|
23
|
-
|
|
96
|
+
_ns = ns;
|
|
97
|
+
|
|
24
98
|
}
|
|
25
99
|
return self;
|
|
26
100
|
}
|
|
27
101
|
|
|
28
|
-
- (void)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
releaseConfigTemplateUrl:(NSString *)releaseConfigTemplateUrl
|
|
32
|
-
headers:(nullable NSDictionary<NSString *, NSString *> *)headers
|
|
33
|
-
lazyDownloadCallback:(nullable HyperOTALazyDownloadCallback)lazyDownloadCallback
|
|
34
|
-
lazySplitsCallback:(nullable HyperOTALazySplitsCallback)lazySplitsCallback {
|
|
35
|
-
|
|
36
|
-
if (self.isInitialized) {
|
|
37
|
-
NSLog(@"AirborneiOS: Already initialized");
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
self.indexFileName = indexFileName;
|
|
42
|
-
|
|
43
|
-
// TODO: Initialize the actual Airborne SDK here
|
|
44
|
-
// This is a placeholder implementation
|
|
45
|
-
// In a real implementation, you would:
|
|
46
|
-
// 1. Import the HyperOTA iOS SDK
|
|
47
|
-
// 2. Initialize HyperOTAServices with the provided parameters
|
|
48
|
-
// 3. Create an ApplicationManager
|
|
49
|
-
// 4. Load the application
|
|
50
|
-
|
|
51
|
-
NSLog(@"AirborneiOS: Initializing with appId: %@, indexFileName: %@, appVersion: %@",
|
|
52
|
-
appId, indexFileName, appVersion);
|
|
53
|
-
|
|
54
|
-
self.isInitialized = YES;
|
|
55
|
-
|
|
56
|
-
// Simulate callbacks for demo purposes
|
|
57
|
-
if (lazyDownloadCallback) {
|
|
58
|
-
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
59
|
-
lazyDownloadCallback(@"demo/file.js", YES);
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (lazySplitsCallback) {
|
|
64
|
-
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
65
|
-
lazySplitsCallback(YES);
|
|
66
|
-
});
|
|
67
|
-
}
|
|
102
|
+
- (void)loadWithReleaseConfig:(NSString *) rcurl delegate:(id<AirborneReactDelegate>) delegate{
|
|
103
|
+
_delegateproxy = [[AirborneLocalDelegate alloc] initWithNamespace: self.ns delegate:delegate];
|
|
104
|
+
_air = [[AirborneServices alloc] initWithReleaseConfigURL:rcurl delegate:_delegateproxy];
|
|
68
105
|
}
|
|
69
106
|
|
|
70
107
|
- (NSString *)getBundlePath {
|
|
71
|
-
|
|
72
|
-
// @throw [NSException exceptionWithName:@"HyperOTANotInitialized"
|
|
73
|
-
// reason:@"HyperOTA is not initialized. Call initialize first."
|
|
74
|
-
// userInfo:nil];
|
|
75
|
-
// }
|
|
76
|
-
//
|
|
77
|
-
// // TODO: Get the actual bundle path from HyperOTA SDK //
|
|
78
|
-
// // This is a placeholder implementation
|
|
79
|
-
// NSString *bundlePath = [[NSBundle mainBundle] pathForResource:self.indexFileName ofType:nil];
|
|
80
|
-
// if (!bundlePath) {
|
|
81
|
-
// bundlePath = [NSString stringWithFormat:@"assets://%@", self.indexFileName];
|
|
82
|
-
// }
|
|
83
|
-
//
|
|
84
|
-
// return bundlePath;
|
|
85
|
-
return @"";
|
|
108
|
+
return [_air getIndexBundlePath] ;
|
|
86
109
|
}
|
|
87
110
|
|
|
88
111
|
- (NSString *)getFileContent:(NSString *)filePath {
|
|
89
|
-
|
|
90
|
-
// @throw [NSException exceptionWithName:@"HyperOTANotInitialized"
|
|
91
|
-
// reason:@"HyperOTA is not initialized. Call initialize first."
|
|
92
|
-
// userInfo:nil];
|
|
93
|
-
// }
|
|
94
|
-
//
|
|
95
|
-
// // TODO: Read the actual file content from HyperOTA SDK //
|
|
96
|
-
// // This is a placeholder implementation
|
|
97
|
-
// return [NSString stringWithFormat:@"File content for: %@", filePath];
|
|
98
|
-
return @"";
|
|
112
|
+
return [_air getFileContentAtPath:filePath];
|
|
99
113
|
}
|
|
100
114
|
|
|
101
115
|
- (NSString *)getReleaseConfig {
|
|
102
|
-
|
|
103
|
-
// @throw [NSException exceptionWithName:@"HyperOTANotInitialized"
|
|
104
|
-
// reason:@"HyperOTA is not initialized. Call initialize first."
|
|
105
|
-
// userInfo:nil];
|
|
106
|
-
// }
|
|
107
|
-
//
|
|
108
|
-
// // TODO: Get the actual release config from HyperOTA SDK //
|
|
109
|
-
// // This is a placeholder implementation
|
|
110
|
-
// NSDictionary *config = @{
|
|
111
|
-
// @"version": @"1.0.0",
|
|
112
|
-
// @"environment": @"production",
|
|
113
|
-
// @"features": @{
|
|
114
|
-
// @"featureA": @YES,
|
|
115
|
-
// @"featureB": @NO
|
|
116
|
-
// }
|
|
117
|
-
// };
|
|
118
|
-
//
|
|
119
|
-
// NSError *error;
|
|
120
|
-
// NSData *jsonData = [NSJSONSerialization dataWithJSONObject:config options:0 error:&error];
|
|
121
|
-
// if (jsonData) {
|
|
122
|
-
// return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
|
123
|
-
// }
|
|
124
|
-
|
|
125
|
-
return @"{}";
|
|
116
|
+
return [_air getReleaseConfig];
|
|
126
117
|
}
|
|
127
118
|
|
|
128
119
|
@end
|
|
120
|
+
|
package/lib/module/index.js
CHANGED
|
@@ -28,14 +28,14 @@ const Airborne = AirborneModule ? AirborneModule : new Proxy({}, {
|
|
|
28
28
|
throw new Error(LINKING_ERROR);
|
|
29
29
|
}
|
|
30
30
|
});
|
|
31
|
-
export function readReleaseConfig() {
|
|
32
|
-
return Airborne.readReleaseConfig();
|
|
31
|
+
export function readReleaseConfig(nameSpace) {
|
|
32
|
+
return Airborne.readReleaseConfig(nameSpace);
|
|
33
33
|
}
|
|
34
|
-
export function getFileContent(filePath) {
|
|
35
|
-
return Airborne.getFileContent(filePath);
|
|
34
|
+
export function getFileContent(nameSpace, filePath) {
|
|
35
|
+
return Airborne.getFileContent(nameSpace, filePath);
|
|
36
36
|
}
|
|
37
|
-
export function getBundlePath() {
|
|
38
|
-
return Airborne.getBundlePath();
|
|
37
|
+
export function getBundlePath(nameSpace) {
|
|
38
|
+
return Airborne.getBundlePath(nameSpace);
|
|
39
39
|
}
|
|
40
40
|
export default Airborne;
|
|
41
41
|
//# sourceMappingURL=index.js.map
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeModules","Platform","LINKING_ERROR","select","ios","default","isTurboModuleEnabled","global","__turboModuleProxy","AirborneModule","require","Airborne","Proxy","get","Error","readReleaseConfig","getFileContent","filePath","getBundlePath"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AAEtD,MAAMC,aAAa,GACjB,gFAAgF,GAChFD,QAAQ,CAACE,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;;AAEjC;AACA,MAAMC,oBAAoB,GAAGC,MAAM,CAACC,kBAAkB,IAAI,IAAI;AAE9D,MAAMC,cAAc,GAAGH,oBAAoB,GACvCI,OAAO,CAAC,kBAAkB,CAAC,CAACL,OAAO,GACnCL,aAAa,CAACW,QAAQ;AAE1B,MAAMA,QAAQ,GAAGF,cAAc,GAC3BA,cAAc,GACd,IAAIG,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACZ,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAEL,OAAO,SAASa,iBAAiBA,
|
|
1
|
+
{"version":3,"names":["NativeModules","Platform","LINKING_ERROR","select","ios","default","isTurboModuleEnabled","global","__turboModuleProxy","AirborneModule","require","Airborne","Proxy","get","Error","readReleaseConfig","nameSpace","getFileContent","filePath","getBundlePath"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AAEtD,MAAMC,aAAa,GACjB,gFAAgF,GAChFD,QAAQ,CAACE,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;;AAEjC;AACA,MAAMC,oBAAoB,GAAGC,MAAM,CAACC,kBAAkB,IAAI,IAAI;AAE9D,MAAMC,cAAc,GAAGH,oBAAoB,GACvCI,OAAO,CAAC,kBAAkB,CAAC,CAACL,OAAO,GACnCL,aAAa,CAACW,QAAQ;AAE1B,MAAMA,QAAQ,GAAGF,cAAc,GAC3BA,cAAc,GACd,IAAIG,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACZ,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAEL,OAAO,SAASa,iBAAiBA,CAACC,SAAiB,EAAmB;EACpE,OAAOL,QAAQ,CAACI,iBAAiB,CAACC,SAAS,CAAC;AAC9C;AAEA,OAAO,SAASC,cAAcA,CAACD,SAAiB,EAAEE,QAAgB,EAAmB;EACnF,OAAOP,QAAQ,CAACM,cAAc,CAACD,SAAS,EAAEE,QAAQ,CAAC;AACrD;AAEA,OAAO,SAASC,aAAaA,CAACH,SAAiB,EAAmB;EAChE,OAAOL,QAAQ,CAACQ,aAAa,CAACH,SAAS,CAAC;AAC1C;AAEA,eAAeL,QAAQ","ignoreList":[]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { TurboModule } from 'react-native';
|
|
2
2
|
export interface Spec extends TurboModule {
|
|
3
|
-
readReleaseConfig(): Promise<string>;
|
|
4
|
-
getFileContent(filePath: string): Promise<string>;
|
|
5
|
-
getBundlePath(): Promise<string>;
|
|
3
|
+
readReleaseConfig(nameSpace: string): Promise<string>;
|
|
4
|
+
getFileContent(nameSpace: string, filePath: string): Promise<string>;
|
|
5
|
+
getBundlePath(nameSpace: string): Promise<string>;
|
|
6
6
|
}
|
|
7
7
|
declare const _default: Spec;
|
|
8
8
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeAirborne.d.ts","sourceRoot":"","sources":["../../../src/NativeAirborne.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,iBAAiB,
|
|
1
|
+
{"version":3,"file":"NativeAirborne.d.ts","sourceRoot":"","sources":["../../../src/NativeAirborne.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACtD,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACrE,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACnD;;AAED,wBAAkE"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
declare const Airborne: any;
|
|
2
|
-
export declare function readReleaseConfig(): Promise<string>;
|
|
3
|
-
export declare function getFileContent(filePath: string): Promise<string>;
|
|
4
|
-
export declare function getBundlePath(): Promise<string>;
|
|
2
|
+
export declare function readReleaseConfig(nameSpace: string): Promise<string>;
|
|
3
|
+
export declare function getFileContent(nameSpace: string, filePath: string): Promise<string>;
|
|
4
|
+
export declare function getBundlePath(nameSpace: string): Promise<string>;
|
|
5
5
|
export default Airborne;
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AA6BA,QAAA,MAAM,QAAQ,KAST,CAAC;AAEN,wBAAgB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AA6BA,QAAA,MAAM,QAAQ,KAST,CAAC;AAEN,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEpE;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnF;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEhE;AAED,eAAe,QAAQ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "airborne-react-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Airborne",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
@@ -58,6 +58,9 @@
|
|
|
58
58
|
"publishConfig": {
|
|
59
59
|
"registry": "https://registry.npmjs.org/"
|
|
60
60
|
},
|
|
61
|
+
"dependencies": {
|
|
62
|
+
"airborne-cli-react-native": "file:../airborne_cli"
|
|
63
|
+
},
|
|
61
64
|
"devDependencies": {
|
|
62
65
|
"@commitlint/config-conventional": "^19.6.0",
|
|
63
66
|
"@eslint/compat": "^1.2.7",
|
package/src/NativeAirborne.ts
CHANGED
|
@@ -16,9 +16,9 @@ import type { TurboModule } from 'react-native';
|
|
|
16
16
|
import { TurboModuleRegistry } from 'react-native';
|
|
17
17
|
|
|
18
18
|
export interface Spec extends TurboModule {
|
|
19
|
-
readReleaseConfig(): Promise<string>;
|
|
20
|
-
getFileContent(filePath: string): Promise<string>;
|
|
21
|
-
getBundlePath(): Promise<string>;
|
|
19
|
+
readReleaseConfig(nameSpace: string): Promise<string>;
|
|
20
|
+
getFileContent(nameSpace: string, filePath: string): Promise<string>;
|
|
21
|
+
getBundlePath(nameSpace: string): Promise<string>;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export default TurboModuleRegistry.getEnforcing<Spec>('Airborne');
|
package/src/index.tsx
CHANGED
|
@@ -38,16 +38,16 @@ const Airborne = AirborneModule
|
|
|
38
38
|
}
|
|
39
39
|
);
|
|
40
40
|
|
|
41
|
-
export function readReleaseConfig(): Promise<string> {
|
|
42
|
-
return Airborne.readReleaseConfig();
|
|
41
|
+
export function readReleaseConfig(nameSpace: string): Promise<string> {
|
|
42
|
+
return Airborne.readReleaseConfig(nameSpace);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
export function getFileContent(filePath: string): Promise<string> {
|
|
46
|
-
return Airborne.getFileContent(filePath);
|
|
45
|
+
export function getFileContent(nameSpace: string, filePath: string): Promise<string> {
|
|
46
|
+
return Airborne.getFileContent(nameSpace, filePath);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
export function getBundlePath(): Promise<string> {
|
|
50
|
-
return Airborne.getBundlePath();
|
|
49
|
+
export function getBundlePath(nameSpace: string): Promise<string> {
|
|
50
|
+
return Airborne.getBundlePath(nameSpace);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export default Airborne;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../../ExampleOldArch/App.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAYnD,iBAAS,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAuFhC;AA+ED,eAAe,GAAG,CAAC"}
|