diff --git a/.gitignore b/.gitignore index 6a670398..42c91ba7 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ dist android/build *.tgz .rn-sdk-source.stamp +.rn-demo-env.stamp # OSX # diff --git a/examples/demo-no-location/metro.config.js b/examples/demo-no-location/metro.config.js index 2a0a21ce..4b112559 100644 --- a/examples/demo-no-location/metro.config.js +++ b/examples/demo-no-location/metro.config.js @@ -1,4 +1,7 @@ const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); +const crypto = require('node:crypto'); +const fs = require('node:fs'); +const path = require('node:path'); /** * Metro configuration @@ -6,6 +9,14 @@ const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); * * @type {import('@react-native/metro-config').MetroConfig} */ -const config = {}; +const envPath = path.join(__dirname, '.env'); +const envHash = fs.existsSync(envPath) + ? crypto.createHash('sha1').update(fs.readFileSync(envPath)).digest('hex') + : 'missing'; + +const config = { + // react-native-dotenv does not include .env in Metro's transform cache key. + cacheVersion: `env-${envHash}`, +}; module.exports = mergeConfig(getDefaultConfig(__dirname), config); diff --git a/examples/demo/metro.config.js b/examples/demo/metro.config.js index 74bce611..7427d98f 100644 --- a/examples/demo/metro.config.js +++ b/examples/demo/metro.config.js @@ -1,4 +1,7 @@ const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); +const crypto = require('node:crypto'); +const fs = require('node:fs'); +const path = require('node:path'); /** * Metro configuration @@ -8,8 +11,14 @@ const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); */ const defaultConfig = getDefaultConfig(__dirname); const { assetExts, sourceExts } = defaultConfig.resolver; +const envPath = path.join(__dirname, '.env'); +const envHash = fs.existsSync(envPath) + ? crypto.createHash('sha1').update(fs.readFileSync(envPath)).digest('hex') + : 'missing'; const config = { + // react-native-dotenv does not include .env in Metro's transform cache key. + cacheVersion: `env-${envHash}`, transformer: { babelTransformerPath: require.resolve('react-native-svg-transformer'), }, diff --git a/examples/run-android.sh b/examples/run-android.sh index df6736f1..1f95b9ae 100755 --- a/examples/run-android.sh +++ b/examples/run-android.sh @@ -37,4 +37,4 @@ else selected="${devices[$idx]}" fi -ANDROID_SERIAL="$selected" bunx react-native run-android --deviceId "$selected" +ANDROID_SERIAL="$selected" vp exec react-native run-android --deviceId "$selected" diff --git a/examples/run-ios.sh b/examples/run-ios.sh index a46af8f4..60d4e940 100755 --- a/examples/run-ios.sh +++ b/examples/run-ios.sh @@ -70,4 +70,4 @@ name="${selected%%|*}" udid="${selected##*|}" echo "Using simulator: $name ($udid)" -bunx react-native run-ios --udid "$udid" +vp exec react-native run-ios --udid "$udid" diff --git a/examples/setup.sh b/examples/setup.sh index 9f2b6313..e92019d3 100755 --- a/examples/setup.sh +++ b/examples/setup.sh @@ -1,103 +1,55 @@ #!/usr/bin/env bash set -euo pipefail -# Invoked from a demo dir (e.g. examples/demo/) via `vp run setup`. -# ORIGINAL_DIR captures that dir so we can return to it after building -# the SDK; SDK_ROOT is two levels up (the SDK package itself). -ORIGINAL_DIR=$(pwd) -SDK_ROOT="$(cd ../../ && pwd)" -STAMP_FILE="$SDK_ROOT/.rn-sdk-source.stamp" -DEMO_ENV_STAMP_FILE="$ORIGINAL_DIR/.rn-demo-env.stamp" -TGZ_FILE="$SDK_ROOT/react-native-onesignal.tgz" -INSTALLED_DIR="$ORIGINAL_DIR/node_modules/react-native-onesignal" - -# Content hash of every input that can affect the published tarball. -# We deliberately hash file contents (shasum each file, then shasum the -# combined list) instead of using `find -newer`, because mtimes get -# bumped by routine git operations (checkout, branch switch, rebase) -# even when the source is identical — that caused needless rebuilds. -src_hash=$(find "$SDK_ROOT/src" "$SDK_ROOT/ios" "$SDK_ROOT/android" \ - "$SDK_ROOT/package.json" "$SDK_ROOT/tsconfig.json" \ - "$SDK_ROOT"/*.podspec \ - -type f 2>/dev/null \ - | sort \ - | xargs shasum 2>/dev/null \ - | shasum \ - | awk '{print $1}') - -demo_env_hash=$( - { - for file in "$ORIGINAL_DIR/.env" "$ORIGINAL_DIR/babel.config.js"; do - if [ -f "$file" ]; then - shasum "$file" - else - echo "missing $file" - fi - done - } | shasum | awk '{print $1}' -) +DEMO_DIR=$(pwd -P) +SDK_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)" +TARBALL="$SDK_ROOT/react-native-onesignal.tgz" +INSTALL_STAMP="$DEMO_DIR/.rn-sdk-source.stamp" +INSTALLED_DIR="$DEMO_DIR/node_modules/react-native-onesignal" +ENV_STAMP="$DEMO_DIR/.rn-demo-env.stamp" + +if [ -f "$DEMO_DIR/.env" ]; then + env_hash=$(shasum "$DEMO_DIR/.env" | awk '{print $1}') +else + env_hash=missing +fi -if [ ! -f "$DEMO_ENV_STAMP_FILE" ] || [ "$(cat "$DEMO_ENV_STAMP_FILE")" != "$demo_env_hash" ]; then - echo "Demo env inputs changed, clearing Metro cache..." - rm -rf "${TMPDIR:-/tmp}"/metro-* "${TMPDIR:-/tmp}"/haste-map-* "$ORIGINAL_DIR/node_modules/.cache/metro" 2>/dev/null || true +if [ ! -f "$ENV_STAMP" ] || [ "$(cat "$ENV_STAMP")" != "$env_hash" ]; then + echo "Demo environment changed; restarting Metro." metro_pids=$(lsof -ti tcp:8081 2>/dev/null || true) for pid in $metro_pids; do - args=$(ps -p "$pid" -o args= 2>/dev/null || true) - case "$args" in - *react-native*|*metro*) - echo "Stopping Metro so @env values are reloaded..." - kill "$pid" 2>/dev/null || true - ;; - esac + metro_cwd=$(lsof -a -p "$pid" -d cwd -Fn 2>/dev/null | sed -n 's/^n//p' || true) + if [ "$metro_cwd" = "$DEMO_DIR" ]; then + kill "$pid" 2>/dev/null || true + fi done - echo "$demo_env_hash" > "$DEMO_ENV_STAMP_FILE" -fi - -# Skip the whole rebuild when: -# - the demo already has the SDK installed, -# - the cached tarball is still on disk, and -# - the source hash matches the last successful build. -# FORCE_SETUP=1 bypasses the cache when something feels off. -if [ "${FORCE_SETUP:-0}" != "1" ] \ - && [ -d "$INSTALLED_DIR" ] \ - && [ -f "$STAMP_FILE" ] \ - && [ -f "$TGZ_FILE" ] \ - && [ "$(cat "$STAMP_FILE")" = "$src_hash" ]; then - echo "SDK source unchanged, skipping rebuild. Set FORCE_SETUP=1 to override." - exit 0 + echo "$env_hash" > "$ENV_STAMP" fi cd "$SDK_ROOT" vp run build - -# `vp pm pack` (wraps bun pm pack) honors package.json's "files" field -# (so the tarball matches what would actually be published). The version -# suffix in the filename is unstable, so we normalize to -# react-native-onesignal.tgz for a deterministic path that package.json + -# the extract step can reference. -rm -f react-native-onesignal*.tgz +rm -f react-native-onesignal-*.tgz vp pm pack -mv react-native-onesignal-*.tgz react-native-onesignal.tgz -cd "$ORIGINAL_DIR" +new_tarball=(react-native-onesignal-*.tgz) +if [ -f "$TARBALL" ] && cmp -s "${new_tarball[0]}" "$TARBALL"; then + rm "${new_tarball[0]}" + echo "SDK package unchanged; using cached react-native-onesignal.tgz." +else + mv "${new_tarball[0]}" "$TARBALL" + echo "SDK package changed; refreshed react-native-onesignal.tgz." +fi -# Always go through `vp add` (wraps bun) so bun.lock's integrity hash for -# the tarball stays in sync with the freshly-built tarball on disk. A -# previous version of this script had a "hot path" that just untarred -# over node_modules directly, which was faster but left a stale sha512 -# in bun.lock — any subsequent `vp install` that re-resolved this entry -# (e.g. when the lockfile was touched by another dep) would fail with -# IntegrityCheckFailed. -# -# `vp remove` first because bun verifies the existing integrity hash -# before replacing the entry; without removing, a stale hash from a prior -# build causes `vp add` itself to fail. The relative `file:../../...` -# path is intentional — an absolute path would leak this machine's -# layout into the lockfile. -echo "Registering tarball with vp (refreshes bun.lock integrity hash)..." -vp remove react-native-onesignal 2>/dev/null || true -vp add file:../../react-native-onesignal.tgz +tarball_hash=$(shasum "$TARBALL" | awk '{print $1}') +if [ -d "$INSTALLED_DIR" ] \ + && [ -f "$INSTALL_STAMP" ] \ + && [ "$(cat "$INSTALL_STAMP")" = "$tarball_hash" ]; then + echo "Demo already has this SDK package; skipping reinstall." + exit 0 +fi -# Record the hash only after a successful build/install so that an -# interrupted run forces a full retry next time. -echo "$src_hash" > "$STAMP_FILE" +cd "$DEMO_DIR" +echo "Installing updated SDK package in demo..." +vp remove react-native-onesignal 2>/dev/null || true +vp install file:../../react-native-onesignal.tgz +echo "$tarball_hash" > "$INSTALL_STAMP" diff --git a/package.json b/package.json index 0172cc73..799bfdb7 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "vite": "npm:@voidzero-dev/vite-plus-core@latest", "vitest": "npm:@voidzero-dev/vite-plus-test@latest" }, - "packageManager": "bun@1.3.13", + "packageManager": "bun@1.4.0", "codegenConfig": { "name": "RNOneSignalSpec", "type": "modules",