@onekeyfe/react-native-range-downloader 3.0.67 → 3.0.69

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 (44) hide show
  1. package/README.md +15 -0
  2. package/android/build.gradle +3 -0
  3. package/android/src/main/java/com/margelo/nitro/reactnativerangedownloader/ConcurrentRangeDownloader.kt +179 -11
  4. package/android/src/main/java/com/margelo/nitro/reactnativerangedownloader/RangeDownloadLogic.kt +98 -0
  5. package/android/src/main/java/com/margelo/nitro/reactnativerangedownloader/ReactNativeRangeDownloader.kt +24 -25
  6. package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/ConcurrentRangeDownloaderOcdsTest.kt +554 -0
  7. package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/FaultServer.kt +282 -0
  8. package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/IsPermanentHttpStatusTest.kt +63 -0
  9. package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/MonotonicProgressGateTest.kt +368 -0
  10. package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/Ocds416ResumeTest.kt +272 -0
  11. package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/OcdsBadTotalRejectTest.kt +147 -0
  12. package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/OcdsMultipartRejectTest.kt +114 -0
  13. package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/OcdsReadOnlyFsTest.kt +250 -0
  14. package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/OcdsTransient5xxTest.kt +275 -0
  15. package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/RangeDownloadLogicTest.kt +124 -0
  16. package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/RunRegistrySingleFlightTest.kt +217 -0
  17. package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/SegmentArtifactSweepTest.kt +350 -0
  18. package/android/src/test/java/com/margelo/nitro/reactnativerangedownloader/SmokeTest.kt +65 -0
  19. package/ios/RangeDownloadLogic.swift +187 -0
  20. package/ios/ReactNativeRangeDownloader.swift +669 -133
  21. package/lib/typescript/src/ReactNativeRangeDownloader.nitro.d.ts +7 -1
  22. package/lib/typescript/src/ReactNativeRangeDownloader.nitro.d.ts.map +1 -1
  23. package/nitrogen/generated/android/c++/JHybridReactNativeRangeDownloaderSpec.cpp +4 -0
  24. package/nitrogen/generated/android/c++/JRangeDownloadOutcome.hpp +6 -0
  25. package/nitrogen/generated/android/c++/JRangeDownloadParams.hpp +19 -3
  26. package/nitrogen/generated/android/c++/JRangeDownloadResult.hpp +9 -3
  27. package/nitrogen/generated/android/c++/JRangeFallbackKind.hpp +83 -0
  28. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativerangedownloader/RangeDownloadOutcome.kt +3 -1
  29. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativerangedownloader/RangeDownloadParams.kt +15 -3
  30. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativerangedownloader/RangeDownloadResult.kt +6 -3
  31. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativerangedownloader/RangeFallbackKind.kt +29 -0
  32. package/nitrogen/generated/ios/ReactNativeRangeDownloader-Swift-Cxx-Bridge.hpp +18 -0
  33. package/nitrogen/generated/ios/ReactNativeRangeDownloader-Swift-Cxx-Umbrella.hpp +3 -0
  34. package/nitrogen/generated/ios/c++/HybridReactNativeRangeDownloaderSpecSwift.hpp +3 -0
  35. package/nitrogen/generated/ios/swift/RangeDownloadOutcome.swift +8 -0
  36. package/nitrogen/generated/ios/swift/RangeDownloadParams.swift +93 -1
  37. package/nitrogen/generated/ios/swift/RangeDownloadResult.swift +24 -1
  38. package/nitrogen/generated/ios/swift/RangeFallbackKind.swift +72 -0
  39. package/nitrogen/generated/shared/c++/RangeDownloadOutcome.hpp +9 -1
  40. package/nitrogen/generated/shared/c++/RangeDownloadParams.hpp +18 -2
  41. package/nitrogen/generated/shared/c++/RangeDownloadResult.hpp +9 -2
  42. package/nitrogen/generated/shared/c++/RangeFallbackKind.hpp +108 -0
  43. package/package.json +1 -1
  44. package/src/ReactNativeRangeDownloader.nitro.ts +36 -2
@@ -0,0 +1,72 @@
1
+ ///
2
+ /// RangeFallbackKind.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
+ /**
9
+ * Represents the JS union `RangeFallbackKind`, backed by a C++ enum.
10
+ */
11
+ public typealias RangeFallbackKind = margelo.nitro.reactnativerangedownloader.RangeFallbackKind
12
+
13
+ public extension RangeFallbackKind {
14
+ /**
15
+ * Get a RangeFallbackKind for the given String value, or
16
+ * return `nil` if the given value was invalid/unknown.
17
+ */
18
+ init?(fromString string: String) {
19
+ switch string {
20
+ case "serverIgnoredRange":
21
+ self = .serverignoredrange
22
+ case "rangeUnsupported":
23
+ self = .rangeunsupported
24
+ case "authExpired":
25
+ self = .authexpired
26
+ case "notFound":
27
+ self = .notfound
28
+ case "redirectRejected":
29
+ self = .redirectrejected
30
+ case "checksumMismatch":
31
+ self = .checksummismatch
32
+ case "multipartOrBadTotal":
33
+ self = .multipartorbadtotal
34
+ case "transientNetwork":
35
+ self = .transientnetwork
36
+ case "throttled":
37
+ self = .throttled
38
+ case "budgetExhausted":
39
+ self = .budgetexhausted
40
+ default:
41
+ return nil
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Get the String value this RangeFallbackKind represents.
47
+ */
48
+ var stringValue: String {
49
+ switch self {
50
+ case .serverignoredrange:
51
+ return "serverIgnoredRange"
52
+ case .rangeunsupported:
53
+ return "rangeUnsupported"
54
+ case .authexpired:
55
+ return "authExpired"
56
+ case .notfound:
57
+ return "notFound"
58
+ case .redirectrejected:
59
+ return "redirectRejected"
60
+ case .checksummismatch:
61
+ return "checksumMismatch"
62
+ case .multipartorbadtotal:
63
+ return "multipartOrBadTotal"
64
+ case .transientnetwork:
65
+ return "transientNetwork"
66
+ case .throttled:
67
+ return "throttled"
68
+ case .budgetexhausted:
69
+ return "budgetExhausted"
70
+ }
71
+ }
72
+ }
@@ -30,7 +30,9 @@ namespace margelo::nitro::reactnativerangedownloader {
30
30
  */
31
31
  enum class RangeDownloadOutcome {
32
32
  COMPLETED SWIFT_NAME(completed) = 0,
33
- FALLBACK SWIFT_NAME(fallback) = 1,
33
+ FALLBACKTRANSIENT SWIFT_NAME(fallbacktransient) = 1,
34
+ FALLBACKPERMANENT SWIFT_NAME(fallbackpermanent) = 2,
35
+ FALLBACK SWIFT_NAME(fallback) = 3,
34
36
  } CLOSED_ENUM;
35
37
 
36
38
  } // namespace margelo::nitro::reactnativerangedownloader
@@ -44,6 +46,8 @@ namespace margelo::nitro {
44
46
  std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, arg);
45
47
  switch (hashString(unionValue.c_str(), unionValue.size())) {
46
48
  case hashString("completed"): return margelo::nitro::reactnativerangedownloader::RangeDownloadOutcome::COMPLETED;
49
+ case hashString("fallbackTransient"): return margelo::nitro::reactnativerangedownloader::RangeDownloadOutcome::FALLBACKTRANSIENT;
50
+ case hashString("fallbackPermanent"): return margelo::nitro::reactnativerangedownloader::RangeDownloadOutcome::FALLBACKPERMANENT;
47
51
  case hashString("fallback"): return margelo::nitro::reactnativerangedownloader::RangeDownloadOutcome::FALLBACK;
48
52
  default: [[unlikely]]
49
53
  throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum RangeDownloadOutcome - invalid value!");
@@ -52,6 +56,8 @@ namespace margelo::nitro {
52
56
  static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::reactnativerangedownloader::RangeDownloadOutcome arg) {
53
57
  switch (arg) {
54
58
  case margelo::nitro::reactnativerangedownloader::RangeDownloadOutcome::COMPLETED: return JSIConverter<std::string>::toJSI(runtime, "completed");
59
+ case margelo::nitro::reactnativerangedownloader::RangeDownloadOutcome::FALLBACKTRANSIENT: return JSIConverter<std::string>::toJSI(runtime, "fallbackTransient");
60
+ case margelo::nitro::reactnativerangedownloader::RangeDownloadOutcome::FALLBACKPERMANENT: return JSIConverter<std::string>::toJSI(runtime, "fallbackPermanent");
55
61
  case margelo::nitro::reactnativerangedownloader::RangeDownloadOutcome::FALLBACK: return JSIConverter<std::string>::toJSI(runtime, "fallback");
56
62
  default: [[unlikely]]
57
63
  throw std::invalid_argument("Cannot convert RangeDownloadOutcome to JS - invalid value: "
@@ -65,6 +71,8 @@ namespace margelo::nitro {
65
71
  std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, value);
66
72
  switch (hashString(unionValue.c_str(), unionValue.size())) {
67
73
  case hashString("completed"):
74
+ case hashString("fallbackTransient"):
75
+ case hashString("fallbackPermanent"):
68
76
  case hashString("fallback"):
69
77
  return true;
70
78
  default:
@@ -44,10 +44,14 @@ namespace margelo::nitro::reactnativerangedownloader {
44
44
  std::optional<std::string> expectedSha256 SWIFT_PRIVATE;
45
45
  std::optional<double> segmentCount SWIFT_PRIVATE;
46
46
  std::optional<double> minConcurrentBytes SWIFT_PRIVATE;
47
+ std::optional<double> maxSegmentAttempts SWIFT_PRIVATE;
48
+ std::optional<double> requestTimeoutSeconds SWIFT_PRIVATE;
49
+ std::optional<double> stallTimeoutSeconds SWIFT_PRIVATE;
50
+ std::optional<double> overallDeadlineSeconds SWIFT_PRIVATE;
47
51
 
48
52
  public:
49
53
  RangeDownloadParams() = default;
50
- explicit RangeDownloadParams(DownloadChannel channel, std::string taskId, std::string url, std::string destFilePath, std::optional<std::string> expectedSha256, std::optional<double> segmentCount, std::optional<double> minConcurrentBytes): channel(channel), taskId(taskId), url(url), destFilePath(destFilePath), expectedSha256(expectedSha256), segmentCount(segmentCount), minConcurrentBytes(minConcurrentBytes) {}
54
+ explicit RangeDownloadParams(DownloadChannel channel, std::string taskId, std::string url, std::string destFilePath, std::optional<std::string> expectedSha256, std::optional<double> segmentCount, std::optional<double> minConcurrentBytes, std::optional<double> maxSegmentAttempts, std::optional<double> requestTimeoutSeconds, std::optional<double> stallTimeoutSeconds, std::optional<double> overallDeadlineSeconds): channel(channel), taskId(taskId), url(url), destFilePath(destFilePath), expectedSha256(expectedSha256), segmentCount(segmentCount), minConcurrentBytes(minConcurrentBytes), maxSegmentAttempts(maxSegmentAttempts), requestTimeoutSeconds(requestTimeoutSeconds), stallTimeoutSeconds(stallTimeoutSeconds), overallDeadlineSeconds(overallDeadlineSeconds) {}
51
55
  };
52
56
 
53
57
  } // namespace margelo::nitro::reactnativerangedownloader
@@ -66,7 +70,11 @@ namespace margelo::nitro {
66
70
  JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, "destFilePath")),
67
71
  JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "expectedSha256")),
68
72
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "segmentCount")),
69
- JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "minConcurrentBytes"))
73
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "minConcurrentBytes")),
74
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "maxSegmentAttempts")),
75
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "requestTimeoutSeconds")),
76
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "stallTimeoutSeconds")),
77
+ JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "overallDeadlineSeconds"))
70
78
  );
71
79
  }
72
80
  static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::reactnativerangedownloader::RangeDownloadParams& arg) {
@@ -78,6 +86,10 @@ namespace margelo::nitro {
78
86
  obj.setProperty(runtime, "expectedSha256", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.expectedSha256));
79
87
  obj.setProperty(runtime, "segmentCount", JSIConverter<std::optional<double>>::toJSI(runtime, arg.segmentCount));
80
88
  obj.setProperty(runtime, "minConcurrentBytes", JSIConverter<std::optional<double>>::toJSI(runtime, arg.minConcurrentBytes));
89
+ obj.setProperty(runtime, "maxSegmentAttempts", JSIConverter<std::optional<double>>::toJSI(runtime, arg.maxSegmentAttempts));
90
+ obj.setProperty(runtime, "requestTimeoutSeconds", JSIConverter<std::optional<double>>::toJSI(runtime, arg.requestTimeoutSeconds));
91
+ obj.setProperty(runtime, "stallTimeoutSeconds", JSIConverter<std::optional<double>>::toJSI(runtime, arg.stallTimeoutSeconds));
92
+ obj.setProperty(runtime, "overallDeadlineSeconds", JSIConverter<std::optional<double>>::toJSI(runtime, arg.overallDeadlineSeconds));
81
93
  return obj;
82
94
  }
83
95
  static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
@@ -95,6 +107,10 @@ namespace margelo::nitro {
95
107
  if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "expectedSha256"))) return false;
96
108
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "segmentCount"))) return false;
97
109
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "minConcurrentBytes"))) return false;
110
+ if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "maxSegmentAttempts"))) return false;
111
+ if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "requestTimeoutSeconds"))) return false;
112
+ if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "stallTimeoutSeconds"))) return false;
113
+ if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "overallDeadlineSeconds"))) return false;
98
114
  return true;
99
115
  }
100
116
  };
@@ -25,10 +25,13 @@
25
25
 
26
26
  // Forward declaration of `RangeDownloadOutcome` to properly resolve imports.
27
27
  namespace margelo::nitro::reactnativerangedownloader { enum class RangeDownloadOutcome; }
28
+ // Forward declaration of `RangeFallbackKind` to properly resolve imports.
29
+ namespace margelo::nitro::reactnativerangedownloader { enum class RangeFallbackKind; }
28
30
 
29
31
  #include "RangeDownloadOutcome.hpp"
30
32
  #include <string>
31
33
  #include <optional>
34
+ #include "RangeFallbackKind.hpp"
32
35
 
33
36
  namespace margelo::nitro::reactnativerangedownloader {
34
37
 
@@ -40,10 +43,11 @@ namespace margelo::nitro::reactnativerangedownloader {
40
43
  RangeDownloadOutcome outcome SWIFT_PRIVATE;
41
44
  std::string filePath SWIFT_PRIVATE;
42
45
  std::optional<std::string> fallbackReason SWIFT_PRIVATE;
46
+ std::optional<RangeFallbackKind> fallbackKind SWIFT_PRIVATE;
43
47
 
44
48
  public:
45
49
  RangeDownloadResult() = default;
46
- explicit RangeDownloadResult(RangeDownloadOutcome outcome, std::string filePath, std::optional<std::string> fallbackReason): outcome(outcome), filePath(filePath), fallbackReason(fallbackReason) {}
50
+ explicit RangeDownloadResult(RangeDownloadOutcome outcome, std::string filePath, std::optional<std::string> fallbackReason, std::optional<RangeFallbackKind> fallbackKind): outcome(outcome), filePath(filePath), fallbackReason(fallbackReason), fallbackKind(fallbackKind) {}
47
51
  };
48
52
 
49
53
  } // namespace margelo::nitro::reactnativerangedownloader
@@ -58,7 +62,8 @@ namespace margelo::nitro {
58
62
  return margelo::nitro::reactnativerangedownloader::RangeDownloadResult(
59
63
  JSIConverter<margelo::nitro::reactnativerangedownloader::RangeDownloadOutcome>::fromJSI(runtime, obj.getProperty(runtime, "outcome")),
60
64
  JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, "filePath")),
61
- JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "fallbackReason"))
65
+ JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "fallbackReason")),
66
+ JSIConverter<std::optional<margelo::nitro::reactnativerangedownloader::RangeFallbackKind>>::fromJSI(runtime, obj.getProperty(runtime, "fallbackKind"))
62
67
  );
63
68
  }
64
69
  static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::reactnativerangedownloader::RangeDownloadResult& arg) {
@@ -66,6 +71,7 @@ namespace margelo::nitro {
66
71
  obj.setProperty(runtime, "outcome", JSIConverter<margelo::nitro::reactnativerangedownloader::RangeDownloadOutcome>::toJSI(runtime, arg.outcome));
67
72
  obj.setProperty(runtime, "filePath", JSIConverter<std::string>::toJSI(runtime, arg.filePath));
68
73
  obj.setProperty(runtime, "fallbackReason", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.fallbackReason));
74
+ obj.setProperty(runtime, "fallbackKind", JSIConverter<std::optional<margelo::nitro::reactnativerangedownloader::RangeFallbackKind>>::toJSI(runtime, arg.fallbackKind));
69
75
  return obj;
70
76
  }
71
77
  static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
@@ -79,6 +85,7 @@ namespace margelo::nitro {
79
85
  if (!JSIConverter<margelo::nitro::reactnativerangedownloader::RangeDownloadOutcome>::canConvert(runtime, obj.getProperty(runtime, "outcome"))) return false;
80
86
  if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, "filePath"))) return false;
81
87
  if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "fallbackReason"))) return false;
88
+ if (!JSIConverter<std::optional<margelo::nitro::reactnativerangedownloader::RangeFallbackKind>>::canConvert(runtime, obj.getProperty(runtime, "fallbackKind"))) return false;
82
89
  return true;
83
90
  }
84
91
  };
@@ -0,0 +1,108 @@
1
+ ///
2
+ /// RangeFallbackKind.hpp
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
+ #pragma once
9
+
10
+ #if __has_include(<NitroModules/NitroHash.hpp>)
11
+ #include <NitroModules/NitroHash.hpp>
12
+ #else
13
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14
+ #endif
15
+ #if __has_include(<NitroModules/JSIConverter.hpp>)
16
+ #include <NitroModules/JSIConverter.hpp>
17
+ #else
18
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
19
+ #endif
20
+ #if __has_include(<NitroModules/NitroDefines.hpp>)
21
+ #include <NitroModules/NitroDefines.hpp>
22
+ #else
23
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
24
+ #endif
25
+
26
+ namespace margelo::nitro::reactnativerangedownloader {
27
+
28
+ /**
29
+ * An enum which can be represented as a JavaScript union (RangeFallbackKind).
30
+ */
31
+ enum class RangeFallbackKind {
32
+ SERVERIGNOREDRANGE SWIFT_NAME(serverignoredrange) = 0,
33
+ RANGEUNSUPPORTED SWIFT_NAME(rangeunsupported) = 1,
34
+ AUTHEXPIRED SWIFT_NAME(authexpired) = 2,
35
+ NOTFOUND SWIFT_NAME(notfound) = 3,
36
+ REDIRECTREJECTED SWIFT_NAME(redirectrejected) = 4,
37
+ CHECKSUMMISMATCH SWIFT_NAME(checksummismatch) = 5,
38
+ MULTIPARTORBADTOTAL SWIFT_NAME(multipartorbadtotal) = 6,
39
+ TRANSIENTNETWORK SWIFT_NAME(transientnetwork) = 7,
40
+ THROTTLED SWIFT_NAME(throttled) = 8,
41
+ BUDGETEXHAUSTED SWIFT_NAME(budgetexhausted) = 9,
42
+ } CLOSED_ENUM;
43
+
44
+ } // namespace margelo::nitro::reactnativerangedownloader
45
+
46
+ namespace margelo::nitro {
47
+
48
+ // C++ RangeFallbackKind <> JS RangeFallbackKind (union)
49
+ template <>
50
+ struct JSIConverter<margelo::nitro::reactnativerangedownloader::RangeFallbackKind> final {
51
+ static inline margelo::nitro::reactnativerangedownloader::RangeFallbackKind fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
52
+ std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, arg);
53
+ switch (hashString(unionValue.c_str(), unionValue.size())) {
54
+ case hashString("serverIgnoredRange"): return margelo::nitro::reactnativerangedownloader::RangeFallbackKind::SERVERIGNOREDRANGE;
55
+ case hashString("rangeUnsupported"): return margelo::nitro::reactnativerangedownloader::RangeFallbackKind::RANGEUNSUPPORTED;
56
+ case hashString("authExpired"): return margelo::nitro::reactnativerangedownloader::RangeFallbackKind::AUTHEXPIRED;
57
+ case hashString("notFound"): return margelo::nitro::reactnativerangedownloader::RangeFallbackKind::NOTFOUND;
58
+ case hashString("redirectRejected"): return margelo::nitro::reactnativerangedownloader::RangeFallbackKind::REDIRECTREJECTED;
59
+ case hashString("checksumMismatch"): return margelo::nitro::reactnativerangedownloader::RangeFallbackKind::CHECKSUMMISMATCH;
60
+ case hashString("multipartOrBadTotal"): return margelo::nitro::reactnativerangedownloader::RangeFallbackKind::MULTIPARTORBADTOTAL;
61
+ case hashString("transientNetwork"): return margelo::nitro::reactnativerangedownloader::RangeFallbackKind::TRANSIENTNETWORK;
62
+ case hashString("throttled"): return margelo::nitro::reactnativerangedownloader::RangeFallbackKind::THROTTLED;
63
+ case hashString("budgetExhausted"): return margelo::nitro::reactnativerangedownloader::RangeFallbackKind::BUDGETEXHAUSTED;
64
+ default: [[unlikely]]
65
+ throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum RangeFallbackKind - invalid value!");
66
+ }
67
+ }
68
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::reactnativerangedownloader::RangeFallbackKind arg) {
69
+ switch (arg) {
70
+ case margelo::nitro::reactnativerangedownloader::RangeFallbackKind::SERVERIGNOREDRANGE: return JSIConverter<std::string>::toJSI(runtime, "serverIgnoredRange");
71
+ case margelo::nitro::reactnativerangedownloader::RangeFallbackKind::RANGEUNSUPPORTED: return JSIConverter<std::string>::toJSI(runtime, "rangeUnsupported");
72
+ case margelo::nitro::reactnativerangedownloader::RangeFallbackKind::AUTHEXPIRED: return JSIConverter<std::string>::toJSI(runtime, "authExpired");
73
+ case margelo::nitro::reactnativerangedownloader::RangeFallbackKind::NOTFOUND: return JSIConverter<std::string>::toJSI(runtime, "notFound");
74
+ case margelo::nitro::reactnativerangedownloader::RangeFallbackKind::REDIRECTREJECTED: return JSIConverter<std::string>::toJSI(runtime, "redirectRejected");
75
+ case margelo::nitro::reactnativerangedownloader::RangeFallbackKind::CHECKSUMMISMATCH: return JSIConverter<std::string>::toJSI(runtime, "checksumMismatch");
76
+ case margelo::nitro::reactnativerangedownloader::RangeFallbackKind::MULTIPARTORBADTOTAL: return JSIConverter<std::string>::toJSI(runtime, "multipartOrBadTotal");
77
+ case margelo::nitro::reactnativerangedownloader::RangeFallbackKind::TRANSIENTNETWORK: return JSIConverter<std::string>::toJSI(runtime, "transientNetwork");
78
+ case margelo::nitro::reactnativerangedownloader::RangeFallbackKind::THROTTLED: return JSIConverter<std::string>::toJSI(runtime, "throttled");
79
+ case margelo::nitro::reactnativerangedownloader::RangeFallbackKind::BUDGETEXHAUSTED: return JSIConverter<std::string>::toJSI(runtime, "budgetExhausted");
80
+ default: [[unlikely]]
81
+ throw std::invalid_argument("Cannot convert RangeFallbackKind to JS - invalid value: "
82
+ + std::to_string(static_cast<int>(arg)) + "!");
83
+ }
84
+ }
85
+ static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
86
+ if (!value.isString()) {
87
+ return false;
88
+ }
89
+ std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, value);
90
+ switch (hashString(unionValue.c_str(), unionValue.size())) {
91
+ case hashString("serverIgnoredRange"):
92
+ case hashString("rangeUnsupported"):
93
+ case hashString("authExpired"):
94
+ case hashString("notFound"):
95
+ case hashString("redirectRejected"):
96
+ case hashString("checksumMismatch"):
97
+ case hashString("multipartOrBadTotal"):
98
+ case hashString("transientNetwork"):
99
+ case hashString("throttled"):
100
+ case hashString("budgetExhausted"):
101
+ return true;
102
+ default:
103
+ return false;
104
+ }
105
+ }
106
+ };
107
+
108
+ } // namespace margelo::nitro
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/react-native-range-downloader",
3
- "version": "3.0.67",
3
+ "version": "3.0.69",
4
4
  "description": "react-native-range-downloader",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -14,16 +14,50 @@ export interface RangeDownloadParams {
14
14
  expectedSha256?: string; // optional: in-module post-download self-check; else caller verifies later
15
15
  segmentCount?: number; // default 8 (mirrors current behavior)
16
16
  minConcurrentBytes?: number; // default 2MB (below this falls straight back to single stream)
17
+ // OCDS §5.4: caller-tunable retry/backoff/deadline knobs. Defaults are platform
18
+ // configuration (filled in by the native module when omitted), not part of the
19
+ // standard. These let the OTA / APK / asset callers tune behavior per channel.
20
+ maxSegmentAttempts?: number; // per-segment transient retry budget within a single run (default 4)
21
+ requestTimeoutSeconds?: number; // connection/request timeout per segment task (default 60)
22
+ stallTimeoutSeconds?: number; // bytes-stalled (no-progress) watchdog window (default 30)
23
+ overallDeadlineSeconds?: number; // single-run wall-clock bound before giving up (default 0 = none)
17
24
  }
18
25
 
26
+ // OCDS §4: the failure class is an EXPLICIT, typed outcome of the operation, never
27
+ // inferred from incidental on-disk side effects (e.g. whether `.segN` survives).
28
+ // - `completed` — destFilePath fully on disk (and expectedSha256, if passed, has passed)
29
+ // - `fallbackTransient` — concurrent path interrupted but RESUMABLE; segments kept; caller
30
+ // should retry the concurrent path / keep its progress floor
31
+ // - `fallbackPermanent` — concurrency fundamentally unusable for this object; segments are
32
+ // unsalvageable and have been discarded; caller restarts single-stream
33
+ // - `fallback` — DEPRECATED legacy alias kept for wire/back-compat during the
34
+ // transition; new callers consume the two typed classes above
19
35
  export type RangeDownloadOutcome =
20
- | 'completed' // destFilePath fully on disk (and expectedSha256, if passed, has passed)
21
- | 'fallback'; // concurrent unavailable, caller should run its own single-stream path
36
+ | 'completed'
37
+ | 'fallbackTransient'
38
+ | 'fallbackPermanent'
39
+ | 'fallback';
40
+
41
+ // OCDS §4: optional sub-classification of a fallback, so the caller (and analytics)
42
+ // can distinguish WHY the concurrent path was abandoned without parsing the reason
43
+ // string. Present only when outcome is a fallback class.
44
+ export type RangeFallbackKind =
45
+ | 'serverIgnoredRange' // server answered 200 to a Range request (Permanent)
46
+ | 'rangeUnsupported' // probe inconclusive / range not supported (Permanent)
47
+ | 'authExpired' // 401/403: signed URL dead; caller must fetch a fresh URL (Permanent)
48
+ | 'notFound' // 404/410: object gone (Permanent)
49
+ | 'redirectRejected' // non-HTTPS redirect rejected per §5.9 (Permanent)
50
+ | 'checksumMismatch' // whole-file checksum mismatch after assembly (Permanent)
51
+ | 'multipartOrBadTotal' // multipart/byteranges or Content-Range total disagrees (Permanent)
52
+ | 'transientNetwork' // connection lost / timeout / DNS / TLS / stall (Transient)
53
+ | 'throttled' // 429 / 5xx (except 501/505) (Transient)
54
+ | 'budgetExhausted'; // per-segment attempts / deadline exhausted while still resumable (Transient)
22
55
 
23
56
  export interface RangeDownloadResult {
24
57
  outcome: RangeDownloadOutcome;
25
58
  filePath: string;
26
59
  fallbackReason?: string; // filled when outcome=fallback (range unsupported / 200 / too small ...)
60
+ fallbackKind?: RangeFallbackKind; // typed sub-class of the fallback (see §4); omitted on completed
27
61
  }
28
62
 
29
63
  export interface RangeDownloadEvent {