@bravemobile/react-native-code-push 13.1.0-beta.3 → 13.1.0-beta.5

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.
Files changed (46) hide show
  1. package/CodePush.podspec +5 -0
  2. package/README.md +20 -145
  3. package/android/app/src/main/java/com/microsoft/codepush/react/ArchiveAttemptLog.java +181 -0
  4. package/android/app/src/main/java/com/microsoft/codepush/react/{BinaryPatchResult.java → ArchiveRestoreResult.java} +17 -7
  5. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushBinaryPatch.java +20 -20
  6. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushConstants.java +20 -1
  7. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushErrorCode.java +86 -0
  8. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushHttpException.java +29 -0
  9. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushIncompleteDownloadException.java +17 -0
  10. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushNativeModule.java +12 -7
  11. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateManager.java +143 -43
  12. package/android/app/src/test/java/com/microsoft/codepush/react/CodePushBinaryPatchTest.java +31 -31
  13. package/android/app/src/test/java/com/microsoft/codepush/react/CodePushErrorCodeTest.java +90 -0
  14. package/android/app/src/test/java/com/microsoft/codepush/react/CodePushUpdateManagerBinaryPatchTest.java +159 -19
  15. package/android/app/src/test/java/com/microsoft/codepush/react/CodePushUpdateManagerDownloadTest.java +304 -15
  16. package/cli/commands/createHistoryCommand/createReleaseHistory.test.ts +133 -0
  17. package/cli/commands/createHistoryCommand/createReleaseHistory.ts +3 -11
  18. package/cli/commands/releaseCommand/addToReleaseHistory.ts +3 -11
  19. package/cli/commands/releaseCommand/release.test.ts +55 -13
  20. package/cli/commands/releaseCommand/release.ts +39 -6
  21. package/cli/commands/updateHistoryCommand/updateReleaseHistory.ts +3 -11
  22. package/cli/dist/commands/createHistoryCommand/createReleaseHistory.js +2 -8
  23. package/cli/dist/commands/createHistoryCommand/createReleaseHistory.test.js +95 -0
  24. package/cli/dist/commands/releaseCommand/addToReleaseHistory.js +2 -8
  25. package/cli/dist/commands/releaseCommand/release.js +23 -8
  26. package/cli/dist/commands/releaseCommand/release.test.js +37 -9
  27. package/cli/dist/commands/updateHistoryCommand/updateReleaseHistory.js +2 -8
  28. package/cli/dist/functions/resolveAssetDiffBases.js +7 -2
  29. package/cli/dist/functions/resolveAssetDiffBases.test.js +26 -12
  30. package/cli/dist/functions/stageReleaseHistoryFile.js +28 -0
  31. package/cli/functions/resolveAssetDiffBases.test.ts +28 -14
  32. package/cli/functions/resolveAssetDiffBases.ts +8 -1
  33. package/cli/functions/stageReleaseHistoryFile.ts +38 -0
  34. package/ios/CodePush/CodePush.h +6 -3
  35. package/ios/CodePush/CodePush.mm +10 -10
  36. package/ios/CodePush/CodePushBinaryPatch.h +18 -8
  37. package/ios/CodePush/CodePushBinaryPatch.m +23 -22
  38. package/ios/CodePush/CodePushDownloadHandler.m +2 -1
  39. package/ios/CodePush/CodePushErrorUtils.m +55 -0
  40. package/ios/CodePush/CodePushPackage.m +242 -71
  41. package/package.json +2 -1
  42. package/src/CodePush.js +28 -18
  43. package/src/CodePush.test.js +110 -55
  44. package/src/package-mixins.js +19 -10
  45. package/typings/react-native-code-push.d.ts +152 -41
  46. package/android/app/src/main/java/com/microsoft/codepush/react/BinaryPatchAttempt.java +0 -92
@@ -36,9 +36,11 @@ export interface ReleaseInfo {
36
36
  binaryPatchDownloadUrl?: string;
37
37
  /**
38
38
  * URLs of patch archives that also carry an asset diff, keyed by the packageHash of the
39
- * release each archive was diffed against. A client whose installed update matches one of
40
- * these keys downloads that archive instead of `binaryPatchDownloadUrl`; every other client
41
- * ignores this field. Only present when the release was published with asset diff archives.
39
+ * release each archive was diffed against. Give a key to every release worth diffing
40
+ * against: a client whose installed update matches one downloads that archive first, and
41
+ * every other client ignores this field. Only present when the release was published with
42
+ * asset diff archives. `UpdateArchiveResult` describes what a client does with one it
43
+ * cannot use.
42
44
  */
43
45
  diffPackages?: Record<string, string>;
44
46
  packageHash: string;
@@ -54,6 +56,13 @@ export interface UpdateCheckResponse {
54
56
  * that cannot use it downloads the full update from `download_url` instead.
55
57
  */
56
58
  binary_patch_download_url?: string;
59
+ /**
60
+ * The URL of the asset diff archive built against the update the client is running.
61
+ * It is only present when the release publishes a diff against exactly that update, and
62
+ * it accompanies `binary_patch_download_url` rather than replacing it: a response can
63
+ * carry both. `UpdateArchiveResult` describes the order the client tries them in.
64
+ */
65
+ asset_diff_download_url?: string;
57
66
  description?: string;
58
67
  is_available: boolean;
59
68
  is_disabled?: boolean;
@@ -71,7 +80,7 @@ export interface UpdateCheckResponse {
71
80
  * instead. These are the words every platform's applier reports, so a rollout can be
72
81
  * judged by them whichever platform it is running on.
73
82
  */
74
- export type BinaryPatchFallbackReason =
83
+ export type ArchiveFallbackReason =
75
84
  /** The bundle inside the app binary could not be opened or read. */
76
85
  | "base_bundle_unavailable"
77
86
  /** The bundle inside the app binary is not the one the patch was computed against. */
@@ -84,30 +93,88 @@ export type BinaryPatchFallbackReason =
84
93
  | "patch_apply_failed"
85
94
  /** The restored bundle is not the one the manifest promised. */
86
95
  | "target_verification_failed"
96
+ /** The asset diff could not be merged with the installed update it was built against. */
97
+ | "asset_merge_failed"
87
98
  /** The update restored from the patch did not pass the checks that follow the restore. */
88
99
  | "package_verification_failed";
89
100
 
90
101
  /**
91
- * How installing an update from its binary patch archive went.
102
+ * The archives on the patch path; the full archive is not one of them. There are two: the
103
+ * patch archive built against the app binary's bundle, and an asset diff archive that
104
+ * additionally leaves out the assets an installed base update already holds.
105
+ */
106
+ export type UpdateArchive = "binary-patch" | "asset-diff";
107
+
108
+ /**
109
+ * One archive tried on the patch path: which archive it was, how long the try took, and,
110
+ * when it was given up on, why.
111
+ */
112
+ export interface UpdateArchiveAttempt {
113
+ archive: UpdateArchive;
114
+
115
+ /**
116
+ * Why this archive was given up on. Absent for the attempt the downloaded update came
117
+ * from, and also when the attempt ended in an error none of the appliers has a word
118
+ * for.
119
+ */
120
+ fallbackReason?: ArchiveFallbackReason;
121
+
122
+ /**
123
+ * How long this attempt ran, in milliseconds, whichever way it ended: from the archive
124
+ * starting to download to the try being finished with.
125
+ */
126
+ durationMs: number;
127
+
128
+ /**
129
+ * How long the applier took to rebuild the bundle from this archive's patch, in
130
+ * milliseconds. Absent when the attempt ended before the bundle was restored.
131
+ */
132
+ applyDurationMs?: number;
133
+ }
134
+
135
+ /**
136
+ * Which of an update's patch archives the download came from, and what the patch path did
137
+ * on the way there. It is reported once the update has been downloaded and before the
138
+ * `LocalPackage` it resolved to is installed, so nothing here speaks to how installing goes.
92
139
  */
93
- export interface BinaryPatchResult {
140
+ export interface UpdateArchiveResult {
94
141
  /**
95
- * Whether the update was installed from its patch archive, or had to be downloaded in
96
- * full instead. A fallback is not an error: the update is installed either way.
142
+ * Whether one of the update's patch archives produced it, or the full archive had to be
143
+ * downloaded instead. A fallback is not an error: the update arrives either way.
97
144
  */
98
145
  status: "applied" | "fallback";
99
146
 
100
147
  /**
101
- * Why the full archive had to be downloaded. Absent when the patch was applied, and
102
- * also when the attempt ended in an error none of the appliers has a word for.
148
+ * The archive of the last attempt: the one the downloaded update came from when a patch
149
+ * archive produced it, and the last one given up on when none did.
150
+ */
151
+ archive: UpdateArchive;
152
+
153
+ /**
154
+ * Why the full archive had to be downloaded: the reason the last attempt ended in.
155
+ * Absent when a patch archive produced the update, and also when the attempt ended in
156
+ * an error none of the appliers has a word for.
103
157
  */
104
- fallbackReason?: BinaryPatchFallbackReason;
158
+ fallbackReason?: ArchiveFallbackReason;
105
159
 
106
160
  /**
107
- * How long the patch work took, in milliseconds: applying the patch when it was
108
- * applied, and the whole attempt when it was given up on.
161
+ * How long the whole patch path took, in milliseconds: from the first archive starting
162
+ * to download to the last attempt being finished with. The full download that follows a
163
+ * fallback is not part of it, because that is not time the patch path spent.
109
164
  */
110
- applyDurationMs: number;
165
+ totalDurationMs: number;
166
+
167
+ /**
168
+ * Every archive that was tried, in the order it was tried. The full archive is never
169
+ * among them, because it is downloaded only once the patch path has given up.
170
+ *
171
+ * Most downloads leave a single entry. A second one appears when the asset diff failed
172
+ * after its bundle was restored - an asset-side failure the patch archive is not
173
+ * implicated in - and the patch archive was tried in its place. A diff that fails before
174
+ * its bundle is restored skips the patch archive instead, because both archives carry the
175
+ * same bundle patch and it would fail the same way.
176
+ */
177
+ attempts: UpdateArchiveAttempt[];
111
178
  }
112
179
 
113
180
  export interface CodePushOptions extends SyncOptions {
@@ -250,8 +317,12 @@ export interface RemotePackage extends Package {
250
317
  * Downloads the available update from the CodePush service.
251
318
  *
252
319
  * @param downloadProgressCallback An optional callback that allows tracking the progress of the update while it is being downloaded.
320
+ * @param updateArchiveResultCallback An optional callback for observing which archive an update published with a binary patch was downloaded from. It is called once when the download had such an archive to try, and only after that download has succeeded; what it says nothing about is whether installing the resolved `LocalPackage` succeeds. An archive that could not be applied is reported here and the update is downloaded in full.
253
321
  */
254
- download(downloadProgressCallback?: DownloadProgressCallback): Promise<LocalPackage>;
322
+ download(
323
+ downloadProgressCallback?: DownloadProgressCallback,
324
+ updateArchiveResultCallback?: (result: UpdateArchiveResult) => void,
325
+ ): Promise<LocalPackage>;
255
326
 
256
327
  /**
257
328
  * The URL at which the package is available for download.
@@ -265,6 +336,15 @@ export interface RemotePackage extends Package {
265
336
  * package is downloaded in full from `downloadUrl`.
266
337
  */
267
338
  binaryPatchDownloadUrl?: string;
339
+
340
+ /**
341
+ * The URL of the asset diff archive built against the update this app is running.
342
+ * It is only present when the release publishes a diff against exactly that update, and
343
+ * it accompanies `binaryPatchDownloadUrl` rather than replacing it, so a package can hold
344
+ * both. `download` chooses between them and reports the choice as an
345
+ * `UpdateArchiveResult`.
346
+ */
347
+ assetDiffDownloadUrl?: string;
268
348
  }
269
349
 
270
350
  export interface SyncOptions {
@@ -297,8 +377,8 @@ export interface SyncOptions {
297
377
 
298
378
  /**
299
379
  * An "options" object used to determine whether a confirmation dialog should be displayed to the end user when an update is available,
300
- * and if so, what strings to use. Defaults to null, which has the effect of disabling the dialog completely. Setting this to any truthy
301
- * value will enable the dialog with the default strings, and passing an object to this parameter allows enabling the dialog as well as
380
+ * and if so, what strings to use. Defaults to null, which has the effect of disabling the dialog completely. Setting this to `true`
381
+ * will enable the dialog with the default strings, and passing an object to this parameter allows enabling the dialog as well as
302
382
  * overriding one or more of the default strings.
303
383
  */
304
384
  updateDialog?: UpdateDialog | true;
@@ -306,24 +386,25 @@ export interface SyncOptions {
306
386
  /**
307
387
  * The rollback retry mechanism allows the application to attempt to reinstall an update that was previously rolled back (with the restrictions
308
388
  * specified in the options). It is an "options" object used to determine whether a rollback retry should occur, and if so, what settings to use
309
- * for the rollback retry. This defaults to null, which has the effect of disabling the retry mechanism. Setting this to any truthy value will enable
310
- * the retry mechanism with the default settings, and passing an object to this parameter allows enabling the rollback retry as well as overriding
311
- * one or more of the default values.
389
+ * for the rollback retry. This defaults to null, which has the effect of disabling the retry mechanism. Passing an object to this parameter enables
390
+ * the rollback retry: an empty object retries with the default settings, and each value the object specifies overrides the default for that
391
+ * setting.
312
392
  */
313
393
  rollbackRetryOptions?: RollbackRetryOptions;
314
394
 
315
395
  /**
316
- * An optional callback for observing how an update published with a binary patch was
317
- * installed: whether it came from the patch archive, why it did not when it did not, and
318
- * how long the patch work took. It is called once per download that had a patch to try,
319
- * with the label of the release being installed.
396
+ * An optional callback for observing which archive an update published with a binary
397
+ * patch was downloaded from: whether it came from one of its patch archives, why each
398
+ * archive that was given up on was, and how long the patch work took. It is called once
399
+ * per download that had such an archive to try, after that download has succeeded and
400
+ * before the update is installed, with the label of the release it carries.
320
401
  *
321
402
  * Purely for observation. The library neither stores the result nor sends it anywhere -
322
403
  * an app that wants it in its telemetry sends it itself - and nothing about the update
323
404
  * depends on the callback: registering none changes nothing, and one that throws is
324
- * logged and does not fail the install.
405
+ * logged and does not fail the download it is reporting on.
325
406
  */
326
- onBinaryPatchResult?: (label: string, result: BinaryPatchResult) => void;
407
+ onUpdateArchiveResult?: (label: string, result: UpdateArchiveResult) => void;
327
408
 
328
409
  /**
329
410
  * Specifies whether to ignore the update if the installation fails.
@@ -583,13 +664,13 @@ declare namespace CodePush {
583
664
  RUNNING,
584
665
 
585
666
  /**
586
- * Indicates than an update has been installed, but the
667
+ * Indicates that an update has been installed, but the
587
668
  * app hasn't been restarted yet in order to apply it.
588
669
  */
589
670
  PENDING,
590
671
 
591
672
  /**
592
- * Indicates than an update represents the latest available
673
+ * Indicates that an update represents the latest available
593
674
  * release, and can be either currently running or pending.
594
675
  */
595
676
  LATEST
@@ -625,7 +706,7 @@ declare namespace CodePush {
625
706
  ON_APP_RESUME,
626
707
 
627
708
  /**
628
- * Don't automatically check for updates, but only do it when codePush.sync() is manully called inside app code.
709
+ * Don't automatically check for updates, but only do it when codePush.sync() is manually called inside app code.
629
710
  */
630
711
  MANUAL
631
712
  }
@@ -633,6 +714,31 @@ declare namespace CodePush {
633
714
 
634
715
  export default CodePush;
635
716
 
717
+ /**
718
+ * Identifies the archive passed to `bundleUploader` during a release.
719
+ *
720
+ * `targetBinaryVersion` is the value of the release command's `--binary-version` option.
721
+ * A full bundle's `packageHash` identifies its contents across target binary versions, while
722
+ * binary patch and asset diff archives need the target binary version to distinguish their contents.
723
+ * Asset diff archives also identify the released package they were built against.
724
+ */
725
+ export type BundleUploadArtifact = {
726
+ targetBinaryVersion: string;
727
+ packageHash: string;
728
+ } & (
729
+ | { type: 'full-bundle' }
730
+ | { type: 'binary-patch' }
731
+ | { type: 'asset-diff'; basePackageHash: string }
732
+ );
733
+
734
+ /** Identifies the previously released full archive passed to `bundleDownloader`. */
735
+ export interface BundleDownloadInfo {
736
+ downloadUrl: string;
737
+ targetBinaryVersion: string;
738
+ releaseVersion: ReleaseVersion;
739
+ packageHash: string;
740
+ }
741
+
636
742
  /**
637
743
  * Interface for the config file required for `npx code-push` CLI operation.
638
744
  *
@@ -647,26 +753,16 @@ export interface CliConfigInterface {
647
753
  *
648
754
  * @param source The relative path of the generated bundle file. (e.g. build/bundleOutput/1087bc338fc45a961c...)
649
755
  * @param platform The target platform of the bundle file. This is the string passed when executing the CLI command. ('ios'/'android')
756
+ * @param artifact Information that identifies the full bundle, binary patch, or asset diff archive. The release command always supplies it; it remains optional so existing callers and three-parameter implementations stay compatible.
650
757
  * @return {Promise<{downloadUrl: string}>} An object containing the `downloadUrl` property, which is the URL from which the uploaded bundle file can be downloaded. This URL will be recorded in the release history.
651
758
  */
652
759
  bundleUploader: (
653
760
  source: string,
654
761
  platform: "ios" | "android",
655
762
  identifier?: string,
763
+ artifact?: BundleUploadArtifact,
656
764
  ) => Promise<{downloadUrl: string}>;
657
765
 
658
- /**
659
- * Downloads a previously released update archive so the release command can compute
660
- * asset diffs against it. Receives the `downloadUrl` recorded in the release history and
661
- * must resolve with the local path of the downloaded file.
662
- * Optional: when absent, releases are published without asset diff archives.
663
- */
664
- bundleDownloader?: (
665
- downloadUrl: string,
666
- platform: "ios" | "android",
667
- identifier?: string,
668
- ) => Promise<{ downloadedFilePath: string }>;
669
-
670
766
  /**
671
767
  * Interface that must be implemented to retrieve ReleaseHistory information.
672
768
  *
@@ -702,4 +798,19 @@ export interface CliConfigInterface {
702
798
  platform: "ios" | "android",
703
799
  identifier?: string,
704
800
  ) => Promise<void>;
801
+
802
+ /**
803
+ * Downloads a previously released update archive so the release command can compute
804
+ * asset diffs against it. Receives the `downloadUrl` recorded in the release history and
805
+ * must resolve with the local path of the downloaded file.
806
+ * Optional: when absent, releases are published without asset diff archives.
807
+ *
808
+ * @param archive Information that identifies the released full archive. The release command
809
+ * supplies its download URL, target binary version, release version, and package hash together.
810
+ */
811
+ bundleDownloader?: (
812
+ archive: BundleDownloadInfo,
813
+ platform: "ios" | "android",
814
+ identifier?: string,
815
+ ) => Promise<{ downloadedFilePath: string }>;
705
816
  }
@@ -1,92 +0,0 @@
1
- package com.microsoft.codepush.react;
2
-
3
- import org.json.JSONObject;
4
-
5
- /**
6
- * The record of one attempt at installing an update from its binary patch archive: whether
7
- * the update was installed from the patch, why the full archive had to be downloaded when it
8
- * was not, and how long the work took.
9
- *
10
- * The record exists for an app that wants to judge a patch rollout with its own telemetry, so
11
- * it travels to whoever asked for the download and nowhere else. It is not part of the
12
- * update's metadata, it is never written to disk, and nothing here sends it anywhere.
13
- */
14
- class BinaryPatchAttempt {
15
-
16
- private static final String APPLY_DURATION_MS_KEY = "applyDurationMs";
17
- private static final String FALLBACK_REASON_KEY = "fallbackReason";
18
- private static final String STATUS_KEY = "status";
19
-
20
- private static final String STATUS_APPLIED = "applied";
21
- private static final String STATUS_FALLBACK = "fallback";
22
-
23
- private final long mStartTimeMs = System.currentTimeMillis();
24
-
25
- /** How long the applier took, once it has restored the bundle. */
26
- private long mApplyDurationMs = -1;
27
-
28
- private boolean mFellBack;
29
- private String mFallbackReason;
30
- private long mAttemptDurationMs;
31
-
32
- /**
33
- * The applier restored the bundle. Whether the update installs is decided by the checks
34
- * that follow, so this is not yet the attempt succeeding.
35
- */
36
- void recordBundleRestored(long applyDurationMs) {
37
- mApplyDurationMs = applyDurationMs;
38
- }
39
-
40
- /**
41
- * The attempt ended in one of the reasons the appliers report.
42
- *
43
- * The attempt is timed here rather than when it is read, because what happens next is the
44
- * full archive being downloaded and that is not time the patch spent.
45
- */
46
- void recordFallback(String failureReason) {
47
- mFellBack = true;
48
- mFallbackReason = failureReason;
49
- mAttemptDurationMs = System.currentTimeMillis() - mStartTimeMs;
50
- }
51
-
52
- /**
53
- * The attempt ended in an error rather than in a verdict of its own.
54
- *
55
- * An error raised after the bundle was restored is the restored update failing the checks
56
- * that every update passes before it is installed. Before that point the appliers have no
57
- * word for what happened - the patch archive not being downloadable, say - and inventing
58
- * one here would put a value on the wire that no platform reports, so the fallback is
59
- * reported without a reason.
60
- */
61
- void recordFallbackAfterError() {
62
- recordFallback(bundleWasRestored() ? BinaryPatchResult.REASON_PACKAGE_VERIFICATION_FAILED : null);
63
- }
64
-
65
- private boolean bundleWasRestored() {
66
- return mApplyDurationMs >= 0;
67
- }
68
-
69
- /**
70
- * What the attempt ended in, as the app reads it.
71
- *
72
- * An attempt that never fell back is one the update was installed from, and it reports the
73
- * time the applier took. A fallback reports how long the attempt ran before it was given
74
- * up on, because there is no completed apply to time.
75
- */
76
- JSONObject result() {
77
- JSONObject result = new JSONObject();
78
- if (!mFellBack) {
79
- CodePushUtils.setJSONValueForKey(result, STATUS_KEY, STATUS_APPLIED);
80
- CodePushUtils.setJSONValueForKey(result, APPLY_DURATION_MS_KEY, Math.max(mApplyDurationMs, 0));
81
- return result;
82
- }
83
-
84
- CodePushUtils.setJSONValueForKey(result, STATUS_KEY, STATUS_FALLBACK);
85
- if (mFallbackReason != null) {
86
- CodePushUtils.setJSONValueForKey(result, FALLBACK_REASON_KEY, mFallbackReason);
87
- }
88
-
89
- CodePushUtils.setJSONValueForKey(result, APPLY_DURATION_MS_KEY, mAttemptDurationMs);
90
- return result;
91
- }
92
- }