react-native-update 10.37.20 → 10.38.0-beta.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.
Files changed (131) hide show
  1. package/README-CN.md +4 -4
  2. package/README.md +2 -12
  3. package/android/bin/.settings/org.eclipse.buildship.core.prefs +13 -0
  4. package/android/build.gradle +4 -0
  5. package/android/jni/Android.mk +14 -1
  6. package/android/jni/Application.mk +5 -2
  7. package/android/lib/arm64-v8a/librnupdate.so +0 -0
  8. package/android/lib/armeabi-v7a/librnupdate.so +0 -0
  9. package/android/lib/x86/librnupdate.so +0 -0
  10. package/android/lib/x86_64/librnupdate.so +0 -0
  11. package/android/src/main/java/cn/reactnative/modules/update/ArchivePatchPlanResult.java +6 -0
  12. package/android/src/main/java/cn/reactnative/modules/update/CopyGroupResult.java +6 -0
  13. package/android/src/main/java/cn/reactnative/modules/update/DownloadTask.java +136 -136
  14. package/android/src/main/java/cn/reactnative/modules/update/NativeUpdateCore.java +34 -0
  15. package/android/src/main/java/cn/reactnative/modules/update/StateCoreResult.java +16 -0
  16. package/android/src/main/java/cn/reactnative/modules/update/UpdateContext.java +131 -48
  17. package/cpp/patch_core/archive_patch_core.cpp +125 -0
  18. package/cpp/patch_core/archive_patch_core.h +59 -0
  19. package/cpp/patch_core/patch_core.cpp +533 -0
  20. package/cpp/patch_core/patch_core.h +68 -0
  21. package/cpp/patch_core/patch_core_android.cpp +112 -0
  22. package/cpp/patch_core/state_core.cpp +110 -0
  23. package/cpp/patch_core/state_core.h +58 -0
  24. package/cpp/patch_core/tests/patch_core_test.cpp +473 -0
  25. package/cpp/patch_core/update_core_android.cpp +469 -0
  26. package/harmony/pushy.har +0 -0
  27. package/ios/RCTPushy/RCTPushy.mm +233 -143
  28. package/package.json +17 -15
  29. package/react-native-update.podspec +3 -0
  30. package/scripts/build-harmony-har.js +12 -0
  31. package/scripts/prepublish.ts +49 -3
  32. package/scripts/prune-host-stl.sh +6 -0
  33. package/scripts/test-patch-core.sh +39 -0
  34. package/src/client.ts +129 -76
  35. package/src/core.ts +2 -1
  36. package/src/endpoint.ts +171 -0
  37. package/src/utils.ts +40 -27
  38. package/android/jni/lzma/DOC/7zC.txt +0 -187
  39. package/android/jni/lzma/DOC/7zFormat.txt +0 -469
  40. package/android/jni/lzma/DOC/Methods.txt +0 -173
  41. package/android/jni/lzma/DOC/installer.txt +0 -166
  42. package/android/jni/lzma/DOC/lzma-history.txt +0 -446
  43. package/android/jni/lzma/DOC/lzma-sdk.txt +0 -357
  44. package/android/jni/lzma/DOC/lzma-specification.txt +0 -1176
  45. package/android/jni/lzma/DOC/lzma.txt +0 -328
  46. package/android/jni/lzma/bin/7zS2.sfx +0 -0
  47. package/android/jni/lzma/bin/7zS2con.sfx +0 -0
  48. package/android/jni/lzma/bin/7zSD.sfx +0 -0
  49. package/android/jni/lzma/bin/7zdec.exe +0 -0
  50. package/android/jni/lzma/bin/7zr.exe +0 -0
  51. package/android/jni/lzma/bin/installer/config.txt +0 -5
  52. package/android/jni/lzma/bin/installer/cr.bat +0 -5
  53. package/android/jni/lzma/bin/lzma.exe +0 -0
  54. package/android/jni/lzma/bin/x64/7zr.exe +0 -0
  55. package/error.js +0 -1609
  56. package/harmony/har-wrapper/AppScope/app.json5 +0 -8
  57. package/harmony/har-wrapper/build-profile.json5 +0 -35
  58. package/harmony/har-wrapper/hvigor/hvigor-config.json5 +0 -5
  59. package/harmony/har-wrapper/hvigorfile.ts +0 -6
  60. package/harmony/har-wrapper/oh-package.json5 +0 -4
  61. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/.cmake/api/v1/reply/cache-v2-77b153ce45aba0ed28ef.json +0 -1415
  62. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-b65a07793384e0ce3e08.json +0 -809
  63. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-ce0e89410afd8bf3a057.json +0 -60
  64. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/.cmake/api/v1/reply/directory-.-Release-f5ebdc15457944623624.json +0 -14
  65. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/.cmake/api/v1/reply/index-2026-03-18T12-50-36-0050.json +0 -89
  66. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/.cmake/api/v1/reply/target-rnupdate-Release-267153624504c9c3ffdd.json +0 -222
  67. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/.ninja_deps +0 -0
  68. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/.ninja_log +0 -8
  69. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeCache.txt +0 -415
  70. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/3.28.2/CMakeCCompiler.cmake +0 -74
  71. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/3.28.2/CMakeCXXCompiler.cmake +0 -85
  72. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/3.28.2/CMakeDetermineCompilerABI_C.bin +0 -0
  73. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/3.28.2/CMakeDetermineCompilerABI_CXX.bin +0 -0
  74. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/3.28.2/CMakeSystem.cmake +0 -15
  75. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/3.28.2/CompilerIdC/CMakeCCompilerId.c +0 -880
  76. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/3.28.2/CompilerIdC/CMakeCCompilerId.o +0 -0
  77. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/3.28.2/CompilerIdCXX/CMakeCXXCompilerId.cpp +0 -869
  78. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/3.28.2/CompilerIdCXX/CMakeCXXCompilerId.o +0 -0
  79. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/CMakeConfigureLog.yaml +0 -388
  80. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/TargetDirectories.txt +0 -3
  81. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/cmake.check_cache +0 -1
  82. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/rnupdate.dir/__w/react-native-update/react-native-update/android/jni/HDiffPatch/file_for_patch.c.o +0 -0
  83. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/rnupdate.dir/__w/react-native-update/react-native-update/android/jni/HDiffPatch/libHDiffPatch/HPatch/patch.c.o +0 -0
  84. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/rnupdate.dir/__w/react-native-update/react-native-update/android/jni/hpatch.c.o +0 -0
  85. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/rnupdate.dir/__w/react-native-update/react-native-update/android/jni/lzma/C/Lzma2Dec.c.o +0 -0
  86. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/rnupdate.dir/__w/react-native-update/react-native-update/android/jni/lzma/C/LzmaDec.c.o +0 -0
  87. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/rnupdate.dir/pushy.c.o +0 -0
  88. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/rules.ninja +0 -64
  89. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/additional_project_files.txt +0 -0
  90. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/build.ninja +0 -206
  91. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/build_file_index.txt +0 -1
  92. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/cmake_install.cmake +0 -54
  93. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/compile_commands.json +0 -38
  94. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/configure_fingerprint.json +0 -1
  95. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/hvigor_native_config.json +0 -1
  96. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/metadata_generation_command.txt +0 -17
  97. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/native_work_dir.txt +0 -1
  98. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/output.log +0 -14
  99. package/harmony/pushy/.cxx/default/default/release/hvigor/arm64-v8a/summary.cmake +0 -0
  100. package/harmony/pushy/BuildProfile.ets +0 -17
  101. package/harmony/pushy/OAT.xml +0 -38
  102. package/harmony/pushy/README.md +0 -0
  103. package/harmony/pushy/build-profile.json5 +0 -15
  104. package/harmony/pushy/hvigor-plugin.ts +0 -34
  105. package/harmony/pushy/hvigorfile.ts +0 -1
  106. package/harmony/pushy/index.ets +0 -2
  107. package/harmony/pushy/oh-package-lock.json5 +0 -20
  108. package/harmony/pushy/oh-package.json5 +0 -13
  109. package/harmony/pushy/src/main/cpp/CMakeLists.txt +0 -51
  110. package/harmony/pushy/src/main/cpp/PushyPackage.h +0 -55
  111. package/harmony/pushy/src/main/cpp/PushyTurboModule.cpp +0 -142
  112. package/harmony/pushy/src/main/cpp/PushyTurboModule.h +0 -38
  113. package/harmony/pushy/src/main/cpp/pushy.c +0 -117
  114. package/harmony/pushy/src/main/cpp/pushy.h +0 -8
  115. package/harmony/pushy/src/main/ets/DownloadTask.ts +0 -570
  116. package/harmony/pushy/src/main/ets/DownloadTaskParams.ts +0 -19
  117. package/harmony/pushy/src/main/ets/EventHub.ts +0 -39
  118. package/harmony/pushy/src/main/ets/Logger.ts +0 -52
  119. package/harmony/pushy/src/main/ets/PushyFileJSBundleProvider.ets +0 -50
  120. package/harmony/pushy/src/main/ets/PushyPackage.ts +0 -22
  121. package/harmony/pushy/src/main/ets/PushyTurboModule.ts +0 -171
  122. package/harmony/pushy/src/main/ets/SaveFile.ts +0 -34
  123. package/harmony/pushy/src/main/ets/UpdateContext.ts +0 -262
  124. package/harmony/pushy/src/main/ets/UpdateModuleImpl.ts +0 -123
  125. package/harmony/pushy/src/main/module.json5 +0 -7
  126. package/harmony/pushy/src/main/resources/base/element/string.json +0 -8
  127. package/harmony/pushy/src/main/resources/en_US/element/string.json +0 -8
  128. package/harmony/pushy/src/main/resources/zh_CN/element/string.json +0 -8
  129. package/harmony/pushy/ts.ts +0 -3
  130. package/src/__tests__/core.test.ts +0 -103
  131. package/src/__tests__/utils.test.ts +0 -36
@@ -1,6 +1,9 @@
1
1
  #import "RCTPushy.h"
2
2
  #import "RCTPushyDownloader.h"
3
3
  #import "RCTPushyManager.h"
4
+ #include "../../cpp/patch_core/archive_patch_core.h"
5
+ #include "../../cpp/patch_core/patch_core.h"
6
+ #include "../../cpp/patch_core/state_core.h"
4
7
 
5
8
  #if __has_include("RCTReloadCommand.h")
6
9
  #import "RCTReloadCommand.h"
@@ -58,6 +61,112 @@ typedef NS_ENUM(NSInteger, PushyType) {
58
61
 
59
62
  static BOOL ignoreRollback = false;
60
63
 
64
+ static std::string PushyToStdString(NSString *value) {
65
+ if (value == nil) {
66
+ return std::string();
67
+ }
68
+ return std::string([value UTF8String]);
69
+ }
70
+
71
+ static NSError *PushyNSErrorFromStatus(const pushy::patch::Status &status) {
72
+ return [NSError errorWithDomain:@"cn.reactnative.pushy"
73
+ code:-1
74
+ userInfo:@{ NSLocalizedDescriptionKey: [NSString stringWithUTF8String:status.message.c_str()] }];
75
+ }
76
+
77
+ static NSString *PushyFromStdString(const std::string &value) {
78
+ if (value.empty()) {
79
+ return nil;
80
+ }
81
+ return [NSString stringWithUTF8String:value.c_str()];
82
+ }
83
+
84
+ static void PushySetNullableString(NSUserDefaults *defaults, NSString *key, NSString *value) {
85
+ if (value != nil) {
86
+ [defaults setObject:value forKey:key];
87
+ } else {
88
+ [defaults removeObjectForKey:key];
89
+ }
90
+ }
91
+
92
+ static pushy::patch::PatchManifest PushyPatchManifestFromJson(NSDictionary *json) {
93
+ pushy::patch::PatchManifest manifest;
94
+
95
+ NSDictionary *copies = json[@"copies"];
96
+ for (NSString *to in copies) {
97
+ NSString *from = copies[to];
98
+ if (from.length <= 0) {
99
+ from = to;
100
+ }
101
+ manifest.copies.push_back(pushy::patch::CopyOperation{
102
+ PushyToStdString(from),
103
+ PushyToStdString(to),
104
+ });
105
+ }
106
+
107
+ NSDictionary *deletes = json[@"deletes"];
108
+ for (NSString *path in deletes) {
109
+ manifest.deletes.push_back(PushyToStdString(path));
110
+ }
111
+
112
+ return manifest;
113
+ }
114
+
115
+ static pushy::state::State PushyStateFromDefaults(NSUserDefaults *defaults) {
116
+ pushy::state::State state;
117
+ state.package_version = PushyToStdString([defaults stringForKey:paramPackageVersion]);
118
+ state.build_time = PushyToStdString([defaults stringForKey:paramBuildTime]);
119
+ NSDictionary *pushyInfo = [defaults dictionaryForKey:keyPushyInfo];
120
+ if (pushyInfo != nil) {
121
+ state.current_version = PushyToStdString(pushyInfo[paramCurrentVersion]);
122
+ state.last_version = PushyToStdString(pushyInfo[paramLastVersion]);
123
+ state.first_time = [pushyInfo[paramIsFirstTime] boolValue];
124
+ id firstLoadOk = pushyInfo[paramIsFirstLoadOk];
125
+ state.first_time_ok = firstLoadOk == nil ? true : [firstLoadOk boolValue];
126
+ }
127
+ state.rolled_back_version = PushyToStdString([defaults stringForKey:keyRolledBackMarked]);
128
+ return state;
129
+ }
130
+
131
+ static void PushyApplyStateToDefaults(NSUserDefaults *defaults, const pushy::state::State &state) {
132
+ PushySetNullableString(defaults, paramPackageVersion, PushyFromStdString(state.package_version));
133
+ PushySetNullableString(defaults, paramBuildTime, PushyFromStdString(state.build_time));
134
+
135
+ BOOL hasPushyInfo = !state.current_version.empty() || !state.last_version.empty() || state.first_time || !state.first_time_ok;
136
+ if (hasPushyInfo) {
137
+ NSMutableDictionary *newInfo = [[NSMutableDictionary alloc] init];
138
+ if (!state.current_version.empty()) {
139
+ newInfo[paramCurrentVersion] = PushyFromStdString(state.current_version);
140
+ }
141
+ if (!state.last_version.empty()) {
142
+ newInfo[paramLastVersion] = PushyFromStdString(state.last_version);
143
+ }
144
+ newInfo[paramIsFirstTime] = @(state.first_time);
145
+ newInfo[paramIsFirstLoadOk] = @(state.first_time_ok);
146
+ [defaults setObject:newInfo forKey:keyPushyInfo];
147
+ } else {
148
+ [defaults removeObjectForKey:keyPushyInfo];
149
+ }
150
+
151
+ PushySetNullableString(
152
+ defaults,
153
+ keyRolledBackMarked,
154
+ PushyFromStdString(state.rolled_back_version));
155
+ }
156
+
157
+ @interface RCTPushy ()
158
+ - (void)_dopatch:(NSString *)hash
159
+ type:(PushyType)type
160
+ fromBundle:(NSString *)bundleOrigin
161
+ source:(NSString *)sourceOrigin
162
+ callback:(void (^)(NSError *error))callback;
163
+ - (void)patch:(NSString *)hash
164
+ type:(PushyType)type
165
+ fromBundle:(NSString *)bundleOrigin
166
+ source:(NSString *)sourceOrigin
167
+ callback:(void (^)(NSError *error))callback;
168
+ @end
169
+
61
170
  @implementation RCTPushy {
62
171
  RCTPushyManager *_fileManager;
63
172
  bool hasListeners;
@@ -77,51 +186,49 @@ RCT_EXPORT_MODULE(RCTPushy);
77
186
  NSString *storedPackageVersion = [defaults stringForKey:paramPackageVersion];
78
187
  NSString *storedBuildTime = [defaults stringForKey:paramBuildTime];
79
188
 
80
- BOOL packageVersionChanged = !storedPackageVersion || ![curPackageVersion isEqualToString:storedPackageVersion];
81
- BOOL buildTimeChanged = !storedBuildTime || ![curBuildTime isEqualToString:storedBuildTime];
82
-
83
- if (packageVersionChanged || buildTimeChanged) {
84
- // Clear all update data and store new versions
85
- [defaults setObject:nil forKey:keyPushyInfo];
86
- [defaults setObject:nil forKey:keyHashInfo];
189
+ pushy::state::State state = PushyStateFromDefaults(defaults);
190
+ pushy::state::BinaryVersionSyncResult sync = pushy::state::SyncBinaryVersion(
191
+ state,
192
+ PushyToStdString(curPackageVersion),
193
+ PushyToStdString(curBuildTime)
194
+ );
195
+ if (sync.changed) {
87
196
  [defaults setObject:@(YES) forKey:KeyPackageUpdatedMarked];
88
- [defaults setObject:curPackageVersion forKey:paramPackageVersion];
89
- [defaults setObject:curBuildTime forKey:paramBuildTime];
197
+ state = sync.state;
198
+ PushyApplyStateToDefaults(defaults, state);
90
199
  }
91
-
92
- NSDictionary *pushyInfo = [defaults dictionaryForKey:keyPushyInfo];
93
- if (pushyInfo) {
94
- NSString *curVersion = pushyInfo[paramCurrentVersion];
95
-
96
- BOOL isFirstTime = [pushyInfo[paramIsFirstTime] boolValue];
97
- BOOL isFirstLoadOK = [pushyInfo[paramIsFirstLoadOk] boolValue];
98
-
99
- NSString *loadVersion = curVersion;
100
- BOOL needRollback = (!ignoreRollback && isFirstTime == NO && isFirstLoadOK == NO) || loadVersion.length<=0;
101
- if (needRollback) {
102
- loadVersion = [self rollback];
103
- } else if (isFirstTime && !ignoreRollback){
104
- // bundleURL may be called many times, ignore rollbacks before process restarted again.
105
- ignoreRollback = true;
106
-
107
- NSMutableDictionary *newInfo = [[NSMutableDictionary alloc] initWithDictionary:pushyInfo];
108
- newInfo[paramIsFirstTime] = @(NO);
109
- [defaults setObject:newInfo forKey:keyPushyInfo];
110
- [defaults setObject:@(YES) forKey:keyFirstLoadMarked];
111
-
112
- }
113
-
114
- NSString *downloadDir = [RCTPushy downloadDir];
115
- while (loadVersion.length) {
116
- NSString *bundlePath = [[downloadDir stringByAppendingPathComponent:loadVersion] stringByAppendingPathComponent:BUNDLE_FILE_NAME];
117
- if ([[NSFileManager defaultManager] fileExistsAtPath:bundlePath isDirectory:NULL]) {
118
- NSURL *bundleURL = [NSURL fileURLWithPath:bundlePath];
119
- return bundleURL;
120
- } else {
121
- RCTLogError(@"RCTPushy -- bundle version %@ not found", loadVersion);
122
- loadVersion = [self rollback];
123
- }
200
+
201
+ if (!state.current_version.empty()) {
202
+ pushy::state::LaunchDecision decision = pushy::state::ResolveLaunchState(
203
+ state,
204
+ ignoreRollback,
205
+ true
206
+ );
207
+ state = decision.state;
208
+
209
+ if (decision.did_rollback || decision.consumed_first_time) {
210
+ PushyApplyStateToDefaults(defaults, state);
211
+ }
212
+ if (decision.consumed_first_time) {
213
+ // bundleURL may be called many times, ignore rollbacks before process restarted again.
214
+ ignoreRollback = true;
215
+ [defaults setObject:@(YES) forKey:keyFirstLoadMarked];
216
+ }
217
+
218
+ NSString *loadVersion = PushyFromStdString(decision.load_version);
219
+ NSString *downloadDir = [RCTPushy downloadDir];
220
+ while (loadVersion.length) {
221
+ NSString *bundlePath = [[downloadDir stringByAppendingPathComponent:loadVersion] stringByAppendingPathComponent:BUNDLE_FILE_NAME];
222
+ if ([[NSFileManager defaultManager] fileExistsAtPath:bundlePath isDirectory:NULL]) {
223
+ NSURL *bundleURL = [NSURL fileURLWithPath:bundlePath];
224
+ return bundleURL;
225
+ } else {
226
+ RCTLogError(@"RCTPushy -- bundle version %@ not found", loadVersion);
227
+ state = pushy::state::Rollback(state);
228
+ PushyApplyStateToDefaults(defaults, state);
229
+ loadVersion = PushyFromStdString(state.current_version);
124
230
  }
231
+ }
125
232
  }
126
233
 
127
234
  return [RCTPushy binaryBundleURL];
@@ -129,24 +236,9 @@ RCT_EXPORT_MODULE(RCTPushy);
129
236
 
130
237
  + (NSString *) rollback {
131
238
  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
132
-
133
- NSDictionary *pushyInfo = [defaults dictionaryForKey:keyPushyInfo];
134
- NSString *lastVersion = pushyInfo[paramLastVersion];
135
- NSString *curVersion = pushyInfo[paramCurrentVersion];
136
- if (lastVersion.length) {
137
- // roll back to last version
138
- [defaults setObject:@{paramCurrentVersion:lastVersion,
139
- paramIsFirstTime:@(NO),
140
- paramIsFirstLoadOk:@(YES)}
141
- forKey:keyPushyInfo];
142
- }
143
- else {
144
- // roll back to bundle
145
- [defaults setObject:nil forKey:keyPushyInfo];
146
- }
147
- [defaults setObject:curVersion forKey:keyRolledBackMarked];
148
-
149
- return lastVersion;
239
+ pushy::state::State state = pushy::state::Rollback(PushyStateFromDefaults(defaults));
240
+ PushyApplyStateToDefaults(defaults, state);
241
+ return PushyFromStdString(state.current_version);
150
242
  }
151
243
 
152
244
  + (BOOL)requiresMainQueueSetup {
@@ -293,20 +385,11 @@ RCT_EXPORT_METHOD(setNeedUpdate:(NSDictionary *)options
293
385
 
294
386
  if (hash.length) {
295
387
  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
296
- NSString *lastVersion = nil;
297
- NSDictionary *pushyInfo = [defaults objectForKey:keyPushyInfo];
298
- if (pushyInfo) {
299
- lastVersion = pushyInfo[paramCurrentVersion];
300
- }
301
-
302
- NSMutableDictionary *newInfo = [[NSMutableDictionary alloc] init];
303
- newInfo[paramCurrentVersion] = hash;
304
- newInfo[paramLastVersion] = lastVersion;
305
- newInfo[paramIsFirstTime] = @(YES);
306
- newInfo[paramIsFirstLoadOk] = @(NO);
307
- [defaults setObject:newInfo forKey:keyPushyInfo];
308
-
309
-
388
+ pushy::state::State next = pushy::state::SwitchVersion(
389
+ PushyStateFromDefaults(defaults),
390
+ PushyToStdString(hash)
391
+ );
392
+ PushyApplyStateToDefaults(defaults, next);
310
393
  resolve(@true);
311
394
  } else {
312
395
  reject(@"执行报错", nil, nil);
@@ -373,19 +456,13 @@ RCT_EXPORT_METHOD(markSuccess:(RCTPromiseResolveBlock)resolve
373
456
  #else
374
457
 
375
458
  @try {
376
- // up package info
377
459
  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
378
- NSMutableDictionary *pushyInfo = [[NSMutableDictionary alloc] initWithDictionary:[defaults objectForKey:keyPushyInfo]];
379
- [pushyInfo setObject:@(NO) forKey:paramIsFirstTime];
380
- [pushyInfo setObject:@(YES) forKey:paramIsFirstLoadOk];
381
-
382
- NSString *lastVersion = pushyInfo[paramLastVersion];
383
- NSString *curVersion = pushyInfo[paramCurrentVersion];
384
- if (lastVersion != nil && ![lastVersion isEqualToString:curVersion]) {
385
- [pushyInfo removeObjectForKey:[keyHashInfo stringByAppendingString:lastVersion]];
460
+ pushy::state::MarkSuccessResult result =
461
+ pushy::state::MarkSuccess(PushyStateFromDefaults(defaults));
462
+ if (!result.stale_version_to_delete.empty()) {
463
+ [defaults removeObjectForKey:[keyHashInfo stringByAppendingString:PushyFromStdString(result.stale_version_to_delete)]];
386
464
  }
387
- [defaults setObject:pushyInfo forKey:keyPushyInfo];
388
-
465
+ PushyApplyStateToDefaults(defaults, result.state);
389
466
 
390
467
  // clear other package dir
391
468
  [self clearInvalidFiles];
@@ -496,7 +573,7 @@ RCT_EXPORT_METHOD(markSuccess:(RCTPromiseResolveBlock)resolve
496
573
  {
497
574
  NSString *sourceOrigin = [[NSBundle mainBundle] resourcePath];
498
575
  NSString *bundleOrigin = [[RCTPushy binaryBundleURL] path];
499
- [self patch:hash fromBundle:bundleOrigin source:sourceOrigin callback:callback];
576
+ [self patch:hash type:type fromBundle:bundleOrigin source:sourceOrigin callback:callback];
500
577
  }
501
578
  break;
502
579
  case PushyTypePatchFromPpk:
@@ -505,7 +582,7 @@ RCT_EXPORT_METHOD(markSuccess:(RCTPromiseResolveBlock)resolve
505
582
 
506
583
  NSString *sourceOrigin = lastVersionDir;
507
584
  NSString *bundleOrigin = [lastVersionDir stringByAppendingPathComponent:BUNDLE_FILE_NAME];
508
- [self patch:hash fromBundle:bundleOrigin source:sourceOrigin callback:callback];
585
+ [self patch:hash type:type fromBundle:bundleOrigin source:sourceOrigin callback:callback];
509
586
  }
510
587
  break;
511
588
  default:
@@ -519,7 +596,10 @@ RCT_EXPORT_METHOD(markSuccess:(RCTPromiseResolveBlock)resolve
519
596
  }];
520
597
  }
521
598
 
522
- - (void)_dopatch:(NSString *)hash fromBundle:(NSString *)bundleOrigin source:(NSString *)sourceOrigin
599
+ - (void)_dopatch:(NSString *)hash
600
+ type:(PushyType)type
601
+ fromBundle:(NSString *)bundleOrigin
602
+ source:(NSString *)sourceOrigin
523
603
  callback:(void (^)(NSError *error))callback
524
604
  {
525
605
  NSString *unzipDir = [[RCTPushy downloadDir] stringByAppendingPathComponent:hash];
@@ -527,73 +607,83 @@ RCT_EXPORT_METHOD(markSuccess:(RCTPromiseResolveBlock)resolve
527
607
  NSString *bundlePatch = [unzipDir stringByAppendingPathComponent:BUNDLE_PATCH_NAME];
528
608
 
529
609
  NSString *destination = [unzipDir stringByAppendingPathComponent:BUNDLE_FILE_NAME];
530
- void (^completionHandler)(BOOL success) = ^(BOOL success) {
531
- if (success) {
532
- NSData *data = [NSData dataWithContentsOfFile:sourcePatch];
533
- NSError *error = nil;
534
- NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
535
- if (error) {
536
- callback(error);
537
- return;
538
- }
539
-
540
- NSDictionary *copies = json[@"copies"];
541
- NSDictionary *deletes = json[@"deletes"];
542
-
543
- [self->_fileManager copyFiles:copies fromDir:sourceOrigin toDir:unzipDir deletes:deletes completionHandler:^(NSError *error) {
544
- if (error) {
545
- callback(error);
546
- }
547
- else {
548
- callback(nil);
549
- }
550
- }];
551
- }
552
- else {
553
- callback([self errorWithMessage:ERROR_HDIFFPATCH]);
554
- }
555
- };
556
-
557
- @try {
558
- [_fileManager hdiffFileAtPath:bundlePatch fromOrigin:bundleOrigin toDestination:destination completionHandler:completionHandler];
610
+ NSData *data = [NSData dataWithContentsOfFile:sourcePatch];
611
+ NSError *error = nil;
612
+ NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
613
+ if (error) {
614
+ callback(error);
615
+ return;
559
616
  }
560
- @catch (NSException *exception) {
561
- NSLog(@"Pushy _dopatch error: exception occurred during hdiffFileAtPath: %@, reason: %@",
562
- exception.name, exception.reason);
563
- callback([self errorWithMessage:ERROR_HDIFFPATCH]);
617
+
618
+ std::vector<std::string> entryNames;
619
+ if ([[NSFileManager defaultManager] fileExistsAtPath:sourcePatch isDirectory:NULL]) {
620
+ entryNames.push_back(PushyToStdString(SOURCE_PATCH_NAME));
621
+ }
622
+ if ([[NSFileManager defaultManager] fileExistsAtPath:bundlePatch isDirectory:NULL]) {
623
+ entryNames.push_back(PushyToStdString(BUNDLE_PATCH_NAME));
624
+ }
625
+
626
+ pushy::archive_patch::ArchivePatchPlan plan;
627
+ pushy::patch::Status planStatus = pushy::archive_patch::BuildArchivePatchPlan(
628
+ type == PushyTypePatchFromPackage
629
+ ? pushy::archive_patch::ArchivePatchType::kPatchFromPackage
630
+ : pushy::archive_patch::ArchivePatchType::kPatchFromPpk,
631
+ PushyPatchManifestFromJson(json),
632
+ entryNames,
633
+ &plan
634
+ );
635
+ if (!planStatus.ok) {
636
+ callback(PushyNSErrorFromStatus(planStatus));
637
+ return;
638
+ }
639
+
640
+ pushy::patch::FileSourcePatchOptions options;
641
+ pushy::patch::Status optionStatus = pushy::archive_patch::BuildFileSourcePatchOptions(
642
+ plan,
643
+ PushyToStdString(sourceOrigin),
644
+ PushyToStdString(unzipDir),
645
+ PushyToStdString(bundleOrigin),
646
+ PushyToStdString(bundlePatch),
647
+ PushyToStdString(destination),
648
+ &options
649
+ );
650
+ if (!optionStatus.ok) {
651
+ callback(PushyNSErrorFromStatus(optionStatus));
652
+ return;
564
653
  }
654
+
655
+ pushy::patch::Status status = pushy::patch::ApplyPatchFromFileSource(options);
656
+ if (!status.ok) {
657
+ callback(PushyNSErrorFromStatus(status));
658
+ return;
659
+ }
660
+
661
+ callback(nil);
565
662
  }
566
663
 
567
- - (void)patch:(NSString *)hash fromBundle:(NSString *)bundleOrigin source:(NSString *)sourceOrigin callback:(void (^)(NSError *error))callback
664
+ - (void)patch:(NSString *)hash
665
+ type:(PushyType)type
666
+ fromBundle:(NSString *)bundleOrigin
667
+ source:(NSString *)sourceOrigin
668
+ callback:(void (^)(NSError *error))callback
568
669
  {
569
- [self _dopatch:hash fromBundle:bundleOrigin source:sourceOrigin callback:callback];
670
+ [self _dopatch:hash type:type fromBundle:bundleOrigin source:sourceOrigin callback:callback];
570
671
  }
571
672
 
572
673
  - (void)clearInvalidFiles
573
674
  {
574
675
  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
575
- NSDictionary *pushyInfo = [defaults objectForKey:keyPushyInfo];
576
- NSString *curVersion = [pushyInfo objectForKey:paramCurrentVersion];
676
+ pushy::state::State state = PushyStateFromDefaults(defaults);
577
677
 
578
678
  NSString *downloadDir = [RCTPushy downloadDir];
579
- NSError *error = nil;
580
- NSArray *list = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:downloadDir error:&error];
581
- if (error) {
582
- return;
583
- }
584
-
585
- for(NSString *fileName in list) {
586
- if (![fileName isEqualToString:curVersion]) {
587
- NSString *filePath = [downloadDir stringByAppendingPathComponent:fileName];
588
- NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:&error];
589
- if (error) {
590
- continue;
591
- }
592
- NSDate *modificationDate = [attributes fileModificationDate];
593
- if ([[NSDate date] timeIntervalSinceDate:modificationDate] > 7 * 24 * 60 * 60) {
594
- [_fileManager removeFile:filePath completionHandler:nil];
595
- }
596
- }
679
+ pushy::patch::Status status = pushy::patch::CleanupOldEntries(
680
+ PushyToStdString(downloadDir),
681
+ state.current_version,
682
+ state.last_version,
683
+ 7
684
+ );
685
+ if (!status.ok) {
686
+ NSLog(@"Pushy cleanup error: %s", status.message.c_str());
597
687
  }
598
688
  }
599
689
 
package/package.json CHANGED
@@ -1,17 +1,19 @@
1
1
  {
2
2
  "name": "react-native-update",
3
- "version": "10.37.20",
3
+ "version": "10.38.0-beta.0",
4
4
  "description": "react-native hot update",
5
5
  "main": "src/index",
6
6
  "scripts": {
7
7
  "prepublishOnly": "NODE_ENV=production bun scripts/prepublish.ts",
8
+ "publish:local": "SKIP_NATIVE_BUILD=1 npm publish",
8
9
  "postinstall": "node scripts/check-expo-version.js",
9
10
  "prepack": "bun submodule && bun lint",
10
11
  "lint": "eslint \"src/*.@(ts|tsx|js|jsx)\" && tsc --noEmit",
11
12
  "submodule": "git submodule update --init --recursive",
12
13
  "test": "echo \"Error: no test specified\" && exit 1",
14
+ "test:patch-core": "./scripts/test-patch-core.sh",
13
15
  "build:harmony-har": "node scripts/build-harmony-har.js",
14
- "build:so": "bun submodule && $ANDROID_HOME/ndk/28.2.13676358/ndk-build NDK_PROJECT_PATH=android APP_BUILD_SCRIPT=android/jni/Android.mk NDK_APPLICATION_MK=android/jni/Application.mk NDK_LIBS_OUT=android/lib",
16
+ "build:so": "bun submodule && $ANDROID_HOME/ndk/28.2.13676358/ndk-build NDK_PROJECT_PATH=android APP_BUILD_SCRIPT=android/jni/Android.mk NDK_APPLICATION_MK=android/jni/Application.mk NDK_LIBS_OUT=android/lib && ./scripts/prune-host-stl.sh android/lib",
15
17
  "build:ios-debug": "cd Example/testHotUpdate && bun && detox build --configuration ios.sim.debug",
16
18
  "build:ios-release": "cd Example/testHotUpdate && bun && detox build --configuration ios.sim.release",
17
19
  "test:ios-debug": "cd Example/testHotUpdate && E2E_PLATFORM=ios detox test --configuration ios.sim.debug",
@@ -49,7 +51,7 @@
49
51
  "homepage": "https://github.com/reactnativecn/react-native-update#readme",
50
52
  "dependencies": {
51
53
  "nanoid": "^3.3.3",
52
- "react-native-url-polyfill": "^2.0.0"
54
+ "react-native-url-polyfill": "^3.0.0"
53
55
  },
54
56
  "codegenConfig": {
55
57
  "name": "RCTPushySpec",
@@ -59,21 +61,21 @@
59
61
  "devDependencies": {
60
62
  "@babel/core": "^7.25.8",
61
63
  "@react-native/babel-preset": "^0.73.21",
62
- "@react-native/eslint-config": "0.79.1",
63
- "@react-native/typescript-config": "0.79.1",
64
- "@types/bun": "^1.3.7",
65
- "@types/jest": "^29.5.14",
66
- "@types/node": "^22.15.2",
67
- "@types/react": "^18.3.11",
68
- "detox": "^20.37.0",
64
+ "@react-native/eslint-config": "0.84.1",
65
+ "@react-native/typescript-config": "0.84.1",
66
+ "@types/bun": "^1.3.11",
67
+ "@types/jest": "^30.0.0",
68
+ "@types/node": "^25.5.0",
69
+ "@types/react": "^19.2.14",
70
+ "detox": "^20.50.1",
69
71
  "eslint": "^8.57.0",
70
- "firebase-tools": "^13.22.1",
71
- "jest": "^29.7.0",
72
- "pod-install": "^0.3.7",
72
+ "firebase-tools": "^15.11.0",
73
+ "jest": "^30.3.0",
74
+ "pod-install": "^1.0.14",
73
75
  "prettier": "^2",
74
76
  "react": "18.2.0",
75
77
  "react-native": "0.73",
76
- "ts-jest": "^29.3.2",
78
+ "ts-jest": "^29.4.6",
77
79
  "typescript": "^5.6.3"
78
80
  }
79
- }
81
+ }
@@ -110,6 +110,9 @@ Pod::Spec.new do |s|
110
110
 
111
111
  s.subspec 'RCTPushy' do |ss|
112
112
  ss.source_files = ['ios/**/*.{h,m,mm,c}',
113
+ 'cpp/patch_core/archive_patch_core.{h,cpp}',
114
+ 'cpp/patch_core/patch_core.{h,cpp}',
115
+ 'cpp/patch_core/state_core.{h,cpp}',
113
116
  'android/jni/hpatch.{h,c}',
114
117
  'android/jni/HDiffPatch/libHDiffPatch/HPatch/*.{h,c}',
115
118
  'android/jni/HDiffPatch/file_for_patch.{h,c}',
@@ -6,6 +6,7 @@ const { spawnSync } = require('child_process');
6
6
 
7
7
  const projectRoot = path.resolve(__dirname, '..');
8
8
  const androidJniDir = path.join(projectRoot, 'android', 'jni');
9
+ const patchCoreDir = path.join(projectRoot, 'cpp', 'patch_core');
9
10
  const harmonyModuleDir = path.join(projectRoot, 'harmony', 'pushy');
10
11
  const harmonyBuildDir = path.join(harmonyModuleDir, 'build');
11
12
  const harmonyNativeStageDir = path.join(
@@ -16,6 +17,10 @@ const harmonyNativeStageDir = path.join(
16
17
  'android-generated',
17
18
  );
18
19
  const harmonyNativeStageJniDir = path.join(harmonyNativeStageDir, 'jni');
20
+ const harmonyNativeStagePatchCoreDir = path.join(
21
+ harmonyNativeStageDir,
22
+ 'patch_core',
23
+ );
19
24
  const wrapperProjectDir = path.join(projectRoot, 'harmony', 'har-wrapper');
20
25
  const defaultOutputPath = path.join(projectRoot, 'harmony', 'pushy.har');
21
26
  const wrapperProjectFiles = [
@@ -197,6 +202,12 @@ function syncHarmonyNativeSources() {
197
202
  path.join(androidJniDir, 'lzma', 'C'),
198
203
  )}`,
199
204
  );
205
+ ensureFileExists(
206
+ path.join(patchCoreDir, 'patch_core.cpp'),
207
+ `Missing shared patch core source: ${relativeToProject(
208
+ path.join(patchCoreDir, 'patch_core.cpp'),
209
+ )}`,
210
+ );
200
211
 
201
212
  fs.rmSync(harmonyNativeStageDir, { recursive: true, force: true });
202
213
  fs.mkdirSync(path.join(harmonyNativeStageJniDir, 'lzma'), {
@@ -219,6 +230,7 @@ function syncHarmonyNativeSources() {
219
230
  path.join(androidJniDir, 'lzma', 'C'),
220
231
  path.join(harmonyNativeStageJniDir, 'lzma', 'C'),
221
232
  );
233
+ copyPath(patchCoreDir, harmonyNativeStagePatchCoreDir);
222
234
  }
223
235
 
224
236
  function cleanupHarmonyNativeSources() {
@@ -98,11 +98,57 @@ async function modifyPackageJson({
98
98
  console.log('package.json has been modified for publishing');
99
99
  }
100
100
 
101
+ function isGitHubCI(): boolean {
102
+ return process.env.GITHUB_ACTIONS === 'true';
103
+ }
104
+
105
+ function shouldSkipNativeBuild(): boolean {
106
+ return process.argv.includes('--skip') || process.env.SKIP_NATIVE_BUILD === '1';
107
+ }
108
+
109
+ async function buildNativeArtifacts(): Promise<void> {
110
+ console.log('Building Harmony HAR...');
111
+ const harResult = Bun.spawnSync(['npm', 'run', 'build:harmony-har'], {
112
+ cwd: path.join(__dirname, '..'),
113
+ stdio: ['inherit', 'inherit', 'inherit'],
114
+ });
115
+ if (harResult.exitCode !== 0) {
116
+ throw new Error(
117
+ `Harmony HAR build failed with exit code ${harResult.exitCode}`,
118
+ );
119
+ }
120
+
121
+ console.log('Building Android SO...');
122
+ const soResult = Bun.spawnSync(['npm', 'run', 'build:so'], {
123
+ cwd: path.join(__dirname, '..'),
124
+ stdio: ['inherit', 'inherit', 'inherit'],
125
+ });
126
+ if (soResult.exitCode !== 0) {
127
+ throw new Error(
128
+ `Android SO build failed with exit code ${soResult.exitCode}`,
129
+ );
130
+ }
131
+ }
132
+
101
133
  async function main(): Promise<void> {
102
134
  try {
103
- const version = await resolveVersion();
104
- console.log(`Using publish version ${version}`);
105
- await modifyPackageJson({ version });
135
+ if (isGitHubCI()) {
136
+ const version = await resolveVersion();
137
+ console.log(`Using publish version ${version}`);
138
+ await modifyPackageJson({ version });
139
+ } else {
140
+ console.log(
141
+ 'ℹ️ Not in GitHub CI, skipping version resolution and package.json modification',
142
+ );
143
+ if (shouldSkipNativeBuild()) {
144
+ console.log(
145
+ 'ℹ️ --skip flag detected, skipping native artifacts build',
146
+ );
147
+ } else {
148
+ await buildNativeArtifacts();
149
+ }
150
+ }
151
+
106
152
  console.log('✅ Prepublish script completed successfully');
107
153
  } catch (error) {
108
154
  console.error('❌ Prepublish script failed:', error);
@@ -0,0 +1,6 @@
1
+ #!/bin/sh
2
+ set -eu
3
+
4
+ TARGET_DIR="${1:-android/lib}"
5
+
6
+ find "$TARGET_DIR" -type f -name 'libc++_shared.so' -delete