@hot-updater/react-native 0.1.4 → 0.1.6-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/HotUpdater.podspec +1 -2
- package/android/build.gradle +16 -3
- package/android/generated/java/com/hotupdater/NativeHotUpdaterSpec.java +54 -0
- package/android/generated/jni/CMakeLists.txt +36 -0
- package/android/generated/jni/HotUpdaterSpec-generated.cpp +56 -0
- package/android/generated/jni/HotUpdaterSpec.h +31 -0
- package/android/generated/jni/react/renderer/components/HotUpdaterSpec/HotUpdaterSpecJSI-generated.cpp +57 -0
- package/android/generated/jni/react/renderer/components/HotUpdaterSpec/HotUpdaterSpecJSI.h +103 -0
- package/android/react-native-helpers.gradle +42 -0
- package/android/src/main/java/com/hotupdater/HotUpdater.kt +151 -240
- package/android/src/main/java/com/hotupdater/HotUpdaterModule.kt +52 -40
- package/android/src/main/java/com/hotupdater/HotUpdaterPackage.kt +25 -24
- package/android/src/main/java/com/hotupdater/ReactIntegrationManagerBase.kt +34 -0
- package/android/src/newarch/HotUpdaterSpec.kt +3 -2
- package/android/src/newarch/ReactIntegrationManager.kt +46 -0
- package/android/src/oldarch/HotUpdaterSpec.kt +12 -8
- package/android/src/oldarch/ReactIntegrationManager.kt +41 -0
- package/dist/index.d.mts +71 -0
- package/dist/index.d.ts +44 -53
- package/dist/index.js +4310 -132
- package/dist/index.mjs +4362 -0
- package/ios/HotUpdater/HotUpdater.h +8 -4
- package/ios/HotUpdater/HotUpdater.mm +167 -116
- package/ios/generated/HotUpdaterSpec/HotUpdaterSpec-generated.mm +67 -0
- package/ios/generated/HotUpdaterSpec/HotUpdaterSpec.h +67 -0
- package/ios/generated/HotUpdaterSpecJSI-generated.cpp +57 -0
- package/ios/generated/HotUpdaterSpecJSI.h +103 -0
- package/package.json +27 -10
- package/react-native.config.js +12 -0
- package/src/ensureBundles.ts +21 -0
- package/src/global.d.ts +3 -0
- package/src/index.ts +27 -5
- package/src/init.tsx +25 -7
- package/src/native.ts +50 -42
- package/src/specs/{NativeHotUpdaterModule.ts → NativeHotUpdater.ts} +6 -7
- package/src/store.ts +48 -0
- package/dist/index.cjs +0 -220
- package/dist/index.d.cts +0 -80
- package/src/checkForUpdate.test.ts +0 -517
- package/src/checkForUpdate.ts +0 -111
- package/src/utils.ts +0 -2
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
package com.hotupdater
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import com.facebook.react.ReactApplication
|
|
6
|
+
import com.facebook.react.common.LifecycleState
|
|
7
|
+
|
|
8
|
+
class ReactIntegrationManager(
|
|
9
|
+
context: Context,
|
|
10
|
+
) : ReactIntegrationManagerBase(context) {
|
|
11
|
+
public fun setJSBundle(
|
|
12
|
+
application: ReactApplication,
|
|
13
|
+
bundleURL: String,
|
|
14
|
+
) {
|
|
15
|
+
try {
|
|
16
|
+
val reactHost = application.reactHost
|
|
17
|
+
check(reactHost != null)
|
|
18
|
+
val reactHostDelegateField = reactHost::class.java.getDeclaredField("mReactHostDelegate")
|
|
19
|
+
reactHostDelegateField.isAccessible = true
|
|
20
|
+
val reactHostDelegate =
|
|
21
|
+
reactHostDelegateField.get(
|
|
22
|
+
reactHost,
|
|
23
|
+
)
|
|
24
|
+
val jsBundleLoaderField = reactHostDelegate::class.java.getDeclaredField("jsBundleLoader")
|
|
25
|
+
jsBundleLoaderField.isAccessible = true
|
|
26
|
+
jsBundleLoaderField.set(reactHostDelegate, getJSBundlerLoader(bundleURL))
|
|
27
|
+
} catch (e: Exception) {
|
|
28
|
+
Log.d("HotUpdater", "Failed to setJSBundle: ${e.message}")
|
|
29
|
+
throw IllegalAccessException("Could not setJSBundle")
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Reload the React Native application.
|
|
35
|
+
*/
|
|
36
|
+
public fun reload(application: ReactApplication) {
|
|
37
|
+
val reactHost = application.reactHost
|
|
38
|
+
check(reactHost != null)
|
|
39
|
+
|
|
40
|
+
val activity = reactHost.currentReactContext?.currentActivity
|
|
41
|
+
if (reactHost.lifecycleState != LifecycleState.RESUMED && activity != null) {
|
|
42
|
+
reactHost.onHostResume(activity)
|
|
43
|
+
}
|
|
44
|
+
reactHost.reload("Requested by HotUpdater")
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
package com.hotupdater
|
|
2
2
|
|
|
3
|
-
import com.facebook.react.bridge.
|
|
3
|
+
import com.facebook.react.bridge.Promise
|
|
4
4
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
5
5
|
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
6
6
|
|
|
7
|
-
abstract class HotUpdaterSpec internal constructor(
|
|
8
|
-
|
|
7
|
+
abstract class HotUpdaterSpec internal constructor(
|
|
8
|
+
context: ReactApplicationContext,
|
|
9
|
+
) : ReactContextBaseJavaModule(context) {
|
|
10
|
+
abstract fun updateBundle(
|
|
11
|
+
bundleId: String,
|
|
12
|
+
zipUrl: String,
|
|
13
|
+
promise: Promise,
|
|
14
|
+
)
|
|
9
15
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
abstract fun getAppVersion(callback: Callback)
|
|
14
|
-
abstract fun getBundleVersion(callback: Callback)
|
|
16
|
+
abstract fun reload()
|
|
17
|
+
|
|
18
|
+
abstract fun getAppVersion(promise: Promise)
|
|
15
19
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
package com.hotupdater
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import com.facebook.react.ReactApplication
|
|
6
|
+
import com.facebook.react.bridge.JSBundleLoader
|
|
7
|
+
import java.lang.reflect.Field
|
|
8
|
+
|
|
9
|
+
class ReactIntegrationManager(
|
|
10
|
+
context: Context,
|
|
11
|
+
) : ReactIntegrationManagerBase(context) {
|
|
12
|
+
public fun setJSBundle(
|
|
13
|
+
application: ReactApplication,
|
|
14
|
+
bundleURL: String,
|
|
15
|
+
) {
|
|
16
|
+
try {
|
|
17
|
+
val instanceManager = application.reactNativeHost.reactInstanceManager
|
|
18
|
+
val bundleLoader: JSBundleLoader? = this.getJSBundlerLoader(bundleURL)
|
|
19
|
+
val bundleLoaderField: Field =
|
|
20
|
+
instanceManager::class.java.getDeclaredField("mBundleLoader")
|
|
21
|
+
bundleLoaderField.isAccessible = true
|
|
22
|
+
|
|
23
|
+
if (bundleLoader != null) {
|
|
24
|
+
bundleLoaderField.set(instanceManager, bundleLoader)
|
|
25
|
+
} else {
|
|
26
|
+
bundleLoaderField.set(instanceManager, null)
|
|
27
|
+
}
|
|
28
|
+
} catch (e: Exception) {
|
|
29
|
+
Log.d("HotUpdater", "Failed to setJSBundle: ${e.message}")
|
|
30
|
+
throw IllegalAccessException("Could not setJSBundle")
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Reload the React Native application.
|
|
36
|
+
*/
|
|
37
|
+
public fun reload(application: ReactApplication) {
|
|
38
|
+
val reactNativeHost = application.reactNativeHost
|
|
39
|
+
reactNativeHost.reactInstanceManager.recreateReactContextInBackground()
|
|
40
|
+
}
|
|
41
|
+
}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import * as _hot_updater_core from '@hot-updater/core';
|
|
2
|
+
import { BundleArg } from '@hot-updater/core';
|
|
3
|
+
|
|
4
|
+
type HotUpdaterEvent = {
|
|
5
|
+
onProgress: {
|
|
6
|
+
progress: number;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
declare const addListener: <T extends keyof HotUpdaterEvent>(eventName: T, listener: (event: HotUpdaterEvent[T]) => void) => void;
|
|
10
|
+
/**
|
|
11
|
+
* Fetches the current bundle version id.
|
|
12
|
+
*
|
|
13
|
+
* @async
|
|
14
|
+
* @returns {Promise<string>} Resolves with the current version id or null if not available.
|
|
15
|
+
*/
|
|
16
|
+
declare const getBundleId: () => string;
|
|
17
|
+
/**
|
|
18
|
+
* Downloads files from given URLs.
|
|
19
|
+
*
|
|
20
|
+
* @param {string} bundleId - identifier for the bundle version.
|
|
21
|
+
* @param {string | null} zipUrl - zip file URL.
|
|
22
|
+
* @returns {Promise<boolean>} Resolves with true if download was successful, otherwise rejects with an error.
|
|
23
|
+
*/
|
|
24
|
+
declare const updateBundle: (bundleId: string, zipUrl: string | null) => Promise<boolean>;
|
|
25
|
+
/**
|
|
26
|
+
* Fetches the current app version.
|
|
27
|
+
*/
|
|
28
|
+
declare const getAppVersion: () => Promise<string | null>;
|
|
29
|
+
/**
|
|
30
|
+
* Reloads the app.
|
|
31
|
+
*/
|
|
32
|
+
declare const reload: () => void;
|
|
33
|
+
|
|
34
|
+
declare class HotUpdaterError extends Error {
|
|
35
|
+
constructor(message: string);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
type HotUpdaterStatus = "INSTALLING_UPDATE" | "UP_TO_DATE";
|
|
39
|
+
interface HotUpdaterInitConfig {
|
|
40
|
+
source: BundleArg;
|
|
41
|
+
onSuccess?: (status: HotUpdaterStatus) => void;
|
|
42
|
+
onError?: (error: HotUpdaterError) => void;
|
|
43
|
+
}
|
|
44
|
+
declare const init: (config: HotUpdaterInitConfig) => Promise<void>;
|
|
45
|
+
|
|
46
|
+
type HotUpdaterState = {
|
|
47
|
+
progress: number;
|
|
48
|
+
};
|
|
49
|
+
declare const hotUpdaterStore: {
|
|
50
|
+
getState: () => HotUpdaterState;
|
|
51
|
+
setState: (newState: Partial<HotUpdaterState>) => void;
|
|
52
|
+
subscribe: (listener: () => void) => () => boolean;
|
|
53
|
+
};
|
|
54
|
+
declare const useHotUpdaterStore: () => HotUpdaterState;
|
|
55
|
+
|
|
56
|
+
declare const HotUpdater: {
|
|
57
|
+
init: (config: HotUpdaterInitConfig) => Promise<void>;
|
|
58
|
+
reload: () => void;
|
|
59
|
+
getAppVersion: () => Promise<string | null>;
|
|
60
|
+
getBundleId: () => string;
|
|
61
|
+
addListener: <T extends keyof HotUpdaterEvent>(eventName: T, listener: (event: HotUpdaterEvent[T]) => void) => void;
|
|
62
|
+
ensureBundles: (bundle: _hot_updater_core.BundleArg) => Promise<_hot_updater_core.Bundle[]>;
|
|
63
|
+
updateBundle: (bundleId: string, zipUrl: string | null) => Promise<boolean>;
|
|
64
|
+
getUpdateInfo: (bundles: _hot_updater_core.Bundle[], { platform, bundleId, appVersion }: _hot_updater_core.GetBundlesArgs) => Promise<_hot_updater_core.UpdateInfo | null>;
|
|
65
|
+
/**
|
|
66
|
+
* In production environment, this value will be replaced with a uuidv7.
|
|
67
|
+
*/
|
|
68
|
+
HOT_UPDATER_BUNDLE_ID: string;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export { HotUpdater, type HotUpdaterEvent, type HotUpdaterInitConfig, type HotUpdaterState, type HotUpdaterStatus, addListener, getAppVersion, getBundleId, hotUpdaterStore, init, reload, updateBundle, useHotUpdaterStore };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,49 +1,27 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
type UpdateStatus = "ROLLBACK" | "UPDATE";
|
|
5
|
-
declare const checkForUpdate: (updateSources: UpdateSourceArg) => Promise<{
|
|
6
|
-
bundleVersion: number;
|
|
7
|
-
forceUpdate: boolean;
|
|
8
|
-
file: null;
|
|
9
|
-
hash: null;
|
|
10
|
-
status: UpdateStatus;
|
|
11
|
-
} | {
|
|
12
|
-
bundleVersion: number;
|
|
13
|
-
forceUpdate: boolean;
|
|
14
|
-
file: string;
|
|
15
|
-
hash: string;
|
|
16
|
-
status: UpdateStatus;
|
|
17
|
-
} | null>;
|
|
18
|
-
|
|
19
|
-
declare class HotUpdaterError extends Error {
|
|
20
|
-
constructor(message: string);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
type HotUpdaterStatus = "INSTALLING_UPDATE" | "UP_TO_DATE";
|
|
24
|
-
interface HotUpdaterInitConfig {
|
|
25
|
-
source: UpdateSourceArg;
|
|
26
|
-
onSuccess?: (status: HotUpdaterStatus) => void;
|
|
27
|
-
onError?: (error: HotUpdaterError) => void;
|
|
28
|
-
}
|
|
29
|
-
declare const init: (config: HotUpdaterInitConfig) => Promise<void>;
|
|
1
|
+
import * as _hot_updater_core from '@hot-updater/core';
|
|
2
|
+
import { BundleArg } from '@hot-updater/core';
|
|
30
3
|
|
|
4
|
+
type HotUpdaterEvent = {
|
|
5
|
+
onProgress: {
|
|
6
|
+
progress: number;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
declare const addListener: <T extends keyof HotUpdaterEvent>(eventName: T, listener: (event: HotUpdaterEvent[T]) => void) => void;
|
|
31
10
|
/**
|
|
32
11
|
* Fetches the current bundle version id.
|
|
33
12
|
*
|
|
34
13
|
* @async
|
|
35
|
-
* @returns {Promise<
|
|
14
|
+
* @returns {Promise<string>} Resolves with the current version id or null if not available.
|
|
36
15
|
*/
|
|
37
|
-
declare const
|
|
16
|
+
declare const getBundleId: () => string;
|
|
38
17
|
/**
|
|
39
18
|
* Downloads files from given URLs.
|
|
40
19
|
*
|
|
41
|
-
* @
|
|
42
|
-
* @param {string} bundleVersion - identifier for the bundle version.
|
|
20
|
+
* @param {string} bundleId - identifier for the bundle version.
|
|
43
21
|
* @param {string | null} zipUrl - zip file URL.
|
|
44
22
|
* @returns {Promise<boolean>} Resolves with true if download was successful, otherwise rejects with an error.
|
|
45
23
|
*/
|
|
46
|
-
declare const updateBundle: (
|
|
24
|
+
declare const updateBundle: (bundleId: string, zipUrl: string | null) => Promise<boolean>;
|
|
47
25
|
/**
|
|
48
26
|
* Fetches the current app version.
|
|
49
27
|
*/
|
|
@@ -52,29 +30,42 @@ declare const getAppVersion: () => Promise<string | null>;
|
|
|
52
30
|
* Reloads the app.
|
|
53
31
|
*/
|
|
54
32
|
declare const reload: () => void;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
33
|
+
|
|
34
|
+
declare class HotUpdaterError extends Error {
|
|
35
|
+
constructor(message: string);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
type HotUpdaterStatus = "INSTALLING_UPDATE" | "UP_TO_DATE";
|
|
39
|
+
interface HotUpdaterInitConfig {
|
|
40
|
+
source: BundleArg;
|
|
41
|
+
onSuccess?: (status: HotUpdaterStatus) => void;
|
|
42
|
+
onError?: (error: HotUpdaterError) => void;
|
|
43
|
+
}
|
|
44
|
+
declare const init: (config: HotUpdaterInitConfig) => Promise<void>;
|
|
45
|
+
|
|
46
|
+
type HotUpdaterState = {
|
|
47
|
+
progress: number;
|
|
48
|
+
};
|
|
49
|
+
declare const hotUpdaterStore: {
|
|
50
|
+
getState: () => HotUpdaterState;
|
|
51
|
+
setState: (newState: Partial<HotUpdaterState>) => void;
|
|
52
|
+
subscribe: (listener: () => void) => () => boolean;
|
|
53
|
+
};
|
|
54
|
+
declare const useHotUpdaterStore: () => HotUpdaterState;
|
|
59
55
|
|
|
60
56
|
declare const HotUpdater: {
|
|
61
57
|
init: (config: HotUpdaterInitConfig) => Promise<void>;
|
|
62
58
|
reload: () => void;
|
|
63
|
-
checkForUpdate: (updateSources: _hot_updater_utils.UpdateSourceArg) => Promise<{
|
|
64
|
-
bundleVersion: number;
|
|
65
|
-
forceUpdate: boolean;
|
|
66
|
-
file: null;
|
|
67
|
-
hash: null;
|
|
68
|
-
status: UpdateStatus;
|
|
69
|
-
} | {
|
|
70
|
-
bundleVersion: number;
|
|
71
|
-
forceUpdate: boolean;
|
|
72
|
-
file: string;
|
|
73
|
-
hash: string;
|
|
74
|
-
status: UpdateStatus;
|
|
75
|
-
} | null>;
|
|
76
59
|
getAppVersion: () => Promise<string | null>;
|
|
77
|
-
|
|
60
|
+
getBundleId: () => string;
|
|
61
|
+
addListener: <T extends keyof HotUpdaterEvent>(eventName: T, listener: (event: HotUpdaterEvent[T]) => void) => void;
|
|
62
|
+
ensureBundles: (bundle: _hot_updater_core.BundleArg) => Promise<_hot_updater_core.Bundle[]>;
|
|
63
|
+
updateBundle: (bundleId: string, zipUrl: string | null) => Promise<boolean>;
|
|
64
|
+
getUpdateInfo: (bundles: _hot_updater_core.Bundle[], { platform, bundleId, appVersion }: _hot_updater_core.GetBundlesArgs) => Promise<_hot_updater_core.UpdateInfo | null>;
|
|
65
|
+
/**
|
|
66
|
+
* In production environment, this value will be replaced with a uuidv7.
|
|
67
|
+
*/
|
|
68
|
+
HOT_UPDATER_BUNDLE_ID: string;
|
|
78
69
|
};
|
|
79
70
|
|
|
80
|
-
export { HotUpdater, type HotUpdaterInitConfig, type
|
|
71
|
+
export { HotUpdater, type HotUpdaterEvent, type HotUpdaterInitConfig, type HotUpdaterState, type HotUpdaterStatus, addListener, getAppVersion, getBundleId, hotUpdaterStore, init, reload, updateBundle, useHotUpdaterStore };
|