react-native-update 10.59.1 → 10.60.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.
- package/README-CN.md +7 -7
- package/README.md +7 -6
- package/android/build.gradle +25 -33
- package/android/jni/Android.mk +16 -24
- package/android/lib/arm64-v8a/librnpushy.so +0 -0
- package/android/lib/armeabi-v7a/librnpushy.so +0 -0
- package/android/lib/x86/librnpushy.so +0 -0
- package/android/lib/x86_64/librnpushy.so +0 -0
- package/android/proguard.pro +9 -7
- package/android/src/main/java/cn/reactnative/modules/update/ApkInstaller.java +11 -12
- package/android/src/main/java/cn/reactnative/modules/update/ArchiveLimits.java +23 -6
- package/android/src/main/java/cn/reactnative/modules/update/BundledResourceCopier.java +50 -51
- package/android/src/main/java/cn/reactnative/modules/update/CleanupKeepNames.java +12 -13
- package/android/src/main/java/cn/reactnative/modules/update/CopyGroupResult.java +3 -0
- package/android/src/main/java/cn/reactnative/modules/update/CrashHold.java +22 -30
- package/android/src/main/java/cn/reactnative/modules/update/DownloadTask.java +181 -332
- package/android/src/main/java/cn/reactnative/modules/update/DownloadTaskParams.java +3 -1
- package/android/src/main/java/cn/reactnative/modules/update/ErrorCodes.java +27 -0
- package/android/src/main/java/cn/reactnative/modules/update/FileOperationException.java +1 -1
- package/android/src/main/java/cn/reactnative/modules/update/FlowBridge.java +32 -8
- package/android/src/main/java/cn/reactnative/modules/update/HttpClients.java +63 -0
- package/android/src/main/java/cn/reactnative/modules/update/HttpUtils.java +0 -11
- package/android/src/main/java/cn/reactnative/modules/update/InstallRecord.java +66 -116
- package/android/src/main/java/cn/reactnative/modules/update/NativeCore.java +9 -1
- package/android/src/main/java/cn/reactnative/modules/update/PatchFailedException.java +1 -1
- package/android/src/main/java/cn/reactnative/modules/update/PushyRuntime.java +32 -60
- package/android/src/main/java/cn/reactnative/modules/update/ReactReloadManager.java +8 -23
- package/android/src/main/java/cn/reactnative/modules/update/SafeZipFile.java +42 -80
- package/android/src/main/java/cn/reactnative/modules/update/StateSerialRunner.java +22 -39
- package/android/src/main/java/cn/reactnative/modules/update/SyncCoordinator.java +176 -299
- package/android/src/main/java/cn/reactnative/modules/update/Threads.java +35 -0
- package/android/src/main/java/cn/reactnative/modules/update/UpdateContext.java +242 -174
- package/android/src/main/java/cn/reactnative/modules/update/UpdateEventEmitter.java +1 -1
- package/android/src/main/java/cn/reactnative/modules/update/UpdateFileUtils.java +75 -17
- package/android/src/main/java/cn/reactnative/modules/update/{UpdateModuleImpl.java → UpdateModule.java} +113 -95
- package/android/src/main/java/cn/reactnative/modules/update/UpdatePackage.java +16 -19
- package/android/src/oldarch/cn/reactnative/modules/update/NativePushySpec.java +69 -0
- package/cpp/android_jni/archive_limits_jni.cpp +83 -0
- package/cpp/android_jni/install_record_jni.cpp +89 -0
- package/cpp/android_jni/jni_log.h +31 -0
- package/cpp/android_jni/jni_natives.h +40 -0
- package/cpp/android_jni/jni_registration.cpp +133 -0
- package/cpp/android_jni/jni_util.h +160 -0
- package/cpp/android_jni/update_core_android.cpp +450 -0
- package/cpp/android_jni/update_flow_jni.cpp +133 -0
- package/{android/jni → cpp/hpatch}/hpatch.c +5 -5
- package/{android/jni → cpp/hpatch}/hpatch.h +4 -1
- package/cpp/patch_core/archive_limits.cpp +194 -0
- package/cpp/patch_core/archive_limits.h +99 -10
- package/cpp/patch_core/archive_patch_core.cpp +96 -12
- package/cpp/patch_core/archive_patch_core.h +49 -0
- package/cpp/patch_core/digest.h +5 -4
- package/cpp/patch_core/error_codes.h +5 -3
- package/cpp/patch_core/install_record.cpp +430 -0
- package/cpp/patch_core/install_record.h +163 -9
- package/cpp/patch_core/patch_core.cpp +62 -16
- package/cpp/patch_core/patch_core.h +27 -7
- package/cpp/patch_core/patch_manifest.cpp +201 -0
- package/cpp/patch_core/patch_manifest.h +74 -0
- package/cpp/patch_core/state_ops.h +3 -3
- package/cpp/update_flow_core/flow_json.cpp +82 -8
- package/cpp/update_flow_core/flow_json.h +21 -0
- package/cpp/update_flow_core/native_config.cpp +456 -0
- package/cpp/update_flow_core/native_config.h +84 -0
- package/cpp/update_flow_core/native_round.cpp +326 -0
- package/cpp/update_flow_core/native_round.h +90 -0
- package/cpp/update_flow_core/update_flow_core.h +2 -2
- package/harmony/hvigor-plugin.ts +11 -19
- package/harmony/pushy/src/main/cpp/CMakeLists.txt +19 -26
- package/harmony/pushy/src/main/cpp/PushyPackage.h +2 -2
- package/harmony/pushy/src/main/cpp/PushyTurboModule.cpp +55 -94
- package/harmony/pushy/src/main/cpp/pushy.cpp +694 -517
- package/harmony/pushy/src/main/ets/ArchiveLimits.ts +48 -72
- package/harmony/pushy/src/main/ets/DownloadTask.ts +164 -404
- package/harmony/pushy/src/main/ets/DownloadTaskParams.ts +1 -3
- package/harmony/pushy/src/main/ets/ErrorCodes.ts +1 -14
- package/harmony/pushy/src/main/ets/EventHub.ts +1 -1
- package/harmony/pushy/src/main/ets/InstallRecord.ts +52 -151
- package/harmony/pushy/src/main/ets/Logger.ts +20 -34
- package/harmony/pushy/src/main/ets/NativePatchCore.ts +116 -42
- package/harmony/pushy/src/main/ets/PushyConfiguration.ts +8 -85
- package/harmony/pushy/src/main/ets/PushyTurboModule.ts +11 -25
- package/harmony/pushy/src/main/ets/SaveFile.ts +99 -18
- package/harmony/pushy/src/main/ets/SyncCoordinator.ts +136 -335
- package/harmony/pushy/src/main/ets/Texts.ts +0 -4
- package/harmony/pushy/src/main/ets/UpdateContext.ts +106 -119
- package/harmony/pushy.har +0 -0
- package/ios/RCTPushy/RCTPushy+Launch.mm +185 -0
- package/ios/RCTPushy/RCTPushy.h +12 -0
- package/ios/RCTPushy/RCTPushy.mm +87 -2628
- package/ios/RCTPushy/RCTPushyCommon.h +34 -0
- package/ios/RCTPushy/RCTPushyConfiguration.h +0 -8
- package/ios/RCTPushy/RCTPushyConfiguration.mm +40 -121
- package/ios/RCTPushy/RCTPushyDownloader.mm +40 -37
- package/ios/RCTPushy/RCTPushyInstallRecord.mm +61 -0
- package/ios/RCTPushy/RCTPushyInstaller.mm +689 -0
- package/ios/RCTPushy/RCTPushyInternal.h +144 -0
- package/ios/RCTPushy/RCTPushyOrchestrator.mm +1001 -0
- package/ios/RCTPushy/RCTPushyState.mm +314 -0
- package/package.json +25 -23
- package/react-native-update.podspec +74 -83
- package/src/client.ts +361 -451
- package/src/context.ts +1 -1
- package/src/core.ts +35 -8
- package/src/endpoint.ts +0 -2
- package/src/error.ts +13 -32
- package/src/i18n.ts +18 -83
- package/src/locales/en.ts +0 -4
- package/src/locales/zh.ts +0 -4
- package/src/provider.tsx +60 -53
- package/src/telemetry.ts +0 -13
- package/src/type.ts +0 -15
- package/src/updateFlowCore.ts +116 -10
- package/src/utils.ts +49 -42
- package/android/src/main/java/cn/reactnative/modules/update/ArchivePatchPlanResult.java +0 -6
- package/android/src/main/java/cn/reactnative/modules/update/PushyConfiguration.java +0 -104
- package/android/src/main/java/cn/reactnative/modules/update/UiThreadRunner.java +0 -37
- package/android/src/newarch/cn/reactnative/modules/update/UpdateModule.java +0 -121
- package/android/src/oldarch/cn/reactnative/modules/update/UpdateModule.java +0 -125
- package/cpp/patch_core/jni_natives.h +0 -27
- package/cpp/patch_core/jni_registration.cpp +0 -103
- package/cpp/patch_core/jni_util.h +0 -60
- package/cpp/patch_core/patch_core_android.cpp +0 -97
- package/cpp/patch_core/update_core_android.cpp +0 -485
- package/cpp/update_flow_core/update_flow_jni.cpp +0 -150
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
// Persisted update state: the defaults keys, the state lock, the State <->
|
|
2
|
+
// defaults mapping, the string/error/JSON helpers every other file uses, and
|
|
3
|
+
// the embedded bundle's hash.
|
|
4
|
+
#import "RCTPushyInternal.h"
|
|
5
|
+
#include "../../cpp/patch_core/digest.h"
|
|
6
|
+
|
|
7
|
+
#import <React/RCTConvert.h>
|
|
8
|
+
#import <os/lock.h>
|
|
9
|
+
|
|
10
|
+
PUSHY_HIDDEN NSString *const keyPushyInfo = @"REACTNATIVECN_PUSHY_INFO_KEY";
|
|
11
|
+
// Binary identity (SyncBinaryVersion input). Prefixed like every other key:
|
|
12
|
+
// the unprefixed names collided with generic host-app/SDK defaults, and a
|
|
13
|
+
// foreign value there made every launch look like a rebuilt binary and wipe
|
|
14
|
+
// the installed update.
|
|
15
|
+
static NSString *const paramPackageVersion = @"REACTNATIVECN_PUSHY_PACKAGEVERSION";
|
|
16
|
+
static NSString *const paramBuildTime = @"REACTNATIVECN_PUSHY_BUILDTIME";
|
|
17
|
+
// The unprefixed names earlier SDKs wrote. Read only as a fallback until the
|
|
18
|
+
// first state write migrates them (PushyStateFromDefaults /
|
|
19
|
+
// PushyApplyStateToDefaults).
|
|
20
|
+
static NSString *const legacyParamPackageVersion = @"packageVersion";
|
|
21
|
+
static NSString *const legacyParamBuildTime = @"buildTime";
|
|
22
|
+
static NSString *const paramLastVersion = @"lastVersion";
|
|
23
|
+
PUSHY_HIDDEN NSString *const paramCurrentVersion = @"currentVersion";
|
|
24
|
+
static NSString *const paramIsFirstTime = @"isFirstTime";
|
|
25
|
+
static NSString *const paramIsFirstLoadOk = @"isFirstLoadOK";
|
|
26
|
+
PUSHY_HIDDEN NSString *const keyUuid = @"REACTNATIVECN_PUSHY_UUID";
|
|
27
|
+
PUSHY_HIDDEN NSString *const keyHashInfo = @"REACTNATIVECN_PUSHY_HASH_";
|
|
28
|
+
PUSHY_HIDDEN NSString *const keyFirstLoadMarked = @"REACTNATIVECN_PUSHY_FIRSTLOADMARKED_KEY";
|
|
29
|
+
PUSHY_HIDDEN NSString *const keyRolledBackMarked = @"REACTNATIVECN_PUSHY_ROLLEDBACKMARKED_KEY";
|
|
30
|
+
// Encoded constants (RCTPushyRevealText) are decoded on first use, not by
|
|
31
|
+
// static initializers at image load.
|
|
32
|
+
PUSHY_HIDDEN NSString *KeyPackageUpdatedMarked(void) {
|
|
33
|
+
static NSString *value = RCTPushyRevealText("0832d5f29aa549710b0939daf88ca058790f3dded7e888b451640d2ec3f69099bb43711523cafa8ea7bb4372132a");
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
// bundleHash cache: "<cacheKey>|<sha256hex>" where cacheKey identifies the
|
|
37
|
+
// installed binary (packageVersion + embedded bundle size + mtime). Recomputed
|
|
38
|
+
// only when the key changes, i.e. once per install.
|
|
39
|
+
static NSString *const keyBundleHashCache = @"REACTNATIVECN_PUSHY_BUNDLEHASH_KEY";
|
|
40
|
+
// Raw response cache written by the native cold-start check for the JS side
|
|
41
|
+
// to reuse (§10.3), scoped to the request and config that produced it.
|
|
42
|
+
PUSHY_HIDDEN NSString *const keyNativeCheckCache = @"REACTNATIVECN_PUSHY_NATIVE_CHECK_RESP_KEY";
|
|
43
|
+
|
|
44
|
+
// error def — messages are human-readable; the stable cross-platform codes
|
|
45
|
+
// live in cpp/patch_core/error_codes.h and travel in RCTPushyErrorCodeKey.
|
|
46
|
+
PUSHY_HIDDEN NSString *const ERROR_OPTIONS = @"options error";
|
|
47
|
+
|
|
48
|
+
PUSHY_HIDDEN std::atomic<bool> ignoreRollback{false};
|
|
49
|
+
// Bumped by resetToPackagedBundle only (config replacement has its own
|
|
50
|
+
// pushyNativeConfigGeneration). The cold-start check runs for minutes and
|
|
51
|
+
// may already hold a decision when the app resets to the packaged bundle; it
|
|
52
|
+
// samples this counter and abandons activation (and its response cache) when
|
|
53
|
+
// the value moved, so an in-flight rescue can never resurrect the version the
|
|
54
|
+
// app just reset away from.
|
|
55
|
+
PUSHY_HIDDEN std::atomic<uint64_t> pushyResetGeneration{0};
|
|
56
|
+
|
|
57
|
+
PUSHY_HIDDEN NSDictionary *PushyHostResult(NSString *status, NSString *reason,
|
|
58
|
+
NSString *hash, BOOL activated) {
|
|
59
|
+
return @{@"status": status, @"reason": reason ?: @"",
|
|
60
|
+
@"hash": hash ?: @"", @"activated": @(activated)};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
PUSHY_HIDDEN NSTimeInterval PushyMonotonicNow(void) {
|
|
64
|
+
return [NSProcessInfo processInfo].systemUptime;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Serializes every read-modify-write of the persisted update state. The state
|
|
68
|
+
// machine itself is a pure function (state_core), but callers run on different
|
|
69
|
+
// threads (main thread bundleURL, module method queue, the file queue), so the
|
|
70
|
+
// read→transform→write sequence must be atomic to avoid e.g. markSuccess being
|
|
71
|
+
// overwritten by a concurrent bundleURL and the version being rolled back.
|
|
72
|
+
static os_unfair_lock pushyStateLock = OS_UNFAIR_LOCK_INIT;
|
|
73
|
+
|
|
74
|
+
PUSHY_HIDDEN void PushyWithStateLock(void (NS_NOESCAPE ^block)(void)) {
|
|
75
|
+
#if DEBUG
|
|
76
|
+
// Not re-entrant: a nested acquisition deadlocks in release, so catch it
|
|
77
|
+
// where it is written.
|
|
78
|
+
os_unfair_lock_assert_not_owner(&pushyStateLock);
|
|
79
|
+
#endif
|
|
80
|
+
os_unfair_lock_lock(&pushyStateLock);
|
|
81
|
+
@try {
|
|
82
|
+
block();
|
|
83
|
+
} @finally {
|
|
84
|
+
os_unfair_lock_unlock(&pushyStateLock);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
PUSHY_HIDDEN std::string PushyToStdString(NSString *value) {
|
|
89
|
+
if (value == nil) {
|
|
90
|
+
return std::string();
|
|
91
|
+
}
|
|
92
|
+
return std::string([value UTF8String]);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
PUSHY_HIDDEN NSUserDefaults *PushyDefaults(void) {
|
|
96
|
+
return [NSUserDefaults standardUserDefaults];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
PUSHY_HIDDEN NSString *PushyFromStdString(const std::string &value) {
|
|
100
|
+
if (value.empty()) {
|
|
101
|
+
return nil;
|
|
102
|
+
}
|
|
103
|
+
return [NSString stringWithUTF8String:value.c_str()];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static void PushySetNullableString(NSUserDefaults *defaults, NSString *key, NSString *value) {
|
|
107
|
+
if (value != nil) {
|
|
108
|
+
[defaults setObject:value forKey:key];
|
|
109
|
+
} else {
|
|
110
|
+
[defaults removeObjectForKey:key];
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
PUSHY_HIDDEN NSString *PushyHashInfoKey(NSString *hash) {
|
|
115
|
+
return [keyHashInfo stringByAppendingString:hash ?: @""];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
PUSHY_HIDDEN NSString *PushyOptionString(NSDictionary *options, NSString *key) {
|
|
119
|
+
return [RCTConvert NSString:options[key]];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
PUSHY_HIDDEN BOOL PushyStringIsBlank(NSString *value) {
|
|
123
|
+
if (value == nil || [value isKindOfClass:[NSNull class]]) {
|
|
124
|
+
return YES;
|
|
125
|
+
}
|
|
126
|
+
return [[value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Server-provided identifiers (hash/originHash) are used as child names under
|
|
130
|
+
// the download root; anything that could resolve outside of it (path
|
|
131
|
+
// separators, "..", ".") must be rejected before touching the filesystem.
|
|
132
|
+
PUSHY_HIDDEN BOOL PushyIsSafePathComponent(NSString *value) {
|
|
133
|
+
if (PushyStringIsBlank(value)) {
|
|
134
|
+
return NO;
|
|
135
|
+
}
|
|
136
|
+
if ([value isEqualToString:@"."] || [value isEqualToString:@".."]) {
|
|
137
|
+
return NO;
|
|
138
|
+
}
|
|
139
|
+
if ([value containsString:@"/"] || [value containsString:@"\\"]) {
|
|
140
|
+
return NO;
|
|
141
|
+
}
|
|
142
|
+
if ([value rangeOfString:@"\0"].location != NSNotFound) {
|
|
143
|
+
return NO;
|
|
144
|
+
}
|
|
145
|
+
return YES;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
PUSHY_HIDDEN NSError *PushyErrorWithCode(const char *code, NSString *message) {
|
|
149
|
+
return [NSError errorWithDomain:RCTPushyErrorDomain
|
|
150
|
+
code:-1
|
|
151
|
+
userInfo:@{
|
|
152
|
+
NSLocalizedDescriptionKey: message ?: @"unknown error",
|
|
153
|
+
RCTPushyErrorCodeKey: @(code),
|
|
154
|
+
}];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
PUSHY_HIDDEN void PushyRejectError(RCTPromiseRejectBlock reject, NSError *error) {
|
|
158
|
+
// Prefer the stable cross-platform code (error_codes.h); fall back to the
|
|
159
|
+
// numeric NSError code for system errors that were not classified.
|
|
160
|
+
NSString *code = error.userInfo[RCTPushyErrorCodeKey];
|
|
161
|
+
if (code == nil) {
|
|
162
|
+
code = [NSString stringWithFormat:@"%ld", (long)error.code];
|
|
163
|
+
}
|
|
164
|
+
reject(code, error.localizedDescription, error);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
PUSHY_HIDDEN NSDictionary *PushyJsonDictionary(id json, NSError **error) {
|
|
168
|
+
NSData *data = [json isKindOfClass:[NSString class]]
|
|
169
|
+
? [(NSString *)json dataUsingEncoding:NSUTF8StringEncoding]
|
|
170
|
+
: ([json isKindOfClass:[NSData class]] ? (NSData *)json : nil);
|
|
171
|
+
id object = data == nil ? nil
|
|
172
|
+
: [NSJSONSerialization JSONObjectWithData:data options:0 error:error];
|
|
173
|
+
return [object isKindOfClass:[NSDictionary class]] ? (NSDictionary *)object : nil;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
PUSHY_HIDDEN NSString *PushyJsonString(id object) {
|
|
177
|
+
NSData *data = object == nil ? nil
|
|
178
|
+
: [NSJSONSerialization dataWithJSONObject:object options:0 error:nil];
|
|
179
|
+
return data == nil ? nil : [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Binary identity under the prefixed key, or — until the first state write
|
|
183
|
+
// migrates it — the value an earlier SDK left under the unprefixed one, so an
|
|
184
|
+
// installed update survives the SDK upgrade instead of reading as a rebuilt
|
|
185
|
+
// binary.
|
|
186
|
+
static NSString *PushyBinaryIdentityValue(NSUserDefaults *defaults, NSString *key, NSString *legacyKey) {
|
|
187
|
+
return [defaults stringForKey:key] ?: [defaults stringForKey:legacyKey];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
PUSHY_HIDDEN pushy::state::State PushyStateFromDefaults(NSUserDefaults *defaults) {
|
|
191
|
+
pushy::state::State state;
|
|
192
|
+
state.package_version = PushyToStdString(
|
|
193
|
+
PushyBinaryIdentityValue(defaults, paramPackageVersion, legacyParamPackageVersion));
|
|
194
|
+
state.build_time = PushyToStdString(
|
|
195
|
+
PushyBinaryIdentityValue(defaults, paramBuildTime, legacyParamBuildTime));
|
|
196
|
+
NSDictionary *pushyInfo = [defaults dictionaryForKey:keyPushyInfo];
|
|
197
|
+
if (pushyInfo != nil) {
|
|
198
|
+
state.current_version = PushyToStdString(pushyInfo[paramCurrentVersion]);
|
|
199
|
+
state.last_version = PushyToStdString(pushyInfo[paramLastVersion]);
|
|
200
|
+
state.first_time = [pushyInfo[paramIsFirstTime] boolValue];
|
|
201
|
+
id firstLoadOk = pushyInfo[paramIsFirstLoadOk];
|
|
202
|
+
state.first_time_ok = firstLoadOk == nil ? true : [firstLoadOk boolValue];
|
|
203
|
+
}
|
|
204
|
+
state.rolled_back_version = PushyToStdString([defaults stringForKey:keyRolledBackMarked]);
|
|
205
|
+
return state;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
PUSHY_HIDDEN void PushyApplyStateToDefaults(NSUserDefaults *defaults, const pushy::state::State &state) {
|
|
209
|
+
PushySetNullableString(defaults, paramPackageVersion, PushyFromStdString(state.package_version));
|
|
210
|
+
PushySetNullableString(defaults, paramBuildTime, PushyFromStdString(state.build_time));
|
|
211
|
+
// One-time migration: once the prefixed keys hold the identity, the
|
|
212
|
+
// legacy ones are retired so a host-app write there is never read again.
|
|
213
|
+
[defaults removeObjectForKey:legacyParamPackageVersion];
|
|
214
|
+
[defaults removeObjectForKey:legacyParamBuildTime];
|
|
215
|
+
|
|
216
|
+
BOOL hasPushyInfo = !state.current_version.empty() || !state.last_version.empty() || state.first_time || !state.first_time_ok;
|
|
217
|
+
if (hasPushyInfo) {
|
|
218
|
+
NSMutableDictionary *newInfo = [[NSMutableDictionary alloc] init];
|
|
219
|
+
if (!state.current_version.empty()) {
|
|
220
|
+
newInfo[paramCurrentVersion] = PushyFromStdString(state.current_version);
|
|
221
|
+
}
|
|
222
|
+
if (!state.last_version.empty()) {
|
|
223
|
+
newInfo[paramLastVersion] = PushyFromStdString(state.last_version);
|
|
224
|
+
}
|
|
225
|
+
newInfo[paramIsFirstTime] = @(state.first_time);
|
|
226
|
+
newInfo[paramIsFirstLoadOk] = @(state.first_time_ok);
|
|
227
|
+
[defaults setObject:newInfo forKey:keyPushyInfo];
|
|
228
|
+
} else {
|
|
229
|
+
[defaults removeObjectForKey:keyPushyInfo];
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
PushySetNullableString(
|
|
233
|
+
defaults,
|
|
234
|
+
keyRolledBackMarked,
|
|
235
|
+
PushyFromStdString(state.rolled_back_version));
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Version switch without acquiring the state lock: the caller must already
|
|
239
|
+
// hold it. Lets the cold-start check commit its whole result (version info,
|
|
240
|
+
// switch, response cache) inside one lock acquisition, so resetToPackagedBundle
|
|
241
|
+
// can never interleave between the generation check and the writes.
|
|
242
|
+
PUSHY_HIDDEN void PushySwitchVersionLocked(NSString *hash) {
|
|
243
|
+
NSUserDefaults *defaults = PushyDefaults();
|
|
244
|
+
pushy::state::State next = pushy::state::SwitchVersion(
|
|
245
|
+
PushyStateFromDefaults(defaults),
|
|
246
|
+
PushyToStdString(hash)
|
|
247
|
+
);
|
|
248
|
+
PushyApplyStateToDefaults(defaults, next);
|
|
249
|
+
// Re-enable first-load consumption and rollback checks for the newly selected bundle.
|
|
250
|
+
ignoreRollback = false;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
static NSString *PushyCachedBundleHash(NSUserDefaults *defaults, NSString *cachedPrefix) {
|
|
254
|
+
NSString *cached = [defaults stringForKey:keyBundleHashCache];
|
|
255
|
+
if ([cached hasPrefix:cachedPrefix]) {
|
|
256
|
+
return [cached substringFromIndex:cachedPrefix.length];
|
|
257
|
+
}
|
|
258
|
+
return nil;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Shared by the getBundleHash RCT method and the native cold-start check.
|
|
262
|
+
// Returns @"" when unknown. With computeIfMissing the sha256 of the embedded
|
|
263
|
+
// bundle is taken on a cache miss (once per install; blocking — call off the
|
|
264
|
+
// main thread). Without it only the cache is consulted: a crash rescue on
|
|
265
|
+
// the main thread has a 3.5s budget in total, and hashing a large bundle on
|
|
266
|
+
// a fresh install would spend all of it before the first request.
|
|
267
|
+
PUSHY_HIDDEN NSString *PushyBundleHashSync(BOOL computeIfMissing) {
|
|
268
|
+
NSString *path = [[RCTPushy binaryBundleURL] path];
|
|
269
|
+
if (path == nil) {
|
|
270
|
+
return @"";
|
|
271
|
+
}
|
|
272
|
+
NSDictionary *attributes =
|
|
273
|
+
[[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
|
|
274
|
+
if (attributes == nil) {
|
|
275
|
+
return @"";
|
|
276
|
+
}
|
|
277
|
+
NSString *cacheKey = [NSString stringWithFormat:@"%@|%llu|%.0f",
|
|
278
|
+
[RCTPushy packageVersion],
|
|
279
|
+
attributes.fileSize,
|
|
280
|
+
[attributes.fileModificationDate timeIntervalSince1970]];
|
|
281
|
+
|
|
282
|
+
NSUserDefaults *defaults = PushyDefaults();
|
|
283
|
+
NSString *cachedPrefix = [cacheKey stringByAppendingString:@"|"];
|
|
284
|
+
NSString *cached = PushyCachedBundleHash(defaults, cachedPrefix);
|
|
285
|
+
if (cached != nil) {
|
|
286
|
+
return cached;
|
|
287
|
+
}
|
|
288
|
+
if (!computeIfMissing) {
|
|
289
|
+
return @"";
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Single-flight for the digest: the delayed cold-start round (utility
|
|
293
|
+
// queue) and JS getBundleHash (file queue) can both miss the cache right
|
|
294
|
+
// after an install; the second caller waits for the first and then reads
|
|
295
|
+
// its cache entry instead of hashing the same multi-MB file twice.
|
|
296
|
+
static NSLock *lock = [NSLock new];
|
|
297
|
+
[lock lock];
|
|
298
|
+
@try {
|
|
299
|
+
// The previous holder may have filled the cache while we waited.
|
|
300
|
+
cached = PushyCachedBundleHash(defaults, cachedPrefix);
|
|
301
|
+
if (cached != nil) {
|
|
302
|
+
return cached;
|
|
303
|
+
}
|
|
304
|
+
NSString *hash = PushyFromStdString(
|
|
305
|
+
pushy::digest::Sha256File(PushyToStdString(path))) ?: @"";
|
|
306
|
+
if (hash.length > 0) {
|
|
307
|
+
[defaults setObject:[cachedPrefix stringByAppendingString:hash]
|
|
308
|
+
forKey:keyBundleHashCache];
|
|
309
|
+
}
|
|
310
|
+
return hash;
|
|
311
|
+
} @finally {
|
|
312
|
+
[lock unlock];
|
|
313
|
+
}
|
|
314
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-update",
|
|
3
|
-
"version": "10.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "10.60.0",
|
|
4
|
+
"description": "Hot update (OTA) for React Native with Hermes-optimized diff patches, crash rollback and staged rollout. A CodePush alternative for iOS, Android and HarmonyOS.",
|
|
5
5
|
"main": "src/index",
|
|
6
6
|
"types": "src/index.ts",
|
|
7
7
|
"files": [
|
|
@@ -15,13 +15,11 @@
|
|
|
15
15
|
"android/build.gradle",
|
|
16
16
|
"android/proguard.pro",
|
|
17
17
|
"ios",
|
|
18
|
-
"cpp
|
|
19
|
-
"cpp/update_flow_core",
|
|
18
|
+
"cpp",
|
|
20
19
|
"!cpp/**/tests",
|
|
21
20
|
"harmony/pushy.har",
|
|
22
21
|
"harmony/hvigor-plugin.ts",
|
|
23
22
|
"harmony/pushy/src",
|
|
24
|
-
"!harmony/pushy/src/test",
|
|
25
23
|
"react-native-update.podspec",
|
|
26
24
|
"react-native.config.js",
|
|
27
25
|
"expo-module.config.json",
|
|
@@ -30,10 +28,8 @@
|
|
|
30
28
|
"LICENSE"
|
|
31
29
|
],
|
|
32
30
|
"scripts": {
|
|
33
|
-
"prepublishOnly": "NODE_ENV=production bun scripts/prepublish.ts",
|
|
34
|
-
"publish:local": "SKIP_NATIVE_BUILD=1 npm publish",
|
|
35
31
|
"prepack": "bun submodule && bun lint",
|
|
36
|
-
"lint": "biome check src && tsc --noEmit && node scripts/check-harmony-types.js && node scripts/check-native-spec-parity.js",
|
|
32
|
+
"lint": "biome check src && tsc --noEmit && node scripts/check-harmony-types.js && node scripts/check-native-spec-parity.js && node scripts/check-constant-parity.js",
|
|
37
33
|
"lint:harmony": "node scripts/check-harmony-types.js",
|
|
38
34
|
"submodule": "git submodule update --init --recursive",
|
|
39
35
|
"test": "bun test src/__tests__",
|
|
@@ -43,14 +39,11 @@
|
|
|
43
39
|
"build:harmony-har": "node scripts/build-harmony-har.js",
|
|
44
40
|
"build:harmony-e2e": "bash Example/e2etest/scripts/build-harmony-e2e.sh",
|
|
45
41
|
"build:so": "bun submodule && bash scripts/build-android-so.sh",
|
|
46
|
-
"build:ios-debug": "cd Example/e2etest && bun && bunx detox build --configuration ios.sim.debug",
|
|
47
42
|
"build:ios-release": "cd Example/e2etest && bun && bunx detox build --configuration ios.sim.release",
|
|
48
|
-
"test:ios-debug": "cd Example/e2etest && E2E_PLATFORM=ios bunx detox test --configuration ios.sim.debug",
|
|
49
43
|
"test:ios-release": "cd Example/e2etest && E2E_PLATFORM=ios bunx detox test --configuration ios.sim.release",
|
|
50
44
|
"build:android-debug": "cd Example/e2etest && bun && bunx detox build --configuration android.emu.debug",
|
|
51
45
|
"build:android-release": "cd Example/e2etest && bun && bunx detox build --configuration android.emu.release",
|
|
52
46
|
"test:android-release": "cd Example/e2etest && E2E_PLATFORM=android bunx detox test --configuration android.emu.release --headless --record-logs all",
|
|
53
|
-
"test:android-debug": "cd Example/e2etest && E2E_PLATFORM=android bunx detox test --configuration android.emu.debug --headless --record-logs all",
|
|
54
47
|
"smoke:android-debug": "cd Example/e2etest && bunx detox test --configuration android.emu.debug --config e2e/smoke/jest.config.js",
|
|
55
48
|
"e2e:ios": "bun build:ios-release && bun test:ios-release",
|
|
56
49
|
"e2e:android": "bun build:android-release && bun test:android-release"
|
|
@@ -63,7 +56,21 @@
|
|
|
63
56
|
"react-native",
|
|
64
57
|
"ios",
|
|
65
58
|
"android",
|
|
66
|
-
"update"
|
|
59
|
+
"update",
|
|
60
|
+
"hot-update",
|
|
61
|
+
"hotfix",
|
|
62
|
+
"ota",
|
|
63
|
+
"over-the-air",
|
|
64
|
+
"codepush",
|
|
65
|
+
"code-push",
|
|
66
|
+
"codepush-alternative",
|
|
67
|
+
"hermes",
|
|
68
|
+
"harmonyos",
|
|
69
|
+
"expo",
|
|
70
|
+
"incremental-update",
|
|
71
|
+
"bsdiff",
|
|
72
|
+
"pushy",
|
|
73
|
+
"cresc"
|
|
67
74
|
],
|
|
68
75
|
"author": "reactnativecn",
|
|
69
76
|
"license": "MIT",
|
|
@@ -75,26 +82,21 @@
|
|
|
75
82
|
"react-native": "*"
|
|
76
83
|
},
|
|
77
84
|
"homepage": "https://github.com/reactnativecn/react-native-update#readme",
|
|
78
|
-
"dependencies": {
|
|
79
|
-
"nanoid": "^3.3.3"
|
|
80
|
-
},
|
|
81
85
|
"codegenConfig": {
|
|
82
86
|
"name": "RCTPushySpec",
|
|
83
87
|
"type": "modules",
|
|
84
88
|
"jsSrcsDir": "src"
|
|
85
89
|
},
|
|
86
90
|
"devDependencies": {
|
|
87
|
-
"@babel/core": "^7.25.8",
|
|
88
91
|
"@biomejs/biome": "^2.5.5",
|
|
89
|
-
"@react-native/
|
|
90
|
-
"@react-native/typescript-config": "0.84.1",
|
|
92
|
+
"@react-native/typescript-config": "0.85.2",
|
|
91
93
|
"@types/bun": "^1.3.11",
|
|
92
94
|
"@types/node": "^25.5.0",
|
|
93
95
|
"@types/react": "^19.2.14",
|
|
94
|
-
"@types/react-test-renderer": "
|
|
95
|
-
"react": "
|
|
96
|
-
"react-native": "0.
|
|
97
|
-
"react-test-renderer": "
|
|
96
|
+
"@types/react-test-renderer": "19.1.0",
|
|
97
|
+
"react": "19.2.3",
|
|
98
|
+
"react-native": "0.85.2",
|
|
99
|
+
"react-test-renderer": "19.2.3",
|
|
98
100
|
"typescript": "^7.0.2"
|
|
99
101
|
}
|
|
100
|
-
}
|
|
102
|
+
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
require 'json'
|
|
2
2
|
require 'rubygems' # Required for version comparison
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
new_arch_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == '1'
|
|
6
4
|
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
7
5
|
podspec_dir = File.dirname(__FILE__)
|
|
8
6
|
|
|
@@ -20,37 +18,40 @@ Pod::Spec.new do |s|
|
|
|
20
18
|
# Silently ignore errors during check
|
|
21
19
|
end
|
|
22
20
|
|
|
23
|
-
#
|
|
24
|
-
# expo
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
# Determine final validity by checking Podfile presence AND Expo version
|
|
33
|
-
valid_expo_project = false # Default
|
|
21
|
+
# One node call answers every Expo question: expo's version, and where
|
|
22
|
+
# expo-modules-core lives and its version. expo-modules-core is a dependency
|
|
23
|
+
# of expo, not of the app: resolve it from expo's own location. A bare
|
|
24
|
+
# require from this podspec's directory misses it when npm nests it under
|
|
25
|
+
# expo/node_modules (seen with react-native-tvos), which left
|
|
26
|
+
# EXPO_SUPPORTS_BUNDLEURL unset; the createBridge fallback that selects no
|
|
27
|
+
# longer exists in ExpoModulesCore (SDK 57), so the build failed.
|
|
28
|
+
expo_info = {}
|
|
34
29
|
if is_expo_in_podfile
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
expo_info_js = <<~JS
|
|
31
|
+
const path = require('path');
|
|
32
|
+
const info = {};
|
|
33
|
+
try {
|
|
34
|
+
const expoJson = require.resolve('expo/package.json');
|
|
35
|
+
info.expoVersion = require(expoJson).version;
|
|
36
|
+
const coreJson = require.resolve('expo-modules-core/package.json',
|
|
37
|
+
{ paths: [path.dirname(expoJson)] });
|
|
38
|
+
info.coreDir = path.dirname(coreJson);
|
|
39
|
+
info.coreVersion = require(coreJson).version;
|
|
40
|
+
} catch (e) {}
|
|
41
|
+
console.log(JSON.stringify(info));
|
|
42
|
+
JS
|
|
37
43
|
begin
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
major_version = match[0].to_i
|
|
43
|
-
is_version_sufficient = major_version >= 50
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
rescue
|
|
47
|
-
# Node command failed, version remains insufficient
|
|
44
|
+
output = IO.popen(['node', '-e', expo_info_js], &:read)
|
|
45
|
+
expo_info = JSON.parse(output) if $?.success?
|
|
46
|
+
rescue StandardError
|
|
47
|
+
# node missing or unparseable output: not a supported Expo project.
|
|
48
48
|
end
|
|
49
|
-
|
|
50
|
-
# Final check
|
|
51
|
-
valid_expo_project = is_version_sufficient
|
|
52
49
|
end
|
|
53
50
|
|
|
51
|
+
# use_expo_modules! in the Podfile and Expo SDK >= 50.
|
|
52
|
+
valid_expo_project =
|
|
53
|
+
is_expo_in_podfile && expo_info['expoVersion'].to_s[/^\d+/].to_i >= 50
|
|
54
|
+
|
|
54
55
|
# Set platform based on whether it's a valid Expo project and if we can parse its target
|
|
55
56
|
# React Native's own minimum (defined by react_native_pods.rb, which the
|
|
56
57
|
# Podfile loads before evaluating podspecs). The pod platform version also
|
|
@@ -59,16 +60,23 @@ Pod::Spec.new do |s|
|
|
|
59
60
|
# anything below 15.0 there, so a hard-coded 11.0 fails the build.
|
|
60
61
|
final_ios_deployment_target =
|
|
61
62
|
defined?(min_ios_version_supported) ? min_ios_version_supported : '11.0'
|
|
63
|
+
# tvOS has its own version line: react-native-tvos reports it through
|
|
64
|
+
# min_supported_versions[:tvos] (stock React Native has no :tvos entry).
|
|
65
|
+
# 15.1 is react-native-tvos's own floor since 0.76, and clears the same
|
|
66
|
+
# Xcode 27 resource-bundle minimum as iOS.
|
|
67
|
+
final_tvos_deployment_target = begin
|
|
68
|
+
defined?(min_supported_versions) ? min_supported_versions[:tvos] : nil
|
|
69
|
+
rescue StandardError
|
|
70
|
+
nil
|
|
71
|
+
end
|
|
72
|
+
final_tvos_deployment_target ||= '15.1'
|
|
62
73
|
|
|
63
74
|
if valid_expo_project
|
|
64
75
|
# --- Try to find and parse ExpoModulesCore.podspec only if it's an Expo project ---
|
|
65
76
|
parsed_expo_ios_target = nil
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
rescue
|
|
70
|
-
nil
|
|
71
|
-
end
|
|
77
|
+
parsed_expo_tvos_target = nil
|
|
78
|
+
expo_modules_core_podspec_path =
|
|
79
|
+
expo_info['coreDir'] && File.join(expo_info['coreDir'], 'ExpoModulesCore.podspec')
|
|
72
80
|
|
|
73
81
|
if expo_modules_core_podspec_path && File.exist?(expo_modules_core_podspec_path)
|
|
74
82
|
begin
|
|
@@ -76,11 +84,8 @@ Pod::Spec.new do |s|
|
|
|
76
84
|
match = content.match(/s\.platforms\s*=\s*\{[\s\S]*?:ios\s*=>\s*'([^\']+)'/) # Match within s.platforms hash
|
|
77
85
|
if match && match[1]
|
|
78
86
|
parsed_expo_ios_target = match[1]
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if match && match[1]
|
|
82
|
-
parsed_expo_ios_target = match[1]
|
|
83
|
-
end
|
|
87
|
+
tvos_match = content.match(/s\.platforms\s*=\s*\{[\s\S]*?:tvos\s*=>\s*'([^\']+)'/)
|
|
88
|
+
parsed_expo_tvos_target = tvos_match[1] if tvos_match
|
|
84
89
|
end
|
|
85
90
|
rescue => e
|
|
86
91
|
# Pod::UI.warn "Failed to read or parse ExpoModulesCore.podspec content: #{e.message}"
|
|
@@ -89,12 +94,15 @@ Pod::Spec.new do |s|
|
|
|
89
94
|
if parsed_expo_ios_target
|
|
90
95
|
final_ios_deployment_target = parsed_expo_ios_target
|
|
91
96
|
end
|
|
97
|
+
if parsed_expo_tvos_target
|
|
98
|
+
final_tvos_deployment_target = parsed_expo_tvos_target
|
|
99
|
+
end
|
|
92
100
|
end
|
|
93
101
|
|
|
94
102
|
# tvOS (react-native-tvos) shares the iOS sources; the only platform
|
|
95
|
-
# differences live behind TARGET_OS_TV in RCTPushy
|
|
103
|
+
# differences live behind TARGET_OS_TV in ios/RCTPushy (download directory,
|
|
96
104
|
# purged-cache recovery).
|
|
97
|
-
s.platforms = { :ios => final_ios_deployment_target, :tvos =>
|
|
105
|
+
s.platforms = { :ios => final_ios_deployment_target, :tvos => final_tvos_deployment_target }
|
|
98
106
|
|
|
99
107
|
s.name = package['name']
|
|
100
108
|
s.version = package['version']
|
|
@@ -109,6 +117,9 @@ Pod::Spec.new do |s|
|
|
|
109
117
|
s.source = { :git => 'https://github.com/reactnativecn/react-native-update.git', :tag => "#{s.version}" }
|
|
110
118
|
|
|
111
119
|
s.libraries = 'bz2', 'z'
|
|
120
|
+
# tvOS checks for a network path before blocking a launch on the
|
|
121
|
+
# purged-version restore (nw_path_monitor).
|
|
122
|
+
s.tvos.frameworks = 'Network'
|
|
112
123
|
# No search path into the pod source: every include under ios/ resolves
|
|
113
124
|
# relative to the including file (the cpp/ core via ../../cpp/...), and the
|
|
114
125
|
# former absolute "#{podspec_dir}/ios" entry made the generated xcconfig
|
|
@@ -116,9 +127,9 @@ Pod::Spec.new do |s|
|
|
|
116
127
|
# DEFINES_MODULE writes the umbrella under Headers/Public/react_native_update/
|
|
117
128
|
# (underscores). CocoaPods copies public headers to react-native-update/
|
|
118
129
|
# (hyphens). Include the latter so the umbrella can #import "ImportReact.h".
|
|
119
|
-
s.pod_target_xcconfig = {
|
|
120
|
-
'USER_HEADER_SEARCH_PATHS' => "\"$(PODS_ROOT)/Headers/Public/react-native-update\"
|
|
121
|
-
"DEFINES_MODULE" => "YES"
|
|
130
|
+
s.pod_target_xcconfig = {
|
|
131
|
+
'USER_HEADER_SEARCH_PATHS' => "\"$(PODS_ROOT)/Headers/Public/react-native-update\"",
|
|
132
|
+
"DEFINES_MODULE" => "YES"
|
|
122
133
|
}
|
|
123
134
|
# buildTime for binary-rebuild detection (SyncBinaryVersion) and the check
|
|
124
135
|
# request. The stamp is refreshed on every build and ships as a resource.
|
|
@@ -147,9 +158,8 @@ Pod::Spec.new do |s|
|
|
|
147
158
|
# Privacy manifest (required-reason APIs: disk space, file timestamps,
|
|
148
159
|
# system boot time, user defaults) delivered as its own resource bundle so
|
|
149
160
|
# static and dynamic integrations both carry it.
|
|
150
|
-
s.resource_bundles = { '
|
|
161
|
+
s.resource_bundles = { 'PushyPrivacy' => ['ios/PrivacyInfo.xcprivacy'] }
|
|
151
162
|
|
|
152
|
-
s.dependency 'React'
|
|
153
163
|
s.dependency "React-Core"
|
|
154
164
|
# The unzip guard relies on the 2.x delegate contract
|
|
155
165
|
# (zipArchiveShouldUnzipFileAtIndex:... cancels, _sanitizedPath); a future
|
|
@@ -171,15 +181,12 @@ Pod::Spec.new do |s|
|
|
|
171
181
|
# Objective-C classes in the RCTPushy subspec keep default visibility, which
|
|
172
182
|
# the host app and the Expo module need to link against RCTPushy.
|
|
173
183
|
s.subspec 'Core' do |ss|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
'cpp/
|
|
179
|
-
'cpp/
|
|
180
|
-
'cpp/patch_core/patch_core.{h,cpp}',
|
|
181
|
-
'cpp/patch_core/state_core.{h,cpp}',
|
|
182
|
-
'android/jni/hpatch.{h,c}',
|
|
184
|
+
# The cores are picked up by directory (non-recursive: tests/ stays out,
|
|
185
|
+
# and the Android JNI glue lives in cpp/android_jni), so a new
|
|
186
|
+
# platform-neutral source needs no edit here.
|
|
187
|
+
ss.source_files = ['cpp/patch_core/*.{h,cpp}',
|
|
188
|
+
'cpp/update_flow_core/*.{h,cpp}',
|
|
189
|
+
'cpp/hpatch/*.{h,c}',
|
|
183
190
|
'android/jni/HDiffPatch/libHDiffPatch/HPatch/*.{h,c}',
|
|
184
191
|
'android/jni/HDiffPatch/file_for_patch.{h,c}',
|
|
185
192
|
'android/jni/lzma/C/LzmaDec.{h,c}',
|
|
@@ -193,23 +200,21 @@ Pod::Spec.new do |s|
|
|
|
193
200
|
s.subspec 'RCTPushy' do |ss|
|
|
194
201
|
ss.dependency 'react-native-update/Core'
|
|
195
202
|
ss.source_files = ['ios/RCTPushy/*.{h,m,mm}']
|
|
196
|
-
ss.public_header_files = ['ios/RCTPushy
|
|
203
|
+
ss.public_header_files = ['ios/RCTPushy/RCTPushy.h',
|
|
204
|
+
'ios/RCTPushy/RCTPushyConfiguration.h',
|
|
205
|
+
'ios/RCTPushy/RCTPushyDownloader.h']
|
|
206
|
+
# Shared by the pod's own sources only (RCTPushyInternal.h pulls in C++
|
|
207
|
+
# headers), so they must stay out of the module umbrella.
|
|
208
|
+
ss.private_header_files = ['ios/RCTPushy/RCTPushyCommon.h',
|
|
209
|
+
'ios/RCTPushy/RCTPushyInternal.h']
|
|
197
210
|
end
|
|
198
211
|
|
|
199
212
|
# Conditionally add Expo subspec and check ExpoModulesCore version
|
|
200
213
|
if valid_expo_project
|
|
201
214
|
supports_bundle_url_final = false # Default
|
|
202
215
|
|
|
203
|
-
|
|
204
|
-
expo_modules_core_version_str
|
|
205
|
-
`node --print "require(#{expo_modules_core_package_json_js}).version"` # Execute, keep raw output
|
|
206
|
-
rescue
|
|
207
|
-
# Node command failed (e.g., node not found, package not found). Return empty string.
|
|
208
|
-
''
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
# 2. Process the obtained version string (if not empty)
|
|
212
|
-
if expo_modules_core_version_str && !expo_modules_core_version_str.empty?
|
|
216
|
+
expo_modules_core_version_str = expo_info['coreVersion'].to_s
|
|
217
|
+
if !expo_modules_core_version_str.empty?
|
|
213
218
|
begin
|
|
214
219
|
# Compare versions using Gem::Version (handles trailing newline)
|
|
215
220
|
installed_version = Gem::Version.new(expo_modules_core_version_str)
|
|
@@ -228,23 +233,9 @@ Pod::Spec.new do |s|
|
|
|
228
233
|
end
|
|
229
234
|
end
|
|
230
235
|
|
|
236
|
+
# React Native >= 0.71 (react_native_pods.rb) wires codegen, the new
|
|
237
|
+
# architecture and its dependencies.
|
|
231
238
|
if defined?(install_modules_dependencies()) != nil
|
|
232
|
-
install_modules_dependencies(s)
|
|
233
|
-
else
|
|
234
|
-
if new_arch_enabled
|
|
235
|
-
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
|
236
|
-
|
|
237
|
-
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
|
238
|
-
|
|
239
|
-
s.pod_target_xcconfig = {
|
|
240
|
-
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
241
|
-
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
242
|
-
}.merge(s.pod_target_xcconfig)
|
|
243
|
-
s.dependency "React-Codegen"
|
|
244
|
-
s.dependency "RCT-Folly"
|
|
245
|
-
s.dependency "RCTRequired"
|
|
246
|
-
s.dependency "RCTTypeSafety"
|
|
247
|
-
s.dependency "ReactCommon/turbomodule/core"
|
|
248
|
-
end
|
|
239
|
+
install_modules_dependencies(s)
|
|
249
240
|
end
|
|
250
241
|
end
|