@hot-updater/react-native 0.6.5 → 0.6.7

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/dist/index.d.ts CHANGED
@@ -10,6 +10,38 @@ export declare const HotUpdater: {
10
10
  getBundleId: () => string;
11
11
  addListener: <T extends keyof import("./native").HotUpdaterEvent>(eventName: T, listener: (event: import("./native").HotUpdaterEvent[T]) => void) => () => void;
12
12
  checkForUpdate: typeof checkForUpdate;
13
+ /**
14
+ * Manually checks and applies updates for the application.
15
+ *
16
+ * @param {RunUpdateProcessConfig} config - Update process configuration
17
+ * @param {string} config.source - Update server URL
18
+ * @param {Record<string, string>} [config.requestHeaders] - Request headers
19
+ * @param {boolean} [config.reloadOnForceUpdate=false] - Whether to automatically reload on force update
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * // Auto reload on force update
24
+ * const result = await HotUpdater.runUpdateProcess({
25
+ * source: "<your-update-server-url>",
26
+ * requestHeaders: {
27
+ * // Add necessary headers
28
+ * },
29
+ * reloadOnForceUpdate: true
30
+ * });
31
+ *
32
+ * // Manually handle reload on force update
33
+ * const result = await HotUpdater.runUpdateProcess({
34
+ * source: "<your-update-server-url>",
35
+ * reloadOnForceUpdate: false
36
+ * });
37
+ *
38
+ * if(result.status !== "UP_TO_DATE" && result.shouldForceUpdate) {
39
+ * HotUpdater.reload();
40
+ * }
41
+ * ```
42
+ *
43
+ * @returns {Promise<RunUpdateProcessResponse>} The result of the update process
44
+ */
13
45
  runUpdateProcess: ({ reloadOnForceUpdate, ...checkForUpdateConfig }: import("./runUpdateProcess").RunUpdateProcessConfig) => Promise<import("./runUpdateProcess").RunUpdateProcessResponse>;
14
46
  updateBundle: (bundleId: string, zipUrl: string | null) => Promise<boolean>;
15
47
  };
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,8 +10,40 @@ 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
  }
17
+ /**
18
+ * Manually checks and applies updates for the application.
19
+ *
20
+ * @param {RunUpdateProcessConfig} config - Update process configuration
21
+ * @param {string} config.source - Update server URL
22
+ * @param {Record<string, string>} [config.requestHeaders] - Request headers
23
+ * @param {boolean} [config.reloadOnForceUpdate=true] - Whether to automatically reload on force update
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * // Auto reload on force update
28
+ * const result = await HotUpdater.runUpdateProcess({
29
+ * source: "<your-update-server-url>",
30
+ * requestHeaders: {
31
+ * // Add necessary headers
32
+ * },
33
+ * reloadOnForceUpdate: true
34
+ * });
35
+ *
36
+ * // Manually handle reload on force update
37
+ * const result = await HotUpdater.runUpdateProcess({
38
+ * source: "<your-update-server-url>",
39
+ * reloadOnForceUpdate: false
40
+ * });
41
+ *
42
+ * if(result.status !== "UP_TO_DATE" && result.shouldForceUpdate) {
43
+ * HotUpdater.reload();
44
+ * }
45
+ * ```
46
+ *
47
+ * @returns {Promise<RunUpdateProcessResponse>} The result of the update process
48
+ */
17
49
  export declare const runUpdateProcess: ({ reloadOnForceUpdate, ...checkForUpdateConfig }: RunUpdateProcessConfig) => Promise<RunUpdateProcessResponse>;
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.5",
3
+ "version": "0.6.7",
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.5",
82
- "@hot-updater/core": "0.6.5"
81
+ "@hot-updater/js": "0.6.7",
82
+ "@hot-updater/core": "0.6.7"
83
83
  },
84
84
  "scripts": {
85
85
  "build": "rslib build",
package/src/index.ts CHANGED
@@ -28,6 +28,38 @@ export const HotUpdater = {
28
28
  addListener,
29
29
 
30
30
  checkForUpdate,
31
+ /**
32
+ * Manually checks and applies updates for the application.
33
+ *
34
+ * @param {RunUpdateProcessConfig} config - Update process configuration
35
+ * @param {string} config.source - Update server URL
36
+ * @param {Record<string, string>} [config.requestHeaders] - Request headers
37
+ * @param {boolean} [config.reloadOnForceUpdate=false] - Whether to automatically reload on force update
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * // Auto reload on force update
42
+ * const result = await HotUpdater.runUpdateProcess({
43
+ * source: "<your-update-server-url>",
44
+ * requestHeaders: {
45
+ * // Add necessary headers
46
+ * },
47
+ * reloadOnForceUpdate: true
48
+ * });
49
+ *
50
+ * // Manually handle reload on force update
51
+ * const result = await HotUpdater.runUpdateProcess({
52
+ * source: "<your-update-server-url>",
53
+ * reloadOnForceUpdate: false
54
+ * });
55
+ *
56
+ * if(result.status !== "UP_TO_DATE" && result.shouldForceUpdate) {
57
+ * HotUpdater.reload();
58
+ * }
59
+ * ```
60
+ *
61
+ * @returns {Promise<RunUpdateProcessResponse>} The result of the update process
62
+ */
31
63
  runUpdateProcess,
32
64
  updateBundle,
33
65
  };
@@ -15,13 +15,45 @@ 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
  }
22
22
 
23
+ /**
24
+ * Manually checks and applies updates for the application.
25
+ *
26
+ * @param {RunUpdateProcessConfig} config - Update process configuration
27
+ * @param {string} config.source - Update server URL
28
+ * @param {Record<string, string>} [config.requestHeaders] - Request headers
29
+ * @param {boolean} [config.reloadOnForceUpdate=true] - Whether to automatically reload on force update
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * // Auto reload on force update
34
+ * const result = await HotUpdater.runUpdateProcess({
35
+ * source: "<your-update-server-url>",
36
+ * requestHeaders: {
37
+ * // Add necessary headers
38
+ * },
39
+ * reloadOnForceUpdate: true
40
+ * });
41
+ *
42
+ * // Manually handle reload on force update
43
+ * const result = await HotUpdater.runUpdateProcess({
44
+ * source: "<your-update-server-url>",
45
+ * reloadOnForceUpdate: false
46
+ * });
47
+ *
48
+ * if(result.status !== "UP_TO_DATE" && result.shouldForceUpdate) {
49
+ * HotUpdater.reload();
50
+ * }
51
+ * ```
52
+ *
53
+ * @returns {Promise<RunUpdateProcessResponse>} The result of the update process
54
+ */
23
55
  export const runUpdateProcess = async ({
24
- reloadOnForceUpdate = false,
56
+ reloadOnForceUpdate = true,
25
57
  ...checkForUpdateConfig
26
58
  }: RunUpdateProcessConfig): Promise<RunUpdateProcessResponse> => {
27
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 />;