Skip to content
This repository was archived by the owner on May 20, 2025. It is now read-only.

Commit c36367a

Browse files
author
Geoffrey Goh
committed
update to master
2 parents 3aa4a98 + 54fb2d6 commit c36367a

25 files changed

+795
-398
lines changed

CodePush.js

Lines changed: 97 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ const PackageMixins = require("./package-mixins")(NativeCodePush);
99
async function checkForUpdate(deploymentKey = null) {
1010
/*
1111
* Before we ask the server if an update exists, we
12-
* need to retrieve three pieces of information from the
12+
* need to retrieve three pieces of information from the
1313
* native side: deployment key, app version (e.g. 1.0.1)
1414
* and the hash of the currently running update (if there is one).
1515
* This allows the client to only receive updates which are targetted
1616
* for their specific deployment and version and which are actually
1717
* different from the CodePush update they have already installed.
1818
*/
1919
const nativeConfig = await getConfiguration();
20-
20+
2121
/*
2222
* If a deployment key was explicitly provided,
2323
* then let's override the one we retrieved
@@ -30,7 +30,7 @@ async function checkForUpdate(deploymentKey = null) {
3030

3131
// Use dynamically overridden getCurrentPackage() during tests.
3232
const localPackage = await module.exports.getCurrentPackage();
33-
33+
3434
/*
3535
* If the app has a previously installed update, and that update
3636
* was targetted at the same app version that is currently running,
@@ -48,9 +48,9 @@ async function checkForUpdate(deploymentKey = null) {
4848
queryPackage.packageHash = config.packageHash;
4949
}
5050
}
51-
51+
5252
const update = await sdk.queryUpdateWithCurrentPackage(queryPackage);
53-
53+
5454
/*
5555
* There are four cases where checkForUpdate will resolve to null:
5656
* ----------------------------------------------------------------
@@ -69,13 +69,13 @@ async function checkForUpdate(deploymentKey = null) {
6969
* because we want to avoid having to install diff updates against the binary's
7070
* version, which we can't do yet on Android.
7171
*/
72-
if (!update || update.updateAppVersion ||
73-
localPackage && (update.packageHash === localPackage.packageHash) ||
72+
if (!update || update.updateAppVersion ||
73+
localPackage && (update.packageHash === localPackage.packageHash) ||
7474
(!localPackage || localPackage._isDebugOnly) && config.packageHash === update.packageHash) {
7575
if (update && update.updateAppVersion) {
7676
log("An update is available but it is targeting a newer binary version than you are currently running.");
7777
}
78-
78+
7979
return null;
8080
} else {
8181
const remotePackage = { ...update, ...PackageMixins.remote(sdk.reportStatusDownload) };
@@ -93,19 +93,23 @@ const getConfiguration = (() => {
9393
} else if (testConfig) {
9494
return testConfig;
9595
} else {
96-
config = await NativeCodePush.getConfiguration();
96+
config = await NativeCodePush.getConfiguration();
9797
return config;
9898
}
9999
}
100100
})();
101101

102102
async function getCurrentPackage() {
103-
const localPackage = await NativeCodePush.getCurrentPackage();
104-
if (localPackage) {
105-
localPackage.failedInstall = await NativeCodePush.isFailedUpdate(localPackage.packageHash);
106-
localPackage.isFirstRun = await NativeCodePush.isFirstRun(localPackage.packageHash);
103+
return await getUpdateMetadata(CodePush.UpdateState.LATEST);
104+
}
105+
106+
async function getUpdateMetadata(updateState) {
107+
const updateMetadata = await NativeCodePush.getUpdateMetadata(updateState || CodePush.UpdateState.RUNNING);
108+
if (updateMetadata) {
109+
updateMetadata.failedInstall = await NativeCodePush.isFailedUpdate(updateMetadata.packageHash);
110+
updateMetadata.isFirstRun = await NativeCodePush.isFirstRun(updateMetadata.packageHash);
107111
}
108-
return localPackage;
112+
return updateMetadata;
109113
}
110114

111115
function getPromisifiedSdk(requestFetchAdapter, config) {
@@ -119,7 +123,7 @@ function getPromisifiedSdk(requestFetchAdapter, config) {
119123
} else {
120124
resolve(update);
121125
}
122-
});
126+
});
123127
});
124128
};
125129

@@ -131,7 +135,7 @@ function getPromisifiedSdk(requestFetchAdapter, config) {
131135
} else {
132136
resolve();
133137
}
134-
});
138+
});
135139
});
136140
};
137141

@@ -143,7 +147,7 @@ function getPromisifiedSdk(requestFetchAdapter, config) {
143147
} else {
144148
resolve();
145149
}
146-
});
150+
});
147151
});
148152
};
149153

@@ -155,21 +159,21 @@ function log(message) {
155159
console.log(`[CodePush] ${message}`)
156160
}
157161

158-
// This ensures that notifyApplicationReadyInternal is only called once
162+
// This ensures that notifyApplicationReadyInternal is only called once
159163
// in the lifetime of this module instance.
160164
const notifyApplicationReady = (() => {
161165
let notifyApplicationReadyPromise;
162166
return () => {
163167
if (!notifyApplicationReadyPromise) {
164168
notifyApplicationReadyPromise = notifyApplicationReadyInternal();
165169
}
166-
170+
167171
return notifyApplicationReadyPromise;
168172
};
169173
})();
170174

171175
async function notifyApplicationReadyInternal() {
172-
await NativeCodePush.notifyApplicationReady();
176+
await NativeCodePush.notifyApplicationReady();
173177
const statusReport = await NativeCodePush.getNewStatusReport();
174178
if (statusReport) {
175179
const config = await getConfiguration();
@@ -204,15 +208,15 @@ function setUpTestDependencies(testSdk, providedTestConfig, testNativeBridge) {
204208
const sync = (() => {
205209
let syncInProgress = false;
206210
const setSyncCompleted = () => { syncInProgress = false; };
207-
211+
208212
return (options = {}, syncStatusChangeCallback, downloadProgressCallback) => {
209213
if (syncInProgress) {
210214
typeof syncStatusChangeCallback === "function"
211215
? syncStatusChangeCallback(CodePush.SyncStatus.SYNC_IN_PROGRESS)
212216
: log("Sync already in progress.");
213217
return Promise.resolve(CodePush.SyncStatus.SYNC_IN_PROGRESS);
214-
}
215-
218+
}
219+
216220
syncInProgress = true;
217221
const syncPromise = syncInternal(options, syncStatusChangeCallback, downloadProgressCallback);
218222
syncPromise
@@ -226,7 +230,7 @@ const sync = (() => {
226230
/*
227231
* The syncInternal method provides a simple, one-line experience for
228232
* incorporating the check, download and installation of an update.
229-
*
233+
*
230234
* It simply composes the existing API methods together and adds additional
231235
* support for respecting mandatory updates, ignoring previously failed
232236
* releases, and displaying a standard confirmation UI to the end-user
@@ -241,9 +245,9 @@ async function syncInternal(options = {}, syncStatusChangeCallback, downloadProg
241245
mandatoryInstallMode: CodePush.InstallMode.IMMEDIATE,
242246
minimumBackgroundDuration: 0,
243247
updateDialog: null,
244-
...options
248+
...options
245249
};
246-
250+
247251
syncStatusChangeCallback = typeof syncStatusChangeCallback === "function"
248252
? syncStatusChangeCallback
249253
: (syncStatus) => {
@@ -267,7 +271,7 @@ async function syncInternal(options = {}, syncStatusChangeCallback, downloadProg
267271
log("User cancelled the update.");
268272
break;
269273
case CodePush.SyncStatus.UPDATE_INSTALLED:
270-
/*
274+
/*
271275
* If the install mode is IMMEDIATE, this will not get returned as the
272276
* app will be restarted to a new Javascript context.
273277
*/
@@ -286,40 +290,34 @@ async function syncInternal(options = {}, syncStatusChangeCallback, downloadProg
286290
break;
287291
}
288292
};
289-
290-
downloadProgressCallback = typeof downloadProgressCallback === "function"
291-
? downloadProgressCallback
292-
: (downloadProgress) => {
293-
log(`Expecting ${downloadProgress.totalBytes} bytes, received ${downloadProgress.receivedBytes} bytes.`);
294-
};
295-
293+
296294
try {
297295
await CodePush.notifyApplicationReady();
298-
296+
299297
syncStatusChangeCallback(CodePush.SyncStatus.CHECKING_FOR_UPDATE);
300298
const remotePackage = await checkForUpdate(syncOptions.deploymentKey);
301-
299+
302300
const doDownloadAndInstall = async () => {
303301
syncStatusChangeCallback(CodePush.SyncStatus.DOWNLOADING_PACKAGE);
304302
const localPackage = await remotePackage.download(downloadProgressCallback);
305-
303+
306304
// Determine the correct install mode based on whether the update is mandatory or not.
307305
resolvedInstallMode = localPackage.isMandatory ? syncOptions.mandatoryInstallMode : syncOptions.installMode;
308-
306+
309307
syncStatusChangeCallback(CodePush.SyncStatus.INSTALLING_UPDATE);
310308
await localPackage.install(resolvedInstallMode, syncOptions.minimumBackgroundDuration, () => {
311309
syncStatusChangeCallback(CodePush.SyncStatus.UPDATE_INSTALLED);
312310
});
313-
311+
314312
return CodePush.SyncStatus.UPDATE_INSTALLED;
315313
};
316-
314+
317315
const updateShouldBeIgnored = remotePackage && (remotePackage.failedInstall && syncOptions.ignoreFailedUpdates);
318316
if (!remotePackage || updateShouldBeIgnored) {
319317
if (updateShouldBeIgnored) {
320318
log("An update is available, but it is being ignored due to having been previously rolled back.");
321319
}
322-
320+
323321
syncStatusChangeCallback(CodePush.SyncStatus.UP_TO_DATE);
324322
return CodePush.SyncStatus.UP_TO_DATE;
325323
} else if (syncOptions.updateDialog) {
@@ -330,24 +328,24 @@ async function syncInternal(options = {}, syncStatusChangeCallback, downloadProg
330328
} else {
331329
syncOptions.updateDialog = { ...CodePush.DEFAULT_UPDATE_DIALOG, ...syncOptions.updateDialog };
332330
}
333-
334-
return await new Promise((resolve, reject) => {
331+
332+
return await new Promise((resolve, reject) => {
335333
let message = null;
336334
const dialogButtons = [{
337335
text: null,
338-
onPress: async () => {
336+
onPress: async () => {
339337
resolve(await doDownloadAndInstall());
340338
}
341339
}];
342-
340+
343341
if (remotePackage.isMandatory) {
344342
message = syncOptions.updateDialog.mandatoryUpdateMessage;
345343
dialogButtons[0].text = syncOptions.updateDialog.mandatoryContinueButtonLabel;
346344
} else {
347345
message = syncOptions.updateDialog.optionalUpdateMessage;
348-
dialogButtons[0].text = syncOptions.updateDialog.optionalInstallButtonLabel;
346+
dialogButtons[0].text = syncOptions.updateDialog.optionalInstallButtonLabel;
349347
// Since this is an optional update, add another button
350-
// to allow the end-user to ignore it
348+
// to allow the end-user to ignore it
351349
dialogButtons.push({
352350
text: syncOptions.updateDialog.optionalIgnoreButtonLabel,
353351
onPress: () => {
@@ -356,13 +354,13 @@ async function syncInternal(options = {}, syncStatusChangeCallback, downloadProg
356354
}
357355
});
358356
}
359-
357+
360358
// If the update has a description, and the developer
361359
// explicitly chose to display it, then set that as the message
362360
if (syncOptions.updateDialog.appendReleaseDescription && remotePackage.description) {
363-
message += `${syncOptions.updateDialog.descriptionPrefix} ${remotePackage.description}`;
361+
message += `${syncOptions.updateDialog.descriptionPrefix} ${remotePackage.description}`;
364362
}
365-
363+
366364
syncStatusChangeCallback(CodePush.SyncStatus.AWAITING_USER_ACTION);
367365
Alert.alert(syncOptions.updateDialog.title, message, dialogButtons);
368366
});
@@ -371,57 +369,64 @@ async function syncInternal(options = {}, syncStatusChangeCallback, downloadProg
371369
}
372370
} catch (error) {
373371
syncStatusChangeCallback(CodePush.SyncStatus.UNKNOWN_ERROR);
374-
log(error.message);
372+
log(error.message);
375373
throw error;
376-
}
374+
}
377375
};
378376

379377
let CodePush;
380378

381-
// If the "NativeCodePush" variable isn't defined, then
379+
// If the "NativeCodePush" variable isn't defined, then
382380
// the app didn't properly install the native module,
383-
// and therefore, it doesn't make sense initializing
381+
// and therefore, it doesn't make sense initializing
384382
// the JS interface when it wouldn't work anyways.
385383
if (NativeCodePush) {
386-
CodePush = {
387-
AcquisitionSdk: Sdk,
388-
checkForUpdate,
389-
getConfiguration,
390-
getCurrentPackage,
391-
log,
392-
notifyApplicationReady,
393-
restartApp,
394-
setUpTestDependencies,
395-
sync,
396-
InstallMode: {
397-
IMMEDIATE: NativeCodePush.codePushInstallModeImmediate, // Restart the app immediately
398-
ON_NEXT_RESTART: NativeCodePush.codePushInstallModeOnNextRestart, // Don't artificially restart the app. Allow the update to be "picked up" on the next app restart
399-
ON_NEXT_RESUME: NativeCodePush.codePushInstallModeOnNextResume // Restart the app the next time it is resumed from the background
400-
},
401-
SyncStatus: {
402-
CHECKING_FOR_UPDATE: 0,
403-
AWAITING_USER_ACTION: 1,
404-
DOWNLOADING_PACKAGE: 2,
405-
INSTALLING_UPDATE: 3,
406-
UP_TO_DATE: 4, // The running app is up-to-date
407-
UPDATE_IGNORED: 5, // The app had an optional update and the end-user chose to ignore it
408-
UPDATE_INSTALLED: 6, // The app had an optional/mandatory update that was successfully downloaded and is about to be installed.
409-
SYNC_IN_PROGRESS: 7, // There is an ongoing "sync" operation in progress.
410-
UNKNOWN_ERROR: -1
411-
},
412-
DEFAULT_UPDATE_DIALOG: {
413-
appendReleaseDescription: false,
414-
descriptionPrefix: " Description: ",
415-
mandatoryContinueButtonLabel: "Continue",
416-
mandatoryUpdateMessage: "An update is available that must be installed.",
417-
optionalIgnoreButtonLabel: "Ignore",
418-
optionalInstallButtonLabel: "Install",
419-
optionalUpdateMessage: "An update is available. Would you like to install it?",
420-
title: "Update available"
421-
}
384+
CodePush = {
385+
AcquisitionSdk: Sdk,
386+
checkForUpdate,
387+
getConfiguration,
388+
getCurrentPackage,
389+
getUpdateMetadata,
390+
log,
391+
notifyAppReady: notifyApplicationReady,
392+
notifyApplicationReady,
393+
restartApp,
394+
setUpTestDependencies,
395+
sync,
396+
InstallMode: {
397+
IMMEDIATE: NativeCodePush.codePushInstallModeImmediate, // Restart the app immediately
398+
ON_NEXT_RESTART: NativeCodePush.codePushInstallModeOnNextRestart, // Don't artificially restart the app. Allow the update to be "picked up" on the next app restart
399+
ON_NEXT_RESUME: NativeCodePush.codePushInstallModeOnNextResume // Restart the app the next time it is resumed from the background
400+
},
401+
SyncStatus: {
402+
CHECKING_FOR_UPDATE: 0,
403+
AWAITING_USER_ACTION: 1,
404+
DOWNLOADING_PACKAGE: 2,
405+
INSTALLING_UPDATE: 3,
406+
UP_TO_DATE: 4, // The running app is up-to-date
407+
UPDATE_IGNORED: 5, // The app had an optional update and the end-user chose to ignore it
408+
UPDATE_INSTALLED: 6, // The app had an optional/mandatory update that was successfully downloaded and is about to be installed.
409+
SYNC_IN_PROGRESS: 7, // There is an ongoing "sync" operation in progress.
410+
UNKNOWN_ERROR: -1
411+
},
412+
UpdateState: {
413+
RUNNING: NativeCodePush.codePushUpdateStateRunning,
414+
PENDING: NativeCodePush.codePushUpdateStatePending,
415+
LATEST: NativeCodePush.codePushUpdateStateLatest
416+
},
417+
DEFAULT_UPDATE_DIALOG: {
418+
appendReleaseDescription: false,
419+
descriptionPrefix: " Description: ",
420+
mandatoryContinueButtonLabel: "Continue",
421+
mandatoryUpdateMessage: "An update is available that must be installed.",
422+
optionalIgnoreButtonLabel: "Ignore",
423+
optionalInstallButtonLabel: "Install",
424+
optionalUpdateMessage: "An update is available. Would you like to install it?",
425+
title: "Update available"
422426
}
427+
};
423428
} else {
424-
log("The CodePush module doesn't appear to be properly installed. Please double-check that everything is setup correctly.");
429+
log("The CodePush module doesn't appear to be properly installed. Please double-check that everything is setup correctly.");
425430
}
426431

427-
module.exports = CodePush;
432+
module.exports = CodePush;

0 commit comments

Comments
 (0)