react-native-instantpay-code-push 1.1.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/InstantpayCodePush.podspec +20 -0
- package/LICENSE +20 -0
- package/README.md +158 -0
- package/android/build.gradle +91 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/instantpaycodepush/BundleFileStorageService.kt +835 -0
- package/android/src/main/java/com/instantpaycodepush/BundleMetadata.kt +249 -0
- package/android/src/main/java/com/instantpaycodepush/CommonHelper.kt +39 -0
- package/android/src/main/java/com/instantpaycodepush/DecompressService.kt +85 -0
- package/android/src/main/java/com/instantpaycodepush/DecompressionStrategy.kt +24 -0
- package/android/src/main/java/com/instantpaycodepush/FileManagerService.kt +105 -0
- package/android/src/main/java/com/instantpaycodepush/HashUtils.kt +50 -0
- package/android/src/main/java/com/instantpaycodepush/InstantpayCodePushModule.kt +182 -0
- package/android/src/main/java/com/instantpaycodepush/InstantpayCodePushPackage.kt +33 -0
- package/android/src/main/java/com/instantpaycodepush/IpayCodePush.kt +101 -0
- package/android/src/main/java/com/instantpaycodepush/IpayCodePushException.kt +135 -0
- package/android/src/main/java/com/instantpaycodepush/IpayCodePushImpl.kt +329 -0
- package/android/src/main/java/com/instantpaycodepush/OkHttpDownloadService.kt +283 -0
- package/android/src/main/java/com/instantpaycodepush/ReactIntegrationManager.kt +141 -0
- package/android/src/main/java/com/instantpaycodepush/ReactIntegrationManagerBase.kt +35 -0
- package/android/src/main/java/com/instantpaycodepush/SignatureVerifier.kt +354 -0
- package/android/src/main/java/com/instantpaycodepush/VersionedPreferencesService.kt +70 -0
- package/android/src/main/java/com/instantpaycodepush/ZipDecompressionStrategy.kt +198 -0
- package/ios/InstantpayCodePush.h +5 -0
- package/ios/InstantpayCodePush.mm +21 -0
- package/lib/module/DefaultResolver.js +34 -0
- package/lib/module/DefaultResolver.js.map +1 -0
- package/lib/module/NativeInstantpayCodePush.js +5 -0
- package/lib/module/NativeInstantpayCodePush.js.map +1 -0
- package/lib/module/checkForUpdate.js +68 -0
- package/lib/module/checkForUpdate.js.map +1 -0
- package/lib/module/error.js +137 -0
- package/lib/module/error.js.map +1 -0
- package/lib/module/fetchUpdateInfo.js +36 -0
- package/lib/module/fetchUpdateInfo.js.map +1 -0
- package/lib/module/global.d.js +8 -0
- package/lib/module/global.d.js.map +1 -0
- package/lib/module/hooks/useEventCallback.js +13 -0
- package/lib/module/hooks/useEventCallback.js.map +1 -0
- package/lib/module/index.js +291 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/native.js +233 -0
- package/lib/module/native.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/store.js +53 -0
- package/lib/module/store.js.map +1 -0
- package/lib/module/types.js +62 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/wrap.js +171 -0
- package/lib/module/wrap.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/DefaultResolver.d.ts +10 -0
- package/lib/typescript/src/DefaultResolver.d.ts.map +1 -0
- package/lib/typescript/src/NativeInstantpayCodePush.d.ts +100 -0
- package/lib/typescript/src/NativeInstantpayCodePush.d.ts.map +1 -0
- package/lib/typescript/src/checkForUpdate.d.ts +29 -0
- package/lib/typescript/src/checkForUpdate.d.ts.map +1 -0
- package/lib/typescript/src/error.d.ts +124 -0
- package/lib/typescript/src/error.d.ts.map +1 -0
- package/lib/typescript/src/fetchUpdateInfo.d.ts +8 -0
- package/lib/typescript/src/fetchUpdateInfo.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useEventCallback.d.ts +5 -0
- package/lib/typescript/src/hooks/useEventCallback.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +203 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/native.d.ts +128 -0
- package/lib/typescript/src/native.d.ts.map +1 -0
- package/lib/typescript/src/store.d.ts +11 -0
- package/lib/typescript/src/store.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +174 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/wrap.d.ts +179 -0
- package/lib/typescript/src/wrap.d.ts.map +1 -0
- package/package.json +174 -0
- package/src/DefaultResolver.ts +36 -0
- package/src/NativeInstantpayCodePush.ts +111 -0
- package/src/checkForUpdate.ts +122 -0
- package/src/error.ts +159 -0
- package/src/fetchUpdateInfo.ts +47 -0
- package/src/global.d.ts +23 -0
- package/src/hooks/useEventCallback.ts +30 -0
- package/src/index.tsx +379 -0
- package/src/native.ts +280 -0
- package/src/store.ts +69 -0
- package/src/types.ts +227 -0
- package/src/wrap.tsx +384 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
package com.instantpaycodepush
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Promise
|
|
4
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
5
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
6
|
+
import com.facebook.react.bridge.ReadableMap
|
|
7
|
+
import com.facebook.react.bridge.WritableNativeArray
|
|
8
|
+
import com.facebook.react.bridge.WritableNativeMap
|
|
9
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
10
|
+
|
|
11
|
+
import kotlinx.coroutines.CoroutineScope
|
|
12
|
+
import kotlinx.coroutines.Dispatchers
|
|
13
|
+
import kotlinx.coroutines.SupervisorJob
|
|
14
|
+
import kotlinx.coroutines.cancel
|
|
15
|
+
import kotlinx.coroutines.launch
|
|
16
|
+
|
|
17
|
+
import android.os.Handler
|
|
18
|
+
import android.os.Looper
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@ReactModule(name = InstantpayCodePushModule.NAME)
|
|
22
|
+
class InstantpayCodePushModule(reactContext: ReactApplicationContext) : NativeInstantpayCodePushSpec(reactContext) {
|
|
23
|
+
|
|
24
|
+
private val mReactApplicationContext: ReactApplicationContext = reactContext
|
|
25
|
+
|
|
26
|
+
// Managed coroutine scope for the module lifecycle
|
|
27
|
+
private val moduleScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
|
28
|
+
|
|
29
|
+
companion object {
|
|
30
|
+
const val NAME = "InstantpayCodePush"
|
|
31
|
+
private const val CLASS_TAG = "*InstantpayCodePushModule"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
override fun invalidate() {
|
|
35
|
+
super.invalidate()
|
|
36
|
+
// Cancel all ongoing coroutines when module is destroyed
|
|
37
|
+
moduleScope.cancel()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Gets the singleton IpayCodePushImpl instance
|
|
42
|
+
*/
|
|
43
|
+
private fun getInstance(): IpayCodePushImpl = IpayCodePush.getInstance(mReactApplicationContext)
|
|
44
|
+
|
|
45
|
+
override fun getName(): String {
|
|
46
|
+
return NAME
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
override fun reload(promise: Promise) {
|
|
50
|
+
moduleScope.launch {
|
|
51
|
+
try {
|
|
52
|
+
val impl = getInstance()
|
|
53
|
+
val currentActivity = mReactApplicationContext.currentActivity
|
|
54
|
+
impl.reload(currentActivity)
|
|
55
|
+
promise.resolve(null)
|
|
56
|
+
} catch (e: Exception) {
|
|
57
|
+
CommonHelper.logPrint(CLASS_TAG, "Failed to reload $e",)
|
|
58
|
+
promise.reject("reload", e)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
override fun updateBundle(
|
|
64
|
+
params: ReadableMap,
|
|
65
|
+
promise: Promise,
|
|
66
|
+
) {
|
|
67
|
+
moduleScope.launch {
|
|
68
|
+
try {
|
|
69
|
+
val bundleId = params.getString("bundleId")
|
|
70
|
+
if (bundleId == null || bundleId.isEmpty()) {
|
|
71
|
+
promise.reject("MISSING_BUNDLE_ID", "Missing or empty 'bundleId'")
|
|
72
|
+
return@launch
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
val fileUrl = params.getString("fileUrl")
|
|
76
|
+
|
|
77
|
+
// Validate fileUrl format if provided
|
|
78
|
+
if (fileUrl != null && fileUrl.isNotEmpty()) {
|
|
79
|
+
try {
|
|
80
|
+
java.net.URL(fileUrl)
|
|
81
|
+
} catch (e: java.net.MalformedURLException) {
|
|
82
|
+
promise.reject("INVALID_FILE_URL", "Invalid 'fileUrl' provided: $fileUrl")
|
|
83
|
+
return@launch
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
val fileHash = params.getString("fileHash")
|
|
88
|
+
|
|
89
|
+
val impl = getInstance()
|
|
90
|
+
|
|
91
|
+
impl.updateBundle(
|
|
92
|
+
bundleId,
|
|
93
|
+
fileUrl,
|
|
94
|
+
fileHash,
|
|
95
|
+
) { progress ->
|
|
96
|
+
// Post to Main thread for React Native event emission
|
|
97
|
+
Handler(Looper.getMainLooper()).post {
|
|
98
|
+
try {
|
|
99
|
+
val progressParams =
|
|
100
|
+
WritableNativeMap().apply {
|
|
101
|
+
putDouble("progress", progress)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
this@InstantpayCodePushModule
|
|
105
|
+
.mReactApplicationContext
|
|
106
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
107
|
+
?.emit("onProgress", progressParams)
|
|
108
|
+
} catch (e: Exception) {
|
|
109
|
+
CommonHelper.logPrint(CommonHelper.WARNING_LOG,CLASS_TAG, "Failed to emit progress (bridge may be unavailable): ${e.message}")
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
promise.resolve(true)
|
|
114
|
+
} catch (e: IpayCodePushException) {
|
|
115
|
+
CommonHelper.logPrint(CommonHelper.ERROR_LOG,CLASS_TAG, "Catch IpayCodePushException: ${e.message}")
|
|
116
|
+
promise.reject(e.code, e.message)
|
|
117
|
+
} catch (e: Exception) {
|
|
118
|
+
CommonHelper.logPrint(CommonHelper.ERROR_LOG,CLASS_TAG, "Catch Exception: ${e.message}")
|
|
119
|
+
promise.reject("UNKNOWN_ERROR", e.message ?: "An unknown error occurred")
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
override fun getTypedExportedConstants(): Map<String, Any?> {
|
|
125
|
+
val constants: MutableMap<String, Any?> = HashMap()
|
|
126
|
+
constants["MIN_BUNDLE_ID"] = IpayCodePush.getMinBundleId()
|
|
127
|
+
constants["APP_VERSION"] = IpayCodePush.getAppVersion(mReactApplicationContext)
|
|
128
|
+
constants["CHANNEL"] = IpayCodePush.getChannel(mReactApplicationContext)
|
|
129
|
+
constants["FINGERPRINT_HASH"] = IpayCodePush.getFingerprintHash(mReactApplicationContext)
|
|
130
|
+
return constants
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
override fun addListener(
|
|
134
|
+
@Suppress("UNUSED_PARAMETER") eventName: String?,
|
|
135
|
+
) {
|
|
136
|
+
// No-op
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
override fun removeListeners(
|
|
140
|
+
@Suppress("UNUSED_PARAMETER") count: Double,
|
|
141
|
+
) {
|
|
142
|
+
// No-op
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
override fun notifyAppReady(params: ReadableMap): WritableNativeMap {
|
|
146
|
+
val result = WritableNativeMap()
|
|
147
|
+
val bundleId = params.getString("bundleId")
|
|
148
|
+
if (bundleId == null) {
|
|
149
|
+
result.putString("status", "STABLE")
|
|
150
|
+
return result
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
val impl = getInstance()
|
|
154
|
+
val statusMap = impl.notifyAppReady(bundleId)
|
|
155
|
+
|
|
156
|
+
result.putString("status", statusMap["status"] as? String ?: "STABLE")
|
|
157
|
+
statusMap["crashedBundleId"]?.let {
|
|
158
|
+
result.putString("crashedBundleId", it as String)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return result
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
override fun getCrashHistory(): WritableNativeArray {
|
|
165
|
+
val impl = getInstance()
|
|
166
|
+
val crashHistory = impl.getCrashHistory()
|
|
167
|
+
val result = WritableNativeArray()
|
|
168
|
+
crashHistory.forEach { result.pushString(it) }
|
|
169
|
+
return result
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
override fun clearCrashHistory(): Boolean {
|
|
173
|
+
val impl = getInstance()
|
|
174
|
+
return impl.clearCrashHistory()
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
override fun getBaseURL(): String {
|
|
178
|
+
val impl = getInstance()
|
|
179
|
+
return impl.getBaseURL()
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
package com.instantpaycodepush
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.BaseReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.module.model.ReactModuleInfo
|
|
7
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
8
|
+
import java.util.HashMap
|
|
9
|
+
|
|
10
|
+
class InstantpayCodePushPackage : BaseReactPackage() {
|
|
11
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
|
|
12
|
+
return if (name == InstantpayCodePushModule.NAME) {
|
|
13
|
+
InstantpayCodePushModule(reactContext)
|
|
14
|
+
} else {
|
|
15
|
+
null
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
|
|
20
|
+
return ReactModuleInfoProvider {
|
|
21
|
+
val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
|
|
22
|
+
moduleInfos[InstantpayCodePushModule.NAME] = ReactModuleInfo(
|
|
23
|
+
InstantpayCodePushModule.NAME,
|
|
24
|
+
InstantpayCodePushModule.NAME,
|
|
25
|
+
false, // canOverrideExistingModule
|
|
26
|
+
false, // needsEagerInit
|
|
27
|
+
false, // isCxxModule
|
|
28
|
+
true // isTurboModule
|
|
29
|
+
)
|
|
30
|
+
moduleInfos
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
package com.instantpaycodepush
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
|
|
7
|
+
class IpayCodePush {
|
|
8
|
+
|
|
9
|
+
companion object{
|
|
10
|
+
|
|
11
|
+
@Volatile
|
|
12
|
+
private var instance: IpayCodePushImpl? = null
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Gets or creates the singleton instance
|
|
16
|
+
* Thread-safe double-checked locking
|
|
17
|
+
* @param context Application context
|
|
18
|
+
* @return The singleton IpayCodePushImpl instance
|
|
19
|
+
*/
|
|
20
|
+
fun getInstance(context: Context): IpayCodePushImpl =
|
|
21
|
+
instance ?: synchronized(this){
|
|
22
|
+
instance ?: IpayCodePushImpl(context.applicationContext).also {
|
|
23
|
+
instance = it
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Gets the JS bundle file path using the default singleton instance
|
|
29
|
+
* @param context Application context
|
|
30
|
+
* @return The path to the bundle file
|
|
31
|
+
*/
|
|
32
|
+
fun getJSBundleFile(context: Context): String = getInstance(context).getJSBundleFile()
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Updates the bundle using the default singleton instance
|
|
36
|
+
* @param context Application context
|
|
37
|
+
* @param bundleId ID of the bundle to update
|
|
38
|
+
* @param fileUrl URL of the bundle file to download (or null to reset)
|
|
39
|
+
* @param fileHash Combined hash string for verification (sig:<signature> or <hex_hash>)
|
|
40
|
+
* @param progressCallback Callback for download progress updates
|
|
41
|
+
* @throws IpayCodePushException if the update fails
|
|
42
|
+
*/
|
|
43
|
+
suspend fun updateBundle(
|
|
44
|
+
context: Context,
|
|
45
|
+
bundleId: String,
|
|
46
|
+
fileUrl: String?,
|
|
47
|
+
fileHash: String?,
|
|
48
|
+
progressCallback: (Double) -> Unit,
|
|
49
|
+
) {
|
|
50
|
+
getInstance(context).updateBundle(bundleId, fileUrl, fileHash, progressCallback)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Reloads the React Native application using the default singleton instance
|
|
55
|
+
* @param context Application context
|
|
56
|
+
*/
|
|
57
|
+
suspend fun reload(context: Context) {
|
|
58
|
+
val currentActivity = getCurrentActivity(context)
|
|
59
|
+
getInstance(context).reload(currentActivity)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Gets the app version - delegates to IpayCodePushImpl static method
|
|
64
|
+
* @param context Application context
|
|
65
|
+
* @return App version name or null if not available
|
|
66
|
+
*/
|
|
67
|
+
fun getAppVersion(context: Context): String? = IpayCodePushImpl.getAppVersion(context)
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Gets the minimum bundle ID - delegates to IpayCodePushImpl static method
|
|
71
|
+
* @return The minimum bundle ID string
|
|
72
|
+
*/
|
|
73
|
+
fun getMinBundleId(): String = IpayCodePushImpl.getMinBundleId()
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Gets the current fingerprint hash - delegates to IpayCodePushImpl static method
|
|
77
|
+
* @param context Application context
|
|
78
|
+
* @return The fingerprint hash or null if not set
|
|
79
|
+
*/
|
|
80
|
+
fun getFingerprintHash(context: Context): String? = IpayCodePushImpl.getFingerprintHash(context)
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Gets the current update channel - delegates to IpayCodePushImpl static method
|
|
84
|
+
* @param context Application context
|
|
85
|
+
* @return The channel name or null if not set
|
|
86
|
+
*/
|
|
87
|
+
fun getChannel(context: Context): String = IpayCodePushImpl.getChannel(context)
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Gets the current activity from ReactApplicationContext
|
|
91
|
+
* @param context Context that might be a ReactApplicationContext
|
|
92
|
+
* @return The current activity or null
|
|
93
|
+
*/
|
|
94
|
+
private fun getCurrentActivity(context: Context): Activity? =
|
|
95
|
+
if (context is ReactApplicationContext) {
|
|
96
|
+
context.currentActivity
|
|
97
|
+
} else {
|
|
98
|
+
null
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
package com.instantpaycodepush
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Exception class for Ipay Code Push errors
|
|
5
|
+
* Matches error codes defined in packages/react-native/src/errors.ts
|
|
6
|
+
*/
|
|
7
|
+
class IpayCodePushException(
|
|
8
|
+
val code: String,
|
|
9
|
+
message: String,
|
|
10
|
+
cause: Throwable? = null,
|
|
11
|
+
) : Exception(message, cause){
|
|
12
|
+
|
|
13
|
+
companion object {
|
|
14
|
+
// Parameter validation errors
|
|
15
|
+
fun missingBundleId() =
|
|
16
|
+
IpayCodePushException(
|
|
17
|
+
"MISSING_BUNDLE_ID",
|
|
18
|
+
"Missing or empty 'bundleId'",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
fun invalidFileUrl() =
|
|
22
|
+
IpayCodePushException(
|
|
23
|
+
"INVALID_FILE_URL",
|
|
24
|
+
"Invalid 'fileUrl' provided",
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
// Bundle storage errors
|
|
28
|
+
fun directoryCreationFailed() =
|
|
29
|
+
IpayCodePushException(
|
|
30
|
+
"DIRECTORY_CREATION_FAILED",
|
|
31
|
+
"Failed to create bundle directory",
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
fun downloadFailed(cause: Throwable? = null) =
|
|
35
|
+
IpayCodePushException(
|
|
36
|
+
"DOWNLOAD_FAILED",
|
|
37
|
+
"Failed to download bundle",
|
|
38
|
+
cause,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
fun incompleteDownload(
|
|
42
|
+
expectedSize: Long,
|
|
43
|
+
actualSize: Long,
|
|
44
|
+
) = IpayCodePushException(
|
|
45
|
+
"INCOMPLETE_DOWNLOAD",
|
|
46
|
+
"Download incomplete: received $actualSize bytes, expected $expectedSize bytes",
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
fun extractionFormatError(cause: Throwable? = null) =
|
|
50
|
+
IpayCodePushException(
|
|
51
|
+
"EXTRACTION_FORMAT_ERROR",
|
|
52
|
+
"Invalid or corrupted bundle archive format",
|
|
53
|
+
cause,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
fun invalidBundle() =
|
|
57
|
+
IpayCodePushException(
|
|
58
|
+
"INVALID_BUNDLE",
|
|
59
|
+
"Bundle missing required platform files (index.ios.bundle or index.android.bundle)",
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
fun insufficientDiskSpace(
|
|
63
|
+
required: Long,
|
|
64
|
+
available: Long,
|
|
65
|
+
) = IpayCodePushException(
|
|
66
|
+
"INSUFFICIENT_DISK_SPACE",
|
|
67
|
+
"Insufficient disk space: need $required bytes, available $available bytes",
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
fun signatureVerificationFailed(cause: Throwable? = null) =
|
|
71
|
+
IpayCodePushException(
|
|
72
|
+
"SIGNATURE_VERIFICATION_FAILED",
|
|
73
|
+
"Bundle signature verification failed",
|
|
74
|
+
cause,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
fun moveOperationFailed() =
|
|
78
|
+
IpayCodePushException(
|
|
79
|
+
"MOVE_OPERATION_FAILED",
|
|
80
|
+
"Failed to move bundle files",
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
fun bundleInCrashedHistory(bundleId: String) =
|
|
84
|
+
IpayCodePushException(
|
|
85
|
+
"BUNDLE_IN_CRASHED_HISTORY",
|
|
86
|
+
"Bundle '$bundleId' is in crashed history and cannot be applied",
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
// Signature verification errors
|
|
90
|
+
fun publicKeyNotConfigured() =
|
|
91
|
+
IpayCodePushException(
|
|
92
|
+
"PUBLIC_KEY_NOT_CONFIGURED",
|
|
93
|
+
"Public key not configured for signature verification",
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
fun invalidPublicKeyFormat() =
|
|
97
|
+
IpayCodePushException(
|
|
98
|
+
"INVALID_PUBLIC_KEY_FORMAT",
|
|
99
|
+
"Invalid public key format",
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
fun fileHashMismatch() =
|
|
103
|
+
IpayCodePushException(
|
|
104
|
+
"FILE_HASH_MISMATCH",
|
|
105
|
+
"File hash verification failed",
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
fun fileReadFailed() =
|
|
109
|
+
IpayCodePushException(
|
|
110
|
+
"FILE_READ_FAILED",
|
|
111
|
+
"Failed to read file for verification",
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
fun unsignedNotAllowed() =
|
|
115
|
+
IpayCodePushException(
|
|
116
|
+
"UNSIGNED_NOT_ALLOWED",
|
|
117
|
+
"Unsigned bundles are not allowed",
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
fun securityFrameworkError(cause: Throwable? = null) =
|
|
121
|
+
IpayCodePushException(
|
|
122
|
+
"SECURITY_FRAMEWORK_ERROR",
|
|
123
|
+
"Security framework error occurred",
|
|
124
|
+
cause,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
// Internal errors
|
|
128
|
+
fun unknownError(cause: Throwable? = null) =
|
|
129
|
+
IpayCodePushException(
|
|
130
|
+
"UNKNOWN_ERROR",
|
|
131
|
+
"An unknown error occurred",
|
|
132
|
+
cause,
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
}
|