@hot-updater/react-native 0.6.6 → 0.7.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.
@@ -59,6 +59,11 @@ class HotUpdater : ReactPackage {
59
59
  putString("HotUpdaterBundleURL", bundleURL)
60
60
  apply()
61
61
  }
62
+
63
+ if (bundleURL == null) {
64
+ return
65
+ }
66
+
62
67
  val reactIntegrationManager = ReactIntegrationManager(context)
63
68
 
64
69
  val activity: Activity? = getCurrentActivity(context)
@@ -133,11 +138,11 @@ class HotUpdater : ReactPackage {
133
138
  fun updateBundle(
134
139
  context: Context,
135
140
  bundleId: String,
136
- zipUrl: String,
141
+ zipUrl: String?,
137
142
  progressCallback: ((Double) -> Unit),
138
143
  ): Boolean {
139
144
  Log.d("HotUpdater", "updateBundle bundleId $bundleId zipUrl $zipUrl")
140
- if (zipUrl.isEmpty()) {
145
+ if (zipUrl.isNullOrEmpty()) {
141
146
  setBundleURL(context, null)
142
147
  return true
143
148
  }
@@ -26,7 +26,7 @@ class HotUpdaterModule internal constructor(
26
26
  @ReactMethod
27
27
  override fun updateBundle(
28
28
  bundleId: String,
29
- zipUrl: String,
29
+ zipUrl: String?,
30
30
  promise: Promise,
31
31
  ) {
32
32
  val isSuccess =
@@ -26,7 +26,7 @@ class HotUpdaterModule internal constructor(
26
26
  @ReactMethod
27
27
  override fun updateBundle(
28
28
  bundleId: String,
29
- zipUrl: String,
29
+ zipUrl: String?,
30
30
  promise: Promise,
31
31
  ) {
32
32
  val isSuccess =
@@ -9,7 +9,7 @@ abstract class HotUpdaterSpec internal constructor(
9
9
  ) : ReactContextBaseJavaModule(context) {
10
10
  abstract fun updateBundle(
11
11
  bundleId: String,
12
- zipUrl: String,
12
+ zipUrl: String?,
13
13
  promise: Promise,
14
14
  )
15
15
 
package/dist/index.js CHANGED
@@ -1721,7 +1721,7 @@ var __webpack_exports__ = {};
1721
1721
  } else updateInfo = ensuredUpdateInfo;
1722
1722
  return updateInfo;
1723
1723
  }
1724
- const runUpdateProcess = async ({ reloadOnForceUpdate = false, ...checkForUpdateConfig })=>{
1724
+ const runUpdateProcess = async ({ reloadOnForceUpdate = true, ...checkForUpdateConfig })=>{
1725
1725
  const updateInfo = await checkForUpdate(checkForUpdateConfig);
1726
1726
  if (!updateInfo) return {
1727
1727
  status: "UP_TO_DATE"
@@ -1783,10 +1783,10 @@ var __webpack_exports__ = {};
1783
1783
  return (WrappedComponent)=>{
1784
1784
  const HotUpdaterHOC = ()=>{
1785
1785
  const { progress } = useHotUpdaterStore();
1786
- const [status, setStatus] = (0, react.useState)("IDLE");
1786
+ const [updateStatus, setUpdateStatus] = (0, react.useState)("CHECK_FOR_UPDATE");
1787
1787
  const initHotUpdater = useEventCallback(async ()=>{
1788
1788
  try {
1789
- setStatus("CHECK_FOR_UPDATE");
1789
+ setUpdateStatus("CHECK_FOR_UPDATE");
1790
1790
  const updateInfo = await checkForUpdate({
1791
1791
  source: restConfig.source,
1792
1792
  requestHeaders: restConfig.requestHeaders
@@ -1795,22 +1795,32 @@ var __webpack_exports__ = {};
1795
1795
  restConfig.onUpdateProcessCompleted?.({
1796
1796
  status: "UP_TO_DATE"
1797
1797
  });
1798
- setStatus("UPDATE_PROCESS_COMPLETED");
1798
+ setUpdateStatus("UPDATE_PROCESS_COMPLETED");
1799
1799
  return;
1800
1800
  }
1801
- setStatus("UPDATING");
1801
+ if (false === updateInfo.shouldForceUpdate) {
1802
+ updateBundle(updateInfo.id, updateInfo.fileUrl);
1803
+ restConfig.onUpdateProcessCompleted?.({
1804
+ id: updateInfo.id,
1805
+ status: updateInfo.status,
1806
+ shouldForceUpdate: updateInfo.shouldForceUpdate
1807
+ });
1808
+ setUpdateStatus("UPDATE_PROCESS_COMPLETED");
1809
+ return;
1810
+ }
1811
+ setUpdateStatus("UPDATING");
1802
1812
  const isSuccess = await updateBundle(updateInfo.id, updateInfo.fileUrl);
1803
1813
  if (!isSuccess) throw new Error("New update was found but failed to download the bundle.");
1804
- if (updateInfo.shouldForceUpdate && reloadOnForceUpdate) reload();
1814
+ if (reloadOnForceUpdate) reload();
1805
1815
  restConfig.onUpdateProcessCompleted?.({
1806
1816
  id: updateInfo.id,
1807
1817
  status: updateInfo.status,
1808
1818
  shouldForceUpdate: updateInfo.shouldForceUpdate
1809
1819
  });
1810
- setStatus("UPDATE_PROCESS_COMPLETED");
1820
+ setUpdateStatus("UPDATE_PROCESS_COMPLETED");
1811
1821
  } catch (error) {
1812
1822
  if (error instanceof HotUpdaterError) restConfig.onError?.(error);
1813
- setStatus("UPDATE_PROCESS_COMPLETED");
1823
+ setUpdateStatus("UPDATE_PROCESS_COMPLETED");
1814
1824
  throw error;
1815
1825
  }
1816
1826
  });
@@ -1822,10 +1832,11 @@ var __webpack_exports__ = {};
1822
1832
  (0, react.useLayoutEffect)(()=>{
1823
1833
  initHotUpdater();
1824
1834
  }, []);
1825
- if (restConfig.fallbackComponent && "UPDATE_PROCESS_COMPLETED" !== status) {
1835
+ if (restConfig.fallbackComponent && "UPDATE_PROCESS_COMPLETED" !== updateStatus) {
1826
1836
  const Fallback = restConfig.fallbackComponent;
1827
1837
  return /*#__PURE__*/ React.createElement(Fallback, {
1828
- progress: progress
1838
+ progress: progress,
1839
+ status: updateStatus
1829
1840
  });
1830
1841
  }
1831
1842
  return /*#__PURE__*/ React.createElement(WrappedComponent, null);
package/dist/index.mjs CHANGED
@@ -1690,7 +1690,7 @@ async function checkForUpdate(config) {
1690
1690
  } else updateInfo = ensuredUpdateInfo;
1691
1691
  return updateInfo;
1692
1692
  }
1693
- const runUpdateProcess = async ({ reloadOnForceUpdate = false, ...checkForUpdateConfig })=>{
1693
+ const runUpdateProcess = async ({ reloadOnForceUpdate = true, ...checkForUpdateConfig })=>{
1694
1694
  const updateInfo = await checkForUpdate(checkForUpdateConfig);
1695
1695
  if (!updateInfo) return {
1696
1696
  status: "UP_TO_DATE"
@@ -1752,10 +1752,10 @@ function wrap(config) {
1752
1752
  return (WrappedComponent)=>{
1753
1753
  const HotUpdaterHOC = ()=>{
1754
1754
  const { progress } = useHotUpdaterStore();
1755
- const [status, setStatus] = (0, react.useState)("IDLE");
1755
+ const [updateStatus, setUpdateStatus] = (0, react.useState)("CHECK_FOR_UPDATE");
1756
1756
  const initHotUpdater = useEventCallback(async ()=>{
1757
1757
  try {
1758
- setStatus("CHECK_FOR_UPDATE");
1758
+ setUpdateStatus("CHECK_FOR_UPDATE");
1759
1759
  const updateInfo = await checkForUpdate({
1760
1760
  source: restConfig.source,
1761
1761
  requestHeaders: restConfig.requestHeaders
@@ -1764,22 +1764,32 @@ function wrap(config) {
1764
1764
  restConfig.onUpdateProcessCompleted?.({
1765
1765
  status: "UP_TO_DATE"
1766
1766
  });
1767
- setStatus("UPDATE_PROCESS_COMPLETED");
1767
+ setUpdateStatus("UPDATE_PROCESS_COMPLETED");
1768
1768
  return;
1769
1769
  }
1770
- setStatus("UPDATING");
1770
+ if (false === updateInfo.shouldForceUpdate) {
1771
+ updateBundle(updateInfo.id, updateInfo.fileUrl);
1772
+ restConfig.onUpdateProcessCompleted?.({
1773
+ id: updateInfo.id,
1774
+ status: updateInfo.status,
1775
+ shouldForceUpdate: updateInfo.shouldForceUpdate
1776
+ });
1777
+ setUpdateStatus("UPDATE_PROCESS_COMPLETED");
1778
+ return;
1779
+ }
1780
+ setUpdateStatus("UPDATING");
1771
1781
  const isSuccess = await updateBundle(updateInfo.id, updateInfo.fileUrl);
1772
1782
  if (!isSuccess) throw new Error("New update was found but failed to download the bundle.");
1773
- if (updateInfo.shouldForceUpdate && reloadOnForceUpdate) reload();
1783
+ if (reloadOnForceUpdate) reload();
1774
1784
  restConfig.onUpdateProcessCompleted?.({
1775
1785
  id: updateInfo.id,
1776
1786
  status: updateInfo.status,
1777
1787
  shouldForceUpdate: updateInfo.shouldForceUpdate
1778
1788
  });
1779
- setStatus("UPDATE_PROCESS_COMPLETED");
1789
+ setUpdateStatus("UPDATE_PROCESS_COMPLETED");
1780
1790
  } catch (error) {
1781
1791
  if (error instanceof HotUpdaterError) restConfig.onError?.(error);
1782
- setStatus("UPDATE_PROCESS_COMPLETED");
1792
+ setUpdateStatus("UPDATE_PROCESS_COMPLETED");
1783
1793
  throw error;
1784
1794
  }
1785
1795
  });
@@ -1791,10 +1801,11 @@ function wrap(config) {
1791
1801
  (0, react.useLayoutEffect)(()=>{
1792
1802
  initHotUpdater();
1793
1803
  }, []);
1794
- if (restConfig.fallbackComponent && "UPDATE_PROCESS_COMPLETED" !== status) {
1804
+ if (restConfig.fallbackComponent && "UPDATE_PROCESS_COMPLETED" !== updateStatus) {
1795
1805
  const Fallback = restConfig.fallbackComponent;
1796
1806
  return /*#__PURE__*/ React.createElement(Fallback, {
1797
- progress: progress
1807
+ progress: progress,
1808
+ status: updateStatus
1798
1809
  });
1799
1810
  }
1800
1811
  return /*#__PURE__*/ React.createElement(WrappedComponent, null);
@@ -10,7 +10,7 @@ export interface RunUpdateProcessConfig extends CheckForUpdateConfig {
10
10
  /**
11
11
  * If `true`, the app will be reloaded when the downloaded bundle is a force update.
12
12
  * If `false`, shouldForceUpdate will be returned as true but the app won't reload.
13
- * @default false
13
+ * @default true
14
14
  */
15
15
  reloadOnForceUpdate?: boolean;
16
16
  }
@@ -20,7 +20,7 @@ export interface RunUpdateProcessConfig extends CheckForUpdateConfig {
20
20
  * @param {RunUpdateProcessConfig} config - Update process configuration
21
21
  * @param {string} config.source - Update server URL
22
22
  * @param {Record<string, string>} [config.requestHeaders] - Request headers
23
- * @param {boolean} [config.reloadOnForceUpdate=false] - Whether to automatically reload on force update
23
+ * @param {boolean} [config.reloadOnForceUpdate=true] - Whether to automatically reload on force update
24
24
  *
25
25
  * @example
26
26
  * ```ts
package/dist/wrap.d.ts CHANGED
@@ -2,7 +2,7 @@ import type React from "react";
2
2
  import { type CheckForUpdateConfig } from "./checkUpdate";
3
3
  import { HotUpdaterError } from "./error";
4
4
  import type { RunUpdateProcessResponse } from "./runUpdateProcess";
5
- import { type HotUpdaterState } from "./store";
5
+ type UpdateStatus = "CHECK_FOR_UPDATE" | "UPDATING" | "UPDATE_PROCESS_COMPLETED";
6
6
  export interface HotUpdaterConfig extends CheckForUpdateConfig {
7
7
  /**
8
8
  * Component to show while downloading a new bundle update.
@@ -25,7 +25,10 @@ export interface HotUpdaterConfig extends CheckForUpdateConfig {
25
25
  *
26
26
  * If not defined, the bundle will download in the background without blocking the screen.
27
27
  */
28
- fallbackComponent?: React.FC<Pick<HotUpdaterState, "progress">>;
28
+ fallbackComponent?: React.FC<{
29
+ status: Exclude<UpdateStatus, "UPDATE_PROCESS_COMPLETED">;
30
+ progress: number;
31
+ }>;
29
32
  onError?: (error: HotUpdaterError) => void;
30
33
  onProgress?: (progress: number) => void;
31
34
  /**
@@ -43,3 +46,4 @@ export interface HotUpdaterConfig extends CheckForUpdateConfig {
43
46
  onUpdateProcessCompleted?: (response: RunUpdateProcessResponse) => void;
44
47
  }
45
48
  export declare function wrap<P>(config: HotUpdaterConfig): (WrappedComponent: React.ComponentType) => React.ComponentType<P>;
49
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hot-updater/react-native",
3
- "version": "0.6.6",
3
+ "version": "0.7.0",
4
4
  "description": "React Native OTA solution for self-hosted",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -78,8 +78,8 @@
78
78
  "react-native-builder-bob": "^0.33.1"
79
79
  },
80
80
  "dependencies": {
81
- "@hot-updater/js": "0.6.6",
82
- "@hot-updater/core": "0.6.6"
81
+ "@hot-updater/js": "0.7.0",
82
+ "@hot-updater/core": "0.7.0"
83
83
  },
84
84
  "scripts": {
85
85
  "build": "rslib build",
@@ -15,7 +15,7 @@ export interface RunUpdateProcessConfig extends CheckForUpdateConfig {
15
15
  /**
16
16
  * If `true`, the app will be reloaded when the downloaded bundle is a force update.
17
17
  * If `false`, shouldForceUpdate will be returned as true but the app won't reload.
18
- * @default false
18
+ * @default true
19
19
  */
20
20
  reloadOnForceUpdate?: boolean;
21
21
  }
@@ -26,7 +26,7 @@ export interface RunUpdateProcessConfig extends CheckForUpdateConfig {
26
26
  * @param {RunUpdateProcessConfig} config - Update process configuration
27
27
  * @param {string} config.source - Update server URL
28
28
  * @param {Record<string, string>} [config.requestHeaders] - Request headers
29
- * @param {boolean} [config.reloadOnForceUpdate=false] - Whether to automatically reload on force update
29
+ * @param {boolean} [config.reloadOnForceUpdate=true] - Whether to automatically reload on force update
30
30
  *
31
31
  * @example
32
32
  * ```ts
@@ -53,7 +53,7 @@ export interface RunUpdateProcessConfig extends CheckForUpdateConfig {
53
53
  * @returns {Promise<RunUpdateProcessResponse>} The result of the update process
54
54
  */
55
55
  export const runUpdateProcess = async ({
56
- reloadOnForceUpdate = false,
56
+ reloadOnForceUpdate = true,
57
57
  ...checkForUpdateConfig
58
58
  }: RunUpdateProcessConfig): Promise<RunUpdateProcessResponse> => {
59
59
  const updateInfo = await checkForUpdate(checkForUpdateConfig);
package/src/wrap.tsx CHANGED
@@ -5,7 +5,12 @@ import { HotUpdaterError } from "./error";
5
5
  import { useEventCallback } from "./hooks/useEventCallback";
6
6
  import { reload, updateBundle } from "./native";
7
7
  import type { RunUpdateProcessResponse } from "./runUpdateProcess";
8
- import { type HotUpdaterState, useHotUpdaterStore } from "./store";
8
+ import { useHotUpdaterStore } from "./store";
9
+
10
+ type UpdateStatus =
11
+ | "CHECK_FOR_UPDATE"
12
+ | "UPDATING"
13
+ | "UPDATE_PROCESS_COMPLETED";
9
14
 
10
15
  export interface HotUpdaterConfig extends CheckForUpdateConfig {
11
16
  /**
@@ -29,7 +34,10 @@ export interface HotUpdaterConfig extends CheckForUpdateConfig {
29
34
  *
30
35
  * If not defined, the bundle will download in the background without blocking the screen.
31
36
  */
32
- fallbackComponent?: React.FC<Pick<HotUpdaterState, "progress">>;
37
+ fallbackComponent?: React.FC<{
38
+ status: Exclude<UpdateStatus, "UPDATE_PROCESS_COMPLETED">;
39
+ progress: number;
40
+ }>;
33
41
  onError?: (error: HotUpdaterError) => void;
34
42
  onProgress?: (progress: number) => void;
35
43
  /**
@@ -54,13 +62,12 @@ export function wrap<P>(
54
62
  return (WrappedComponent) => {
55
63
  const HotUpdaterHOC: React.FC<P> = () => {
56
64
  const { progress } = useHotUpdaterStore();
57
- const [status, setStatus] = useState<
58
- "IDLE" | "CHECK_FOR_UPDATE" | "UPDATING" | "UPDATE_PROCESS_COMPLETED"
59
- >("IDLE");
65
+ const [updateStatus, setUpdateStatus] =
66
+ useState<UpdateStatus>("CHECK_FOR_UPDATE");
60
67
 
61
68
  const initHotUpdater = useEventCallback(async () => {
62
69
  try {
63
- setStatus("CHECK_FOR_UPDATE");
70
+ setUpdateStatus("CHECK_FOR_UPDATE");
64
71
  const updateInfo = await checkForUpdate({
65
72
  source: restConfig.source,
66
73
  requestHeaders: restConfig.requestHeaders,
@@ -69,12 +76,23 @@ export function wrap<P>(
69
76
  restConfig.onUpdateProcessCompleted?.({
70
77
  status: "UP_TO_DATE",
71
78
  });
72
- setStatus("UPDATE_PROCESS_COMPLETED");
79
+ setUpdateStatus("UPDATE_PROCESS_COMPLETED");
73
80
  return;
74
81
  }
75
82
 
76
- setStatus("UPDATING");
83
+ if (updateInfo.shouldForceUpdate === false) {
84
+ void updateBundle(updateInfo.id, updateInfo.fileUrl);
85
+ restConfig.onUpdateProcessCompleted?.({
86
+ id: updateInfo.id,
87
+ status: updateInfo.status,
88
+ shouldForceUpdate: updateInfo.shouldForceUpdate,
89
+ });
90
+ setUpdateStatus("UPDATE_PROCESS_COMPLETED");
91
+ return;
92
+ }
77
93
 
94
+ // Force Update Scenario
95
+ setUpdateStatus("UPDATING");
78
96
  const isSuccess = await updateBundle(
79
97
  updateInfo.id,
80
98
  updateInfo.fileUrl,
@@ -85,7 +103,7 @@ export function wrap<P>(
85
103
  );
86
104
  }
87
105
 
88
- if (updateInfo.shouldForceUpdate && reloadOnForceUpdate) {
106
+ if (reloadOnForceUpdate) {
89
107
  reload();
90
108
  }
91
109
 
@@ -94,12 +112,12 @@ export function wrap<P>(
94
112
  status: updateInfo.status,
95
113
  shouldForceUpdate: updateInfo.shouldForceUpdate,
96
114
  });
97
- setStatus("UPDATE_PROCESS_COMPLETED");
115
+ setUpdateStatus("UPDATE_PROCESS_COMPLETED");
98
116
  } catch (error) {
99
117
  if (error instanceof HotUpdaterError) {
100
118
  restConfig.onError?.(error);
101
119
  }
102
- setStatus("UPDATE_PROCESS_COMPLETED");
120
+ setUpdateStatus("UPDATE_PROCESS_COMPLETED");
103
121
  throw error;
104
122
  }
105
123
  });
@@ -114,10 +132,10 @@ export function wrap<P>(
114
132
 
115
133
  if (
116
134
  restConfig.fallbackComponent &&
117
- status !== "UPDATE_PROCESS_COMPLETED"
135
+ updateStatus !== "UPDATE_PROCESS_COMPLETED"
118
136
  ) {
119
137
  const Fallback = restConfig.fallbackComponent;
120
- return <Fallback progress={progress} />;
138
+ return <Fallback progress={progress} status={updateStatus} />;
121
139
  }
122
140
 
123
141
  return <WrappedComponent />;