@bravemobile/react-native-code-push 12.4.0 → 13.0.0

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.
@@ -7,7 +7,7 @@
7
7
  objects = {
8
8
 
9
9
  /* Begin PBXBuildFile section */
10
- 13BE3DEE1AC21097009241FE /* CodePush.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* CodePush.m */; };
10
+ 13BE3DEE1AC21097009241FE /* CodePush.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* CodePush.mm */; };
11
11
  1B23B9141BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */; };
12
12
  1B762E901C9A5E9A006EF800 /* CodePushErrorUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B762E8F1C9A5E9A006EF800 /* CodePushErrorUtils.m */; };
13
13
  1BCC09A71CC19EB700DDC0DD /* RCTConvert+CodePushUpdateState.m in Sources */ = {isa = PBXBuildFile; fileRef = 1BCC09A61CC19EB700DDC0DD /* RCTConvert+CodePushUpdateState.m */; };
@@ -82,7 +82,7 @@
82
82
  5498D8F61D21F14100B5EB43 /* CodePushUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 5498D8F51D21F14100B5EB43 /* CodePushUtils.m */; };
83
83
  54FFEDE01BF550630061DD23 /* CodePushDownloadHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 54FFEDDF1BF550630061DD23 /* CodePushDownloadHandler.m */; };
84
84
  6463C82D1EBA0CFB0095B8CD /* CodePushUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 5498D8F51D21F14100B5EB43 /* CodePushUtils.m */; };
85
- 6463C82E1EBA0CFB0095B8CD /* CodePush.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* CodePush.m */; };
85
+ 6463C82E1EBA0CFB0095B8CD /* CodePush.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* CodePush.mm */; };
86
86
  6463C82F1EBA0CFB0095B8CD /* CodePushConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 81D51F391B6181C2000DA084 /* CodePushConfig.m */; };
87
87
  6463C8301EBA0CFB0095B8CD /* CodePushDownloadHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 54FFEDDF1BF550630061DD23 /* CodePushDownloadHandler.m */; };
88
88
  6463C8311EBA0CFB0095B8CD /* CodePushErrorUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B762E8F1C9A5E9A006EF800 /* CodePushErrorUtils.m */; };
@@ -125,7 +125,7 @@
125
125
  /* Begin PBXFileReference section */
126
126
  134814201AA4EA6300B7C361 /* libCodePush.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCodePush.a; sourceTree = BUILT_PRODUCTS_DIR; };
127
127
  13BE3DEC1AC21097009241FE /* CodePush.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CodePush.h; path = CodePush/CodePush.h; sourceTree = "<group>"; };
128
- 13BE3DED1AC21097009241FE /* CodePush.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CodePush.m; path = CodePush/CodePush.m; sourceTree = "<group>"; };
128
+ 13BE3DED1AC21097009241FE /* CodePush.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = CodePush.mm; path = CodePush/CodePush.mm; sourceTree = "<group>"; };
129
129
  1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "RCTConvert+CodePushInstallMode.m"; path = "CodePush/RCTConvert+CodePushInstallMode.m"; sourceTree = "<group>"; };
130
130
  1B762E8F1C9A5E9A006EF800 /* CodePushErrorUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CodePushErrorUtils.m; path = CodePush/CodePushErrorUtils.m; sourceTree = "<group>"; };
131
131
  1BCC09A61CC19EB700DDC0DD /* RCTConvert+CodePushUpdateState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "RCTConvert+CodePushUpdateState.m"; path = "CodePush/RCTConvert+CodePushUpdateState.m"; sourceTree = "<group>"; };
@@ -277,7 +277,7 @@
277
277
  FF90DEF92C5A808600CA8692 /* PrivacyInfo.xcprivacy */,
278
278
  5498D8F51D21F14100B5EB43 /* CodePushUtils.m */,
279
279
  13BE3DEC1AC21097009241FE /* CodePush.h */,
280
- 13BE3DED1AC21097009241FE /* CodePush.m */,
280
+ 13BE3DED1AC21097009241FE /* CodePush.mm */,
281
281
  81D51F391B6181C2000DA084 /* CodePushConfig.m */,
282
282
  54FFEDDF1BF550630061DD23 /* CodePushDownloadHandler.m */,
283
283
  1B762E8F1C9A5E9A006EF800 /* CodePushErrorUtils.m */,
@@ -451,7 +451,7 @@
451
451
  3221E4912C8ABE1400268379 /* SSZipArchive.m in Sources */,
452
452
  5421FE311C58AD5A00986A55 /* CodePushTelemetryManager.m in Sources */,
453
453
  3221E46F2C8ABE1300268379 /* mz_strm_wzaes.c in Sources */,
454
- 13BE3DEE1AC21097009241FE /* CodePush.m in Sources */,
454
+ 13BE3DEE1AC21097009241FE /* CodePush.mm in Sources */,
455
455
  3221E45D2C8ABE1300268379 /* mz_zip.c in Sources */,
456
456
  1B762E901C9A5E9A006EF800 /* CodePushErrorUtils.m in Sources */,
457
457
  3221E4832C8ABE1400268379 /* mz_strm_split.c in Sources */,
@@ -473,7 +473,7 @@
473
473
  3221E4822C8ABE1400268379 /* mz_strm_buf.c in Sources */,
474
474
  3221E45E2C8ABE1300268379 /* mz_zip.c in Sources */,
475
475
  6463C82D1EBA0CFB0095B8CD /* CodePushUtils.m in Sources */,
476
- 6463C82E1EBA0CFB0095B8CD /* CodePush.m in Sources */,
476
+ 6463C82E1EBA0CFB0095B8CD /* CodePush.mm in Sources */,
477
477
  6463C82F1EBA0CFB0095B8CD /* CodePushConfig.m in Sources */,
478
478
  6463C8301EBA0CFB0095B8CD /* CodePushDownloadHandler.m in Sources */,
479
479
  6463C8311EBA0CFB0095B8CD /* CodePushErrorUtils.m in Sources */,
package/package.json CHANGED
@@ -1,11 +1,24 @@
1
1
  {
2
2
  "name": "@bravemobile/react-native-code-push",
3
- "version": "12.4.0",
3
+ "version": "13.0.0",
4
4
  "description": "React Native plugin for the CodePush service",
5
5
  "main": "src/CodePush.js",
6
6
  "react-native": "src/CodePush.js",
7
7
  "source": "src/CodePush.js",
8
8
  "types": "typings/react-native-code-push.d.ts",
9
+ "codegenConfig": {
10
+ "name": "RNCodePushSpec",
11
+ "type": "modules",
12
+ "jsSrcsDir": "src/specs",
13
+ "android": {
14
+ "javaPackageName": "com.microsoft.codepush.react"
15
+ },
16
+ "ios": {
17
+ "modulesProvider": {
18
+ "CodePush": "CodePush"
19
+ }
20
+ }
21
+ },
9
22
  "homepage": "https://microsoft.github.io/code-push",
10
23
  "keywords": [
11
24
  "react-native",
@@ -54,10 +67,11 @@
54
67
  "setup": "npm install --quiet --no-progress",
55
68
  "setup-example-app": "ts-node --project scripts/setupExampleApp/tsconfig.json scripts/setupExampleApp/runSetupExampleApp.ts",
56
69
  "setup-expo-example-app": "ts-node --project scripts/setupExampleApp/tsconfig.json scripts/setupExpoExampleApp/runSetupExpoExampleApp.ts",
70
+ "type:src": "tsc --project tsconfig.json --noEmit",
57
71
  "type:cli": "npm run --workspace cli typecheck",
58
72
  "type:scripts": "tsc --project scripts/tsconfig.json --noEmit",
59
73
  "type:e2e": "tsc --project e2e/tsconfig.json --noEmit",
60
- "typecheck": "npm run type:cli && npm run type:scripts && npm run type:e2e",
74
+ "typecheck": "npm run type:src && npm run type:cli && npm run type:scripts && npm run type:e2e",
61
75
  "build:cli": "npm run --workspace cli clean && npm run --workspace cli build",
62
76
  "prepack": "npm run build:cli",
63
77
  "publish": "npm publish --access=public",
@@ -94,6 +108,7 @@
94
108
  "@eslint/js": "^9.13.0",
95
109
  "@types/express": "^5.0.6",
96
110
  "@types/node": "^18.19.129",
111
+ "@types/react": "19.2.14",
97
112
  "@types/semver": "^7.5.8",
98
113
  "@types/shelljs": "^0.8.15",
99
114
  "@types/yauzl": "^2.10.3",
@@ -103,6 +118,8 @@
103
118
  "express": "latest",
104
119
  "globals": "^15.11.0",
105
120
  "jest": "^29.7.0",
121
+ "react": "19.2.3",
122
+ "react-native": "0.84.1",
106
123
  "ts-node": "^10.9.2",
107
124
  "typescript": "5.0.4",
108
125
  "typescript-eslint": "^8.11.0"
@@ -5,7 +5,9 @@ module.exports = {
5
5
  packageImportPath: "import com.microsoft.codepush.react.CodePush;",
6
6
  packageInstance:
7
7
  "CodePush.getInstance(getApplicationContext(), BuildConfig.DEBUG)",
8
- sourceDir: './android/app'
8
+ sourceDir: './android/app',
9
+ libraryName: 'RNCodePushSpec',
10
+ cmakeListsPath: 'build/generated/source/codegen/jni/CMakeLists.txt',
9
11
  }
10
12
  }
11
13
  }
package/src/CodePush.js CHANGED
@@ -1,14 +1,46 @@
1
- import { Alert } from "./AlertAdapter";
2
- import { AppState, Platform } from "react-native";
1
+ import { Alert, AppState, Platform } from "react-native";
3
2
  import log from "./logging";
4
3
  import hoistStatics from 'hoist-non-react-statics';
5
4
  import { SemverVersioning } from './versioning/SemverVersioning'
6
5
 
7
- let NativeCodePush = require("react-native").NativeModules.CodePush;
8
- const PackageMixins = require("./package-mixins")(NativeCodePush);
6
+ const NativeCodePushModule = require("./native/NativeCodePush");
7
+ let NativeCodePush = NativeCodePushModule.getNativeCodePush?.() ?? NativeCodePushModule.default;
8
+ const { InstallMode, UpdateState } = NativeCodePushModule;
9
+ let PackageMixins = NativeCodePush ? require("./package-mixins")(NativeCodePush) : null;
9
10
 
10
11
  const DEPLOYMENT_KEY = 'deprecated_deployment_key';
11
12
 
13
+ function getNativeCodePush() {
14
+ if (!NativeCodePush) {
15
+ const NativeCodePushModule = require("./native/NativeCodePush");
16
+ NativeCodePush = NativeCodePushModule.getNativeCodePush?.() ?? NativeCodePushModule.default;
17
+ }
18
+
19
+ if (NativeCodePush && !PackageMixins) {
20
+ PackageMixins = require("./package-mixins")(NativeCodePush);
21
+ }
22
+
23
+ return NativeCodePush;
24
+ }
25
+
26
+ function requireNativeCodePush(callerName) {
27
+ const nativeCodePush = getNativeCodePush();
28
+ if (!nativeCodePush) {
29
+ throw new Error(`The CodePush native module isn't available during ${callerName}.`);
30
+ }
31
+
32
+ return nativeCodePush;
33
+ }
34
+
35
+ function requirePackageMixins(callerName) {
36
+ const nativeCodePush = requireNativeCodePush(callerName);
37
+ if (!PackageMixins) {
38
+ PackageMixins = require("./package-mixins")(nativeCodePush);
39
+ }
40
+
41
+ return PackageMixins;
42
+ }
43
+
12
44
  /**
13
45
  * @param deviceId {string}
14
46
  * @returns {number}
@@ -67,7 +99,7 @@ async function checkForUpdate(handleBinaryVersionMismatchCallback = null) {
67
99
  * for their specific deployment and version and which are actually
68
100
  * different from the CodePush update they have already installed.
69
101
  */
70
- const nativeConfig = await getConfiguration();
102
+ const nativeConfig = await getConfiguration("checkForUpdate");
71
103
 
72
104
  // Use dynamically overridden getCurrentPackage() during tests.
73
105
  const localPackage = await module.exports.getCurrentPackage();
@@ -217,8 +249,10 @@ async function checkForUpdate(handleBinaryVersionMismatchCallback = null) {
217
249
 
218
250
  return null;
219
251
  } else {
220
- const remotePackage = { ...update, ...PackageMixins.remote() };
221
- remotePackage.failedInstall = await NativeCodePush.isFailedUpdate(remotePackage.packageHash);
252
+ const nativeCodePush = requireNativeCodePush("checkForUpdate");
253
+ const packageMixins = requirePackageMixins("checkForUpdate");
254
+ const remotePackage = { ...update, ...packageMixins.remote() };
255
+ remotePackage.failedInstall = await nativeCodePush.isFailedUpdate(remotePackage.packageHash);
222
256
  return remotePackage;
223
257
  }
224
258
  }
@@ -252,13 +286,14 @@ function mapToRemotePackageMetadata(updateInfo) {
252
286
 
253
287
  const getConfiguration = (() => {
254
288
  let config;
255
- return async function getConfiguration() {
289
+ return async function getConfiguration(callerName = "getConfiguration") {
256
290
  if (config) {
257
291
  return config;
258
292
  } else if (testConfig) {
259
293
  return testConfig;
260
294
  } else {
261
- config = await NativeCodePush.getConfiguration();
295
+ const nativeCodePush = requireNativeCodePush(callerName);
296
+ config = await nativeCodePush.getConfiguration();
262
297
  return config;
263
298
  }
264
299
  }
@@ -269,11 +304,13 @@ async function getCurrentPackage() {
269
304
  }
270
305
 
271
306
  async function getUpdateMetadata(updateState) {
272
- let updateMetadata = await NativeCodePush.getUpdateMetadata(updateState || CodePush.UpdateState.RUNNING);
307
+ const nativeCodePush = requireNativeCodePush("getUpdateMetadata");
308
+ const packageMixins = requirePackageMixins("getUpdateMetadata");
309
+ let updateMetadata = await nativeCodePush.getUpdateMetadata(updateState || CodePush.UpdateState.RUNNING);
273
310
  if (updateMetadata) {
274
- updateMetadata = { ...PackageMixins.local, ...updateMetadata };
275
- updateMetadata.failedInstall = await NativeCodePush.isFailedUpdate(updateMetadata.packageHash);
276
- updateMetadata.isFirstRun = await NativeCodePush.isFirstRun(updateMetadata.packageHash);
311
+ updateMetadata = { ...packageMixins.local, ...updateMetadata };
312
+ updateMetadata.failedInstall = await nativeCodePush.isFailedUpdate(updateMetadata.packageHash);
313
+ updateMetadata.isFirstRun = await nativeCodePush.isFirstRun(updateMetadata.packageHash);
277
314
  }
278
315
  return updateMetadata;
279
316
  }
@@ -292,14 +329,21 @@ const notifyApplicationReady = (() => {
292
329
  })();
293
330
 
294
331
  async function notifyApplicationReadyInternal() {
295
- await NativeCodePush.notifyApplicationReady();
296
- const statusReport = await NativeCodePush.getNewStatusReport();
332
+ const nativeCodePush = requireNativeCodePush("notifyApplicationReady");
333
+ await nativeCodePush.notifyApplicationReady();
334
+ const statusReport = await nativeCodePush.getNewStatusReport();
297
335
  statusReport && tryReportStatus(statusReport); // Don't wait for this to complete.
298
336
 
299
337
  return statusReport;
300
338
  }
301
339
 
302
340
  async function tryReportStatus(statusReport, retryOnAppResume) {
341
+ const nativeCodePush = getNativeCodePush();
342
+ if (!nativeCodePush) {
343
+ retryOnAppResume && retryOnAppResume.remove();
344
+ return;
345
+ }
346
+
303
347
  try {
304
348
  if (statusReport.appVersion) {
305
349
  log(`Reporting binary update (${statusReport.appVersion})`);
@@ -310,22 +354,27 @@ async function tryReportStatus(statusReport, retryOnAppResume) {
310
354
  sharedCodePushOptions?.onUpdateSuccess?.(label);
311
355
  } else {
312
356
  log(`Reporting CodePush update rollback (${label})`);
313
- await NativeCodePush.setLatestRollbackInfo(statusReport.package.packageHash);
357
+ await nativeCodePush.setLatestRollbackInfo(statusReport.package.packageHash);
314
358
  sharedCodePushOptions?.onUpdateRollback?.(label);
315
359
  }
316
360
  }
317
361
 
318
- NativeCodePush.recordStatusReported(statusReport);
362
+ nativeCodePush.recordStatusReported(statusReport);
319
363
  retryOnAppResume && retryOnAppResume.remove();
320
364
  } catch (e) {
321
365
  log(`${e}`)
322
366
  log(`Report status failed: ${JSON.stringify(statusReport)}`);
323
- NativeCodePush.saveStatusReportForRetry(statusReport);
367
+ nativeCodePush.saveStatusReportForRetry(statusReport);
324
368
  // Try again when the app resumes
325
369
  if (!retryOnAppResume) {
326
370
  const resumeListener = AppState.addEventListener("change", async (newState) => {
327
371
  if (newState !== "active") return;
328
- const refreshedStatusReport = await NativeCodePush.getNewStatusReport();
372
+ const refreshedNativeCodePush = getNativeCodePush();
373
+ if (!refreshedNativeCodePush) {
374
+ return;
375
+ }
376
+
377
+ const refreshedStatusReport = await refreshedNativeCodePush.getNewStatusReport();
329
378
  if (refreshedStatusReport) {
330
379
  tryReportStatus(refreshedStatusReport, resumeListener);
331
380
  } else {
@@ -358,7 +407,8 @@ async function shouldUpdateBeIgnored(remotePackage, syncOptions) {
358
407
  return true;
359
408
  }
360
409
 
361
- const latestRollbackInfo = await NativeCodePush.getLatestRollbackInfo();
410
+ const nativeCodePush = requireNativeCodePush("shouldUpdateBeIgnored");
411
+ const latestRollbackInfo = await nativeCodePush.getLatestRollbackInfo();
362
412
  if (!validateLatestRollbackInfo(latestRollbackInfo, remotePackage.packageHash)) {
363
413
  log("The latest rollback info is not valid.");
364
414
  return true;
@@ -407,11 +457,15 @@ let testConfig;
407
457
  function setUpTestDependencies(testSdk, providedTestConfig, testNativeBridge) {
408
458
  if (testSdk) module.exports.AcquisitionSdk = testSdk;
409
459
  if (providedTestConfig) testConfig = providedTestConfig;
410
- if (testNativeBridge) NativeCodePush = testNativeBridge;
460
+ if (testNativeBridge) {
461
+ NativeCodePush = testNativeBridge;
462
+ PackageMixins = require("./package-mixins")(NativeCodePush);
463
+ }
411
464
  }
412
465
 
413
466
  async function restartApp(onlyIfUpdateIsPending = false) {
414
- NativeCodePush.restartApp(onlyIfUpdateIsPending);
467
+ const nativeCodePush = requireNativeCodePush("restartApp");
468
+ nativeCodePush.restartApp(onlyIfUpdateIsPending);
415
469
  }
416
470
 
417
471
  // This function allows only one syncInternal operation to proceed at any given time.
@@ -817,76 +871,73 @@ function codePushify(options = {}) {
817
871
  }
818
872
  }
819
873
 
820
- // If the "NativeCodePush" variable isn't defined, then
821
- // the app didn't properly install the native module,
822
- // and therefore, it doesn't make sense initializing
823
- // the JS interface when it wouldn't work anyways.
824
- if (NativeCodePush) {
825
- CodePush = codePushify;
826
- Object.assign(CodePush, {
827
- checkForUpdate,
828
- getConfiguration,
829
- getCurrentPackage,
830
- getUpdateMetadata,
831
- log,
832
- notifyAppReady: notifyApplicationReady,
833
- notifyApplicationReady,
834
- restartApp,
835
- setUpTestDependencies,
836
- sync,
837
- disallowRestart: NativeCodePush.disallow,
838
- allowRestart: NativeCodePush.allow,
839
- clearUpdates: NativeCodePush.clearUpdates,
840
- InstallMode: {
841
- IMMEDIATE: NativeCodePush.codePushInstallModeImmediate, // Restart the app immediately
842
- ON_NEXT_RESTART: NativeCodePush.codePushInstallModeOnNextRestart, // Don't artificially restart the app. Allow the update to be "picked up" on the next app restart
843
- ON_NEXT_RESUME: NativeCodePush.codePushInstallModeOnNextResume, // Restart the app the next time it is resumed from the background
844
- ON_NEXT_SUSPEND: NativeCodePush.codePushInstallModeOnNextSuspend, // Restart the app _while_ it is in the background,
845
- // but only after it has been in the background for "minimumBackgroundDuration" seconds (0 by default),
846
- // so that user context isn't lost unless the app suspension is long enough to not matter
847
- },
848
- SyncStatus: {
849
- UP_TO_DATE: 0, // The running app is up-to-date
850
- UPDATE_INSTALLED: 1, // The app had an optional/mandatory update that was successfully downloaded and is about to be installed.
851
- UPDATE_IGNORED: 2, // The app had an optional update and the end-user chose to ignore it
852
- UNKNOWN_ERROR: 3,
853
- SYNC_IN_PROGRESS: 4, // There is an ongoing "sync" operation in progress.
854
- CHECKING_FOR_UPDATE: 5,
855
- AWAITING_USER_ACTION: 6,
856
- DOWNLOADING_PACKAGE: 7,
857
- INSTALLING_UPDATE: 8,
858
- },
859
- CheckFrequency: {
860
- ON_APP_START: 0,
861
- ON_APP_RESUME: 1,
862
- MANUAL: 2,
863
- },
864
- UpdateState: {
865
- RUNNING: NativeCodePush.codePushUpdateStateRunning,
866
- PENDING: NativeCodePush.codePushUpdateStatePending,
867
- LATEST: NativeCodePush.codePushUpdateStateLatest,
868
- },
869
- DeploymentStatus: {
870
- FAILED: "DeploymentFailed",
871
- SUCCEEDED: "DeploymentSucceeded",
872
- },
873
- DEFAULT_UPDATE_DIALOG: {
874
- appendReleaseDescription: false,
875
- descriptionPrefix: " Description: ",
876
- mandatoryContinueButtonLabel: "Continue",
877
- mandatoryUpdateMessage: "An update is available that must be installed.",
878
- optionalIgnoreButtonLabel: "Ignore",
879
- optionalInstallButtonLabel: "Install",
880
- optionalUpdateMessage: "An update is available. Would you like to install it?",
881
- title: "Update available",
882
- },
883
- DEFAULT_ROLLBACK_RETRY_OPTIONS: {
884
- delayInHours: 24,
885
- maxRetryAttempts: 1,
886
- },
887
- });
888
- } else {
889
- log("The CodePush module doesn't appear to be properly installed. Please double-check that everything is setup correctly.");
890
- }
874
+ CodePush = codePushify;
875
+ Object.assign(CodePush, {
876
+ checkForUpdate,
877
+ getConfiguration,
878
+ getCurrentPackage,
879
+ getUpdateMetadata,
880
+ log,
881
+ notifyAppReady: notifyApplicationReady,
882
+ notifyApplicationReady,
883
+ restartApp,
884
+ setUpTestDependencies,
885
+ sync,
886
+ disallowRestart: () => {
887
+ const nativeCodePush = requireNativeCodePush("disallowRestart");
888
+ return nativeCodePush.disallow();
889
+ },
890
+ allowRestart: () => {
891
+ const nativeCodePush = requireNativeCodePush("allowRestart");
892
+ return nativeCodePush.allow();
893
+ },
894
+ clearUpdates: () => {
895
+ const nativeCodePush = requireNativeCodePush("clearUpdates");
896
+ return nativeCodePush.clearUpdates();
897
+ },
898
+ InstallMode: {
899
+ IMMEDIATE: InstallMode.IMMEDIATE, // Restart the app immediately
900
+ ON_NEXT_RESTART: InstallMode.ON_NEXT_RESTART, // Don't artificially restart the app. Allow the update to be "picked up" on the next app restart
901
+ ON_NEXT_RESUME: InstallMode.ON_NEXT_RESUME, // Restart the app the next time it is resumed from the background
902
+ ON_NEXT_SUSPEND: InstallMode.ON_NEXT_SUSPEND, // Restart the app _while_ it is in the background,
903
+ // but only after it has been in the background for "minimumBackgroundDuration" seconds (0 by default),
904
+ // so that user context isn't lost unless the app suspension is long enough to not matter
905
+ },
906
+ SyncStatus: {
907
+ UP_TO_DATE: 0, // The running app is up-to-date
908
+ UPDATE_INSTALLED: 1, // The app had an optional/mandatory update that was successfully downloaded and is about to be installed.
909
+ UPDATE_IGNORED: 2, // The app had an optional update and the end-user chose to ignore it
910
+ UNKNOWN_ERROR: 3,
911
+ SYNC_IN_PROGRESS: 4, // There is an ongoing "sync" operation in progress.
912
+ CHECKING_FOR_UPDATE: 5,
913
+ AWAITING_USER_ACTION: 6,
914
+ DOWNLOADING_PACKAGE: 7,
915
+ INSTALLING_UPDATE: 8,
916
+ },
917
+ CheckFrequency: {
918
+ ON_APP_START: 0,
919
+ ON_APP_RESUME: 1,
920
+ MANUAL: 2,
921
+ },
922
+ UpdateState,
923
+ DeploymentStatus: {
924
+ FAILED: "DeploymentFailed",
925
+ SUCCEEDED: "DeploymentSucceeded",
926
+ },
927
+ DEFAULT_UPDATE_DIALOG: {
928
+ appendReleaseDescription: false,
929
+ descriptionPrefix: " Description: ",
930
+ mandatoryContinueButtonLabel: "Continue",
931
+ mandatoryUpdateMessage: "An update is available that must be installed.",
932
+ optionalIgnoreButtonLabel: "Ignore",
933
+ optionalInstallButtonLabel: "Install",
934
+ optionalUpdateMessage: "An update is available. Would you like to install it?",
935
+ title: "Update available",
936
+ },
937
+ DEFAULT_ROLLBACK_RETRY_OPTIONS: {
938
+ delayInHours: 24,
939
+ maxRetryAttempts: 1,
940
+ },
941
+ });
891
942
 
892
943
  module.exports = CodePush;
@@ -0,0 +1,162 @@
1
+ import { NativeEventEmitter, NativeModules } from 'react-native';
2
+ import { getNativeCodePushTurboModule } from '../specs/NativeCodePush';
3
+ import type { DownloadProgress, Spec as NativeCodePushSpec } from '../specs/NativeCodePush';
4
+
5
+ export const DOWNLOAD_PROGRESS_EVENT_NAME = 'CodePushDownloadProgress';
6
+
7
+ export const InstallMode = Object.freeze({
8
+ IMMEDIATE: 0,
9
+ ON_NEXT_RESTART: 1,
10
+ ON_NEXT_RESUME: 2,
11
+ ON_NEXT_SUSPEND: 3,
12
+ });
13
+
14
+ export const UpdateState = Object.freeze({
15
+ RUNNING: 0,
16
+ PENDING: 1,
17
+ LATEST: 2,
18
+ });
19
+
20
+ type Subscription = {
21
+ remove: () => void;
22
+ };
23
+
24
+ type LegacyCodePushModule = {
25
+ addListener?: (eventName: string) => void;
26
+ allow: () => void | Promise<void>;
27
+ clearPendingRestart: () => void | Promise<void>;
28
+ clearUpdates: () => void;
29
+ disallow: () => void | Promise<void>;
30
+ downloadAndReplaceCurrentBundle?: (remoteBundleUrl: string) => void;
31
+ downloadUpdate: (updatePackage: object, notifyProgress: boolean) => Promise<object>;
32
+ getConfiguration: () => Promise<object>;
33
+ getLatestRollbackInfo: () => Promise<object | null>;
34
+ getNewStatusReport: () => Promise<object | string | null>;
35
+ getUpdateMetadata: (updateState: number) => Promise<object | null>;
36
+ installUpdate: (
37
+ updatePackage: object,
38
+ installMode: number,
39
+ minimumBackgroundDuration: number,
40
+ ) => Promise<void>;
41
+ isFailedUpdate: (packageHash: string) => Promise<boolean>;
42
+ isFirstRun: (packageHash: string) => Promise<boolean>;
43
+ notifyApplicationReady: () => Promise<void>;
44
+ recordStatusReported: (statusReport: object) => void;
45
+ removeListeners?: (count: number) => void;
46
+ restartApp: (onlyIfUpdateIsPending: boolean) => void | Promise<void>;
47
+ saveStatusReportForRetry: (statusReport: object) => void;
48
+ setLatestRollbackInfo: (packageHash: string) => Promise<void>;
49
+ };
50
+
51
+ type CodePushModule = LegacyCodePushModule & {
52
+ onDownloadProgress?: NativeCodePushSpec['onDownloadProgress'];
53
+ };
54
+
55
+ type EventEmitterCapableCodePushModule = LegacyCodePushModule & {
56
+ addListener: NonNullable<LegacyCodePushModule['addListener']>;
57
+ removeListeners: NonNullable<LegacyCodePushModule['removeListeners']>;
58
+ };
59
+
60
+ function getTurboModule(): CodePushModule | null {
61
+ return getNativeCodePushTurboModule() as CodePushModule | null;
62
+ }
63
+
64
+ function getLegacyModule(): LegacyCodePushModule | null {
65
+ return (NativeModules.CodePush ?? null) as LegacyCodePushModule | null;
66
+ }
67
+
68
+ function getNativeModule(): CodePushModule | null {
69
+ const turboModule = getTurboModule();
70
+ if (turboModule) {
71
+ return turboModule;
72
+ }
73
+
74
+ return getLegacyModule();
75
+ }
76
+
77
+ function normalizeStatusReport(statusReport: object | string | null | undefined) {
78
+ if (!statusReport || typeof statusReport === 'string') {
79
+ return null;
80
+ }
81
+
82
+ return statusReport;
83
+ }
84
+
85
+ function canUseNativeEventEmitter(
86
+ module: LegacyCodePushModule,
87
+ ): module is EventEmitterCapableCodePushModule {
88
+ return (
89
+ typeof module.addListener === 'function' &&
90
+ typeof module.removeListeners === 'function'
91
+ );
92
+ }
93
+
94
+ function addDownloadProgressListener(
95
+ listener: (progress: DownloadProgress) => void,
96
+ ): Subscription {
97
+ const nativeModule = getNativeModule();
98
+ if (!nativeModule) {
99
+ return {
100
+ remove() {},
101
+ };
102
+ }
103
+
104
+ const turboModule = getTurboModule();
105
+ if (turboModule?.onDownloadProgress) {
106
+ return turboModule.onDownloadProgress(listener);
107
+ }
108
+
109
+ const legacyModule = getLegacyModule();
110
+ if (!legacyModule || !canUseNativeEventEmitter(legacyModule)) {
111
+ return {
112
+ remove() {},
113
+ };
114
+ }
115
+
116
+ const eventEmitter = new NativeEventEmitter(legacyModule);
117
+ return eventEmitter.addListener(DOWNLOAD_PROGRESS_EVENT_NAME, listener);
118
+ }
119
+
120
+ function createNativeCodePush() {
121
+ return {
122
+ InstallMode,
123
+ UpdateState,
124
+ addDownloadProgressListener,
125
+ allow: () => getNativeModule()?.allow(),
126
+ clearPendingRestart: () => getNativeModule()?.clearPendingRestart(),
127
+ clearUpdates: () => getNativeModule()?.clearUpdates(),
128
+ disallow: () => getNativeModule()?.disallow(),
129
+ downloadAndReplaceCurrentBundle: (remoteBundleUrl: string) =>
130
+ getNativeModule()?.downloadAndReplaceCurrentBundle?.(remoteBundleUrl),
131
+ downloadUpdate: (updatePackage: object, notifyProgress: boolean) =>
132
+ getNativeModule()?.downloadUpdate(updatePackage, notifyProgress),
133
+ getConfiguration: () => getNativeModule()?.getConfiguration(),
134
+ getLatestRollbackInfo: () => getNativeModule()?.getLatestRollbackInfo(),
135
+ getNewStatusReport: async () =>
136
+ normalizeStatusReport(await getNativeModule()?.getNewStatusReport()),
137
+ getUpdateMetadata: (updateState: number) => getNativeModule()?.getUpdateMetadata(updateState),
138
+ installUpdate: (
139
+ updatePackage: object,
140
+ installMode: number,
141
+ minimumBackgroundDuration: number,
142
+ ) => getNativeModule()?.installUpdate(updatePackage, installMode, minimumBackgroundDuration),
143
+ isFailedUpdate: (packageHash: string) => getNativeModule()?.isFailedUpdate(packageHash),
144
+ isFirstRun: (packageHash: string) => getNativeModule()?.isFirstRun(packageHash),
145
+ notifyApplicationReady: () => getNativeModule()?.notifyApplicationReady(),
146
+ recordStatusReported: (statusReport: object) =>
147
+ getNativeModule()?.recordStatusReported(statusReport),
148
+ restartApp: (onlyIfUpdateIsPending: boolean) =>
149
+ getNativeModule()?.restartApp(onlyIfUpdateIsPending),
150
+ saveStatusReportForRetry: (statusReport: object) =>
151
+ getNativeModule()?.saveStatusReportForRetry(statusReport),
152
+ setLatestRollbackInfo: (packageHash: string) =>
153
+ getNativeModule()?.setLatestRollbackInfo(packageHash),
154
+ };
155
+ }
156
+
157
+ export function getNativeCodePush() {
158
+ const nativeModule = getNativeModule();
159
+ return nativeModule ? createNativeCodePush() : null;
160
+ }
161
+
162
+ export default getNativeCodePush();
@@ -1,6 +1,3 @@
1
- import { NativeEventEmitter } from "react-native";
2
- import log from "./logging";
3
-
4
1
  // This function is used to augment remote and local
5
2
  // package objects with additional functionality/properties
6
3
  // beyond what is included in the metadata sent by the server.
@@ -14,10 +11,8 @@ module.exports = (NativeCodePush) => {
14
11
 
15
12
  let downloadProgressSubscription;
16
13
  if (downloadProgressCallback) {
17
- const codePushEventEmitter = new NativeEventEmitter(NativeCodePush);
18
14
  // Use event subscription to obtain download progress.
19
- downloadProgressSubscription = codePushEventEmitter.addListener(
20
- "CodePushDownloadProgress",
15
+ downloadProgressSubscription = NativeCodePush.addDownloadProgressListener(
21
16
  downloadProgressCallback
22
17
  );
23
18
  }
@@ -41,12 +36,12 @@ module.exports = (NativeCodePush) => {
41
36
  };
42
37
 
43
38
  const local = {
44
- async install(installMode = NativeCodePush.codePushInstallModeOnNextRestart, minimumBackgroundDuration = 0, updateInstalledCallback) {
39
+ async install(installMode = NativeCodePush.InstallMode.ON_NEXT_RESTART, minimumBackgroundDuration = 0, updateInstalledCallback) {
45
40
  const localPackage = this;
46
41
  const localPackageCopy = Object.assign({}, localPackage); // In dev mode, React Native deep freezes any object queued over the bridge
47
42
  await NativeCodePush.installUpdate(localPackageCopy, installMode, minimumBackgroundDuration);
48
43
  updateInstalledCallback && updateInstalledCallback();
49
- if (installMode == NativeCodePush.codePushInstallModeImmediate) {
44
+ if (installMode == NativeCodePush.InstallMode.IMMEDIATE) {
50
45
  NativeCodePush.restartApp(false);
51
46
  } else {
52
47
  NativeCodePush.clearPendingRestart();
@@ -58,4 +53,4 @@ module.exports = (NativeCodePush) => {
58
53
  };
59
54
 
60
55
  return { local, remote };
61
- };
56
+ };