expo-updates 0.25.16 → 0.25.17

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 CHANGED
@@ -10,6 +10,13 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 0.25.17 — 2024-06-13
14
+
15
+ ### 💡 Others
16
+
17
+ - Improved stability of E2E testing. ([#29402](https://github.com/expo/expo/pull/29402) by [@kudo](https://github.com/kudo))
18
+ - Improved JS event performance on Android and stability of E2E testing. ([#29593](https://github.com/expo/expo/pull/29593) by [@kudo](https://github.com/kudo))
19
+
13
20
  ## 0.25.16 — 2024-06-06
14
21
 
15
22
  _This version does not introduce any user-facing changes._
@@ -2,7 +2,7 @@ apply plugin: 'com.android.library'
2
2
  apply plugin: 'kotlin-kapt'
3
3
 
4
4
  group = 'host.exp.exponent'
5
- version = '0.25.16'
5
+ version = '0.25.17'
6
6
 
7
7
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
8
8
  apply from: expoModulesCorePlugin
@@ -48,7 +48,7 @@ android {
48
48
  namespace "expo.modules.updates"
49
49
  defaultConfig {
50
50
  versionCode 31
51
- versionName '0.25.16'
51
+ versionName '0.25.17'
52
52
  consumerProguardFiles("proguard-rules.pro")
53
53
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
54
54
 
@@ -8,6 +8,7 @@ import com.facebook.react.bridge.ReactContext
8
8
  import com.facebook.react.bridge.WritableMap
9
9
  import com.facebook.react.devsupport.interfaces.DevSupportManager
10
10
  import expo.modules.kotlin.AppContext
11
+ import expo.modules.kotlin.events.EventEmitter
11
12
  import expo.modules.kotlin.exception.CodedException
12
13
  import expo.modules.kotlin.exception.toCodedException
13
14
  import expo.modules.updates.launcher.Launcher
@@ -34,6 +35,7 @@ class DisabledUpdatesController(
34
35
  private val fatalException: Exception?
35
36
  ) : IUpdatesController, UpdatesStateChangeEventSender {
36
37
  override var appContext: WeakReference<AppContext>? = null
38
+ override var eventEmitter: EventEmitter? = null
37
39
 
38
40
  /** Keep the activity for [RecreateReactContextProcedure] to relaunch the app. */
39
41
  private var weakActivity: WeakReference<Activity>? = null
@@ -174,6 +176,6 @@ class DisabledUpdatesController(
174
176
  }
175
177
 
176
178
  private fun sendEventToJS(eventName: String, eventType: String, params: WritableMap?) {
177
- UpdatesUtils.sendEventToAppContext(shouldEmitJsEvents, appContext, logger, eventName, eventType, params)
179
+ UpdatesUtils.sendEvent(eventEmitter, shouldEmitJsEvents, logger, eventName, eventType, params)
178
180
  }
179
181
  }
@@ -9,6 +9,7 @@ import com.facebook.react.bridge.ReactContext
9
9
  import com.facebook.react.bridge.WritableMap
10
10
  import com.facebook.react.devsupport.interfaces.DevSupportManager
11
11
  import expo.modules.kotlin.AppContext
12
+ import expo.modules.kotlin.events.EventEmitter
12
13
  import expo.modules.kotlin.exception.CodedException
13
14
  import expo.modules.kotlin.exception.toCodedException
14
15
  import expo.modules.updates.db.BuildData
@@ -42,6 +43,7 @@ class EnabledUpdatesController(
42
43
  override val updatesDirectory: File
43
44
  ) : IUpdatesController, UpdatesStateChangeEventSender {
44
45
  override var appContext: WeakReference<AppContext>? = null
46
+ override var eventEmitter: EventEmitter? = null
45
47
 
46
48
  /** Keep the activity for [RelaunchProcedure] to relaunch the app. */
47
49
  private var weakActivity: WeakReference<Activity>? = null
@@ -170,7 +172,7 @@ class EnabledUpdatesController(
170
172
  }
171
173
 
172
174
  private fun sendEventToJS(eventName: String, eventType: String, params: WritableMap?) {
173
- UpdatesUtils.sendEventToAppContext(shouldEmitJsEvents, appContext, logger, eventName, eventType, params)
175
+ UpdatesUtils.sendEvent(eventEmitter, shouldEmitJsEvents, logger, eventName, eventType, params)
174
176
  }
175
177
 
176
178
  override fun getConstantsForModule(): IUpdatesController.UpdatesModuleConstants {
@@ -5,6 +5,7 @@ import com.facebook.react.ReactApplication
5
5
  import com.facebook.react.bridge.ReactContext
6
6
  import com.facebook.react.devsupport.interfaces.DevSupportManager
7
7
  import expo.modules.kotlin.AppContext
8
+ import expo.modules.kotlin.events.EventEmitter
8
9
  import expo.modules.kotlin.exception.CodedException
9
10
  import expo.modules.updates.db.entity.AssetEntity
10
11
  import expo.modules.updates.db.entity.UpdateEntity
@@ -45,6 +46,11 @@ interface IUpdatesController {
45
46
  */
46
47
  var appContext: WeakReference<AppContext>?
47
48
 
49
+ /**
50
+ * The [EventEmitter] assigned from [UpdatesModule]
51
+ */
52
+ var eventEmitter: EventEmitter?
53
+
48
54
  fun onDidCreateDevSupportManager(devSupportManager: DevSupportManager)
49
55
 
50
56
  fun onDidCreateReactInstance(reactContext: ReactContext)
@@ -3,6 +3,7 @@ package expo.modules.updates
3
3
  import android.content.Context
4
4
  import com.facebook.react.ReactApplication
5
5
  import expo.modules.kotlin.AppContext
6
+ import expo.modules.kotlin.events.EventEmitter
6
7
  import expo.modules.updates.loader.LoaderTask
7
8
  import expo.modules.updates.logging.UpdatesErrorCode
8
9
  import expo.modules.updates.logging.UpdatesLogger
@@ -160,11 +161,12 @@ class UpdatesController {
160
161
  }
161
162
 
162
163
  /**
163
- * Binds the [AppContext] instance from [UpdatesModule].
164
+ * Binds the [AppContext] and [EventEmitter] instance from [UpdatesModule].
164
165
  */
165
- internal fun bindAppContext(appContext: WeakReference<AppContext>) {
166
+ internal fun bindAppContext(appContext: WeakReference<AppContext>, eventEmitter: EventEmitter?) {
166
167
  singletonInstance?.let {
167
168
  it.appContext = appContext
169
+ it.eventEmitter = eventEmitter
168
170
  }
169
171
  }
170
172
  }
@@ -7,6 +7,7 @@ import android.util.Log
7
7
  import com.facebook.react.bridge.ReactContext
8
8
  import com.facebook.react.devsupport.interfaces.DevSupportManager
9
9
  import expo.modules.kotlin.AppContext
10
+ import expo.modules.kotlin.events.EventEmitter
10
11
  import expo.modules.kotlin.exception.CodedException
11
12
  import expo.modules.updates.db.DatabaseHolder
12
13
  import expo.modules.updates.db.Reaper
@@ -48,6 +49,7 @@ class UpdatesDevLauncherController(
48
49
  private val updatesDirectoryException: Exception?
49
50
  ) : IUpdatesController, UpdatesInterface {
50
51
  override var appContext: WeakReference<AppContext>? = null
52
+ override var eventEmitter: EventEmitter? = null
51
53
  override var shouldEmitJsEvents = false
52
54
  override var updatesInterfaceCallbacks: WeakReference<UpdatesInterfaceCallbacks>? = null
53
55
 
@@ -74,7 +74,10 @@ class UpdatesModule : Module() {
74
74
  }
75
75
 
76
76
  OnCreate {
77
- UpdatesController.bindAppContext(WeakReference(appContext))
77
+ UpdatesController.bindAppContext(
78
+ WeakReference(appContext),
79
+ appContext.eventEmitter(this@UpdatesModule)
80
+ )
78
81
  }
79
82
 
80
83
  OnStartObserving {
@@ -7,6 +7,7 @@ import android.util.Log
7
7
  import com.facebook.react.bridge.Arguments
8
8
  import com.facebook.react.bridge.WritableMap
9
9
  import expo.modules.kotlin.AppContext
10
+ import expo.modules.kotlin.events.EventEmitter
10
11
  import expo.modules.updates.UpdatesConfiguration.CheckAutomaticallyConfiguration
11
12
  import expo.modules.updates.db.entity.AssetEntity
12
13
  import expo.modules.updates.logging.UpdatesErrorCode
@@ -160,9 +161,9 @@ object UpdatesUtils {
160
161
  }
161
162
  }
162
163
 
163
- fun sendEventToAppContext(
164
+ fun sendEvent(
165
+ eventEmitter: EventEmitter?,
164
166
  shouldEmitJsEvents: Boolean,
165
- weakAppContext: WeakReference<AppContext>?,
166
167
  logger: UpdatesLogger,
167
168
  eventName: String,
168
169
  eventType: String,
@@ -176,24 +177,19 @@ object UpdatesUtils {
176
177
  logger.error("Could not emit $eventName $eventType event; no subscribers registered.", UpdatesErrorCode.JSRuntimeError)
177
178
  return
178
179
  }
179
- val appContext = weakAppContext?.get() ?: run {
180
- eventsToSendToJS.add(Pair(eventName, eventParams))
181
- logger.error("Could not emit $eventName $eventType event; no app context was found.", UpdatesErrorCode.JSRuntimeError)
182
- return
183
- }
184
- val updatesModule = appContext.registry.getModule("ExpoUpdates") ?: run {
185
- eventsToSendToJS.add(Pair(eventName, eventParams))
186
- logger.error("Could not emit $eventName $eventType event; no ExpoUpdates module was found.", UpdatesErrorCode.JSRuntimeError)
187
- return
188
- }
189
- val eventEmitter = appContext.eventEmitter(updatesModule) ?: run {
180
+ if (eventEmitter == null) {
190
181
  eventsToSendToJS.add(Pair(eventName, eventParams))
191
182
  logger.error("Could not emit $eventName $eventType event; no event emitter was found.", UpdatesErrorCode.JSRuntimeError)
192
183
  return
193
184
  }
194
185
 
195
186
  logger.info("Emitted event: name = $eventName, type = $eventType")
196
- eventEmitter.emit(eventName, eventParams)
187
+ try {
188
+ eventEmitter.emit(eventName, eventParams)
189
+ } catch (e: Exception) {
190
+ logger.error("Could not emit $eventName $eventType event; ${e.message}", UpdatesErrorCode.JSRuntimeError)
191
+ eventsToSendToJS.add(Pair(eventName, eventParams))
192
+ }
197
193
  }
198
194
 
199
195
  fun sendQueuedEventsToAppContext(
package/e2e/README.md CHANGED
@@ -76,9 +76,8 @@ eas build --profile=updates_testing_debug --platform=<android|ios>
76
76
  @@ -15,7 +15,8 @@
77
77
  "updates_testing_debug": {
78
78
  "env": {
79
- "EX_UPDATES_NATIVE_DEBUG": "1",
80
- - "NO_FLIPPER": "1"
81
- + "NO_FLIPPER": "1",
79
+ - "EX_UPDATES_NATIVE_DEBUG": "1"
80
+ + "EX_UPDATES_NATIVE_DEBUG": "1",
82
81
  + "LOCAL_TESTING": "1"
83
82
  },
84
83
  "android": {
@@ -15,7 +15,7 @@ function TestValue(props: { testID: string; value: string }) {
15
15
  <Text style={styles.labelText}>{props.testID}</Text>
16
16
  <Text style={styles.labelText}>&nbsp;</Text>
17
17
  <Text style={styles.labelText} testID={props.testID}>
18
- {props.value}
18
+ {props.value || 'null'}
19
19
  </Text>
20
20
  </View>
21
21
  </View>
@@ -24,7 +24,7 @@ function TestValue(props: { testID: string; value: string }) {
24
24
  <Text style={styles.labelText}>{props.testID}</Text>
25
25
  <Text style={styles.labelText}>&nbsp;</Text>
26
26
  <Text style={styles.labelText} testID={props.testID}>
27
- {props.value}
27
+ {props.value || 'null'}
28
28
  </Text>
29
29
  </View>
30
30
  </View>
@@ -14,7 +14,7 @@ const pressTestButtonAsync = async (testID: string) => await element(by.id(testI
14
14
  const waitForAppToBecomeVisible = async () => {
15
15
  await waitFor(element(by.id('updateString')))
16
16
  .toBeVisible()
17
- .withTimeout(2000);
17
+ .withTimeout(3000);
18
18
  };
19
19
 
20
20
  describe('Basic tests', () => {
@@ -34,7 +34,7 @@ describe('Basic tests', () => {
34
34
 
35
35
  jestExpect(await testElementValueAsync('updateString')).toBe('test');
36
36
  jestExpect(await testElementValueAsync('updateID')).toBeTruthy();
37
- jestExpect(await testElementValueAsync('runtimeVersion')).toBe('');
37
+ jestExpect(await testElementValueAsync('runtimeVersion')).toBe('null');
38
38
  jestExpect(await testElementValueAsync('checkAutomatically')).toBe('NEVER');
39
39
  jestExpect(await testElementValueAsync('isEmbeddedLaunch')).toBe('false');
40
40
  jestExpect(await testElementValueAsync('availableUpdateID')).toBe('undefined');
@@ -14,7 +14,7 @@ const pressTestButtonAsync = async (testID: string) => await element(by.id(testI
14
14
  const waitForAppToBecomeVisible = async () => {
15
15
  await waitFor(element(by.id('updateString')))
16
16
  .toBeVisible()
17
- .withTimeout(2000);
17
+ .withTimeout(3000);
18
18
  };
19
19
 
20
20
  describe('Basic tests', () => {
@@ -32,7 +32,7 @@ describe('Basic tests', () => {
32
32
 
33
33
  jestExpect(await testElementValueAsync('updateString')).toBe('test');
34
34
  jestExpect(await testElementValueAsync('updateID')).toBeTruthy();
35
- jestExpect(await testElementValueAsync('runtimeVersion')).toBe('');
35
+ jestExpect(await testElementValueAsync('runtimeVersion')).toBe('null');
36
36
  jestExpect(await testElementValueAsync('checkAutomatically')).toBe('NEVER');
37
37
  jestExpect(await testElementValueAsync('isEmbeddedLaunch')).toBe('false');
38
38
  jestExpect(await testElementValueAsync('availableUpdateID')).toBe('undefined');
@@ -49,6 +49,11 @@ describe('Basic tests', () => {
49
49
  await device.installApp();
50
50
  await device.launchApp({
51
51
  newInstance: true,
52
+
53
+ // The ReactContext is required by detox synchronization on Android.
54
+ // However ReactContext will be changed after the app is reloaded.
55
+ // All future tests will be blocked after reloading, so we need to disable synchronization for reload tests.
56
+ launchArgs: device.getPlatform() === 'android' ? { detoxEnableSynchronization: 0 } : {},
52
57
  });
53
58
  await waitForAppToBecomeVisible();
54
59
 
@@ -63,18 +68,6 @@ describe('Basic tests', () => {
63
68
  // it's delayed 2 seconds after the button press in the client so the button press finish registers in detox
64
69
  await setTimeout(3000);
65
70
 
66
- // on android, the react context must be reacquired by detox.
67
- // there's no detox public API to tell it that react native
68
- // has been reloaded by the client application and that it should
69
- // reacquire the react context. Instead, we use the detox reload
70
- // API to do a second reload which reacquires the context. This
71
- // detox reload method does the same thing that expo-updates reload does
72
- // under the hood, so this is ok and is the best we can do. It should
73
- // do the job of catching issues in react native either way.
74
- if (device.getPlatform() === 'android') {
75
- await device.reloadReactNative();
76
- }
77
-
78
71
  const isReloadingAfter = await testElementValueAsync('isReloading');
79
72
  jestExpect(isReloadingAfter).toBe('false');
80
73
  const startTimeAfter = parseInt(await testElementValueAsync('startTime'), 10);
@@ -16,7 +16,7 @@ const testElementValueAsync = async (testID: string) => {
16
16
  const waitForAppToBecomeVisible = async () => {
17
17
  await waitFor(element(by.id('updateString')))
18
18
  .toBeVisible()
19
- .withTimeout(2000);
19
+ .withTimeout(3000);
20
20
  };
21
21
 
22
22
  describe('Error recovery tests', () => {
@@ -16,7 +16,7 @@ const testElementValueAsync = async (testID: string) => {
16
16
  const waitForAppToBecomeVisible = async () => {
17
17
  await waitFor(element(by.id('updateString')))
18
18
  .toBeVisible()
19
- .withTimeout(2000);
19
+ .withTimeout(3000);
20
20
  };
21
21
 
22
22
  describe('Basic tests', () => {
@@ -81,7 +81,7 @@ const readLogEntriesAsync = async () => {
81
81
  const waitForAppToBecomeVisible = async () => {
82
82
  await waitFor(element(by.id('updateString')))
83
83
  .toBeVisible()
84
- .withTimeout(2000);
84
+ .withTimeout(3000);
85
85
  };
86
86
 
87
87
  describe('Basic tests', () => {
@@ -117,6 +117,11 @@ describe('Basic tests', () => {
117
117
  await device.installApp();
118
118
  await device.launchApp({
119
119
  newInstance: true,
120
+
121
+ // The ReactContext is required by detox synchronization on Android.
122
+ // However ReactContext will be changed after the app is reloaded.
123
+ // All future tests will be blocked after reloading, so we need to disable synchronization for reload tests.
124
+ launchArgs: device.getPlatform() === 'android' ? { detoxEnableSynchronization: 0 } : {},
120
125
  });
121
126
  await waitForAppToBecomeVisible();
122
127
 
@@ -131,18 +136,6 @@ describe('Basic tests', () => {
131
136
  // it's delayed 2 seconds after the button press in the client so the button press finish registers in detox
132
137
  await setTimeout(3000);
133
138
 
134
- // on android, the react context must be reacquired by detox.
135
- // there's no detox public API to tell it that react native
136
- // has been reloaded by the client application and that it should
137
- // reacquire the react context. Instead, we use the detox reload
138
- // API to do a second reload which reacquires the context. This
139
- // detox reload method does the same thing that expo-updates reload does
140
- // under the hood, so this is ok and is the best we can do. It should
141
- // do the job of catching issues in react native either way.
142
- if (device.getPlatform() === 'android') {
143
- await device.reloadReactNative();
144
- }
145
-
146
139
  const isReloadingAfter = await testElementValueAsync('isReloading');
147
140
  jestExpect(isReloadingAfter).toBe('false');
148
141
  const startTimeAfter = parseInt(await testElementValueAsync('startTime'), 10);
@@ -775,14 +768,14 @@ describe('JS API tests', () => {
775
768
  jestExpect(isUpdateAvailable).toEqual('false');
776
769
  jestExpect(isUpdatePending).toEqual('false');
777
770
  jestExpect(isRollback).toEqual('false');
778
- jestExpect(latestManifestId).toEqual('');
779
- jestExpect(downloadedManifestId).toEqual('');
771
+ jestExpect(latestManifestId).toEqual('null');
772
+ jestExpect(downloadedManifestId).toEqual('null');
780
773
  // After check for update and getting a manifest
781
774
  jestExpect(isUpdateAvailable2).toEqual('true');
782
775
  jestExpect(isUpdatePending2).toEqual('false');
783
776
  jestExpect(isRollback2).toEqual('false');
784
777
  jestExpect(latestManifestId2).toEqual(manifest.id);
785
- jestExpect(downloadedManifestId2).toEqual('');
778
+ jestExpect(downloadedManifestId2).toEqual('null');
786
779
  // After downloading the update
787
780
  jestExpect(isUpdateAvailable3).toEqual('true');
788
781
  jestExpect(isUpdatePending3).toEqual('true');
@@ -797,16 +790,16 @@ describe('JS API tests', () => {
797
790
  jestExpect(isUpdateAvailable4).toEqual('false');
798
791
  jestExpect(isUpdatePending4).toEqual('false');
799
792
  jestExpect(isRollback4).toEqual('false');
800
- jestExpect(latestManifestId4).toEqual('');
801
- jestExpect(downloadedManifestId4).toEqual('');
802
- jestExpect(rollbackCommitTime4).toEqual('');
793
+ jestExpect(latestManifestId4).toEqual('null');
794
+ jestExpect(downloadedManifestId4).toEqual('null');
795
+ jestExpect(rollbackCommitTime4).toEqual('null');
803
796
  // After check for update and getting a rollback
804
797
  jestExpect(isUpdateAvailable5).toEqual('true');
805
798
  jestExpect(isUpdatePending5).toEqual('false');
806
799
  jestExpect(isRollback5).toEqual('true');
807
- jestExpect(latestManifestId5).toEqual('');
808
- jestExpect(downloadedManifestId5).toEqual('');
809
- jestExpect(rollbackCommitTime5).not.toEqual('');
800
+ jestExpect(latestManifestId5).toEqual('null');
801
+ jestExpect(downloadedManifestId5).toEqual('null');
802
+ jestExpect(rollbackCommitTime5).not.toEqual('null');
810
803
 
811
804
  // Check for update, and expect isRollback to be true
812
805
  await pressTestButtonAsync('triggerParallelFetchAndDownload');
@@ -36,7 +36,7 @@
36
36
  "type": "ios.simulator",
37
37
  "headless": true,
38
38
  "device": {
39
- "type": "iPhone 14"
39
+ "type": "iPhone 15"
40
40
  }
41
41
  },
42
42
  "emulator": {
@@ -32,7 +32,6 @@ export UPDATES_PORT=4747
32
32
  export PROJECT_ROOT=$PWD
33
33
 
34
34
  export EX_UPDATES_NATIVE_DEBUG=1
35
- export NO_FLIPPER=1
36
35
 
37
36
  mkdir ./logs
38
37
 
@@ -4,7 +4,13 @@
4
4
  },
5
5
  "build": {
6
6
  "base": {
7
- "node": "18.18.0"
7
+ "node": "20.14.0",
8
+ "android": {
9
+ "image": "latest"
10
+ },
11
+ "ios": {
12
+ "image": "latest"
13
+ }
8
14
  },
9
15
  "development": {
10
16
  "extends": "base",
@@ -19,23 +25,17 @@
19
25
  "updates_testing_debug": {
20
26
  "extends": "base",
21
27
  "env": {
22
- "EX_UPDATES_NATIVE_DEBUG": "1",
23
- "NO_FLIPPER": "1"
28
+ "EX_UPDATES_NATIVE_DEBUG": "1"
24
29
  },
25
30
  "android": {
26
- "image": "ubuntu-22.04-jdk-17-ndk-r21e",
31
+ "applicationArchivePath": "eas.json",
27
32
  "gradleCommand": ":app:assembleDebug :app:assembleAndroidTest -DtestBuildType=debug",
28
- "withoutCredentials": true,
29
- "resourceClass": "large"
33
+ "withoutCredentials": true
30
34
  },
31
35
  "ios": {
36
+ "applicationArchivePath": "eas.json",
32
37
  "simulator": true,
33
- "resourceClass": "m-medium",
34
- "image": "macos-ventura-13.3-xcode-14.3",
35
- "buildConfiguration": "Debug",
36
- "cache": {
37
- "cacheDefaultPaths": false
38
- }
38
+ "buildConfiguration": "Debug"
39
39
  },
40
40
  "distribution": "internal",
41
41
  "buildArtifactPaths": ["logs/*.log"]
@@ -43,27 +43,20 @@
43
43
  "updates_testing_release": {
44
44
  "extends": "base",
45
45
  "env": {
46
- "EX_UPDATES_NATIVE_DEBUG": "1",
47
- "NO_FLIPPER": "1"
46
+ "EX_UPDATES_NATIVE_DEBUG": "1"
48
47
  },
49
48
  "android": {
50
- "image": "ubuntu-22.04-jdk-17-ndk-r21e",
51
49
  "gradleCommand": ":app:assembleRelease :app:assembleAndroidTest -DtestBuildType=release",
52
- "withoutCredentials": true,
53
- "resourceClass": "large"
50
+ "withoutCredentials": true
54
51
  },
55
52
  "ios": {
56
53
  "simulator": true,
57
- "resourceClass": "m-medium",
58
- "image": "macos-ventura-13.3-xcode-14.3",
59
- "buildConfiguration": "Release",
60
- "cache": {
61
- "cacheDefaultPaths": false
62
- }
54
+ "buildConfiguration": "Release"
63
55
  },
64
56
  "distribution": "internal",
65
57
  "buildArtifactPaths": ["logs/*.log"]
66
58
  },
59
+
67
60
  "production": {
68
61
  "extends": "base"
69
62
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-updates",
3
- "version": "0.25.16",
3
+ "version": "0.25.17",
4
4
  "description": "Fetches and manages remotely-hosted assets and updates to your app's JS bundle.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -67,5 +67,5 @@
67
67
  "peerDependencies": {
68
68
  "expo": "*"
69
69
  },
70
- "gitHead": "f424c7ea50d8787fa8d3354a33fe402160b63032"
70
+ "gitHead": "6f609a05a2d4dac7fd281bcc502575440c5af7c9"
71
71
  }