expo-updates 0.25.24 → 0.25.25

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,12 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 0.25.25 — 2024-09-20
14
+
15
+ ### 🐛 Bug fixes
16
+
17
+ - [ios] Store strong references to long-lived objects created in procedures ([#31599](https://github.com/expo/expo/pull/31599) by [@wschurman](https://github.com/wschurman))
18
+
13
19
  ## 0.25.24 — 2024-08-23
14
20
 
15
21
  _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.24'
5
+ version = '0.25.25'
6
6
 
7
7
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
8
8
  apply from: expoModulesCorePlugin
@@ -49,7 +49,7 @@ android {
49
49
  namespace "expo.modules.updates"
50
50
  defaultConfig {
51
51
  versionCode 31
52
- versionName '0.25.24'
52
+ versionName '0.25.25'
53
53
  consumerProguardFiles(rnVersion >= versionToNumber(0, 75, 0) ? 'proguard-rules-75.pro' : 'proguard-rules.pro')
54
54
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
55
55
 
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from './cli';
3
+ export declare const expoAssetsVerify: Command;
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.expoAssetsVerify = void 0;
5
+ const tslib_1 = require("tslib");
6
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
+ const path_1 = tslib_1.__importDefault(require("path"));
8
+ const assetsVerifyAsync_1 = require("./assetsVerifyAsync");
9
+ const assetsVerifyTypes_1 = require("./assetsVerifyTypes");
10
+ const args_1 = require("./utils/args");
11
+ const Log = tslib_1.__importStar(require("./utils/log"));
12
+ const debug = require('debug')('expo-updates:assets:verify');
13
+ const expoAssetsVerify = async (argv) => {
14
+ const args = (0, args_1.assertArgs)({
15
+ // Types
16
+ '--asset-map-path': String,
17
+ '--exported-manifest-path': String,
18
+ '--build-manifest-path': String,
19
+ '--platform': String,
20
+ '--help': Boolean,
21
+ // Aliases
22
+ '-a': '--asset-map-path',
23
+ '-e': '--exported-manifest-path',
24
+ '-b': '--build-manifest-path',
25
+ '-p': '--platform',
26
+ '-h': '--help',
27
+ }, argv !== null && argv !== void 0 ? argv : []);
28
+ if (args['--help']) {
29
+ Log.exit((0, chalk_1.default) `
30
+ {bold Description}
31
+ Verify that all static files in an exported bundle are in either the export or an embedded bundle
32
+
33
+ {bold Usage}
34
+ {dim $} npx expo-updates assets:verify {dim <dir>}
35
+
36
+ Options
37
+ <dir> Directory of the Expo project. Default: Current working directory
38
+ -a, --asset-map-path <path> Path to the \`assetmap.json\` in an export produced by the command \`npx expo export --dump-assetmap\`
39
+ -e, --exported-manifest-path <path> Path to the \`metadata.json\` in an export produced by the command \`npx expo export --dump-assetmap\`
40
+ -b, --build-manifest-path <path> Path to the \`app.manifest\` file created by expo-updates in an Expo application build (either ios or android)
41
+ -p, --platform <platform> Options: ${JSON.stringify(assetsVerifyTypes_1.validPlatforms)}
42
+ -h, --help Usage info
43
+ `, 0);
44
+ }
45
+ return (async () => {
46
+ const projectRoot = (0, args_1.getProjectRoot)(args);
47
+ const validatedArgs = resolveOptions(projectRoot, args);
48
+ debug(`Validated params: ${JSON.stringify(validatedArgs, null, 2)}`);
49
+ const { buildManifestPath, exportedManifestPath, assetMapPath, platform } = validatedArgs;
50
+ const missingAssets = await (0, assetsVerifyAsync_1.getMissingAssetsAsync)(buildManifestPath, exportedManifestPath, assetMapPath, platform);
51
+ if (missingAssets.length > 0) {
52
+ throw new Error(`${missingAssets.length} assets not found in either embedded manifest or in exported bundle:${JSON.stringify(missingAssets, null, 2)}`);
53
+ }
54
+ else {
55
+ Log.log(`All resolved assets found in either embedded manifest or in exported bundle.`);
56
+ }
57
+ process.exit(0);
58
+ })().catch((e) => {
59
+ Log.log(`${e}`);
60
+ process.exit(1);
61
+ });
62
+ };
63
+ exports.expoAssetsVerify = expoAssetsVerify;
64
+ function resolveOptions(projectRoot, args) {
65
+ const exportedManifestPath = validatedPathFromArgument(projectRoot, args, '--exported-manifest-path');
66
+ const buildManifestPath = validatedPathFromArgument(projectRoot, args, '--build-manifest-path');
67
+ const assetMapPath = validatedPathFromArgument(projectRoot, args, '--asset-map-path');
68
+ const platform = args['--platform'];
69
+ if (!(0, assetsVerifyTypes_1.isValidPlatform)(platform)) {
70
+ throw new Error(`Platform must be one of ${JSON.stringify(assetsVerifyTypes_1.validPlatforms)}`);
71
+ }
72
+ return {
73
+ exportedManifestPath,
74
+ buildManifestPath,
75
+ assetMapPath,
76
+ platform,
77
+ };
78
+ }
79
+ function validatedPathFromArgument(projectRoot, args, key) {
80
+ const maybeRelativePath = args[key];
81
+ if (!maybeRelativePath) {
82
+ throw new Error(`No value for ${key}`);
83
+ }
84
+ if (maybeRelativePath.indexOf('/') === 0) {
85
+ return maybeRelativePath; // absolute path
86
+ }
87
+ return path_1.default.resolve(projectRoot, maybeRelativePath);
88
+ }
@@ -0,0 +1,59 @@
1
+ import { BuildManifest, ExportedMetadata, FullAssetDump, FullAssetDumpEntry, MissingAsset, Platform } from './assetsVerifyTypes';
2
+ /**
3
+ * Finds any assets that will be missing from an app given a build and an exported update bundle.
4
+ *
5
+ * @param buildManifestPath Path to the `app.manifest` file created by expo-updates in an Expo application build (either ios or android)
6
+ * @param exportMetadataPath Path to the `metadata.json` in an export produced by the command `npx expo export --dump-assetmap`
7
+ * @param assetMapPath Path to the `assetmap.json` in an export produced by the command `npx expo export --dump-assetmap`
8
+ * @param projectRoot The project root path
9
+ * @returns An array containing any assets that are found in the Metro asset dump, but not included in either app.manifest or the exported bundle
10
+ */
11
+ export declare function getMissingAssetsAsync(buildManifestPath: string, exportMetadataPath: string, assetMapPath: string, platform: Platform): Promise<MissingAsset[]>;
12
+ /**
13
+ * Reads and returns the embedded manifest (app.manifest) for a build.
14
+ *
15
+ * @param buildManifestPath Path to the build folder
16
+ * @param platform Either 'android' or 'ios'
17
+ * @param projectRoot The project root path
18
+ * @returns the JSON structure of the manifest
19
+ */
20
+ export declare function getBuildManifestAsync(buildManifestPath: string): Promise<BuildManifest>;
21
+ /**
22
+ * Extracts the set of asset hashes from a build manifest.
23
+ *
24
+ * @param buildManifest The build manifest
25
+ * @returns The set of asset hashes contained in the build manifest
26
+ */
27
+ export declare function getBuildManifestHashSet(buildManifest: BuildManifest): Set<string>;
28
+ /**
29
+ * Reads and extracts the asset dump for an exported bundle.
30
+ *
31
+ * @param assetMapPath The path to the exported assetmap.json.
32
+ * @returns The asset dump as an object.
33
+ */
34
+ export declare function getFullAssetDumpAsync(assetMapPath: string): Promise<FullAssetDump>;
35
+ /**
36
+ * Extracts the set of asset hashes from an asset dump.
37
+ *
38
+ * @param assetDump
39
+ * @returns The set of asset hashes in the asset dump, and a map of hash to asset
40
+ */
41
+ export declare function getFullAssetDumpHashSet(assetDump: FullAssetDump): {
42
+ fullAssetHashSet: Set<string>;
43
+ fullAssetHashMap: Map<string, FullAssetDumpEntry>;
44
+ };
45
+ /**
46
+ * Reads and extracts the metadata.json from an exported bundle.
47
+ *
48
+ * @param exportedMetadataPath Path to the exported metadata.json.
49
+ * @returns The metadata of the bundle.
50
+ */
51
+ export declare function getExportedMetadataAsync(exportedMetadataPath: string): Promise<ExportedMetadata>;
52
+ /**
53
+ * Extracts the set of asset hashes from an exported bundle's metadata for a given platform.
54
+ *
55
+ * @param metadata The metadata from the exported bundle
56
+ * @param platform Either 'android' or 'ios'
57
+ * @returns the set of asset hashes
58
+ */
59
+ export declare function getExportedMetadataHashSet(metadata: ExportedMetadata, platform: Platform): Set<string>;
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getExportedMetadataHashSet = exports.getExportedMetadataAsync = exports.getFullAssetDumpHashSet = exports.getFullAssetDumpAsync = exports.getBuildManifestHashSet = exports.getBuildManifestAsync = exports.getMissingAssetsAsync = void 0;
4
+ const fs_1 = require("fs");
5
+ const debug = require('debug')('expo-updates:assets:verify');
6
+ /**
7
+ * Finds any assets that will be missing from an app given a build and an exported update bundle.
8
+ *
9
+ * @param buildManifestPath Path to the `app.manifest` file created by expo-updates in an Expo application build (either ios or android)
10
+ * @param exportMetadataPath Path to the `metadata.json` in an export produced by the command `npx expo export --dump-assetmap`
11
+ * @param assetMapPath Path to the `assetmap.json` in an export produced by the command `npx expo export --dump-assetmap`
12
+ * @param projectRoot The project root path
13
+ * @returns An array containing any assets that are found in the Metro asset dump, but not included in either app.manifest or the exported bundle
14
+ */
15
+ async function getMissingAssetsAsync(buildManifestPath, exportMetadataPath, assetMapPath, platform) {
16
+ const buildManifestHashSet = getBuildManifestHashSet(await getBuildManifestAsync(buildManifestPath));
17
+ const fullAssetDump = await getFullAssetDumpAsync(assetMapPath);
18
+ const { fullAssetHashSet, fullAssetHashMap } = getFullAssetDumpHashSet(fullAssetDump);
19
+ const exportedAssetSet = getExportedMetadataHashSet(await getExportedMetadataAsync(exportMetadataPath), platform);
20
+ debug(`Assets in build: ${JSON.stringify([...buildManifestHashSet], null, 2)}`);
21
+ debug(`Assets in exported bundle: ${JSON.stringify([...exportedAssetSet], null, 2)}`);
22
+ debug(`All assets resolved by Metro: ${JSON.stringify([...fullAssetHashSet], null, 2)}`);
23
+ const buildAssetsPlusExportedAssets = new Set(buildManifestHashSet);
24
+ exportedAssetSet.forEach((hash) => buildAssetsPlusExportedAssets.add(hash));
25
+ const missingAssets = [];
26
+ fullAssetHashSet.forEach((hash) => {
27
+ if (!buildAssetsPlusExportedAssets.has(hash)) {
28
+ const asset = fullAssetHashMap.get(hash);
29
+ asset === null || asset === void 0 ? void 0 : asset.fileHashes.forEach((fileHash, index) => {
30
+ if ((asset === null || asset === void 0 ? void 0 : asset.fileHashes[index]) === hash) {
31
+ missingAssets.push({
32
+ hash,
33
+ path: asset === null || asset === void 0 ? void 0 : asset.files[index],
34
+ });
35
+ }
36
+ });
37
+ }
38
+ });
39
+ return missingAssets;
40
+ }
41
+ exports.getMissingAssetsAsync = getMissingAssetsAsync;
42
+ /**
43
+ * Reads and returns the embedded manifest (app.manifest) for a build.
44
+ *
45
+ * @param buildManifestPath Path to the build folder
46
+ * @param platform Either 'android' or 'ios'
47
+ * @param projectRoot The project root path
48
+ * @returns the JSON structure of the manifest
49
+ */
50
+ async function getBuildManifestAsync(buildManifestPath) {
51
+ const buildManifestString = await fs_1.promises.readFile(buildManifestPath, { encoding: 'utf-8' });
52
+ const buildManifest = JSON.parse(buildManifestString);
53
+ return buildManifest;
54
+ }
55
+ exports.getBuildManifestAsync = getBuildManifestAsync;
56
+ /**
57
+ * Extracts the set of asset hashes from a build manifest.
58
+ *
59
+ * @param buildManifest The build manifest
60
+ * @returns The set of asset hashes contained in the build manifest
61
+ */
62
+ function getBuildManifestHashSet(buildManifest) {
63
+ var _a;
64
+ return new Set(((_a = buildManifest.assets) !== null && _a !== void 0 ? _a : []).map((asset) => asset.packagerHash));
65
+ }
66
+ exports.getBuildManifestHashSet = getBuildManifestHashSet;
67
+ /**
68
+ * Reads and extracts the asset dump for an exported bundle.
69
+ *
70
+ * @param assetMapPath The path to the exported assetmap.json.
71
+ * @returns The asset dump as an object.
72
+ */
73
+ async function getFullAssetDumpAsync(assetMapPath) {
74
+ const assetMapString = await fs_1.promises.readFile(assetMapPath, { encoding: 'utf-8' });
75
+ const assetMap = new Map(Object.entries(JSON.parse(assetMapString)));
76
+ return assetMap;
77
+ }
78
+ exports.getFullAssetDumpAsync = getFullAssetDumpAsync;
79
+ /**
80
+ * Extracts the set of asset hashes from an asset dump.
81
+ *
82
+ * @param assetDump
83
+ * @returns The set of asset hashes in the asset dump, and a map of hash to asset
84
+ */
85
+ function getFullAssetDumpHashSet(assetDump) {
86
+ const fullAssetHashSet = new Set();
87
+ const fullAssetHashMap = new Map();
88
+ assetDump.forEach((asset) => asset.fileHashes.forEach((hash) => {
89
+ fullAssetHashSet.add(hash);
90
+ fullAssetHashMap.set(hash, asset);
91
+ }));
92
+ return {
93
+ fullAssetHashSet,
94
+ fullAssetHashMap,
95
+ };
96
+ }
97
+ exports.getFullAssetDumpHashSet = getFullAssetDumpHashSet;
98
+ /**
99
+ * Reads and extracts the metadata.json from an exported bundle.
100
+ *
101
+ * @param exportedMetadataPath Path to the exported metadata.json.
102
+ * @returns The metadata of the bundle.
103
+ */
104
+ async function getExportedMetadataAsync(exportedMetadataPath) {
105
+ const metadataString = await fs_1.promises.readFile(exportedMetadataPath, { encoding: 'utf-8' });
106
+ const metadata = JSON.parse(metadataString);
107
+ return metadata;
108
+ }
109
+ exports.getExportedMetadataAsync = getExportedMetadataAsync;
110
+ /**
111
+ * Extracts the set of asset hashes from an exported bundle's metadata for a given platform.
112
+ *
113
+ * @param metadata The metadata from the exported bundle
114
+ * @param platform Either 'android' or 'ios'
115
+ * @returns the set of asset hashes
116
+ */
117
+ function getExportedMetadataHashSet(metadata, platform) {
118
+ var _a;
119
+ const fileMetadata = platform === 'android' ? metadata.fileMetadata.android : metadata.fileMetadata.ios;
120
+ if (!fileMetadata) {
121
+ throw new Error(`Exported bundle was not exported for platform ${platform}`);
122
+ }
123
+ const assets = (_a = fileMetadata === null || fileMetadata === void 0 ? void 0 : fileMetadata.assets) !== null && _a !== void 0 ? _a : [];
124
+ // Asset paths in the export metadata are of the form 'assets/<hash string>'
125
+ return new Set(assets.map((asset) => asset.path.substring(7, asset.path.length)));
126
+ }
127
+ exports.getExportedMetadataHashSet = getExportedMetadataHashSet;
@@ -0,0 +1,45 @@
1
+ export declare const validPlatforms: string[];
2
+ export type Platform = (typeof validPlatforms)[number];
3
+ export declare const isValidPlatform: (p: any) => boolean;
4
+ export interface ValidatedOptions {
5
+ exportedManifestPath: string;
6
+ buildManifestPath: string;
7
+ assetMapPath: string;
8
+ platform: Platform;
9
+ }
10
+ export type FullAssetDumpEntry = {
11
+ files: string[];
12
+ hash: string;
13
+ name: string;
14
+ type: string;
15
+ fileHashes: string[];
16
+ };
17
+ export type FullAssetDump = Map<string, FullAssetDumpEntry>;
18
+ export type BuildManifestAsset = {
19
+ name: string;
20
+ type: string;
21
+ packagerHash: string;
22
+ };
23
+ export type BuildManifest = {
24
+ assets: BuildManifestAsset[];
25
+ } & {
26
+ [key: string]: any;
27
+ };
28
+ export type ExportedMetadataAsset = {
29
+ path: string;
30
+ ext: string;
31
+ };
32
+ export type FileMetadata = {
33
+ bundle: string;
34
+ assets: ExportedMetadataAsset[];
35
+ };
36
+ export type ExportedMetadata = {
37
+ fileMetadata: {
38
+ ios?: FileMetadata;
39
+ android?: FileMetadata;
40
+ };
41
+ };
42
+ export type MissingAsset = {
43
+ hash: string;
44
+ path: string;
45
+ };
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ // Types for the options passed into the command
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.isValidPlatform = exports.validPlatforms = void 0;
5
+ exports.validPlatforms = ['android', 'ios'];
6
+ const isValidPlatform = (p) => exports.validPlatforms.includes(p);
7
+ exports.isValidPlatform = isValidPlatform;
package/build-cli/cli.js CHANGED
@@ -4,11 +4,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const tslib_1 = require("tslib");
5
5
  const arg_1 = tslib_1.__importDefault(require("arg"));
6
6
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
+ const debug_1 = tslib_1.__importDefault(require("debug"));
8
+ const getenv_1 = require("getenv");
7
9
  const Log = tslib_1.__importStar(require("./utils/log"));
10
+ // Setup before requiring `debug`.
11
+ if ((0, getenv_1.boolish)('EXPO_DEBUG', false)) {
12
+ debug_1.default.enable('expo-updates:*');
13
+ }
14
+ else if (debug_1.default.enabled('expo-updates:')) {
15
+ process.env.EXPO_DEBUG = '1';
16
+ }
8
17
  const commands = {
9
18
  // Add a new command here
10
19
  'codesigning:generate': () => import('./generateCodeSigning.js').then((i) => i.generateCodeSigning),
11
20
  'codesigning:configure': () => import('./configureCodeSigning.js').then((i) => i.configureCodeSigning),
21
+ 'assets:verify': () => import('./assetsVerify.js').then((i) => i.expoAssetsVerify),
12
22
  };
13
23
  const args = (0, arg_1.default)({
14
24
  // Types
@@ -13,6 +13,8 @@ final class CheckForUpdateProcedure: StateMachineProcedure {
13
13
  private let successBlock: (_ checkForUpdateResult: CheckForUpdateResult) -> Void
14
14
  private let errorBlock: (_ error: Exception) -> Void
15
15
 
16
+ private let fileDownloader: FileDownloader
17
+
16
18
  init(
17
19
  database: UpdatesDatabase,
18
20
  config: UpdatesConfig,
@@ -29,6 +31,8 @@ final class CheckForUpdateProcedure: StateMachineProcedure {
29
31
  self.getLaunchedUpdate = getLaunchedUpdate
30
32
  self.successBlock = successBlock
31
33
  self.errorBlock = errorBlock
34
+
35
+ self.fileDownloader = FileDownloader(config: self.config)
32
36
  }
33
37
 
34
38
  func getLoggerTimerLabel() -> String {
@@ -47,7 +51,7 @@ final class CheckForUpdateProcedure: StateMachineProcedure {
47
51
  embeddedUpdate: embeddedUpdate
48
52
  )
49
53
 
50
- FileDownloader(config: self.config).downloadRemoteUpdate(
54
+ self.fileDownloader.downloadRemoteUpdate(
51
55
  fromURL: self.config.updateUrl,
52
56
  withDatabase: self.database,
53
57
  extraHeaders: extraHeaders) { updateResponse in
@@ -15,6 +15,8 @@ final class FetchUpdateProcedure: StateMachineProcedure {
15
15
  private let successBlock: (_ fetchUpdateResult: FetchUpdateResult) -> Void
16
16
  private let errorBlock: (_ error: Exception) -> Void
17
17
 
18
+ private let remoteAppLoader: RemoteAppLoader
19
+
18
20
  init(
19
21
  database: UpdatesDatabase,
20
22
  config: UpdatesConfig,
@@ -35,6 +37,14 @@ final class FetchUpdateProcedure: StateMachineProcedure {
35
37
  self.getLaunchedUpdate = getLaunchedUpdate
36
38
  self.successBlock = successBlock
37
39
  self.errorBlock = errorBlock
40
+
41
+ self.remoteAppLoader = RemoteAppLoader(
42
+ config: self.config,
43
+ database: self.database,
44
+ directory: self.updatesDirectory,
45
+ launchedUpdate: self.getLaunchedUpdate(),
46
+ completionQueue: controllerQueue
47
+ )
38
48
  }
39
49
 
40
50
  func getLoggerTimerLabel() -> String {
@@ -43,14 +53,6 @@ final class FetchUpdateProcedure: StateMachineProcedure {
43
53
 
44
54
  func run(procedureContext: ProcedureContext) {
45
55
  procedureContext.processStateEvent(UpdatesStateEventDownload())
46
-
47
- let remoteAppLoader = RemoteAppLoader(
48
- config: self.config,
49
- database: self.database,
50
- directory: self.updatesDirectory,
51
- launchedUpdate: self.getLaunchedUpdate(),
52
- completionQueue: controllerQueue
53
- )
54
56
  remoteAppLoader.loadUpdate(
55
57
  fromURL: self.config.updateUrl
56
58
  ) { updateResponse in
@@ -18,6 +18,8 @@ final class RelaunchProcedure: StateMachineProcedure {
18
18
  private let successBlock: () -> Void
19
19
  private let errorBlock: (_ error: Exception) -> Void
20
20
 
21
+ private let launcherWithDatabase: AppLauncherWithDatabase
22
+
21
23
  init(
22
24
  database: UpdatesDatabase,
23
25
  config: UpdatesConfig,
@@ -46,6 +48,13 @@ final class RelaunchProcedure: StateMachineProcedure {
46
48
  self.requestStartErrorMonitoring = requestStartErrorMonitoring
47
49
  self.successBlock = successBlock
48
50
  self.errorBlock = errorBlock
51
+
52
+ self.launcherWithDatabase = AppLauncherWithDatabase(
53
+ config: config,
54
+ database: database,
55
+ directory: updatesDirectory,
56
+ completionQueue: controllerQueue
57
+ )
49
58
  }
50
59
 
51
60
  func getLoggerTimerLabel() -> String {
@@ -54,17 +63,11 @@ final class RelaunchProcedure: StateMachineProcedure {
54
63
 
55
64
  func run(procedureContext: ProcedureContext) {
56
65
  procedureContext.processStateEvent(UpdatesStateEventRestart())
57
- let launcherWithDatabase = AppLauncherWithDatabase(
58
- config: config,
59
- database: database,
60
- directory: updatesDirectory,
61
- completionQueue: controllerQueue
62
- )
63
66
  launcherWithDatabase.launchUpdate(withSelectionPolicy: selectionPolicy) { error, success in
64
67
  if success {
65
- self.setLauncher(launcherWithDatabase)
68
+ self.setLauncher(self.launcherWithDatabase)
66
69
  self.requestStartErrorMonitoring()
67
- RCTReloadCommandSetBundleURL(launcherWithDatabase.launchAssetUrl)
70
+ RCTReloadCommandSetBundleURL(self.launcherWithDatabase.launchAssetUrl)
68
71
  RCTTriggerReloadCommandListeners(self.triggerReloadCommandListenersReason)
69
72
 
70
73
  // TODO(wschurman): this was moved to after the RCT calls to unify reload
@@ -49,6 +49,7 @@ final class StartupProcedure: StateMachineProcedure, AppLoaderTaskDelegate, AppL
49
49
  }
50
50
 
51
51
  private let errorRecovery = ErrorRecovery()
52
+ private var errorRecoveryRemoteAppLoader: RemoteAppLoader?
52
53
  internal func requestStartErrorMonitoring() {
53
54
  errorRecovery.startMonitoring()
54
55
  }
@@ -250,14 +251,15 @@ final class StartupProcedure: StateMachineProcedure, AppLoaderTaskDelegate, AppL
250
251
 
251
252
  remoteLoadStatus = .Loading
252
253
 
253
- let remoteAppLoader = RemoteAppLoader(
254
+ // swiftlint:disable force_unwrapping
255
+ errorRecoveryRemoteAppLoader = RemoteAppLoader(
254
256
  config: config,
255
257
  database: database,
256
258
  directory: self.updatesDirectory,
257
259
  launchedUpdate: launchedUpdate(),
258
260
  completionQueue: controllerQueue
259
261
  )
260
- remoteAppLoader.loadUpdate(
262
+ errorRecoveryRemoteAppLoader!.loadUpdate(
261
263
  fromURL: config.updateUrl
262
264
  ) { updateResponse in
263
265
  if let updateDirective = updateResponse.directiveUpdateResponsePart?.updateDirective {
@@ -291,6 +293,7 @@ final class StartupProcedure: StateMachineProcedure, AppLoaderTaskDelegate, AppL
291
293
  self.remoteLoadStatus = .Idle
292
294
  self.errorRecovery.notify(newRemoteLoadStatus: self.remoteLoadStatus)
293
295
  }
296
+ // swiftlint:enable force_unwrapping
294
297
  }
295
298
 
296
299
  func markFailedLaunchForLaunchedUpdate() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-updates",
3
- "version": "0.25.24",
3
+ "version": "0.25.25",
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": "a1b4a5fbbc9e1a5bb310cac977ed84da13040ad5"
70
+ "gitHead": "db4f687820352ae5bc206eecbcd6faf57d6fdd61"
71
71
  }