@onekeyfe/react-native-bundle-update 3.0.58 → 3.0.59
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/android/src/main/java/com/margelo/nitro/reactnativebundleupdate/ReactNativeBundleUpdate.kt +159 -7
- package/ios/ReactNativeBundleUpdate.swift +124 -0
- package/lib/typescript/src/ReactNativeBundleUpdate.nitro.d.ts +1 -0
- package/nitrogen/generated/android/c++/JHybridReactNativeBundleUpdateSpec.cpp +16 -0
- package/nitrogen/generated/android/c++/JHybridReactNativeBundleUpdateSpec.hpp +1 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativebundleupdate/HybridReactNativeBundleUpdateSpec.kt +4 -0
- package/nitrogen/generated/ios/ReactNativeBundleUpdate-Swift-Cxx-Bridge.cpp +8 -0
- package/nitrogen/generated/ios/ReactNativeBundleUpdate-Swift-Cxx-Bridge.hpp +43 -0
- package/nitrogen/generated/ios/c++/HybridReactNativeBundleUpdateSpecSwift.hpp +8 -0
- package/nitrogen/generated/ios/swift/Func_void_double.swift +47 -0
- package/nitrogen/generated/ios/swift/HybridReactNativeBundleUpdateSpec.swift +1 -0
- package/nitrogen/generated/ios/swift/HybridReactNativeBundleUpdateSpec_cxx.swift +19 -0
- package/nitrogen/generated/shared/c++/HybridReactNativeBundleUpdateSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridReactNativeBundleUpdateSpec.hpp +1 -0
- package/package.json +1 -1
- package/src/ReactNativeBundleUpdate.nitro.ts +4 -0
package/android/src/main/java/com/margelo/nitro/reactnativebundleupdate/ReactNativeBundleUpdate.kt
CHANGED
|
@@ -1013,16 +1013,26 @@ object BundleUpdateStoreAndroid {
|
|
|
1013
1013
|
}
|
|
1014
1014
|
}
|
|
1015
1015
|
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1016
|
+
/**
|
|
1017
|
+
* Recursively deletes [directory], returning true only when nothing is left
|
|
1018
|
+
* behind. An already-missing entry counts as success (tolerates concurrent
|
|
1019
|
+
* removal); a child that fails to delete makes the whole call return false
|
|
1020
|
+
* so callers never report a half-deleted tree as a clean delete.
|
|
1021
|
+
*/
|
|
1022
|
+
private fun deleteDirectory(directory: File): Boolean {
|
|
1023
|
+
if (!directory.exists()) return true
|
|
1024
|
+
var allDeleted = true
|
|
1025
|
+
directory.listFiles()?.forEach { file ->
|
|
1026
|
+
val ok = if (file.isDirectory) deleteDirectory(file) else (!file.exists() || file.delete())
|
|
1027
|
+
if (!ok) allDeleted = false
|
|
1022
1028
|
}
|
|
1029
|
+
// delete() on a non-empty dir returns false, so a child failure above
|
|
1030
|
+
// naturally propagates here too.
|
|
1031
|
+
val dirDeleted = !directory.exists() || directory.delete()
|
|
1032
|
+
return allDeleted && dirDeleted
|
|
1023
1033
|
}
|
|
1024
1034
|
|
|
1025
|
-
fun deleteDir(dir: File) = deleteDirectory(dir)
|
|
1035
|
+
fun deleteDir(dir: File): Boolean = deleteDirectory(dir)
|
|
1026
1036
|
|
|
1027
1037
|
private const val MAX_UNZIPPED_SIZE = 512L * 1024 * 1024 // 512 MB limit
|
|
1028
1038
|
|
|
@@ -1757,6 +1767,148 @@ class ReactNativeBundleUpdate : HybridReactNativeBundleUpdateSpec() {
|
|
|
1757
1767
|
}
|
|
1758
1768
|
}
|
|
1759
1769
|
|
|
1770
|
+
/**
|
|
1771
|
+
* Prunes every artifact whose appVersion != the running native binary
|
|
1772
|
+
* version: stale onekey-bundle/* dirs, onekey-bundle-download/* stages
|
|
1773
|
+
* (.zip / .partial / .progress / .resume), orphan asc signatures, and
|
|
1774
|
+
* lingering fallback entries. Hard-refuses to delete the current
|
|
1775
|
+
* appVersion's artifacts and the active currentBundleVersion. Tolerates
|
|
1776
|
+
* already-missing files. Returns the count of deleted version directories.
|
|
1777
|
+
*
|
|
1778
|
+
* appVersion is parsed from the "{appVersion}-{bundleVersion}" stem using
|
|
1779
|
+
* the SAME last-dash split as listLocalBundles / the installBundle fallback
|
|
1780
|
+
* logic, so behavior matches the rest of the module.
|
|
1781
|
+
*/
|
|
1782
|
+
override fun pruneStaleAppVersionBundles(): Promise<Double> {
|
|
1783
|
+
BundleUpdateStoreAndroid.invalidateValidatedBundleInfoCache()
|
|
1784
|
+
return Promise.async {
|
|
1785
|
+
val context = getContext()
|
|
1786
|
+
val currentAppV = BundleUpdateStoreAndroid.getAppVersion(context) ?: ""
|
|
1787
|
+
// Safety net: never delete the bundle backing the active pointer.
|
|
1788
|
+
val currentBundleVersion = BundleUpdateStoreAndroid.getCurrentBundleVersion(context)
|
|
1789
|
+
OneKeyLog.info("BundleUpdate", "pruneStaleAppVersionBundles: currentAppV=$currentAppV, currentBundleVersion=$currentBundleVersion")
|
|
1790
|
+
|
|
1791
|
+
// Without a known native version we cannot decide what is stale;
|
|
1792
|
+
// bail out rather than risk deleting the wrong artifacts.
|
|
1793
|
+
if (currentAppV.isEmpty()) {
|
|
1794
|
+
OneKeyLog.warn("BundleUpdate", "pruneStaleAppVersionBundles: empty currentAppV, skipping")
|
|
1795
|
+
return@async 0.0
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
// Parses an "{appVersion}-{bundleVersion}" stem into its appVersion
|
|
1799
|
+
// component using the same last-dash split as listLocalBundles.
|
|
1800
|
+
// Returns null for stems without a dash or with an empty appVersion.
|
|
1801
|
+
fun appVersionFromStem(stem: String): String? {
|
|
1802
|
+
val lastDash = stem.lastIndexOf('-')
|
|
1803
|
+
if (lastDash <= 0) return null
|
|
1804
|
+
val appV = stem.substring(0, lastDash)
|
|
1805
|
+
return if (appV.isEmpty()) null else appV
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
// True when this entry stem must be kept: its appVersion matches the
|
|
1809
|
+
// running binary, it IS the active currentBundleVersion, or it is
|
|
1810
|
+
// unparseable (leave foreign names alone).
|
|
1811
|
+
fun shouldKeep(stem: String): Boolean {
|
|
1812
|
+
if (currentBundleVersion != null && stem == currentBundleVersion) return true
|
|
1813
|
+
val appV = appVersionFromStem(stem) ?: return true
|
|
1814
|
+
return appV == currentAppV
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
var deletedDirCount = 0
|
|
1818
|
+
|
|
1819
|
+
// 1. onekey-bundle/* extracted dirs
|
|
1820
|
+
val bundleDir = File(BundleUpdateStoreAndroid.getBundleDir(context))
|
|
1821
|
+
if (bundleDir.exists() && bundleDir.isDirectory) {
|
|
1822
|
+
bundleDir.listFiles()?.forEach { child ->
|
|
1823
|
+
if (!child.isDirectory) return@forEach
|
|
1824
|
+
val name = child.name
|
|
1825
|
+
// Skip non-version entries (asc dir, fallback json, etc.)
|
|
1826
|
+
if (name == "asc" || name == "fallbackUpdateBundleData.json") return@forEach
|
|
1827
|
+
if (shouldKeep(name)) return@forEach
|
|
1828
|
+
try {
|
|
1829
|
+
if (BundleUpdateStoreAndroid.deleteDir(child)) {
|
|
1830
|
+
deletedDirCount++
|
|
1831
|
+
OneKeyLog.info("BundleUpdate", "pruneStaleAppVersionBundles: deleted stale bundle dir $name")
|
|
1832
|
+
} else {
|
|
1833
|
+
OneKeyLog.warn("BundleUpdate", "pruneStaleAppVersionBundles: incomplete delete of bundle dir $name (left behind)")
|
|
1834
|
+
}
|
|
1835
|
+
} catch (e: Exception) {
|
|
1836
|
+
OneKeyLog.warn("BundleUpdate", "pruneStaleAppVersionBundles: failed to delete bundle dir $name: ${e.message}")
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
// 2. onekey-bundle-download/* stages (zip / partial / progress / resume)
|
|
1842
|
+
val downloadDir = File(BundleUpdateStoreAndroid.getDownloadBundleDir(context))
|
|
1843
|
+
if (downloadDir.exists() && downloadDir.isDirectory) {
|
|
1844
|
+
downloadDir.listFiles()?.forEach { file ->
|
|
1845
|
+
val name = file.name
|
|
1846
|
+
// Strip the trailing extension chain to recover the
|
|
1847
|
+
// "{appV}-{bV}" stem (e.g. "6.3.0-123.zip.partial").
|
|
1848
|
+
var stem = name
|
|
1849
|
+
for (suffix in listOf(".resume", ".progress", ".partial", ".zip")) {
|
|
1850
|
+
if (stem.endsWith(suffix)) {
|
|
1851
|
+
stem = stem.substring(0, stem.length - suffix.length)
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
if (shouldKeep(stem)) return@forEach
|
|
1855
|
+
try {
|
|
1856
|
+
val deleted = if (file.isDirectory) {
|
|
1857
|
+
BundleUpdateStoreAndroid.deleteDir(file)
|
|
1858
|
+
} else {
|
|
1859
|
+
!file.exists() || file.delete()
|
|
1860
|
+
}
|
|
1861
|
+
if (deleted) {
|
|
1862
|
+
OneKeyLog.info("BundleUpdate", "pruneStaleAppVersionBundles: deleted stale download $name")
|
|
1863
|
+
} else {
|
|
1864
|
+
OneKeyLog.warn("BundleUpdate", "pruneStaleAppVersionBundles: failed to delete download $name")
|
|
1865
|
+
}
|
|
1866
|
+
} catch (e: Exception) {
|
|
1867
|
+
OneKeyLog.warn("BundleUpdate", "pruneStaleAppVersionBundles: failed to delete download $name: ${e.message}")
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
|
|
1872
|
+
// 3. onekey-bundle/asc/*-signature.asc orphan signatures
|
|
1873
|
+
val ascDir = File(BundleUpdateStoreAndroid.getAscDir(context))
|
|
1874
|
+
if (ascDir.exists() && ascDir.isDirectory) {
|
|
1875
|
+
val suffix = "-signature.asc"
|
|
1876
|
+
ascDir.listFiles()?.forEach { file ->
|
|
1877
|
+
val name = file.name
|
|
1878
|
+
if (!name.endsWith(suffix)) return@forEach
|
|
1879
|
+
val stem = name.substring(0, name.length - suffix.length)
|
|
1880
|
+
if (shouldKeep(stem)) return@forEach
|
|
1881
|
+
try {
|
|
1882
|
+
file.delete()
|
|
1883
|
+
OneKeyLog.info("BundleUpdate", "pruneStaleAppVersionBundles: deleted orphan asc $name")
|
|
1884
|
+
} catch (e: Exception) {
|
|
1885
|
+
OneKeyLog.warn("BundleUpdate", "pruneStaleAppVersionBundles: failed to delete asc $name: ${e.message}")
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
// 4. Persisted fallback list: drop entries whose appVersion != currentAppV.
|
|
1891
|
+
// Fixes the latent leak where stale fallback entries linger after a
|
|
1892
|
+
// native upgrade. Reuses the existing read/write helpers.
|
|
1893
|
+
try {
|
|
1894
|
+
val fallbackData = BundleUpdateStoreAndroid.readFallbackUpdateBundleDataFile(context)
|
|
1895
|
+
val prunedFallback = fallbackData.filter { entry ->
|
|
1896
|
+
val appV = entry["appVersion"]
|
|
1897
|
+
appV.isNullOrEmpty() || appV == currentAppV
|
|
1898
|
+
}
|
|
1899
|
+
if (prunedFallback.size != fallbackData.size) {
|
|
1900
|
+
BundleUpdateStoreAndroid.writeFallbackUpdateBundleDataFile(prunedFallback, context)
|
|
1901
|
+
OneKeyLog.info("BundleUpdate", "pruneStaleAppVersionBundles: pruned fallback entries ${fallbackData.size} -> ${prunedFallback.size}")
|
|
1902
|
+
}
|
|
1903
|
+
} catch (e: Exception) {
|
|
1904
|
+
OneKeyLog.warn("BundleUpdate", "pruneStaleAppVersionBundles: fallback prune error: ${e.message}")
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
OneKeyLog.info("BundleUpdate", "pruneStaleAppVersionBundles: completed, deletedDirCount=$deletedDirCount")
|
|
1908
|
+
deletedDirCount.toDouble()
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
|
|
1760
1912
|
override fun resetToBuiltInBundle(): Promise<Unit> {
|
|
1761
1913
|
BundleUpdateStoreAndroid.invalidateValidatedBundleInfoCache()
|
|
1762
1914
|
return Promise.async {
|
|
@@ -1725,6 +1725,130 @@ class ReactNativeBundleUpdate: HybridReactNativeBundleUpdateSpec {
|
|
|
1725
1725
|
}
|
|
1726
1726
|
}
|
|
1727
1727
|
|
|
1728
|
+
/// Parses an "{appVersion}-{bundleVersion}" folder/file stem into its
|
|
1729
|
+
/// appVersion component using the SAME last-dash split as listLocalBundles
|
|
1730
|
+
/// and the installBundle fallback logic. Returns nil when the stem has no
|
|
1731
|
+
/// dash or an empty appVersion, so callers leave unrecognized entries
|
|
1732
|
+
/// untouched.
|
|
1733
|
+
private static func appVersionFromStem(_ stem: String) -> String? {
|
|
1734
|
+
guard let lastDash = stem.range(of: "-", options: .backwards),
|
|
1735
|
+
lastDash.lowerBound > stem.startIndex else { return nil }
|
|
1736
|
+
let appVersion = String(stem[stem.startIndex..<lastDash.lowerBound])
|
|
1737
|
+
return appVersion.isEmpty ? nil : appVersion
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
/// Prunes every artifact whose appVersion != the running native binary
|
|
1741
|
+
/// version: stale onekey-bundle/* dirs, onekey-bundle-download/* stages
|
|
1742
|
+
/// (.zip / .partial / .progress / .resume), orphan asc signatures, and
|
|
1743
|
+
/// lingering fallback entries. Hard-refuses to delete the current
|
|
1744
|
+
/// appVersion's artifacts and the active currentBundleVersion. Tolerates
|
|
1745
|
+
/// already-missing files. Returns the count of deleted version directories.
|
|
1746
|
+
func pruneStaleAppVersionBundles() throws -> Promise<Double> {
|
|
1747
|
+
BundleUpdateStore.invalidateValidatedBundleInfoCache()
|
|
1748
|
+
return Promise.async {
|
|
1749
|
+
let fm = FileManager.default
|
|
1750
|
+
let currentAppV = BundleUpdateStore.getCurrentNativeVersion()
|
|
1751
|
+
// Safety net: never delete the bundle backing the active pointer.
|
|
1752
|
+
let currentBundleVersion = BundleUpdateStore.currentBundleVersion()
|
|
1753
|
+
OneKeyLog.info("BundleUpdate", "pruneStaleAppVersionBundles: currentAppV=\(currentAppV), currentBundleVersion=\(currentBundleVersion ?? "nil")")
|
|
1754
|
+
|
|
1755
|
+
// Without a known native version we cannot decide what is stale;
|
|
1756
|
+
// bail out rather than risk deleting the wrong artifacts.
|
|
1757
|
+
guard !currentAppV.isEmpty else {
|
|
1758
|
+
OneKeyLog.warn("BundleUpdate", "pruneStaleAppVersionBundles: empty currentAppV, skipping")
|
|
1759
|
+
return 0
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
/// True when this entry stem must be kept: its appVersion matches
|
|
1763
|
+
/// the running binary, it IS the active currentBundleVersion, or it
|
|
1764
|
+
/// is unparseable (leave foreign names alone).
|
|
1765
|
+
func shouldKeep(stem: String) -> Bool {
|
|
1766
|
+
if let active = currentBundleVersion, stem == active { return true }
|
|
1767
|
+
guard let appV = Self.appVersionFromStem(stem) else { return true }
|
|
1768
|
+
return appV == currentAppV
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
var deletedDirCount = 0
|
|
1772
|
+
|
|
1773
|
+
// 1. onekey-bundle/* extracted dirs
|
|
1774
|
+
let bundleDir = BundleUpdateStore.bundleDir()
|
|
1775
|
+
if let contents = try? fm.contentsOfDirectory(atPath: bundleDir) {
|
|
1776
|
+
for name in contents {
|
|
1777
|
+
// Skip non-version entries (asc dir, fallback json, etc.)
|
|
1778
|
+
if name == "asc" || name == "fallbackUpdateBundleData.json" { continue }
|
|
1779
|
+
let fullPath = (bundleDir as NSString).appendingPathComponent(name)
|
|
1780
|
+
var isDir: ObjCBool = false
|
|
1781
|
+
guard fm.fileExists(atPath: fullPath, isDirectory: &isDir), isDir.boolValue else { continue }
|
|
1782
|
+
if shouldKeep(stem: name) { continue }
|
|
1783
|
+
do {
|
|
1784
|
+
try fm.removeItem(atPath: fullPath)
|
|
1785
|
+
deletedDirCount += 1
|
|
1786
|
+
OneKeyLog.info("BundleUpdate", "pruneStaleAppVersionBundles: deleted stale bundle dir \(name)")
|
|
1787
|
+
} catch {
|
|
1788
|
+
OneKeyLog.warn("BundleUpdate", "pruneStaleAppVersionBundles: failed to delete bundle dir \(name): \(error)")
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
// 2. onekey-bundle-download/* stages (zip / partial / progress / resume)
|
|
1794
|
+
let downloadDir = BundleUpdateStore.downloadBundleDir()
|
|
1795
|
+
if let contents = try? fm.contentsOfDirectory(atPath: downloadDir) {
|
|
1796
|
+
for name in contents {
|
|
1797
|
+
// Strip the trailing extension chain to recover the
|
|
1798
|
+
// "{appV}-{bV}" stem (e.g. "6.3.0-123.zip.partial").
|
|
1799
|
+
var stem = name
|
|
1800
|
+
for suffix in [".resume", ".progress", ".partial", ".zip"] {
|
|
1801
|
+
if stem.hasSuffix(suffix) {
|
|
1802
|
+
stem = String(stem.dropLast(suffix.count))
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
if shouldKeep(stem: stem) { continue }
|
|
1806
|
+
let fullPath = (downloadDir as NSString).appendingPathComponent(name)
|
|
1807
|
+
do {
|
|
1808
|
+
try fm.removeItem(atPath: fullPath)
|
|
1809
|
+
OneKeyLog.info("BundleUpdate", "pruneStaleAppVersionBundles: deleted stale download \(name)")
|
|
1810
|
+
} catch {
|
|
1811
|
+
OneKeyLog.warn("BundleUpdate", "pruneStaleAppVersionBundles: failed to delete download \(name): \(error)")
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
// 3. onekey-bundle/asc/*-signature.asc orphan signatures
|
|
1817
|
+
let ascDir = BundleUpdateStore.ascDir()
|
|
1818
|
+
if let contents = try? fm.contentsOfDirectory(atPath: ascDir) {
|
|
1819
|
+
let suffix = "-signature.asc"
|
|
1820
|
+
for name in contents {
|
|
1821
|
+
guard name.hasSuffix(suffix) else { continue }
|
|
1822
|
+
let stem = String(name.dropLast(suffix.count))
|
|
1823
|
+
if shouldKeep(stem: stem) { continue }
|
|
1824
|
+
let fullPath = (ascDir as NSString).appendingPathComponent(name)
|
|
1825
|
+
do {
|
|
1826
|
+
try fm.removeItem(atPath: fullPath)
|
|
1827
|
+
OneKeyLog.info("BundleUpdate", "pruneStaleAppVersionBundles: deleted orphan asc \(name)")
|
|
1828
|
+
} catch {
|
|
1829
|
+
OneKeyLog.warn("BundleUpdate", "pruneStaleAppVersionBundles: failed to delete asc \(name): \(error)")
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
// 4. Persisted fallback list: drop entries whose appVersion != currentAppV.
|
|
1835
|
+
// Fixes the latent leak where stale fallback entries linger after a
|
|
1836
|
+
// native upgrade. Reuses the existing read/write helpers.
|
|
1837
|
+
let fallbackData = BundleUpdateStore.readFallbackUpdateBundleDataFile()
|
|
1838
|
+
let prunedFallback = fallbackData.filter { entry in
|
|
1839
|
+
guard let appV = entry["appVersion"], !appV.isEmpty else { return true }
|
|
1840
|
+
return appV == currentAppV
|
|
1841
|
+
}
|
|
1842
|
+
if prunedFallback.count != fallbackData.count {
|
|
1843
|
+
BundleUpdateStore.writeFallbackUpdateBundleDataFile(prunedFallback)
|
|
1844
|
+
OneKeyLog.info("BundleUpdate", "pruneStaleAppVersionBundles: pruned fallback entries \(fallbackData.count) -> \(prunedFallback.count)")
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
OneKeyLog.info("BundleUpdate", "pruneStaleAppVersionBundles: completed, deletedDirCount=\(deletedDirCount)")
|
|
1848
|
+
return Double(deletedDirCount)
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1728
1852
|
func resetToBuiltInBundle() throws -> Promise<Void> {
|
|
1729
1853
|
BundleUpdateStore.invalidateValidatedBundleInfoCache()
|
|
1730
1854
|
return Promise.async {
|
|
@@ -81,6 +81,7 @@ export interface ReactNativeBundleUpdate extends HybridObject<{
|
|
|
81
81
|
clearBundle(): Promise<void>;
|
|
82
82
|
clearAllJSBundleData(): Promise<TestResult>;
|
|
83
83
|
resetToBuiltInBundle(): Promise<void>;
|
|
84
|
+
pruneStaleAppVersionBundles(): Promise<number>;
|
|
84
85
|
getFallbackUpdateBundleData(): Promise<FallbackBundleInfo[]>;
|
|
85
86
|
setCurrentUpdateBundleData(params: BundleSwitchParams): Promise<void>;
|
|
86
87
|
getWebEmbedPath(): string;
|
|
@@ -233,6 +233,22 @@ namespace margelo::nitro::reactnativebundleupdate {
|
|
|
233
233
|
return __promise;
|
|
234
234
|
}();
|
|
235
235
|
}
|
|
236
|
+
std::shared_ptr<Promise<double>> JHybridReactNativeBundleUpdateSpec::pruneStaleAppVersionBundles() {
|
|
237
|
+
static const auto method = javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>()>("pruneStaleAppVersionBundles");
|
|
238
|
+
auto __result = method(_javaPart);
|
|
239
|
+
return [&]() {
|
|
240
|
+
auto __promise = Promise<double>::create();
|
|
241
|
+
__result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& __boxedResult) {
|
|
242
|
+
auto __result = jni::static_ref_cast<jni::JDouble>(__boxedResult);
|
|
243
|
+
__promise->resolve(__result->value());
|
|
244
|
+
});
|
|
245
|
+
__result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
|
|
246
|
+
jni::JniException __jniError(__throwable);
|
|
247
|
+
__promise->reject(std::make_exception_ptr(__jniError));
|
|
248
|
+
});
|
|
249
|
+
return __promise;
|
|
250
|
+
}();
|
|
251
|
+
}
|
|
236
252
|
std::shared_ptr<Promise<std::vector<FallbackBundleInfo>>> JHybridReactNativeBundleUpdateSpec::getFallbackUpdateBundleData() {
|
|
237
253
|
static const auto method = javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>()>("getFallbackUpdateBundleData");
|
|
238
254
|
auto __result = method(_javaPart);
|
|
@@ -63,6 +63,7 @@ namespace margelo::nitro::reactnativebundleupdate {
|
|
|
63
63
|
std::shared_ptr<Promise<void>> clearBundle() override;
|
|
64
64
|
std::shared_ptr<Promise<TestResult>> clearAllJSBundleData() override;
|
|
65
65
|
std::shared_ptr<Promise<void>> resetToBuiltInBundle() override;
|
|
66
|
+
std::shared_ptr<Promise<double>> pruneStaleAppVersionBundles() override;
|
|
66
67
|
std::shared_ptr<Promise<std::vector<FallbackBundleInfo>>> getFallbackUpdateBundleData() override;
|
|
67
68
|
std::shared_ptr<Promise<void>> setCurrentUpdateBundleData(const BundleSwitchParams& params) override;
|
|
68
69
|
std::string getWebEmbedPath() override;
|
|
@@ -82,6 +82,10 @@ abstract class HybridReactNativeBundleUpdateSpec: HybridObject() {
|
|
|
82
82
|
@Keep
|
|
83
83
|
abstract fun resetToBuiltInBundle(): Promise<Unit>
|
|
84
84
|
|
|
85
|
+
@DoNotStrip
|
|
86
|
+
@Keep
|
|
87
|
+
abstract fun pruneStaleAppVersionBundles(): Promise<Double>
|
|
88
|
+
|
|
85
89
|
@DoNotStrip
|
|
86
90
|
@Keep
|
|
87
91
|
abstract fun getFallbackUpdateBundleData(): Promise<Array<FallbackBundleInfo>>
|
|
@@ -46,6 +46,14 @@ namespace margelo::nitro::reactnativebundleupdate::bridge::swift {
|
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
// pragma MARK: std::function<void(double /* result */)>
|
|
50
|
+
Func_void_double create_Func_void_double(void* NON_NULL swiftClosureWrapper) noexcept {
|
|
51
|
+
auto swiftClosure = ReactNativeBundleUpdate::Func_void_double::fromUnsafe(swiftClosureWrapper);
|
|
52
|
+
return [swiftClosure = std::move(swiftClosure)](double result) mutable -> void {
|
|
53
|
+
swiftClosure.call(result);
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
49
57
|
// pragma MARK: std::function<void(const std::vector<FallbackBundleInfo>& /* result */)>
|
|
50
58
|
Func_void_std__vector_FallbackBundleInfo_ create_Func_void_std__vector_FallbackBundleInfo_(void* NON_NULL swiftClosureWrapper) noexcept {
|
|
51
59
|
auto swiftClosure = ReactNativeBundleUpdate::Func_void_std__vector_FallbackBundleInfo_::fromUnsafe(swiftClosureWrapper);
|
|
@@ -174,6 +174,40 @@ namespace margelo::nitro::reactnativebundleupdate::bridge::swift {
|
|
|
174
174
|
return Func_void_TestResult_Wrapper(std::move(value));
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
+
// pragma MARK: std::shared_ptr<Promise<double>>
|
|
178
|
+
/**
|
|
179
|
+
* Specialized version of `std::shared_ptr<Promise<double>>`.
|
|
180
|
+
*/
|
|
181
|
+
using std__shared_ptr_Promise_double__ = std::shared_ptr<Promise<double>>;
|
|
182
|
+
inline std::shared_ptr<Promise<double>> create_std__shared_ptr_Promise_double__() noexcept {
|
|
183
|
+
return Promise<double>::create();
|
|
184
|
+
}
|
|
185
|
+
inline PromiseHolder<double> wrap_std__shared_ptr_Promise_double__(std::shared_ptr<Promise<double>> promise) noexcept {
|
|
186
|
+
return PromiseHolder<double>(std::move(promise));
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// pragma MARK: std::function<void(double /* result */)>
|
|
190
|
+
/**
|
|
191
|
+
* Specialized version of `std::function<void(double)>`.
|
|
192
|
+
*/
|
|
193
|
+
using Func_void_double = std::function<void(double /* result */)>;
|
|
194
|
+
/**
|
|
195
|
+
* Wrapper class for a `std::function<void(double / * result * /)>`, this can be used from Swift.
|
|
196
|
+
*/
|
|
197
|
+
class Func_void_double_Wrapper final {
|
|
198
|
+
public:
|
|
199
|
+
explicit Func_void_double_Wrapper(std::function<void(double /* result */)>&& func): _function(std::make_unique<std::function<void(double /* result */)>>(std::move(func))) {}
|
|
200
|
+
inline void call(double result) const noexcept {
|
|
201
|
+
_function->operator()(result);
|
|
202
|
+
}
|
|
203
|
+
private:
|
|
204
|
+
std::unique_ptr<std::function<void(double /* result */)>> _function;
|
|
205
|
+
} SWIFT_NONCOPYABLE;
|
|
206
|
+
Func_void_double create_Func_void_double(void* NON_NULL swiftClosureWrapper) noexcept;
|
|
207
|
+
inline Func_void_double_Wrapper wrap_Func_void_double(Func_void_double value) noexcept {
|
|
208
|
+
return Func_void_double_Wrapper(std::move(value));
|
|
209
|
+
}
|
|
210
|
+
|
|
177
211
|
// pragma MARK: std::vector<FallbackBundleInfo>
|
|
178
212
|
/**
|
|
179
213
|
* Specialized version of `std::vector<FallbackBundleInfo>`.
|
|
@@ -438,6 +472,15 @@ namespace margelo::nitro::reactnativebundleupdate::bridge::swift {
|
|
|
438
472
|
return Result<std::shared_ptr<Promise<TestResult>>>::withError(error);
|
|
439
473
|
}
|
|
440
474
|
|
|
475
|
+
// pragma MARK: Result<std::shared_ptr<Promise<double>>>
|
|
476
|
+
using Result_std__shared_ptr_Promise_double___ = Result<std::shared_ptr<Promise<double>>>;
|
|
477
|
+
inline Result_std__shared_ptr_Promise_double___ create_Result_std__shared_ptr_Promise_double___(const std::shared_ptr<Promise<double>>& value) noexcept {
|
|
478
|
+
return Result<std::shared_ptr<Promise<double>>>::withValue(value);
|
|
479
|
+
}
|
|
480
|
+
inline Result_std__shared_ptr_Promise_double___ create_Result_std__shared_ptr_Promise_double___(const std::exception_ptr& error) noexcept {
|
|
481
|
+
return Result<std::shared_ptr<Promise<double>>>::withError(error);
|
|
482
|
+
}
|
|
483
|
+
|
|
441
484
|
// pragma MARK: Result<std::shared_ptr<Promise<std::vector<FallbackBundleInfo>>>>
|
|
442
485
|
using Result_std__shared_ptr_Promise_std__vector_FallbackBundleInfo____ = Result<std::shared_ptr<Promise<std::vector<FallbackBundleInfo>>>>;
|
|
443
486
|
inline Result_std__shared_ptr_Promise_std__vector_FallbackBundleInfo____ create_Result_std__shared_ptr_Promise_std__vector_FallbackBundleInfo____(const std::shared_ptr<Promise<std::vector<FallbackBundleInfo>>>& value) noexcept {
|
|
@@ -170,6 +170,14 @@ namespace margelo::nitro::reactnativebundleupdate {
|
|
|
170
170
|
auto __value = std::move(__result.value());
|
|
171
171
|
return __value;
|
|
172
172
|
}
|
|
173
|
+
inline std::shared_ptr<Promise<double>> pruneStaleAppVersionBundles() override {
|
|
174
|
+
auto __result = _swiftPart.pruneStaleAppVersionBundles();
|
|
175
|
+
if (__result.hasError()) [[unlikely]] {
|
|
176
|
+
std::rethrow_exception(__result.error());
|
|
177
|
+
}
|
|
178
|
+
auto __value = std::move(__result.value());
|
|
179
|
+
return __value;
|
|
180
|
+
}
|
|
173
181
|
inline std::shared_ptr<Promise<std::vector<FallbackBundleInfo>>> getFallbackUpdateBundleData() override {
|
|
174
182
|
auto __result = _swiftPart.getFallbackUpdateBundleData();
|
|
175
183
|
if (__result.hasError()) [[unlikely]] {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
///
|
|
2
|
+
/// Func_void_double.swift
|
|
3
|
+
/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
|
|
4
|
+
/// https://github.com/mrousavy/nitro
|
|
5
|
+
/// Copyright © 2026 Marc Rousavy @ Margelo
|
|
6
|
+
///
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import NitroModules
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Wraps a Swift `(_ value: Double) -> Void` as a class.
|
|
13
|
+
* This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.
|
|
14
|
+
*/
|
|
15
|
+
public final class Func_void_double {
|
|
16
|
+
public typealias bridge = margelo.nitro.reactnativebundleupdate.bridge.swift
|
|
17
|
+
|
|
18
|
+
private let closure: (_ value: Double) -> Void
|
|
19
|
+
|
|
20
|
+
public init(_ closure: @escaping (_ value: Double) -> Void) {
|
|
21
|
+
self.closure = closure
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@inline(__always)
|
|
25
|
+
public func call(value: Double) -> Void {
|
|
26
|
+
self.closure(value)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Casts this instance to a retained unsafe raw pointer.
|
|
31
|
+
* This acquires one additional strong reference on the object!
|
|
32
|
+
*/
|
|
33
|
+
@inline(__always)
|
|
34
|
+
public func toUnsafe() -> UnsafeMutableRawPointer {
|
|
35
|
+
return Unmanaged.passRetained(self).toOpaque()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Casts an unsafe pointer to a `Func_void_double`.
|
|
40
|
+
* The pointer has to be a retained opaque `Unmanaged<Func_void_double>`.
|
|
41
|
+
* This removes one strong reference from the object!
|
|
42
|
+
*/
|
|
43
|
+
@inline(__always)
|
|
44
|
+
public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_double {
|
|
45
|
+
return Unmanaged<Func_void_double>.fromOpaque(pointer).takeRetainedValue()
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -23,6 +23,7 @@ public protocol HybridReactNativeBundleUpdateSpec_protocol: HybridObject {
|
|
|
23
23
|
func clearBundle() throws -> Promise<Void>
|
|
24
24
|
func clearAllJSBundleData() throws -> Promise<TestResult>
|
|
25
25
|
func resetToBuiltInBundle() throws -> Promise<Void>
|
|
26
|
+
func pruneStaleAppVersionBundles() throws -> Promise<Double>
|
|
26
27
|
func getFallbackUpdateBundleData() throws -> Promise<[FallbackBundleInfo]>
|
|
27
28
|
func setCurrentUpdateBundleData(params: BundleSwitchParams) throws -> Promise<Void>
|
|
28
29
|
func getWebEmbedPath() throws -> String
|
|
@@ -288,6 +288,25 @@ open class HybridReactNativeBundleUpdateSpec_cxx {
|
|
|
288
288
|
}
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
+
@inline(__always)
|
|
292
|
+
public final func pruneStaleAppVersionBundles() -> bridge.Result_std__shared_ptr_Promise_double___ {
|
|
293
|
+
do {
|
|
294
|
+
let __result = try self.__implementation.pruneStaleAppVersionBundles()
|
|
295
|
+
let __resultCpp = { () -> bridge.std__shared_ptr_Promise_double__ in
|
|
296
|
+
let __promise = bridge.create_std__shared_ptr_Promise_double__()
|
|
297
|
+
let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_double__(__promise)
|
|
298
|
+
__result
|
|
299
|
+
.then({ __result in __promiseHolder.resolve(__result) })
|
|
300
|
+
.catch({ __error in __promiseHolder.reject(__error.toCpp()) })
|
|
301
|
+
return __promise
|
|
302
|
+
}()
|
|
303
|
+
return bridge.create_Result_std__shared_ptr_Promise_double___(__resultCpp)
|
|
304
|
+
} catch (let __error) {
|
|
305
|
+
let __exceptionPtr = __error.toCpp()
|
|
306
|
+
return bridge.create_Result_std__shared_ptr_Promise_double___(__exceptionPtr)
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
291
310
|
@inline(__always)
|
|
292
311
|
public final func getFallbackUpdateBundleData() -> bridge.Result_std__shared_ptr_Promise_std__vector_FallbackBundleInfo____ {
|
|
293
312
|
do {
|
|
@@ -23,6 +23,7 @@ namespace margelo::nitro::reactnativebundleupdate {
|
|
|
23
23
|
prototype.registerHybridMethod("clearBundle", &HybridReactNativeBundleUpdateSpec::clearBundle);
|
|
24
24
|
prototype.registerHybridMethod("clearAllJSBundleData", &HybridReactNativeBundleUpdateSpec::clearAllJSBundleData);
|
|
25
25
|
prototype.registerHybridMethod("resetToBuiltInBundle", &HybridReactNativeBundleUpdateSpec::resetToBuiltInBundle);
|
|
26
|
+
prototype.registerHybridMethod("pruneStaleAppVersionBundles", &HybridReactNativeBundleUpdateSpec::pruneStaleAppVersionBundles);
|
|
26
27
|
prototype.registerHybridMethod("getFallbackUpdateBundleData", &HybridReactNativeBundleUpdateSpec::getFallbackUpdateBundleData);
|
|
27
28
|
prototype.registerHybridMethod("setCurrentUpdateBundleData", &HybridReactNativeBundleUpdateSpec::setCurrentUpdateBundleData);
|
|
28
29
|
prototype.registerHybridMethod("getWebEmbedPath", &HybridReactNativeBundleUpdateSpec::getWebEmbedPath);
|
|
@@ -95,6 +95,7 @@ namespace margelo::nitro::reactnativebundleupdate {
|
|
|
95
95
|
virtual std::shared_ptr<Promise<void>> clearBundle() = 0;
|
|
96
96
|
virtual std::shared_ptr<Promise<TestResult>> clearAllJSBundleData() = 0;
|
|
97
97
|
virtual std::shared_ptr<Promise<void>> resetToBuiltInBundle() = 0;
|
|
98
|
+
virtual std::shared_ptr<Promise<double>> pruneStaleAppVersionBundles() = 0;
|
|
98
99
|
virtual std::shared_ptr<Promise<std::vector<FallbackBundleInfo>>> getFallbackUpdateBundleData() = 0;
|
|
99
100
|
virtual std::shared_ptr<Promise<void>> setCurrentUpdateBundleData(const BundleSwitchParams& params) = 0;
|
|
100
101
|
virtual std::string getWebEmbedPath() = 0;
|
package/package.json
CHANGED
|
@@ -99,6 +99,10 @@ export interface ReactNativeBundleUpdate
|
|
|
99
99
|
clearBundle(): Promise<void>;
|
|
100
100
|
clearAllJSBundleData(): Promise<TestResult>;
|
|
101
101
|
resetToBuiltInBundle(): Promise<void>;
|
|
102
|
+
// Prune every artifact whose appVersion differs from the running native
|
|
103
|
+
// binary version (stale OTA dirs, download stages, orphan asc, lingering
|
|
104
|
+
// fallback entries). Returns the count of deleted version directories.
|
|
105
|
+
pruneStaleAppVersionBundles(): Promise<number>;
|
|
102
106
|
|
|
103
107
|
// Bundle data
|
|
104
108
|
getFallbackUpdateBundleData(): Promise<FallbackBundleInfo[]>;
|