@@ -9,15 +9,15 @@ const PackageMixins = require("./package-mixins")(NativeCodePush);
9
9
async function checkForUpdate ( deploymentKey = null ) {
10
10
/*
11
11
* 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
13
13
* native side: deployment key, app version (e.g. 1.0.1)
14
14
* and the hash of the currently running update (if there is one).
15
15
* This allows the client to only receive updates which are targetted
16
16
* for their specific deployment and version and which are actually
17
17
* different from the CodePush update they have already installed.
18
18
*/
19
19
const nativeConfig = await getConfiguration ( ) ;
20
-
20
+
21
21
/*
22
22
* If a deployment key was explicitly provided,
23
23
* then let's override the one we retrieved
@@ -30,7 +30,7 @@ async function checkForUpdate(deploymentKey = null) {
30
30
31
31
// Use dynamically overridden getCurrentPackage() during tests.
32
32
const localPackage = await module . exports . getCurrentPackage ( ) ;
33
-
33
+
34
34
/*
35
35
* If the app has a previously installed update, and that update
36
36
* was targetted at the same app version that is currently running,
@@ -48,9 +48,9 @@ async function checkForUpdate(deploymentKey = null) {
48
48
queryPackage . packageHash = config . packageHash ;
49
49
}
50
50
}
51
-
51
+
52
52
const update = await sdk . queryUpdateWithCurrentPackage ( queryPackage ) ;
53
-
53
+
54
54
/*
55
55
* There are four cases where checkForUpdate will resolve to null:
56
56
* ----------------------------------------------------------------
@@ -69,13 +69,13 @@ async function checkForUpdate(deploymentKey = null) {
69
69
* because we want to avoid having to install diff updates against the binary's
70
70
* version, which we can't do yet on Android.
71
71
*/
72
- if ( ! update || update . updateAppVersion ||
73
- localPackage && ( update . packageHash === localPackage . packageHash ) ||
72
+ if ( ! update || update . updateAppVersion ||
73
+ localPackage && ( update . packageHash === localPackage . packageHash ) ||
74
74
( ! localPackage || localPackage . _isDebugOnly ) && config . packageHash === update . packageHash ) {
75
75
if ( update && update . updateAppVersion ) {
76
76
log ( "An update is available but it is targeting a newer binary version than you are currently running." ) ;
77
77
}
78
-
78
+
79
79
return null ;
80
80
} else {
81
81
const remotePackage = { ...update , ...PackageMixins . remote ( sdk . reportStatusDownload ) } ;
@@ -93,19 +93,23 @@ const getConfiguration = (() => {
93
93
} else if ( testConfig ) {
94
94
return testConfig ;
95
95
} else {
96
- config = await NativeCodePush . getConfiguration ( ) ;
96
+ config = await NativeCodePush . getConfiguration ( ) ;
97
97
return config ;
98
98
}
99
99
}
100
100
} ) ( ) ;
101
101
102
102
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 ) ;
107
111
}
108
- return localPackage ;
112
+ return updateMetadata ;
109
113
}
110
114
111
115
function getPromisifiedSdk ( requestFetchAdapter , config ) {
@@ -119,7 +123,7 @@ function getPromisifiedSdk(requestFetchAdapter, config) {
119
123
} else {
120
124
resolve ( update ) ;
121
125
}
122
- } ) ;
126
+ } ) ;
123
127
} ) ;
124
128
} ;
125
129
@@ -131,7 +135,7 @@ function getPromisifiedSdk(requestFetchAdapter, config) {
131
135
} else {
132
136
resolve ( ) ;
133
137
}
134
- } ) ;
138
+ } ) ;
135
139
} ) ;
136
140
} ;
137
141
@@ -143,7 +147,7 @@ function getPromisifiedSdk(requestFetchAdapter, config) {
143
147
} else {
144
148
resolve ( ) ;
145
149
}
146
- } ) ;
150
+ } ) ;
147
151
} ) ;
148
152
} ;
149
153
@@ -155,21 +159,21 @@ function log(message) {
155
159
console . log ( `[CodePush] ${ message } ` )
156
160
}
157
161
158
- // This ensures that notifyApplicationReadyInternal is only called once
162
+ // This ensures that notifyApplicationReadyInternal is only called once
159
163
// in the lifetime of this module instance.
160
164
const notifyApplicationReady = ( ( ) => {
161
165
let notifyApplicationReadyPromise ;
162
166
return ( ) => {
163
167
if ( ! notifyApplicationReadyPromise ) {
164
168
notifyApplicationReadyPromise = notifyApplicationReadyInternal ( ) ;
165
169
}
166
-
170
+
167
171
return notifyApplicationReadyPromise ;
168
172
} ;
169
173
} ) ( ) ;
170
174
171
175
async function notifyApplicationReadyInternal ( ) {
172
- await NativeCodePush . notifyApplicationReady ( ) ;
176
+ await NativeCodePush . notifyApplicationReady ( ) ;
173
177
const statusReport = await NativeCodePush . getNewStatusReport ( ) ;
174
178
if ( statusReport ) {
175
179
const config = await getConfiguration ( ) ;
@@ -204,15 +208,15 @@ function setUpTestDependencies(testSdk, providedTestConfig, testNativeBridge) {
204
208
const sync = ( ( ) => {
205
209
let syncInProgress = false ;
206
210
const setSyncCompleted = ( ) => { syncInProgress = false ; } ;
207
-
211
+
208
212
return ( options = { } , syncStatusChangeCallback , downloadProgressCallback ) => {
209
213
if ( syncInProgress ) {
210
214
typeof syncStatusChangeCallback === "function"
211
215
? syncStatusChangeCallback ( CodePush . SyncStatus . SYNC_IN_PROGRESS )
212
216
: log ( "Sync already in progress." ) ;
213
217
return Promise . resolve ( CodePush . SyncStatus . SYNC_IN_PROGRESS ) ;
214
- }
215
-
218
+ }
219
+
216
220
syncInProgress = true ;
217
221
const syncPromise = syncInternal ( options , syncStatusChangeCallback , downloadProgressCallback ) ;
218
222
syncPromise
@@ -226,7 +230,7 @@ const sync = (() => {
226
230
/*
227
231
* The syncInternal method provides a simple, one-line experience for
228
232
* incorporating the check, download and installation of an update.
229
- *
233
+ *
230
234
* It simply composes the existing API methods together and adds additional
231
235
* support for respecting mandatory updates, ignoring previously failed
232
236
* releases, and displaying a standard confirmation UI to the end-user
@@ -241,9 +245,9 @@ async function syncInternal(options = {}, syncStatusChangeCallback, downloadProg
241
245
mandatoryInstallMode : CodePush . InstallMode . IMMEDIATE ,
242
246
minimumBackgroundDuration : 0 ,
243
247
updateDialog : null ,
244
- ...options
248
+ ...options
245
249
} ;
246
-
250
+
247
251
syncStatusChangeCallback = typeof syncStatusChangeCallback === "function"
248
252
? syncStatusChangeCallback
249
253
: ( syncStatus ) => {
@@ -267,7 +271,7 @@ async function syncInternal(options = {}, syncStatusChangeCallback, downloadProg
267
271
log ( "User cancelled the update." ) ;
268
272
break ;
269
273
case CodePush . SyncStatus . UPDATE_INSTALLED :
270
- /*
274
+ /*
271
275
* If the install mode is IMMEDIATE, this will not get returned as the
272
276
* app will be restarted to a new Javascript context.
273
277
*/
@@ -286,40 +290,34 @@ async function syncInternal(options = {}, syncStatusChangeCallback, downloadProg
286
290
break ;
287
291
}
288
292
} ;
289
-
290
- downloadProgressCallback = typeof downloadProgressCallback === "function"
291
- ? downloadProgressCallback
292
- : ( downloadProgress ) => {
293
- log ( `Expecting ${ downloadProgress . totalBytes } bytes, received ${ downloadProgress . receivedBytes } bytes.` ) ;
294
- } ;
295
-
293
+
296
294
try {
297
295
await CodePush . notifyApplicationReady ( ) ;
298
-
296
+
299
297
syncStatusChangeCallback ( CodePush . SyncStatus . CHECKING_FOR_UPDATE ) ;
300
298
const remotePackage = await checkForUpdate ( syncOptions . deploymentKey ) ;
301
-
299
+
302
300
const doDownloadAndInstall = async ( ) => {
303
301
syncStatusChangeCallback ( CodePush . SyncStatus . DOWNLOADING_PACKAGE ) ;
304
302
const localPackage = await remotePackage . download ( downloadProgressCallback ) ;
305
-
303
+
306
304
// Determine the correct install mode based on whether the update is mandatory or not.
307
305
resolvedInstallMode = localPackage . isMandatory ? syncOptions . mandatoryInstallMode : syncOptions . installMode ;
308
-
306
+
309
307
syncStatusChangeCallback ( CodePush . SyncStatus . INSTALLING_UPDATE ) ;
310
308
await localPackage . install ( resolvedInstallMode , syncOptions . minimumBackgroundDuration , ( ) => {
311
309
syncStatusChangeCallback ( CodePush . SyncStatus . UPDATE_INSTALLED ) ;
312
310
} ) ;
313
-
311
+
314
312
return CodePush . SyncStatus . UPDATE_INSTALLED ;
315
313
} ;
316
-
314
+
317
315
const updateShouldBeIgnored = remotePackage && ( remotePackage . failedInstall && syncOptions . ignoreFailedUpdates ) ;
318
316
if ( ! remotePackage || updateShouldBeIgnored ) {
319
317
if ( updateShouldBeIgnored ) {
320
318
log ( "An update is available, but it is being ignored due to having been previously rolled back." ) ;
321
319
}
322
-
320
+
323
321
syncStatusChangeCallback ( CodePush . SyncStatus . UP_TO_DATE ) ;
324
322
return CodePush . SyncStatus . UP_TO_DATE ;
325
323
} else if ( syncOptions . updateDialog ) {
@@ -330,24 +328,24 @@ async function syncInternal(options = {}, syncStatusChangeCallback, downloadProg
330
328
} else {
331
329
syncOptions . updateDialog = { ...CodePush . DEFAULT_UPDATE_DIALOG , ...syncOptions . updateDialog } ;
332
330
}
333
-
334
- return await new Promise ( ( resolve , reject ) => {
331
+
332
+ return await new Promise ( ( resolve , reject ) => {
335
333
let message = null ;
336
334
const dialogButtons = [ {
337
335
text : null ,
338
- onPress : async ( ) => {
336
+ onPress : async ( ) => {
339
337
resolve ( await doDownloadAndInstall ( ) ) ;
340
338
}
341
339
} ] ;
342
-
340
+
343
341
if ( remotePackage . isMandatory ) {
344
342
message = syncOptions . updateDialog . mandatoryUpdateMessage ;
345
343
dialogButtons [ 0 ] . text = syncOptions . updateDialog . mandatoryContinueButtonLabel ;
346
344
} else {
347
345
message = syncOptions . updateDialog . optionalUpdateMessage ;
348
- dialogButtons [ 0 ] . text = syncOptions . updateDialog . optionalInstallButtonLabel ;
346
+ dialogButtons [ 0 ] . text = syncOptions . updateDialog . optionalInstallButtonLabel ;
349
347
// 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
351
349
dialogButtons . push ( {
352
350
text : syncOptions . updateDialog . optionalIgnoreButtonLabel ,
353
351
onPress : ( ) => {
@@ -356,13 +354,13 @@ async function syncInternal(options = {}, syncStatusChangeCallback, downloadProg
356
354
}
357
355
} ) ;
358
356
}
359
-
357
+
360
358
// If the update has a description, and the developer
361
359
// explicitly chose to display it, then set that as the message
362
360
if ( syncOptions . updateDialog . appendReleaseDescription && remotePackage . description ) {
363
- message += `${ syncOptions . updateDialog . descriptionPrefix } ${ remotePackage . description } ` ;
361
+ message += `${ syncOptions . updateDialog . descriptionPrefix } ${ remotePackage . description } ` ;
364
362
}
365
-
363
+
366
364
syncStatusChangeCallback ( CodePush . SyncStatus . AWAITING_USER_ACTION ) ;
367
365
Alert . alert ( syncOptions . updateDialog . title , message , dialogButtons ) ;
368
366
} ) ;
@@ -371,57 +369,64 @@ async function syncInternal(options = {}, syncStatusChangeCallback, downloadProg
371
369
}
372
370
} catch ( error ) {
373
371
syncStatusChangeCallback ( CodePush . SyncStatus . UNKNOWN_ERROR ) ;
374
- log ( error . message ) ;
372
+ log ( error . message ) ;
375
373
throw error ;
376
- }
374
+ }
377
375
} ;
378
376
379
377
let CodePush ;
380
378
381
- // If the "NativeCodePush" variable isn't defined, then
379
+ // If the "NativeCodePush" variable isn't defined, then
382
380
// 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
384
382
// the JS interface when it wouldn't work anyways.
385
383
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"
422
426
}
427
+ } ;
423
428
} 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." ) ;
425
430
}
426
431
427
- module . exports = CodePush ;
432
+ module . exports = CodePush ;
0 commit comments