pulse-updates 1.0.18 → 1.0.19

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pulse-updates",
3
- "version": "1.0.18",
3
+ "version": "1.0.19",
4
4
  "description": "OTA updates for React Native - lightweight alternative to expo-updates",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -646,6 +646,43 @@ function detectRuntimeVersion(platform) {
646
646
  return null;
647
647
  }
648
648
 
649
+ /**
650
+ * Detect whether the app is configured to run on Hermes, from its native build
651
+ * config. Used to auto-resolve requireHermes when it isn't explicitly set: a Hermes
652
+ * app should never receive a plain-JS OTA, so detection turns enforcement on for it
653
+ * without the developer having to declare the flag. Returns true / false / null
654
+ * (null = couldn't determine → caller stays best-effort).
655
+ */
656
+ function detectHermesEnabled(platform) {
657
+ try {
658
+ if (platform === 'android') {
659
+ const gp = path.resolve('android/gradle.properties');
660
+ if (fs.existsSync(gp)) {
661
+ const m = fs.readFileSync(gp, 'utf8').match(/^\s*hermesEnabled\s*=\s*(\S+)/m);
662
+ if (m) return /^true$/i.test(m[1].trim());
663
+ }
664
+ } else if (platform === 'ios') {
665
+ const podfile = path.resolve('ios/Podfile');
666
+ if (fs.existsSync(podfile)) {
667
+ const txt = fs.readFileSync(podfile, 'utf8');
668
+ // ENV['USE_HERMES'] = '1' / USE_HERMES => true, or :hermes_enabled => true
669
+ const useHermes = txt.match(/USE_HERMES['"\]\s]*[=>]+\s*['"]?(\w+)/);
670
+ if (useHermes) return /^(1|true|yes)$/i.test(useHermes[1]);
671
+ const flag = txt.match(/:hermes_enabled\s*=>\s*(\w+)/);
672
+ if (flag) return /^true$/i.test(flag[1]);
673
+ }
674
+ // Fallback: the Pods lockfile lists hermes-engine when Hermes is on.
675
+ const lock = path.resolve('ios/Podfile.lock');
676
+ if (fs.existsSync(lock)) {
677
+ return /hermes-engine/.test(fs.readFileSync(lock, 'utf8'));
678
+ }
679
+ }
680
+ } catch {
681
+ /* detection is best-effort */
682
+ }
683
+ return null; // unknown
684
+ }
685
+
649
686
  /**
650
687
  * Extract base API URL from full manifest URL
651
688
  * e.g., "https://pulse.example.com/pulse/manifest/my-app" -> "https://pulse.example.com"
@@ -728,6 +765,27 @@ function loadConfig(options) {
728
765
  }
729
766
  }
730
767
 
768
+ // Resolve Hermes enforcement (tri-state): explicit true/false wins; when left
769
+ // unset, auto-detect from the app's native config — a Hermes app is enforced,
770
+ // anything else stays best-effort.
771
+ let requireHermes =
772
+ options['require-hermes'] ? true
773
+ : options['no-require-hermes'] ? false
774
+ : process.env.PULSE_REQUIRE_HERMES != null ? (process.env.PULSE_REQUIRE_HERMES === '1')
775
+ : fileConfig.requireHermes; // true | false | undefined
776
+ if (requireHermes === undefined) {
777
+ const detected = platform ? detectHermesEnabled(platform) : null;
778
+ requireHermes = detected === true;
779
+ log(
780
+ ` Auto-detected Hermes enforcement: ${
781
+ detected === true ? 'ON (app uses Hermes)'
782
+ : detected === false ? 'OFF (app not on Hermes)'
783
+ : 'OFF (could not determine — best-effort)'
784
+ }`,
785
+ colors.dim
786
+ );
787
+ }
788
+
731
789
  return {
732
790
  apiUrl,
733
791
  apiKey: options['api-key'] || process.env.PULSE_API_KEY || fileConfig.apiKey,
@@ -739,12 +797,12 @@ function loadConfig(options) {
739
797
  skipBundle: options['skip-bundle'] || false,
740
798
  build: options.build || process.env.PULSE_BUILD || fileConfig.build || null,
741
799
  message: options.message || fileConfig.message || null,
742
- // Opt-in: the app runs on Hermes, so a plain-JS OTA must never be shipped.
743
- // Makes a missing/failing hermesc fatal (with a one-shot pod-install attempt on
744
- // macOS), enables -fstrip-function-names, and asserts bytecode output.
745
- // Leave unset for apps that intentionally run plain JS (best-effort default).
746
- requireHermes: options['require-hermes'] || process.env.PULSE_REQUIRE_HERMES === '1' ||
747
- fileConfig.requireHermes || false,
800
+ // Whether to enforce Hermes (resolved above): explicit config/flag/env, or
801
+ // auto-detected from the app's native build config when left unset. When on, a
802
+ // missing/failing hermesc is fatal (one-shot pod-install attempt on macOS),
803
+ // -fstrip-function-names is passed, and bytecode output is asserted so a
804
+ // Hermes app can never ship a readable plain-JS OTA.
805
+ requireHermes,
748
806
  };
749
807
  }
750
808