expo-dev-launcher 4.0.11 → 4.0.13
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/CHANGELOG.md +13 -0
- package/android/build.gradle +1 -1
- package/android/src/debug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherAppLoaderFactory.kt +4 -3
- package/android/src/main/java/com/facebook/react/devsupport/DevLauncherDevServerHelper.kt +52 -2
- package/android/src/testDebug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherAppLoaderFactoryTest.kt +27 -1
- package/ios/EXDevLauncherController.m +4 -2
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,19 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 4.0.13 — 2024-05-09
|
|
14
|
+
|
|
15
|
+
### 🐛 Bug fixes
|
|
16
|
+
|
|
17
|
+
- Fixed loading error when both `expo-dev-client` and `expo-updates` installed but no `runtimeVersion` configured. ([#28662](https://github.com/expo/expo/pull/28662) by [@kudo](https://github.com/kudo))
|
|
18
|
+
- Fixed loading error from a https dev-server on Android. ([#28691](https://github.com/expo/expo/pull/28691) by [@kudo](https://github.com/kudo))
|
|
19
|
+
|
|
20
|
+
## 4.0.12 — 2024-05-08
|
|
21
|
+
|
|
22
|
+
### 🐛 Bug fixes
|
|
23
|
+
|
|
24
|
+
- [iOS] Fixed DevMenu getting unresponsive after reloading bundle. ([#28664](https://github.com/expo/expo/pull/28664) by [@gabrieldonadel](https://github.com/gabrieldonadel))
|
|
25
|
+
|
|
13
26
|
## 4.0.11 — 2024-05-04
|
|
14
27
|
|
|
15
28
|
_This version does not introduce any user-facing changes._
|
package/android/build.gradle
CHANGED
|
@@ -38,15 +38,16 @@ class DevLauncherAppLoaderFactory : DevLauncherKoinComponent, DevLauncherAppLoad
|
|
|
38
38
|
// It's (maybe) a raw React Native bundle
|
|
39
39
|
DevLauncherReactNativeAppLoader(url, appHost, context, controller)
|
|
40
40
|
} else {
|
|
41
|
-
|
|
41
|
+
val runtimeVersion = getRuntimeVersion(context)
|
|
42
|
+
val configuration = createUpdatesConfigurationWithUrl(url, projectUrl, runtimeVersion, installationIDHelper.getOrCreateInstallationID(context))
|
|
43
|
+
|
|
44
|
+
if (updatesInterface?.isValidUpdatesConfiguration(configuration, context) != true) {
|
|
42
45
|
manifest = manifestParser.parseManifest()
|
|
43
46
|
if (!manifest!!.isUsingDeveloperTool()) {
|
|
44
47
|
throw Exception("expo-updates is not properly installed or integrated. In order to load published projects with this development client, follow all installation and setup instructions for both the expo-dev-client and expo-updates packages.")
|
|
45
48
|
}
|
|
46
49
|
DevLauncherLocalAppLoader(manifest!!, appHost, context, controller)
|
|
47
50
|
} else {
|
|
48
|
-
val runtimeVersion = getRuntimeVersion(context)
|
|
49
|
-
val configuration = createUpdatesConfigurationWithUrl(url, projectUrl, runtimeVersion, installationIDHelper.getOrCreateInstallationID(context))
|
|
50
51
|
val update = updatesInterface!!.loadUpdate(configuration, context) {
|
|
51
52
|
manifest = Manifest.fromManifestJson(it) // TODO: might be able to pass actual manifest object in here
|
|
52
53
|
return@loadUpdate !manifest!!.isUsingDeveloperTool()
|
|
@@ -2,17 +2,36 @@ package com.facebook.react.devsupport
|
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
4
|
import android.net.Uri
|
|
5
|
+
import com.facebook.react.devsupport.interfaces.PackagerStatusCallback
|
|
5
6
|
import com.facebook.react.modules.debug.interfaces.DeveloperSettings
|
|
6
7
|
import com.facebook.react.packagerconnection.PackagerConnectionSettings
|
|
7
8
|
import expo.modules.devlauncher.launcher.DevLauncherControllerInterface
|
|
9
|
+
import okhttp3.Call
|
|
10
|
+
import okhttp3.Callback
|
|
11
|
+
import okhttp3.OkHttpClient
|
|
12
|
+
import okhttp3.Request
|
|
13
|
+
import okhttp3.Response
|
|
14
|
+
import java.io.IOException
|
|
15
|
+
import java.util.concurrent.TimeUnit
|
|
16
|
+
|
|
17
|
+
private const val PACKAGER_OK_STATUS = "packager-status:running"
|
|
18
|
+
private const val HTTP_CONNECT_TIMEOUT_MS = 5000L
|
|
19
|
+
private const val PACKAGER_STATUS_ENDPOINT = "status"
|
|
8
20
|
|
|
9
21
|
class DevLauncherDevServerHelper(
|
|
10
22
|
context: Context,
|
|
11
23
|
private val controller: DevLauncherControllerInterface?,
|
|
12
24
|
devSettings: DeveloperSettings,
|
|
13
25
|
packagerConnection: PackagerConnectionSettings
|
|
14
|
-
) :
|
|
15
|
-
|
|
26
|
+
) : DevServerHelper(devSettings, context.packageName, packagerConnection) {
|
|
27
|
+
|
|
28
|
+
private val httpClient: OkHttpClient by lazy {
|
|
29
|
+
OkHttpClient.Builder()
|
|
30
|
+
.connectTimeout(HTTP_CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS)
|
|
31
|
+
.readTimeout(0, TimeUnit.MILLISECONDS)
|
|
32
|
+
.writeTimeout(0, TimeUnit.MILLISECONDS)
|
|
33
|
+
.build()
|
|
34
|
+
}
|
|
16
35
|
|
|
17
36
|
override fun getDevServerBundleURL(jsModulePath: String?): String {
|
|
18
37
|
return controller?.manifest?.getBundleURL() ?: super.getDevServerBundleURL(jsModulePath)
|
|
@@ -47,4 +66,35 @@ class DevLauncherDevServerHelper(
|
|
|
47
66
|
}
|
|
48
67
|
return "$defaultValue&$customOptionsString"
|
|
49
68
|
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Re-implement [PackagerStatusCheck](https://github.com/facebook/react-native/blob/958f8e2bb55ba3a2ac/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/PackagerStatusCheck.java)
|
|
72
|
+
* to support https.
|
|
73
|
+
*/
|
|
74
|
+
override fun isPackagerRunning(callback: PackagerStatusCallback) {
|
|
75
|
+
val bundleURL = controller?.manifest?.getBundleURL() ?: return super.isPackagerRunning(callback)
|
|
76
|
+
val bundleUri = Uri.parse(bundleURL)
|
|
77
|
+
val statusUrl = bundleUri.buildUpon()
|
|
78
|
+
.path(PACKAGER_STATUS_ENDPOINT)
|
|
79
|
+
.clearQuery()
|
|
80
|
+
.build()
|
|
81
|
+
.toString()
|
|
82
|
+
val request = Request.Builder().url(statusUrl).build()
|
|
83
|
+
httpClient
|
|
84
|
+
.newCall(request)
|
|
85
|
+
.enqueue(object : Callback {
|
|
86
|
+
override fun onFailure(call: Call, e: IOException) {
|
|
87
|
+
callback.onPackagerStatusFetched(false)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
override fun onResponse(call: Call, response: Response) {
|
|
91
|
+
if (!response.isSuccessful) {
|
|
92
|
+
callback.onPackagerStatusFetched(false)
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
val body = response.body?.string() ?: ""
|
|
96
|
+
callback.onPackagerStatusFetched(body == PACKAGER_OK_STATUS)
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
}
|
|
50
100
|
}
|
|
@@ -13,6 +13,7 @@ import expo.modules.devlauncher.launcher.manifest.DevLauncherManifestParser
|
|
|
13
13
|
import expo.modules.manifests.core.Manifest
|
|
14
14
|
import expo.modules.updatesinterface.UpdatesInterface
|
|
15
15
|
import io.mockk.coEvery
|
|
16
|
+
import io.mockk.every
|
|
16
17
|
import io.mockk.mockk
|
|
17
18
|
import io.mockk.mockkStatic
|
|
18
19
|
import io.mockk.slot
|
|
@@ -94,6 +95,8 @@ internal class DevLauncherAppLoaderFactoryTest {
|
|
|
94
95
|
fun `loads app locally if manifest indicates developer tool and updatesInterface exists`() = runBlocking<Unit> {
|
|
95
96
|
mockUpdatesInterface(developmentManifestJSONString) {
|
|
96
97
|
Truth.assertThat(it).isFalse()
|
|
98
|
+
}.let { updatesInterface ->
|
|
99
|
+
every { updatesInterface.isValidUpdatesConfiguration(any(), any()) } returns true
|
|
97
100
|
}
|
|
98
101
|
val appLoaderFactory = DevLauncherAppLoaderFactory()
|
|
99
102
|
|
|
@@ -109,6 +112,8 @@ internal class DevLauncherAppLoaderFactoryTest {
|
|
|
109
112
|
fun `loads published app if manifest is published and updatesInterface exists`() = runBlocking<Unit> {
|
|
110
113
|
mockUpdatesInterface(publishedManifestJSONString) {
|
|
111
114
|
Truth.assertThat(it).isTrue()
|
|
115
|
+
}.let { updatesInterface ->
|
|
116
|
+
every { updatesInterface.isValidUpdatesConfiguration(any(), any()) } returns true
|
|
112
117
|
}
|
|
113
118
|
val appLoaderFactory = DevLauncherAppLoaderFactory()
|
|
114
119
|
|
|
@@ -120,7 +125,26 @@ internal class DevLauncherAppLoaderFactoryTest {
|
|
|
120
125
|
Truth.assertThat(appLoaderFactory.shouldUseDeveloperSupport()).isFalse()
|
|
121
126
|
}
|
|
122
127
|
|
|
123
|
-
|
|
128
|
+
@Test
|
|
129
|
+
fun `loads app locally if manifest indicates developer tool but updates is mis-configured`() = runBlocking<Unit> {
|
|
130
|
+
mockUpdatesInterface(developmentManifestJSONString) {
|
|
131
|
+
Truth.assertThat(it).isTrue()
|
|
132
|
+
}.let { updatesInterface ->
|
|
133
|
+
every { updatesInterface.isValidUpdatesConfiguration(any(), any()) } returns false
|
|
134
|
+
}
|
|
135
|
+
val appLoaderFactory = DevLauncherAppLoaderFactory()
|
|
136
|
+
|
|
137
|
+
val manifestParser = mockk<DevLauncherManifestParser>()
|
|
138
|
+
val manifest = Manifest.fromManifestJson(JSONObject(developmentManifestJSONString))
|
|
139
|
+
coEvery { manifestParser.isManifestUrl() } returns true
|
|
140
|
+
coEvery { manifestParser.parseManifest() } returns manifest
|
|
141
|
+
|
|
142
|
+
val appLoader = appLoaderFactory.createAppLoader(developmentManifestURL, developmentManifestURL, manifestParser)
|
|
143
|
+
Truth.assertThat(appLoader).isInstanceOf(DevLauncherLocalAppLoader::class.java)
|
|
144
|
+
Truth.assertThat(appLoaderFactory.shouldUseDeveloperSupport()).isTrue()
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
private fun mockUpdatesInterface(manifestJSONString: String, verifyShouldContinue: (Boolean) -> Unit): UpdatesInterface {
|
|
124
148
|
val updatesInterface = mockk<UpdatesInterface>()
|
|
125
149
|
val manifest = JSONObject(manifestJSONString)
|
|
126
150
|
val slot = slot<(JSONObject) -> Boolean>()
|
|
@@ -151,5 +175,7 @@ internal class DevLauncherAppLoaderFactoryTest {
|
|
|
151
175
|
}
|
|
152
176
|
)
|
|
153
177
|
)
|
|
178
|
+
|
|
179
|
+
return updatesInterface
|
|
154
180
|
}
|
|
155
181
|
}
|
|
@@ -503,7 +503,7 @@
|
|
|
503
503
|
return;
|
|
504
504
|
}
|
|
505
505
|
|
|
506
|
-
if (
|
|
506
|
+
if ([self->_updatesInterface isValidUpdatesConfiguration:updatesConfiguration] != YES) {
|
|
507
507
|
[manifestParser tryToParseManifest:^(EXManifestsManifest *manifest) {
|
|
508
508
|
if (!manifest.isUsingDeveloperTool) {
|
|
509
509
|
onError([NSError errorWithDomain:@"DevelopmentClient" code:1 userInfo:@{NSLocalizedDescriptionKey: @"expo-updates is not properly installed or integrated. In order to load published projects with this development client, follow all installation and setup instructions for both the expo-dev-client and expo-updates packages."}]);
|
|
@@ -672,6 +672,8 @@
|
|
|
672
672
|
// expo-dev-menu registers its commands here: https://github.com/expo/expo/blob/6da15324ff0b4a9cb24055e9815b8aa11f0ac3af/packages/expo-dev-menu/ios/Interceptors/DevMenuKeyCommandsInterceptor.swift#L27-L29
|
|
673
673
|
[[RCTKeyCommands sharedInstance] unregisterKeyCommandWithInput:@"d"
|
|
674
674
|
modifierFlags:UIKeyModifierCommand];
|
|
675
|
+
[[RCTKeyCommands sharedInstance] unregisterKeyCommandWithInput:@"r"
|
|
676
|
+
modifierFlags:UIKeyModifierCommand];
|
|
675
677
|
}
|
|
676
678
|
}
|
|
677
679
|
|
|
@@ -722,7 +724,7 @@
|
|
|
722
724
|
- (void)setDevMenuAppBridge
|
|
723
725
|
{
|
|
724
726
|
DevMenuManager *manager = [DevMenuManager shared];
|
|
725
|
-
manager.currentBridge = self.appBridge;
|
|
727
|
+
manager.currentBridge = self.appBridge.parentBridge;
|
|
726
728
|
|
|
727
729
|
if (self.manifest != nil) {
|
|
728
730
|
manager.currentManifest = self.manifest;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-dev-launcher",
|
|
3
3
|
"title": "Expo Development Launcher",
|
|
4
|
-
"version": "4.0.
|
|
4
|
+
"version": "4.0.13",
|
|
5
5
|
"description": "Pre-release version of the Expo development launcher package for testing.",
|
|
6
6
|
"main": "build/DevLauncher.js",
|
|
7
7
|
"types": "build/DevLauncher.d.ts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"homepage": "https://docs.expo.dev",
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"ajv": "8.11.0",
|
|
34
|
-
"expo-dev-menu": "5.0.
|
|
34
|
+
"expo-dev-menu": "5.0.13",
|
|
35
35
|
"expo-manifests": "~0.14.0",
|
|
36
36
|
"resolve-from": "^5.0.0",
|
|
37
37
|
"semver": "^7.6.0"
|
|
@@ -66,5 +66,5 @@
|
|
|
66
66
|
"./setupTests.ts"
|
|
67
67
|
]
|
|
68
68
|
},
|
|
69
|
-
"gitHead": "
|
|
69
|
+
"gitHead": "9c05bec11c7f5b031d1b9b0ebee78c3b71a7e11d"
|
|
70
70
|
}
|