@hot-updater/react-native 0.16.6 → 0.16.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.
package/app.plugin.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require("./plugin/build/withHotUpdater");
package/dist/index.js CHANGED
@@ -104,7 +104,7 @@ var __webpack_exports__ = {};
104
104
  const NIL_UUID = "00000000-0000-0000-0000-000000000000";
105
105
  const HotUpdater = {
106
106
  HOT_UPDATER_BUNDLE_ID: __HOT_UPDATER_BUNDLE_ID || NIL_UUID,
107
- CHANNEL: __HOT_UPDATER_CHANNEL || "production"
107
+ CHANNEL: __HOT_UPDATER_CHANNEL || (__DEV__ ? null : "production")
108
108
  };
109
109
  const RCTNativeHotUpdater = __webpack_require__("./src/specs/NativeHotUpdater.ts").Z;
110
110
  const LINKING_ERROR = `The package '@hot-updater/react-native' doesn't seem to be linked. Make sure: \n\n` + external_react_native_.Platform.select({
package/dist/index.mjs CHANGED
@@ -79,7 +79,7 @@ const fetchUpdateInfo = async (source, { appVersion, bundleId, platform, minBund
79
79
  const NIL_UUID = "00000000-0000-0000-0000-000000000000";
80
80
  const HotUpdater = {
81
81
  HOT_UPDATER_BUNDLE_ID: __HOT_UPDATER_BUNDLE_ID || NIL_UUID,
82
- CHANNEL: __HOT_UPDATER_CHANNEL || "production"
82
+ CHANNEL: __HOT_UPDATER_CHANNEL || (__DEV__ ? null : "production")
83
83
  };
84
84
  const RCTNativeHotUpdater = __webpack_require__("./src/specs/NativeHotUpdater.ts").Z;
85
85
  const LINKING_ERROR = `The package '@hot-updater/react-native' doesn't seem to be linked. Make sure: \n\n` + external_react_native_.Platform.select({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hot-updater/react-native",
3
- "version": "0.16.6",
3
+ "version": "0.16.7-0",
4
4
  "description": "React Native OTA solution for self-hosted",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -14,6 +14,8 @@
14
14
  "ios",
15
15
  "cpp",
16
16
  "*.podspec",
17
+ "app.plugin.js",
18
+ "plugin/build/withHotUpdater.js",
17
19
  "react-native.config.js",
18
20
  "!ios/build",
19
21
  "!android/build",
@@ -66,9 +68,15 @@
66
68
  },
67
69
  "includesGeneratedCode": true
68
70
  },
71
+ "peerDependenciesMeta": {
72
+ "expo": {
73
+ "optional": true
74
+ }
75
+ },
69
76
  "peerDependencies": {
70
77
  "react": "*",
71
- "react-native": "*"
78
+ "react-native": "*",
79
+ "expo": ">=50.0.0"
72
80
  },
73
81
  "devDependencies": {
74
82
  "@react-native-community/cli": "15.0.1",
@@ -77,15 +85,17 @@
77
85
  "del-cli": "^6.0.0",
78
86
  "react": "18.3.1",
79
87
  "react-native": "0.76.2",
80
- "react-native-builder-bob": "^0.33.1"
88
+ "react-native-builder-bob": "^0.33.1",
89
+ "expo": "^50.0.0"
81
90
  },
82
91
  "dependencies": {
83
92
  "use-sync-external-store": "1.4.0",
84
- "@hot-updater/js": "0.16.6",
85
- "@hot-updater/core": "0.16.6"
93
+ "@hot-updater/js": "0.16.7-0",
94
+ "@hot-updater/core": "0.16.7-0"
86
95
  },
87
96
  "scripts": {
88
- "build": "rslib build",
97
+ "build": "rslib build && npm run build:plugin",
98
+ "build:plugin": "tsc -p plugin/tsconfig.json",
89
99
  "test:type": "tsc --noEmit",
90
100
  "test": "vitest",
91
101
  "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib"
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ var config_plugins_1 = require("expo/config-plugins");
7
+ var package_json_1 = __importDefault(require("../../package.json"));
8
+ /**
9
+ * Helper to add lines if they don't exist, anchored by a specific string.
10
+ */
11
+ function addLinesOnce(contents, anchor, linesToAdd) {
12
+ if (linesToAdd.every(function (line) { return contents.includes(line); })) {
13
+ // All lines already exist, do nothing
14
+ return contents;
15
+ }
16
+ // Check if the anchor exists
17
+ if (!contents.includes(anchor)) {
18
+ // Anchor not found, cannot add lines reliably.
19
+ // Consider logging a warning or throwing an error here if necessary.
20
+ return contents;
21
+ }
22
+ // Add lines after the anchor
23
+ // Ensure newline separation
24
+ return contents.replace(anchor, "".concat(anchor, "\n").concat(linesToAdd.join("\n")));
25
+ }
26
+ /**
27
+ * Helper to replace content only if the target content exists and hasn't been replaced yet.
28
+ */
29
+ function replaceContentOnce(contents, searchRegex, replacement, checkIfAlreadyReplaced) {
30
+ // If the replacement content is already present, assume it's done.
31
+ if (contents.includes(checkIfAlreadyReplaced)) {
32
+ return contents;
33
+ }
34
+ // Otherwise, perform the replacement if the search target exists.
35
+ return contents.replace(searchRegex, replacement);
36
+ }
37
+ var withHotUpdater = function (config) {
38
+ var modifiedConfig = config;
39
+ // === iOS: Objective-C & Swift in AppDelegate ===
40
+ modifiedConfig = (0, config_plugins_1.withAppDelegate)(modifiedConfig, function (cfg) {
41
+ var contents = cfg.modResults.contents;
42
+ var iosImport = "#import <HotUpdater/HotUpdater.h>";
43
+ var iosBundleUrl = "[HotUpdater bundleURL]";
44
+ var iosOriginalBundleUrlRegex = /\[\[NSBundle mainBundle\] URLForResource:@"main" withExtension:@"jsbundle"\]/g;
45
+ var iosAppDelegateHeader = '#import "AppDelegate.h"'; // Anchor for import
46
+ var swiftImport = "import HotUpdater";
47
+ var swiftBundleUrl = "HotUpdater.bundleURL()";
48
+ var swiftOriginalBundleUrlRegex = /Bundle\.main\.url\(forResource: "?main"?, withExtension: "jsbundle"\)/g;
49
+ var swiftReactImport = "import React"; // Anchor for import
50
+ // --- Objective-C ---
51
+ if (contents.includes(iosAppDelegateHeader)) {
52
+ // Check if it's likely Obj-C
53
+ // 1. Add import if missing
54
+ contents = addLinesOnce(contents, iosAppDelegateHeader, [iosImport]);
55
+ // 2. Replace bundleURL provider if the original exists and hasn't been replaced
56
+ contents = replaceContentOnce(contents, iosOriginalBundleUrlRegex, iosBundleUrl, iosBundleUrl);
57
+ }
58
+ // --- Swift ---
59
+ if (contents.includes(swiftReactImport)) {
60
+ // Check if it's likely Swift
61
+ // 1. Add import if missing
62
+ contents = addLinesOnce(contents, swiftReactImport, [swiftImport]);
63
+ // 2. Replace bundleURL provider if the original exists and hasn't been replaced
64
+ contents = replaceContentOnce(contents, swiftOriginalBundleUrlRegex, swiftBundleUrl, swiftBundleUrl);
65
+ }
66
+ cfg.modResults.contents = contents;
67
+ return cfg;
68
+ });
69
+ // === Android: Kotlin & Java in MainApplication ===
70
+ modifiedConfig = (0, config_plugins_1.withMainApplication)(modifiedConfig, function (cfg) {
71
+ var contents = cfg.modResults.contents;
72
+ var kotlinImport = "import com.hotupdater.HotUpdater";
73
+ var kotlinImportAnchor = "import com.facebook.react.ReactApplication";
74
+ var kotlinReactNativeHostAnchor = "object : DefaultReactNativeHost(this) {"; // Start of block
75
+ var kotlinMethodCheck = "HotUpdater.getJSBundleFile(applicationContext)"; // Unique part of the method body
76
+ // Regex to find an existing getJSBundleFile override (non-greedy)
77
+ var kotlinExistingMethodRegex = /^\s*override fun getJSBundleFile\(\): String\?\s*\{[\s\S]*?^\s*\}/gm;
78
+ var kotlinHermesAnchor = "override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED";
79
+ var kotlinNewMethod = "\n override fun getJSBundleFile(): String? {\n return HotUpdater.getJSBundleFile(applicationContext)\n }";
80
+ var javaImport = "import com.hotupdater.HotUpdater;";
81
+ var javaImportAnchor = "import com.facebook.react.ReactApplication;";
82
+ var javaReactNativeHostAnchor = "new DefaultReactNativeHost"; // Part of the instantiation
83
+ var javaMethodCheck = "HotUpdater.Companion.getJSBundleFile"; // Unique part of the method body
84
+ var javaMethodSignature = "protected String getJSBundleFile()";
85
+ // Regex to find an existing getJSBundleFile override (non-greedy)
86
+ var javaExistingMethodRegex = /^\s*@Override\s+protected String getJSBundleFile\(\)\s*\{[\s\S]*?^\s*\}/gm;
87
+ var javaHermesBlockEndAnchor = "return BuildConfig.IS_HERMES_ENABLED;\n }"; // End of the isHermesEnabled method block
88
+ var javaNewMethod = "\n @Override\n protected String getJSBundleFile() {\n return HotUpdater.Companion.getJSBundleFile(this.getApplication().getApplicationContext());\n }";
89
+ // --- Kotlin ---
90
+ if (contents.includes(kotlinReactNativeHostAnchor)) {
91
+ // Check if likely Kotlin
92
+ // 1. Add import if missing
93
+ contents = addLinesOnce(contents, kotlinImportAnchor, [kotlinImport]);
94
+ // 2. Add/Replace getJSBundleFile method if needed
95
+ if (!contents.includes(kotlinMethodCheck)) {
96
+ // Desired method content not found
97
+ // Remove potentially existing (different) override first
98
+ contents = contents.replace(kotlinExistingMethodRegex, "");
99
+ // Add the new method after the isHermesEnabled property
100
+ if (contents.includes(kotlinHermesAnchor)) {
101
+ contents = contents.replace(kotlinHermesAnchor, "".concat(kotlinHermesAnchor, "\n").concat(kotlinNewMethod));
102
+ }
103
+ else {
104
+ // Fallback: Add before the closing brace of the object if anchor not found
105
+ var rnHostEndRegex = /(\s*object\s*:\s*DefaultReactNativeHost\s*\([\s\S]*?\n)(\s*\})\s*$/m;
106
+ if (rnHostEndRegex.test(contents)) {
107
+ contents = contents.replace(rnHostEndRegex, "$1".concat(kotlinNewMethod, "\n$2"));
108
+ throw new Error("[withHotUpdater] Kotlin: Could not find Hermes anchor. Added getJSBundleFile before closing brace.");
109
+ }
110
+ throw new Error("[withHotUpdater] Kotlin: Could not find Hermes anchor or closing brace to insert getJSBundleFile.");
111
+ }
112
+ }
113
+ }
114
+ // --- Java ---
115
+ if (contents.includes(javaReactNativeHostAnchor) &&
116
+ contents.includes("@Override")) {
117
+ // Check if likely Java
118
+ // 1. Add import if missing
119
+ contents = addLinesOnce(contents, javaImportAnchor, [javaImport]);
120
+ // 2. Add/Replace getJSBundleFile method if needed
121
+ if (!contents.includes(javaMethodCheck)) {
122
+ // Desired method content not found
123
+ // Remove potentially existing (different) override first
124
+ contents = contents.replace(javaExistingMethodRegex, "");
125
+ // Add the new method after the isHermesEnabled method block
126
+ if (contents.includes(javaHermesBlockEndAnchor)) {
127
+ contents = contents.replace(javaHermesBlockEndAnchor, "".concat(javaHermesBlockEndAnchor, "\n").concat(javaNewMethod));
128
+ }
129
+ else {
130
+ // Fallback: Add before the closing brace of the anonymous class
131
+ var rnHostEndRegex = /(\s*new\s*DefaultReactNativeHost\s*\([\s\S]*?\n)(\s*\});\s*$/m;
132
+ if (rnHostEndRegex.test(contents)) {
133
+ contents = contents.replace(rnHostEndRegex, "$1".concat(javaNewMethod, "\n$2"));
134
+ throw new Error("[withHotUpdater] Java: Could not find Hermes anchor. Added getJSBundleFile before closing brace.");
135
+ }
136
+ throw new Error("[withHotUpdater] Java: Could not find Hermes anchor or closing brace to insert getJSBundleFile.");
137
+ }
138
+ }
139
+ }
140
+ cfg.modResults.contents = contents;
141
+ return cfg;
142
+ });
143
+ return modifiedConfig;
144
+ };
145
+ // Export the plugin using createRunOncePlugin for idempotency at the plugin level
146
+ exports.default = (0, config_plugins_1.createRunOncePlugin)(withHotUpdater, package_json_1.default.name, package_json_1.default.version);
package/src/native.ts CHANGED
@@ -7,7 +7,7 @@ declare const __HOT_UPDATER_CHANNEL: string | undefined;
7
7
 
8
8
  const HotUpdater = {
9
9
  HOT_UPDATER_BUNDLE_ID: __HOT_UPDATER_BUNDLE_ID || NIL_UUID,
10
- CHANNEL: __HOT_UPDATER_CHANNEL || "production",
10
+ CHANNEL: __HOT_UPDATER_CHANNEL || (!__DEV__ ? "production" : null),
11
11
  };
12
12
 
13
13
  const RCTNativeHotUpdater = require("./specs/NativeHotUpdater").default;