From 2d6961e91331cda43b311bcaeb1e51e78a27de17 Mon Sep 17 00:00:00 2001 From: Tommy Nguyen <4123478+tido64@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:48:51 +0100 Subject: [PATCH 1/7] fix(metro-config): fix assets outside of project root not rendering --- .changeset/busy-ads-rescue.md | 5 + .../src/assetPluginForMonorepos.js | 30 +- packages/metro-config/src/index.js | 19 +- packages/test-app/ios/Podfile.lock | 1373 ++++++++++++----- 4 files changed, 1059 insertions(+), 368 deletions(-) create mode 100644 .changeset/busy-ads-rescue.md diff --git a/.changeset/busy-ads-rescue.md b/.changeset/busy-ads-rescue.md new file mode 100644 index 0000000000..7bcfc5bdfd --- /dev/null +++ b/.changeset/busy-ads-rescue.md @@ -0,0 +1,5 @@ +--- +"@rnx-kit/metro-config": patch +--- + +Fixed assets outside of project root not rendering diff --git a/packages/metro-config/src/assetPluginForMonorepos.js b/packages/metro-config/src/assetPluginForMonorepos.js index 02f28b40e8..0b73a91909 100644 --- a/packages/metro-config/src/assetPluginForMonorepos.js +++ b/packages/metro-config/src/assetPluginForMonorepos.js @@ -1,4 +1,5 @@ /** + * @typedef {import("connect").NextHandleFunction} NextHandleFunction; * @typedef {import("metro").AssetData} AssetData; * @typedef {import("metro-config").ConfigT} ConfigT; * @typedef {import("metro-config").Middleware} Middleware; @@ -55,22 +56,39 @@ function injectAssetPlugin(server) { } /** - * This middleware restores `..` in asset URLs. - * + * Rewrites (and restores) `..` to `@@` in asset URLs to avoid transformations. * @param {Middleware} middleware * @param {Server} server - * @returns {import("connect").NextHandleFunction} + * @returns {NextHandleFunction} */ -function enhanceMiddleware(middleware, server) { +function escapeRelativePaths(middleware, server) { injectAssetPlugin(server); return (req, res, next) => { const { url } = req; - if (url && url.startsWith("/assets/")) { + if (url?.startsWith("/assets/")) { req.url = url.replaceAll("@@/", "../"); } return middleware(req, res, next); }; } +/** + * Rewrites asset URLs as a query parameter. + * @param {Middleware} middleware + * @param {Server} _server + * @returns {NextHandleFunction} + */ +function rewriteRelativePathsAsQueryParam(middleware, _server) { + return (req, res, next) => { + const { url } = req; + if (url?.startsWith("/assets/../")) { + req.url = url.replace("../", "?unstable_path=../"); + } + return middleware(req, res, next); + }; +} + module.exports = assetPlugin; -module.exports.enhanceMiddleware = enhanceMiddleware; +module.exports.escapeRelativePaths = escapeRelativePaths; +module.exports.rewriteRelativePathsAsQueryParam = + rewriteRelativePathsAsQueryParam; diff --git a/packages/metro-config/src/index.js b/packages/metro-config/src/index.js index 3aae9b4921..4de895345d 100644 --- a/packages/metro-config/src/index.js +++ b/packages/metro-config/src/index.js @@ -3,6 +3,7 @@ const { findMetroPath, + getMetroVersion, requireModuleFromMetro, } = require("@rnx-kit/tools-react-native/metro"); const fs = require("node:fs"); @@ -280,6 +281,18 @@ function exclusionList(additionalExclusions = [], projectRoot = process.cwd()) { ]; } +/** + * Returns whether Metro supports the `unstable_path` query parameter. + * @param {string} projectRoot + * @returns {boolean} + */ +function supportsAssetPathQueryParam(projectRoot) { + // https://github.com/facebook/metro/commit/f3d1157bacc341dff82efea2f70b634141105fc0 + const version = getMetroVersion(projectRoot) || "0.0.0"; + const [major = 0, minor = 0] = version.split("."); + return Number(major) * 1000 + Number(minor) >= 67; +} + module.exports = { defaultWatchFolders, excludeExtraCopiesOf, @@ -296,7 +309,7 @@ module.exports = { const projectRoot = inputConfig.projectRoot || process.cwd(); const { mergeConfig } = requireModuleFromMetro("metro-config", projectRoot); - const { enhanceMiddleware } = require("./assetPluginForMonorepos"); + const assetPlugins = require("./assetPluginForMonorepos"); const { getDefaultConfig } = require("./defaultConfig"); const blockList = exclusionList([], projectRoot); @@ -314,7 +327,9 @@ module.exports = { blockList, // For Metro >= 0.60 }, server: { - enhanceMiddleware, + enhanceMiddleware: supportsAssetPathQueryParam(projectRoot) + ? assetPlugins.rewriteRelativePathsAsQueryParam + : assetPlugins.escapeRelativePaths, }, transformer: { getTransformOptions: async () => ({ diff --git a/packages/test-app/ios/Podfile.lock b/packages/test-app/ios/Podfile.lock index f378bd3c56..123cadccca 100644 --- a/packages/test-app/ios/Podfile.lock +++ b/packages/test-app/ios/Podfile.lock @@ -1,11 +1,35 @@ PODS: + - boost (1.84.0) + - DoubleConversion (1.1.6) + - fast_float (8.0.0) - FBLazyVector (0.81.1) + - fmt (11.0.2) + - glog (0.3.5) - hermes-engine (0.81.1): - hermes-engine/Pre-built (= 0.81.1) - hermes-engine/Pre-built (0.81.1) - MSAL (1.9.0): - MSAL/app-lib (= 1.9.0) - MSAL/app-lib (1.9.0) + - RCT-Folly (2024.11.18.00): + - boost + - DoubleConversion + - fast_float (= 8.0.0) + - fmt (= 11.0.2) + - glog + - RCT-Folly/Default (= 2024.11.18.00) + - RCT-Folly/Default (2024.11.18.00): + - boost + - DoubleConversion + - fast_float (= 8.0.0) + - fmt (= 11.0.2) + - glog + - RCT-Folly/Fabric (2024.11.18.00): + - boost + - DoubleConversion + - fast_float (= 8.0.0) + - fmt (= 11.0.2) + - glog - RCTDeprecation (0.81.1) - RCTRequired (0.81.1) - RCTTypeSafety (0.81.1): @@ -27,9 +51,15 @@ PODS: - React-RCTVibration (= 0.81.1) - React-callinvoker (0.81.1) - React-Core (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - - React-Core-prebuilt - React-Core/Default (= 0.81.1) - React-cxxreact - React-featureflags @@ -43,14 +73,18 @@ PODS: - React-runtimeexecutor - React-runtimescheduler - React-utils - - ReactNativeDependencies + - SocketRocket - Yoga - - React-Core-prebuilt (0.81.1): - - ReactNativeDependencies - React-Core/CoreModulesHeaders (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - - React-Core-prebuilt - React-Core/Default - React-cxxreact - React-featureflags @@ -64,12 +98,18 @@ PODS: - React-runtimeexecutor - React-runtimescheduler - React-utils - - ReactNativeDependencies + - SocketRocket - Yoga - React-Core/Default (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - - React-Core-prebuilt - React-cxxreact - React-featureflags - React-hermes @@ -82,12 +122,18 @@ PODS: - React-runtimeexecutor - React-runtimescheduler - React-utils - - ReactNativeDependencies + - SocketRocket - Yoga - React-Core/DevSupport (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - - React-Core-prebuilt - React-Core/Default (= 0.81.1) - React-Core/RCTWebSocket (= 0.81.1) - React-cxxreact @@ -102,12 +148,18 @@ PODS: - React-runtimeexecutor - React-runtimescheduler - React-utils - - ReactNativeDependencies + - SocketRocket - Yoga - React-Core/RCTActionSheetHeaders (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - - React-Core-prebuilt - React-Core/Default - React-cxxreact - React-featureflags @@ -121,12 +173,18 @@ PODS: - React-runtimeexecutor - React-runtimescheduler - React-utils - - ReactNativeDependencies + - SocketRocket - Yoga - React-Core/RCTAnimationHeaders (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - - React-Core-prebuilt - React-Core/Default - React-cxxreact - React-featureflags @@ -140,12 +198,18 @@ PODS: - React-runtimeexecutor - React-runtimescheduler - React-utils - - ReactNativeDependencies + - SocketRocket - Yoga - React-Core/RCTBlobHeaders (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - - React-Core-prebuilt - React-Core/Default - React-cxxreact - React-featureflags @@ -159,12 +223,18 @@ PODS: - React-runtimeexecutor - React-runtimescheduler - React-utils - - ReactNativeDependencies + - SocketRocket - Yoga - React-Core/RCTImageHeaders (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - - React-Core-prebuilt - React-Core/Default - React-cxxreact - React-featureflags @@ -178,12 +248,18 @@ PODS: - React-runtimeexecutor - React-runtimescheduler - React-utils - - ReactNativeDependencies + - SocketRocket - Yoga - React-Core/RCTLinkingHeaders (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - - React-Core-prebuilt - React-Core/Default - React-cxxreact - React-featureflags @@ -197,12 +273,18 @@ PODS: - React-runtimeexecutor - React-runtimescheduler - React-utils - - ReactNativeDependencies + - SocketRocket - Yoga - React-Core/RCTNetworkHeaders (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - - React-Core-prebuilt - React-Core/Default - React-cxxreact - React-featureflags @@ -216,12 +298,18 @@ PODS: - React-runtimeexecutor - React-runtimescheduler - React-utils - - ReactNativeDependencies + - SocketRocket - Yoga - React-Core/RCTSettingsHeaders (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - - React-Core-prebuilt - React-Core/Default - React-cxxreact - React-featureflags @@ -235,12 +323,18 @@ PODS: - React-runtimeexecutor - React-runtimescheduler - React-utils - - ReactNativeDependencies + - SocketRocket - Yoga - React-Core/RCTTextHeaders (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - - React-Core-prebuilt - React-Core/Default - React-cxxreact - React-featureflags @@ -254,12 +348,18 @@ PODS: - React-runtimeexecutor - React-runtimescheduler - React-utils - - ReactNativeDependencies + - SocketRocket - Yoga - React-Core/RCTVibrationHeaders (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - - React-Core-prebuilt - React-Core/Default - React-cxxreact - React-featureflags @@ -273,12 +373,18 @@ PODS: - React-runtimeexecutor - React-runtimescheduler - React-utils - - ReactNativeDependencies + - SocketRocket - Yoga - React-Core/RCTWebSocket (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTDeprecation - - React-Core-prebuilt - React-Core/Default (= 0.81.1) - React-cxxreact - React-featureflags @@ -292,11 +398,17 @@ PODS: - React-runtimeexecutor - React-runtimescheduler - React-utils - - ReactNativeDependencies + - SocketRocket - Yoga - React-CoreModules (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - RCTTypeSafety (= 0.81.1) - - React-Core-prebuilt - React-Core/CoreModulesHeaders (= 0.81.1) - React-jsi (= 0.81.1) - React-jsinspector @@ -308,11 +420,17 @@ PODS: - React-RCTImage (= 0.81.1) - React-runtimeexecutor - ReactCommon - - ReactNativeDependencies + - SocketRocket - React-cxxreact (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - React-callinvoker (= 0.81.1) - - React-Core-prebuilt - React-debug (= 0.81.1) - React-jsi (= 0.81.1) - React-jsinspector @@ -322,11 +440,17 @@ PODS: - React-perflogger (= 0.81.1) - React-runtimeexecutor - React-timing (= 0.81.1) - - ReactNativeDependencies + - SocketRocket - React-debug (0.81.1) - React-defaultsnativemodule (0.81.1): - - hermes-engine - - React-Core-prebuilt + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - React-domnativemodule - React-featureflagsnativemodule - React-idlecallbacksnativemodule @@ -334,10 +458,16 @@ PODS: - React-jsiexecutor - React-microtasksnativemodule - React-RCTFBReactNativeSpec - - ReactNativeDependencies + - SocketRocket - React-domnativemodule (0.81.1): - - hermes-engine - - React-Core-prebuilt + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - React-Fabric - React-Fabric/bridging - React-FabricComponents @@ -347,14 +477,20 @@ PODS: - React-RCTFBReactNativeSpec - React-runtimeexecutor - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - Yoga - React-Fabric (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric/animations (= 0.81.1) @@ -384,13 +520,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/animations (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -403,13 +545,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/attributedstring (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -422,13 +570,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/bridging (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -441,13 +595,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/componentregistry (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -460,13 +620,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/componentregistrynative (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -479,13 +645,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/components (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric/components/legacyviewmanagerinterop (= 0.81.1) @@ -502,13 +674,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/components/legacyviewmanagerinterop (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -521,13 +699,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/components/root (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -540,13 +724,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/components/scrollview (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -559,13 +749,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/components/view (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -579,14 +775,20 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - Yoga - React-Fabric/consistency (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -599,13 +801,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/core (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -618,13 +826,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/dom (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -637,13 +851,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/imagemanager (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -656,13 +876,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/leakchecker (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -675,13 +901,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/mounting (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -694,13 +926,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/observers (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric/observers/events (= 0.81.1) @@ -714,13 +952,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/observers/events (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -733,13 +977,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/scheduler (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric/observers/events @@ -754,13 +1004,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/telemetry (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -773,13 +1029,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/templateprocessor (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -792,13 +1054,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/uimanager (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric/uimanager/consistency (= 0.81.1) @@ -813,13 +1081,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-Fabric/uimanager/consistency (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -833,13 +1107,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-FabricComponents (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric @@ -855,14 +1135,20 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - Yoga - React-FabricComponents/components (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric @@ -887,14 +1173,20 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - Yoga - React-FabricComponents/components/inputaccessory (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric @@ -908,14 +1200,20 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - Yoga - React-FabricComponents/components/iostextinput (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric @@ -929,14 +1227,20 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - Yoga - React-FabricComponents/components/modal (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric @@ -950,14 +1254,20 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - Yoga - React-FabricComponents/components/rncore (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric @@ -971,14 +1281,20 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - Yoga - React-FabricComponents/components/safeareaview (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric @@ -992,14 +1308,20 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - Yoga - React-FabricComponents/components/scrollview (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric @@ -1013,14 +1335,20 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - Yoga - React-FabricComponents/components/switch (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric @@ -1034,14 +1362,20 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - Yoga - React-FabricComponents/components/text (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric @@ -1055,14 +1389,20 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - Yoga - React-FabricComponents/components/textinput (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric @@ -1076,14 +1416,20 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - Yoga - React-FabricComponents/components/unimplementedview (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric @@ -1097,14 +1443,20 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - Yoga - React-FabricComponents/components/virtualview (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric @@ -1118,14 +1470,20 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - Yoga - React-FabricComponents/textlayoutmanager (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric @@ -1139,13 +1497,19 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - Yoga - React-FabricImage (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired (= 0.81.1) - RCTTypeSafety (= 0.81.1) - - React-Core-prebuilt - React-Fabric - React-featureflags - React-graphics @@ -1156,30 +1520,54 @@ PODS: - React-rendererdebug - React-utils - ReactCommon - - ReactNativeDependencies + - SocketRocket - Yoga - React-featureflags (0.81.1): - - React-Core-prebuilt - - ReactNativeDependencies + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket - React-featureflagsnativemodule (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog - hermes-engine - - React-Core-prebuilt + - RCT-Folly + - RCT-Folly/Fabric - React-featureflags - React-jsi - React-jsiexecutor - React-RCTFBReactNativeSpec - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-graphics (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog - hermes-engine - - React-Core-prebuilt + - RCT-Folly + - RCT-Folly/Fabric - React-jsi - React-jsiexecutor - React-utils - - ReactNativeDependencies + - SocketRocket - React-hermes (0.81.1): - - hermes-engine - - React-Core-prebuilt + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - React-cxxreact (= 0.81.1) - React-jsi - React-jsiexecutor (= 0.81.1) @@ -1188,42 +1576,72 @@ PODS: - React-jsinspectortracing - React-perflogger (= 0.81.1) - React-runtimeexecutor - - ReactNativeDependencies + - SocketRocket - React-idlecallbacksnativemodule (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog - hermes-engine - - React-Core-prebuilt + - RCT-Folly + - RCT-Folly/Fabric - React-jsi - React-jsiexecutor - React-RCTFBReactNativeSpec - React-runtimeexecutor - React-runtimescheduler - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-ImageManager (0.81.1): - - React-Core-prebuilt + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - React-Core/Default - React-debug - React-Fabric - React-graphics - React-rendererdebug - React-utils - - ReactNativeDependencies + - SocketRocket - React-jserrorhandler (0.81.1): - - hermes-engine - - React-Core-prebuilt + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - React-cxxreact - React-debug - React-featureflags - React-jsi - ReactCommon/turbomodule/bridging - - ReactNativeDependencies + - SocketRocket - React-jsi (0.81.1): - - hermes-engine - - React-Core-prebuilt - - ReactNativeDependencies + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket - React-jsiexecutor (0.81.1): - - hermes-engine - - React-Core-prebuilt + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - React-cxxreact (= 0.81.1) - React-jsi (= 0.81.1) - React-jsinspector @@ -1231,10 +1649,16 @@ PODS: - React-jsinspectortracing - React-perflogger (= 0.81.1) - React-runtimeexecutor - - ReactNativeDependencies + - SocketRocket - React-jsinspector (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog - hermes-engine - - React-Core-prebuilt + - RCT-Folly + - RCT-Folly/Fabric - React-featureflags - React-jsi - React-jsinspectorcdp @@ -1243,53 +1667,101 @@ PODS: - React-oscompat - React-perflogger (= 0.81.1) - React-runtimeexecutor - - ReactNativeDependencies + - SocketRocket - React-jsinspectorcdp (0.81.1): - - React-Core-prebuilt - - ReactNativeDependencies + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket - React-jsinspectornetwork (0.81.1): - - React-Core-prebuilt + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - React-featureflags - React-jsinspectorcdp - React-performancetimeline - React-timing - - ReactNativeDependencies + - SocketRocket - React-jsinspectortracing (0.81.1): - - React-Core-prebuilt + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - React-oscompat - React-timing - - ReactNativeDependencies + - SocketRocket - React-jsitooling (0.81.1): - - React-Core-prebuilt + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - React-cxxreact (= 0.81.1) - React-jsi (= 0.81.1) - React-jsinspector - React-jsinspectorcdp - React-jsinspectortracing - React-runtimeexecutor - - ReactNativeDependencies + - SocketRocket - React-jsitracing (0.81.1): - React-jsi - React-logger (0.81.1): - - React-Core-prebuilt - - ReactNativeDependencies + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket - React-Mapbuffer (0.81.1): - - React-Core-prebuilt + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - React-debug - - ReactNativeDependencies + - SocketRocket - React-microtasksnativemodule (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog - hermes-engine - - React-Core-prebuilt + - RCT-Folly + - RCT-Folly/Fabric - React-jsi - React-jsiexecutor - React-RCTFBReactNativeSpec - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-NativeModulesApple (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - React-callinvoker - React-Core - - React-Core-prebuilt - React-cxxreact - React-featureflags - React-jsi @@ -1298,36 +1770,60 @@ PODS: - React-runtimeexecutor - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - React-oscompat (0.81.1) - React-perflogger (0.81.1): - - React-Core-prebuilt - - ReactNativeDependencies + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket - React-performancetimeline (0.81.1): - - React-Core-prebuilt + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - React-featureflags - React-jsinspectortracing - React-perflogger - React-timing - - ReactNativeDependencies + - SocketRocket - React-RCTActionSheet (0.81.1): - React-Core/RCTActionSheetHeaders (= 0.81.1) - React-RCTAnimation (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - RCTTypeSafety - - React-Core-prebuilt - React-Core/RCTAnimationHeaders - React-featureflags - React-jsi - React-NativeModulesApple - React-RCTFBReactNativeSpec - ReactCommon - - ReactNativeDependencies + - SocketRocket - React-RCTAppDelegate (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-CoreModules - React-debug - React-defaultsnativemodule @@ -1349,10 +1845,16 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon - - ReactNativeDependencies + - SocketRocket - React-RCTBlob (0.81.1): - - hermes-engine - - React-Core-prebuilt + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - React-Core/RCTBlobHeaders - React-Core/RCTWebSocket - React-jsi @@ -1362,11 +1864,17 @@ PODS: - React-RCTFBReactNativeSpec - React-RCTNetwork - ReactCommon - - ReactNativeDependencies + - SocketRocket - React-RCTFabric (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - React-Core - - React-Core-prebuilt - React-debug - React-Fabric - React-FabricComponents @@ -1390,25 +1898,37 @@ PODS: - React-runtimeexecutor - React-runtimescheduler - React-utils - - ReactNativeDependencies + - SocketRocket - Yoga - React-RCTFBReactNativeSpec (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-jsi - React-NativeModulesApple - React-RCTFBReactNativeSpec/components (= 0.81.1) - ReactCommon - - ReactNativeDependencies + - SocketRocket - React-RCTFBReactNativeSpec/components (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-debug - React-Fabric - React-featureflags @@ -1418,18 +1938,24 @@ PODS: - React-rendererdebug - React-utils - ReactCommon - - ReactNativeDependencies + - SocketRocket - Yoga - React-RCTImage (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - RCTTypeSafety - - React-Core-prebuilt - React-Core/RCTImageHeaders - React-jsi - React-NativeModulesApple - React-RCTFBReactNativeSpec - React-RCTNetwork - ReactCommon - - ReactNativeDependencies + - SocketRocket - React-RCTLinking (0.81.1): - React-Core/RCTLinkingHeaders (= 0.81.1) - React-jsi (= 0.81.1) @@ -1438,8 +1964,14 @@ PODS: - ReactCommon - ReactCommon/turbomodule/core (= 0.81.1) - React-RCTNetwork (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - RCTTypeSafety - - React-Core-prebuilt - React-Core/RCTNetworkHeaders - React-featureflags - React-jsi @@ -1448,11 +1980,17 @@ PODS: - React-NativeModulesApple - React-RCTFBReactNativeSpec - ReactCommon - - ReactNativeDependencies + - SocketRocket - React-RCTRuntime (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - React-Core - - React-Core-prebuilt - React-jsi - React-jsinspector - React-jsinspectorcdp @@ -1462,39 +2000,63 @@ PODS: - React-RuntimeCore - React-runtimeexecutor - React-RuntimeHermes - - ReactNativeDependencies + - SocketRocket - React-RCTSettings (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - RCTTypeSafety - - React-Core-prebuilt - React-Core/RCTSettingsHeaders - React-jsi - React-NativeModulesApple - React-RCTFBReactNativeSpec - ReactCommon - - ReactNativeDependencies + - SocketRocket - React-RCTText (0.81.1): - React-Core/RCTTextHeaders (= 0.81.1) - Yoga - React-RCTVibration (0.81.1): - - React-Core-prebuilt + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - React-Core/RCTVibrationHeaders - React-jsi - React-NativeModulesApple - React-RCTFBReactNativeSpec - ReactCommon - - ReactNativeDependencies + - SocketRocket - React-rendererconsistency (0.81.1) - React-renderercss (0.81.1): - React-debug - React-utils - React-rendererdebug (0.81.1): - - React-Core-prebuilt + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - React-debug - - ReactNativeDependencies + - SocketRocket - React-RuntimeApple (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - React-callinvoker - - React-Core-prebuilt - React-Core/Default - React-CoreModules - React-cxxreact @@ -1513,10 +2075,16 @@ PODS: - React-RuntimeHermes - React-runtimescheduler - React-utils - - ReactNativeDependencies + - SocketRocket - React-RuntimeCore (0.81.1): - - hermes-engine - - React-Core-prebuilt + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - React-cxxreact - React-Fabric - React-featureflags @@ -1529,17 +2097,29 @@ PODS: - React-runtimeexecutor - React-runtimescheduler - React-utils - - ReactNativeDependencies + - SocketRocket - React-runtimeexecutor (0.81.1): - - React-Core-prebuilt + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - React-debug - React-featureflags - React-jsi (= 0.81.1) - React-utils - - ReactNativeDependencies + - SocketRocket - React-RuntimeHermes (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog - hermes-engine - - React-Core-prebuilt + - RCT-Folly + - RCT-Folly/Fabric - React-featureflags - React-hermes - React-jsi @@ -1551,11 +2131,17 @@ PODS: - React-RuntimeCore - React-runtimeexecutor - React-utils - - ReactNativeDependencies + - SocketRocket - React-runtimescheduler (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - React-callinvoker - - React-Core-prebuilt - React-cxxreact - React-debug - React-featureflags @@ -1567,23 +2153,35 @@ PODS: - React-runtimeexecutor - React-timing - React-utils - - ReactNativeDependencies + - SocketRocket - React-timing (0.81.1): - React-debug - React-utils (0.81.1): - - hermes-engine - - React-Core-prebuilt + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - React-debug - React-jsi (= 0.81.1) - - ReactNativeDependencies + - SocketRocket - ReactAppDependencyProvider (0.81.1): - ReactCodegen - ReactCodegen (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-debug - React-Fabric - React-FabricImage @@ -1597,35 +2195,59 @@ PODS: - React-utils - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - ReactCommon (0.81.1): - - React-Core-prebuilt + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric - ReactCommon/turbomodule (= 0.81.1) - - ReactNativeDependencies + - SocketRocket - ReactCommon/turbomodule (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - React-callinvoker (= 0.81.1) - - React-Core-prebuilt - React-cxxreact (= 0.81.1) - React-jsi (= 0.81.1) - React-logger (= 0.81.1) - React-perflogger (= 0.81.1) - ReactCommon/turbomodule/bridging (= 0.81.1) - ReactCommon/turbomodule/core (= 0.81.1) - - ReactNativeDependencies + - SocketRocket - ReactCommon/turbomodule/bridging (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - React-callinvoker (= 0.81.1) - - React-Core-prebuilt - React-cxxreact (= 0.81.1) - React-jsi (= 0.81.1) - React-logger (= 0.81.1) - React-perflogger (= 0.81.1) - - ReactNativeDependencies + - SocketRocket - ReactCommon/turbomodule/core (0.81.1): - - hermes-engine + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - React-callinvoker (= 0.81.1) - - React-Core-prebuilt - React-cxxreact (= 0.81.1) - React-debug (= 0.81.1) - React-featureflags (= 0.81.1) @@ -1633,14 +2255,19 @@ PODS: - React-logger (= 0.81.1) - React-perflogger (= 0.81.1) - React-utils (= 0.81.1) - - ReactNativeDependencies - - ReactNativeDependencies (0.81.1) - - ReactNativeHost (0.5.13): - - hermes-engine + - SocketRocket + - ReactNativeHost (0.5.15): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-cxxreact - React-debug - React-Fabric @@ -1657,7 +2284,7 @@ PODS: - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - Yoga - ReactTestApp-DevSupport (4.4.12): - React-Core @@ -1665,12 +2292,18 @@ PODS: - ReactTestApp-MSAL (5.0.3): - MSAL - ReactTestApp-Resources (1.0.0-dev) - - RNWWebStorage (0.4.3): - - hermes-engine + - RNWWebStorage (0.4.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric - RCTRequired - RCTTypeSafety - React-Core - - React-Core-prebuilt - React-debug - React-Fabric - React-featureflags @@ -1685,23 +2318,29 @@ PODS: - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - ReactNativeDependencies + - SocketRocket - Yoga - - RNXAuth (0.3.2): + - RNXAuth (0.3.3): - React-Core + - SocketRocket (0.7.1) - Yoga (0.0.0) DEPENDENCIES: + - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) + - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) + - fast_float (from `../node_modules/react-native/third-party-podspecs/fast_float.podspec`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) + - fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`) + - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) - MSAL + - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - RCTDeprecation (from `../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`) - RCTRequired (from `../node_modules/react-native/Libraries/Required`) - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) - React (from `../node_modules/react-native/`) - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) - React-Core (from `../node_modules/react-native/`) - - React-Core-prebuilt (from `../node_modules/react-native/React-Core-prebuilt.podspec`) - React-Core/RCTWebSocket (from `../node_modules/react-native/`) - React-CoreModules (from `../node_modules/react-native/React/CoreModules`) - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) @@ -1759,25 +2398,38 @@ DEPENDENCIES: - ReactAppDependencyProvider (from `build/generated/ios`) - ReactCodegen (from `build/generated/ios`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) - - ReactNativeDependencies (from `../node_modules/react-native/third-party-podspecs/ReactNativeDependencies.podspec`) - "ReactNativeHost (from `../../../node_modules/.store/react-native-test-app-virtual-ff4d3b9855/node_modules/@rnx-kit/react-native-host`)" - ReactTestApp-DevSupport (from `../node_modules/react-native-test-app`) - "ReactTestApp-MSAL (from `../node_modules/@rnx-kit/react-native-test-app-msal`)" - ReactTestApp-Resources (from `..`) - "RNWWebStorage (from `../node_modules/@react-native-webapis/web-storage`)" - "RNXAuth (from `../node_modules/@rnx-kit/react-native-auth`)" + - SocketRocket (~> 0.7.1) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) SPEC REPOS: trunk: - MSAL + - SocketRocket EXTERNAL SOURCES: + boost: + :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" + DoubleConversion: + :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" + fast_float: + :podspec: "../node_modules/react-native/third-party-podspecs/fast_float.podspec" FBLazyVector: :path: "../node_modules/react-native/Libraries/FBLazyVector" + fmt: + :podspec: "../node_modules/react-native/third-party-podspecs/fmt.podspec" + glog: + :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" hermes-engine: :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" :tag: hermes-2025-07-07-RNv0.81.0-e0fc67142ec0763c6b6153ca2bf96df815539782 + RCT-Folly: + :podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" RCTDeprecation: :path: "../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation" RCTRequired: @@ -1790,8 +2442,6 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/callinvoker" React-Core: :path: "../node_modules/react-native/" - React-Core-prebuilt: - :podspec: "../node_modules/react-native/React-Core-prebuilt.podspec" React-CoreModules: :path: "../node_modules/react-native/React/CoreModules" React-cxxreact: @@ -1904,8 +2554,6 @@ EXTERNAL SOURCES: :path: build/generated/ios ReactCommon: :path: "../node_modules/react-native/ReactCommon" - ReactNativeDependencies: - :podspec: "../node_modules/react-native/third-party-podspecs/ReactNativeDependencies.podspec" ReactNativeHost: :path: "../../../node_modules/.store/react-native-test-app-virtual-ff4d3b9855/node_modules/@rnx-kit/react-native-host" ReactTestApp-DevSupport: @@ -1922,80 +2570,85 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/yoga" SPEC CHECKSUMS: - FBLazyVector: 8da1272845e10a35c1e661a4c8ba644526c014fb + boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 + DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb + fast_float: b32c788ed9c6a8c584d114d0047beda9664e7cc6 + FBLazyVector: b8f1312d48447cca7b4abc21ed155db14742bd03 + fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd + glog: 5683914934d5b6e4240e497e0f4a3b42d1854183 hermes-engine: 4f8246b1f6d79f625e0d99472d1f3a71da4d28ca MSAL: 1a32a1070ccf55d9641d31edd8869ea2b5a78beb - RCTDeprecation: 24056820c873bf5115c0441651440bfde2b82d51 - RCTRequired: d0b6e766be3c17896d92059c917d682433ff8a34 - RCTTypeSafety: 1954dcf545fe67e969e11e1b4fe6cf864e1ac632 + RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669 + RCTDeprecation: c4b9e2fd0ab200e3af72b013ed6113187c607077 + RCTRequired: e97dd5dafc1db8094e63bc5031e0371f092ae92a + RCTTypeSafety: 720403058b7c1380c6a3ae5706981d6362962c89 React: f1486d005993b0af01943af1850d3d4f3b597545 - React-callinvoker: 944c9e97ef08e3995b05cc29b40c071a7bd0eaec - React-Core: 33c2f29eb1054f2fe4b6c7bb1e595495170f6c15 - React-Core-prebuilt: 70adad8a28cf9ec5c1f349ced6375354644500ac - React-CoreModules: 6d0945fdc20d150789baaeefe2794b0dbc8f6379 - React-cxxreact: 1d8096423b2b3e7b05c24f40277d117896e8873f - React-debug: 0268bacb2cc38d98790ce15159e962a6b0b1895e - React-defaultsnativemodule: 5f2f1cdd3765b7fd7aed963e9b61cc6292343c46 - React-domnativemodule: 4407d05b3bf87d604be08307e71ca308c7201043 - React-Fabric: f68b67dd472fc90352fe80e2a6837a8642e7ef23 - React-FabricComponents: e138111ec8093b42a3d74dc75865091d99bace64 - React-FabricImage: cedf4cee2a69eb3518753291aa056f65189f09ef - React-featureflags: 7a70fce3a3c7c7745560d5c0ade1d46d7460c9c7 - React-featureflagsnativemodule: 267f61c8648729837851cefe9a5017eb40855473 - React-graphics: 70d3b71cde945c870d5528a4763abc34456a35d8 - React-hermes: 66d0e0adcd5d7d8852efcee7129b1d248d9e76fc - React-idlecallbacksnativemodule: 987fcd4d77fed9d7f3ed5595d08bc283ac302d28 - React-ImageManager: ceccf49e14a8c306e144ed192fe16f7704fbe6dd - React-jserrorhandler: e58b58bd3135795310b52d18d37d86b339d3753e - React-jsi: 1a403eb9781c8ab89d27bbe9a0573d9bb039b6a5 - React-jsiexecutor: 81ea81bfd3f2ef78858e11d13179b740e2ea46d8 - React-jsinspector: 5677b6102cc59b5c89ff471c1f461c8af99ed648 - React-jsinspectorcdp: b4f743cb748c30677faf600f093c6bbd2aa5352b - React-jsinspectornetwork: 4c3fe84b72157f483a292e2605af88ace0c20177 - React-jsinspectortracing: 4313f327e2bf0c6e4e0cfda1949734732e9f5530 - React-jsitooling: 8a6546ee9c511c5497e013c05abbbc4f2dd1e87c - React-jsitracing: 8d11a4f0d444dbc9cf24862728d16afbb0cf67bb - React-logger: a1c9c8dfc56711d06a21109b55908e177113e554 - React-Mapbuffer: bc36232966c55d5b1cbef3b84cb97c4317fa4403 - React-microtasksnativemodule: cbabfedcf6c2984e59d07f9ab553f3d277599b1b - React-NativeModulesApple: 055e2d1417c663e7a26fc0847609f503e626e9e1 - React-oscompat: 8f2893713639e12c7558750a9f7de3f08ac255b0 - React-perflogger: 34b632f94b15e1068f7997e5a68b40a55162ad13 - React-performancetimeline: 6e067040e1af47a26e306c726e228e53718518ac - React-RCTActionSheet: 0280ff8cf63ef67a5a74898b18316b204d686c83 - React-RCTAnimation: a33e999cdfc9ebc8eb17f8f9f262ac765635d3b8 - React-RCTAppDelegate: 8ca4feb7290edf02f70ee824b0ef735c24d78b0e - React-RCTBlob: ab87e8283899ec563c429f55a7a584c8bae78f17 - React-RCTFabric: 465111d965717cbe4e1fe4a5caffc66723423d68 - React-RCTFBReactNativeSpec: 7637e1b9e3838c7a43e870a1c519346ec1787e90 - React-RCTImage: 7e07ef9065bf18dd8566421b550c041455f24bdb - React-RCTLinking: 0877fa82d7a04bbdd6167e7d93ebbab2147d4398 - React-RCTNetwork: f26cc6a43530af00bc6c3c73cfdb0df58e319126 - React-RCTRuntime: c22ce17d068c7447c7406c00050785776cb376a4 - React-RCTSettings: 58a19d845f0e05555246c8325b527bd90cdc88e7 - React-RCTText: 972fe79182d4082d36e988c094c5876f9ddfaab0 - React-RCTVibration: 56c26c46c7c574a46fb424e9ba9445e686ddf53f - React-rendererconsistency: 4917405e8864ded5d3b350f04ee7f1712435d8e7 - React-renderercss: dd4f24445dcb209267e1034df31cc156e336342d - React-rendererdebug: c335166d55d20a7c1a7a7ac0ca491d996f4adf5b - React-RuntimeApple: 9e7edf7c631cf2446fbb728e68bfbbc859d8aabd - React-RuntimeCore: a6a70ca5ab98f08191f6c7dfd3424b4fc86ed24d - React-runtimeexecutor: 2d4128882cf41c7824e9d8a72c6b9461897889af - React-RuntimeHermes: 4e74b3ea837c4bae9903b6a9210f97329007b7f2 - React-runtimescheduler: 5ec6bcc02a05de1e87b9830dbfccff4dc1bddcae - React-timing: b49069174c0330be78b67c8a24d7127dfca99bba - React-utils: de22e0dfdd4494e401dfd0194f552c7175480939 + React-callinvoker: 133f69368c8559e744efa345223625d412f5dfbe + React-Core: 559823921b4f294c2840fa8238ca958a29ddc211 + React-CoreModules: c41e7bbfabbc420783bb926f45837a0d5e53341e + React-cxxreact: 9cb9fa738274a1b36b97ede09c8a6717dec1a20b + React-debug: e01581e1589f329e61c95b332bf7f4969b10564b + React-defaultsnativemodule: bbb39447caa6b6cf9405fa0099f828c083640faa + React-domnativemodule: 03744d12b6d56d098531a933730bf1d4cb79bdfb + React-Fabric: 530b3993a12a96e8a7cdb9f0ef48e605277b572e + React-FabricComponents: 271ec2a9b2c00ac66fd6d1fd24e9e964d907751d + React-FabricImage: d0af66e976dbab7f8b81e36dd369fc70727d2695 + React-featureflags: 269704c8eff86e0485c9d384e286350fcda6eb70 + React-featureflagsnativemodule: db1e5d88a912fb08a5ece33fcf64e1b732da8467 + React-graphics: b19d03a01b0722b4dc82f47acb56dc3ed41937e7 + React-hermes: 811606c0aca5a3f9c6fa8e4994e02ca8f677e68e + React-idlecallbacksnativemodule: 3a3df629cd50046c7e4354f9025aefe8f2c84601 + React-ImageManager: 0d53866c63132791e37bb2373f93044fdef14aa3 + React-jserrorhandler: d5700d6ab7162fd575287502a3c5d601d98e7f09 + React-jsi: ece95417fedbed0e7153a855cb8342b7c72ab75e + React-jsiexecutor: 2b0bb644b533df2f5c0cd6ade9a4560d0bf1dd84 + React-jsinspector: 0c160f8510a8852bdf2dac12f0b1949efc18200b + React-jsinspectorcdp: f4b84409f453f61ddd8614ad45139bc594ec6bb5 + React-jsinspectornetwork: 8f2f0ca8c871ca19b571f426002c0012e7fb2aee + React-jsinspectortracing: 33f6b977eb8a4bc1e3d1a4b948809aca083143f9 + React-jsitooling: 2c61529b589e17229a9f0a4a4fc35aa7ad495850 + React-jsitracing: 838a7b0c013c4aff7d382d7fdc78cf442013ba1d + React-logger: 7aef4d74123e5e3d267e5af1fbf5135b5a0d8381 + React-Mapbuffer: 91e0eab42a6ae7f3e34091a126d70fc53bd3823e + React-microtasksnativemodule: 1ead4fe154df3b1ba34b5a9e35ef3c4bdfa72ccb + React-NativeModulesApple: eff2eba56030eb0d107b1642b8f853bc36a833ac + React-oscompat: b12c633e9c00f1f99467b1e0e0b8038895dae436 + React-perflogger: 58d12c4e5df1403030c97b9c621375c312cca454 + React-performancetimeline: 0ee0a3236c77a4ee6d8a6189089e41e4003d292e + React-RCTActionSheet: 3f741a3712653611a6bfc5abceb8260af9d0b218 + React-RCTAnimation: 408ad69ea136e99a463dd33eadecc29e586b3d72 + React-RCTAppDelegate: f03b46e80b8a3dbfa84b35abfe123e02f3ceef83 + React-RCTBlob: bd42e92a00ad22eaab92ffe5c137e7a2f725887a + React-RCTFabric: b99ab638c73cf2d57b886eafdbfb2e4909b0eb9a + React-RCTFBReactNativeSpec: 7ad9aba0e0655e3f29be0a1c3fd4a888fab04dcf + React-RCTImage: 0f1c74f7cd20027f8c34976a211b35d4263a0add + React-RCTLinking: 6d7dfc3a74110df56c3a73cc7626bf4415656542 + React-RCTNetwork: 6a25d8645a80d5b86098675ca39bf8fcf1afa08b + React-RCTRuntime: 38bfe9766565ae3293ca230bc51c9c020a8bc98a + React-RCTSettings: 651d9ae2cdd32f547ad0d225a2c13886d6ad2358 + React-RCTText: 9bc66cd288478e23195e01f5cb45eba79986b2b4 + React-RCTVibration: 371226f5667a00c76d792dcdb5c2e0fcbcde0c3b + React-rendererconsistency: a05f6c37f9389c53213d1e28798e441fa6fbdbcd + React-renderercss: 6e4febfa014b0f53bc171a62b0f713ddbdbb9860 + React-rendererdebug: e94bf27b9d55ef2795caa8e43aa92abc4a373b8b + React-RuntimeApple: 723be5159519eba1cd92449acb29436d21571b82 + React-RuntimeCore: f58eb0f01065c9d27d91de10b2e4ab4c76d83b0e + React-runtimeexecutor: f615ec8742d0b5820170f7c8b4d2c7cb75d93ac9 + React-RuntimeHermes: fddb258e03d330d1132bb19e78fe51ac2f3f41ac + React-runtimescheduler: e92a31460e654ced8587debeec37553315e1b6a5 + React-timing: 97ada2c47b4c5932e7f773c7d239c52b90d6ca68 + React-utils: f0949d247a46b4c09f03e5a3cb1167602d0b729a ReactAppDependencyProvider: 3eb9096cb139eb433965693bbe541d96eb3d3ec9 - ReactCodegen: ddfb6730dcb92c4973a38d556fe9b8f4ebb10e29 - ReactCommon: 3579ef7cd884fbb5218bed929f25b7b212299700 - ReactNativeDependencies: 9444683ddc7eaa98d2289224ce730a7632b705ff - ReactNativeHost: 1926588a2533dc141bdb365e001d08be3e2ed14a + ReactCodegen: cf9f9011964b570d946681225307e377ee2038d5 + ReactCommon: ce5d4226dfaf9d5dacbef57b4528819e39d3a120 + ReactNativeHost: f5e054387e917216a2a021a3f7fdc4f9f158e7e4 ReactTestApp-DevSupport: 963986104f003af978562535682fec417b4aadfa ReactTestApp-MSAL: 778502496ada0c04f0a96cbcc8359d681c458ace ReactTestApp-Resources: 70da1d78d943a1fdff6362ce3f778e5b4560c95a - RNWWebStorage: 76fd699d57697cfa9c06e49fcf0620932c3b6c59 - RNXAuth: fd683d15e8b032a48de28048098f875ab8bda98c - Yoga: 18b87f28df0aee34fa7370518a35aa8107ba47b9 + RNWWebStorage: 500b1829ce207400ca1ead66d4afad58f470d0d6 + RNXAuth: a54c1a2349766f9d0876d23d90a206a73ddd7d87 + SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 + Yoga: 11c9686a21e2cd82a094a723649d9f4507200fb0 PODFILE CHECKSUM: 264808f7e2f957e37ba3db39a042eaf1b078c827 From 0a33a67669ca634bfc916103e636a5074eb46002 Mon Sep 17 00:00:00 2001 From: Tommy Nguyen <4123478+tido64@users.noreply.github.com> Date: Mon, 5 Jan 2026 17:01:12 +0100 Subject: [PATCH 2/7] use config.server.rewriteRequestUrl and add tests --- .../src/assetPluginForMonorepos.js | 17 +++++++++-- packages/metro-config/src/index.js | 1 + .../test/assetPluginForMonorepos.test.ts | 30 +++++++++++++++++-- packages/metro-config/test/index.test.ts | 11 +++++-- 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/packages/metro-config/src/assetPluginForMonorepos.js b/packages/metro-config/src/assetPluginForMonorepos.js index 0b73a91909..4bb49ea831 100644 --- a/packages/metro-config/src/assetPluginForMonorepos.js +++ b/packages/metro-config/src/assetPluginForMonorepos.js @@ -72,6 +72,18 @@ function escapeRelativePaths(middleware, server) { }; } +/** + * Rewrites asset URLs as a query parameter. + * @param {string} url + * @returns {string} + */ +function rewriteRequestWithQueryParam(url) { + const prefix = "/assets/../"; + return url.startsWith(prefix) + ? url.replace(prefix, "/assets?unstable_path=../") + : url; +} + /** * Rewrites asset URLs as a query parameter. * @param {Middleware} middleware @@ -81,8 +93,8 @@ function escapeRelativePaths(middleware, server) { function rewriteRelativePathsAsQueryParam(middleware, _server) { return (req, res, next) => { const { url } = req; - if (url?.startsWith("/assets/../")) { - req.url = url.replace("../", "?unstable_path=../"); + if (url) { + req.url = rewriteRequestWithQueryParam(url); } return middleware(req, res, next); }; @@ -92,3 +104,4 @@ module.exports = assetPlugin; module.exports.escapeRelativePaths = escapeRelativePaths; module.exports.rewriteRelativePathsAsQueryParam = rewriteRelativePathsAsQueryParam; +module.exports.rewriteRequestWithQueryParam = rewriteRequestWithQueryParam; diff --git a/packages/metro-config/src/index.js b/packages/metro-config/src/index.js index 4de895345d..c8f6dd9be4 100644 --- a/packages/metro-config/src/index.js +++ b/packages/metro-config/src/index.js @@ -330,6 +330,7 @@ module.exports = { enhanceMiddleware: supportsAssetPathQueryParam(projectRoot) ? assetPlugins.rewriteRelativePathsAsQueryParam : assetPlugins.escapeRelativePaths, + rewriteRequestUrl: assetPlugins.rewriteRequestWithQueryParam, }, transformer: { getTransformOptions: async () => ({ diff --git a/packages/metro-config/test/assetPluginForMonorepos.test.ts b/packages/metro-config/test/assetPluginForMonorepos.test.ts index b7215eba4a..2d856d78d8 100644 --- a/packages/metro-config/test/assetPluginForMonorepos.test.ts +++ b/packages/metro-config/test/assetPluginForMonorepos.test.ts @@ -6,8 +6,8 @@ import type { IncomingMessage, ServerResponse } from "node:http"; import { describe, it } from "node:test"; import assetPlugin from "../src/assetPluginForMonorepos.js"; -describe("@rnx-kit/metro-config/assetPluginForMonorepos", () => { - const { enhanceMiddleware } = assetPlugin; +describe("assetPluginForMonorepos/escapeRelativePaths", () => { + const { escapeRelativePaths } = assetPlugin; const cases = [ ["/assets/./node_modules", "/assets/./node_modules"], @@ -39,7 +39,7 @@ describe("@rnx-kit/metro-config/assetPluginForMonorepos", () => { const incoming = { url: input } as IncomingMessage; const response = {} as ServerResponse; - enhanceMiddleware(middleware, server)( + escapeRelativePaths(middleware, server)( incoming, response, () => undefined @@ -47,3 +47,27 @@ describe("@rnx-kit/metro-config/assetPluginForMonorepos", () => { } }); }); + +describe("assetPluginForMonorepos/rewriteRequestWithQueryParam", () => { + const { rewriteRequestWithQueryParam } = assetPlugin; + + const cases = [ + ["/assets/./node_modules", "/assets/./node_modules"], + ["/assets/../node_modules", "/assets?unstable_path=../node_modules"], + ["/assets/../../node_modules", "/assets?unstable_path=../../node_modules"], + [ + "/assets/node_modules/../../react-native", + "/assets/node_modules/../../react-native", + ], + [ + "/assets/local/path/with/nested/assets/../../react-native", + "/assets/local/path/with/nested/assets/../../react-native", + ], + ] as const; + + it("rewrites request URLs with relative paths", () => { + for (const [input, output] of cases) { + equal(rewriteRequestWithQueryParam(input), output); + } + }); +}); diff --git a/packages/metro-config/test/index.test.ts b/packages/metro-config/test/index.test.ts index 024e5bf3c7..87483f0a9e 100644 --- a/packages/metro-config/test/index.test.ts +++ b/packages/metro-config/test/index.test.ts @@ -2,7 +2,10 @@ import { deepEqual, equal, fail, match, ok, throws } from "node:assert/strict"; import * as fs from "node:fs"; import * as path from "node:path"; import { afterEach, describe, it } from "node:test"; -import { enhanceMiddleware } from "../src/assetPluginForMonorepos.js"; +import { + rewriteRelativePathsAsQueryParam, + rewriteRequestWithQueryParam, +} from "../src/assetPluginForMonorepos.js"; import metroConfigModule from "../src/index.js"; const currentWorkingDir = process.cwd(); @@ -408,7 +411,8 @@ describe("makeMetroConfig()", () => { deepEqual(config.resolver.blacklistRE, blockList); deepEqual(config.resolver.blockList, blockList); - equal(config.server.enhanceMiddleware, enhanceMiddleware); + equal(config.server.enhanceMiddleware, rewriteRelativePathsAsQueryParam); + equal(config.server.rewriteRequestUrl, rewriteRequestWithQueryParam); deepEqual(config.transformer.assetPlugins, []); const opts = { dev: false, hot: true, platform: undefined } as const; @@ -481,7 +485,8 @@ describe("makeMetroConfig()", () => { deepEqual(config.resolver.blacklistRE, blockList); deepEqual(config.resolver.blockList, blockList); - equal(config.server.enhanceMiddleware, enhanceMiddleware); + equal(config.server.enhanceMiddleware, rewriteRelativePathsAsQueryParam); + equal(config.server.rewriteRequestUrl, rewriteRequestWithQueryParam); deepEqual(config.transformer.assetPlugins, []); const opts = { dev: false, hot: true, platform: undefined } as const; From 3a45f36207432a1ec48d0c72d7d2e599e85ba7b1 Mon Sep 17 00:00:00 2001 From: Tommy Nguyen <4123478+tido64@users.noreply.github.com> Date: Tue, 6 Jan 2026 12:51:15 +0100 Subject: [PATCH 3/7] rewriteRequestUrl was added long before unstable_path --- packages/metro-config/src/index.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/metro-config/src/index.js b/packages/metro-config/src/index.js index c8f6dd9be4..ac589f8de1 100644 --- a/packages/metro-config/src/index.js +++ b/packages/metro-config/src/index.js @@ -317,6 +317,15 @@ module.exports = { inputConfig.resolver && (inputConfig.resolver.blockList || inputConfig.resolver.blacklistRE); + const server = supportsAssetPathQueryParam(projectRoot) + ? { + enhanceMiddleware: assetPlugins.rewriteRelativePathsAsQueryParam, + rewriteRequestUrl: assetPlugins.rewriteRequestWithQueryParam, + } + : { + enhanceMiddleware: assetPlugins.escapeRelativePaths, + }; + /** @type {MetroConfig[]} */ const [defaultConfig, ...configs] = [ ...getDefaultConfig(projectRoot, platform), @@ -326,12 +335,7 @@ module.exports = { blacklistRE: blockList, // For Metro < 0.60 blockList, // For Metro >= 0.60 }, - server: { - enhanceMiddleware: supportsAssetPathQueryParam(projectRoot) - ? assetPlugins.rewriteRelativePathsAsQueryParam - : assetPlugins.escapeRelativePaths, - rewriteRequestUrl: assetPlugins.rewriteRequestWithQueryParam, - }, + server, transformer: { getTransformOptions: async () => ({ transform: { From e6d424d57c3a7c099f1dab6ea4f7b1bac74d11ac Mon Sep 17 00:00:00 2001 From: Tommy Nguyen <4123478+tido64@users.noreply.github.com> Date: Tue, 6 Jan 2026 15:41:51 +0100 Subject: [PATCH 4/7] update metro-service to handle query param --- .changeset/busy-ads-rescue.md | 1 + packages/metro-service/src/assets-registry/path-support.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.changeset/busy-ads-rescue.md b/.changeset/busy-ads-rescue.md index 7bcfc5bdfd..87dc95eaac 100644 --- a/.changeset/busy-ads-rescue.md +++ b/.changeset/busy-ads-rescue.md @@ -1,5 +1,6 @@ --- "@rnx-kit/metro-config": patch +"@rnx-kit/metro-service": patch --- Fixed assets outside of project root not rendering diff --git a/packages/metro-service/src/assets-registry/path-support.js b/packages/metro-service/src/assets-registry/path-support.js index 831509305f..d6b1bfc311 100644 --- a/packages/metro-service/src/assets-registry/path-support.js +++ b/packages/metro-service/src/assets-registry/path-support.js @@ -82,7 +82,7 @@ function getAndroidResourceIdentifier(asset) { .toLowerCase() .replace(/\//g, '_') // Encode folder structure in file name .replace(/([^a-z0-9_])/g, '') // Remove illegal chars - .replace(/^assets_/, ''); // Remove "assets_" prefix + .replace(/^(?:assets|assetsunstable_path)_/, ''); // Remove "assets_" or "assetsunstable_path_" prefix } function getBasePath(asset) { From 46a59ea7fccf3e98c8d10fd14d9c2f6b928a021d Mon Sep 17 00:00:00 2001 From: Tommy Nguyen <4123478+tido64@users.noreply.github.com> Date: Tue, 6 Jan 2026 20:15:20 +0100 Subject: [PATCH 5/7] refactor asset plugins --- .../src/assetPluginForMonorepos.js | 107 ------------------ .../src/assetPlugins/escapeAssetURLs.js | 50 ++++++++ .../src/assetPlugins/rewriteAssetURLs.js | 29 +++++ packages/metro-config/src/index.js | 73 +++++++----- .../escapeAssetURLs.test.ts} | 35 +----- .../assetPlugins/rewriteAssetURLs.test.ts | 27 +++++ packages/metro-config/test/index.test.ts | 30 +++-- 7 files changed, 176 insertions(+), 175 deletions(-) delete mode 100644 packages/metro-config/src/assetPluginForMonorepos.js create mode 100644 packages/metro-config/src/assetPlugins/escapeAssetURLs.js create mode 100644 packages/metro-config/src/assetPlugins/rewriteAssetURLs.js rename packages/metro-config/test/{assetPluginForMonorepos.test.ts => assetPlugins/escapeAssetURLs.test.ts} (57%) create mode 100644 packages/metro-config/test/assetPlugins/rewriteAssetURLs.test.ts diff --git a/packages/metro-config/src/assetPluginForMonorepos.js b/packages/metro-config/src/assetPluginForMonorepos.js deleted file mode 100644 index 4bb49ea831..0000000000 --- a/packages/metro-config/src/assetPluginForMonorepos.js +++ /dev/null @@ -1,107 +0,0 @@ -/** - * @typedef {import("connect").NextHandleFunction} NextHandleFunction; - * @typedef {import("metro").AssetData} AssetData; - * @typedef {import("metro-config").ConfigT} ConfigT; - * @typedef {import("metro-config").Middleware} Middleware; - * - * @typedef {import("metro/private/Server").default & { - * _config?: ConfigT; - * }} Server; - */ - -/** - * Metro doesn't support assets in a monorepo setup. When the app requests - * assets at URLs such as `/assets/../../../node_modules/react-native/<...>`, - * the URL will be resolved to `/node_modules/react-native/<...>` and Metro will - * fail to resolve them. The workaround is to replace `..` with something else - * so the URL doesn't collapse when resolved, then restore them in - * `server.enhanceMiddleware`. - * - * For more details, see https://github.com/facebook/metro/issues/290. - * - * @param {import("type-fest").Writable} assetData - * @returns {AssetData} - */ -function assetPlugin(assetData) { - assetData.httpServerLocation = assetData.httpServerLocation.replaceAll( - "../", - "@@/" - ); - return assetData; -} - -/** - * Injects {@link assetPlugin} into server asset plugins. - * - * This should only be called from {@link enhanceMiddleware} to ensure that the - * asset plugin is only applied when we are serving. This has the nice - * side-effect that the plugin doesn't get included if the middleware is - * unused (during bundling) or removed. - * - * @param {Server} server - */ -function injectAssetPlugin(server) { - const config = server._config; - if (!config || !Array.isArray(config.transformer.assetPlugins)) { - console.warn( - "'@rnx-kit/metro-config' was unable to install the asset plugin for " + - "monorepos. Please try again with the latest version. If this " + - "warning still persists, you can file an issue at " + - "https://github.com/microsoft/rnx-kit/issues/new?assignees=&labels=bug&template=bug_report.yml" - ); - return; - } - - config.transformer.assetPlugins.push(__filename); -} - -/** - * Rewrites (and restores) `..` to `@@` in asset URLs to avoid transformations. - * @param {Middleware} middleware - * @param {Server} server - * @returns {NextHandleFunction} - */ -function escapeRelativePaths(middleware, server) { - injectAssetPlugin(server); - return (req, res, next) => { - const { url } = req; - if (url?.startsWith("/assets/")) { - req.url = url.replaceAll("@@/", "../"); - } - return middleware(req, res, next); - }; -} - -/** - * Rewrites asset URLs as a query parameter. - * @param {string} url - * @returns {string} - */ -function rewriteRequestWithQueryParam(url) { - const prefix = "/assets/../"; - return url.startsWith(prefix) - ? url.replace(prefix, "/assets?unstable_path=../") - : url; -} - -/** - * Rewrites asset URLs as a query parameter. - * @param {Middleware} middleware - * @param {Server} _server - * @returns {NextHandleFunction} - */ -function rewriteRelativePathsAsQueryParam(middleware, _server) { - return (req, res, next) => { - const { url } = req; - if (url) { - req.url = rewriteRequestWithQueryParam(url); - } - return middleware(req, res, next); - }; -} - -module.exports = assetPlugin; -module.exports.escapeRelativePaths = escapeRelativePaths; -module.exports.rewriteRelativePathsAsQueryParam = - rewriteRelativePathsAsQueryParam; -module.exports.rewriteRequestWithQueryParam = rewriteRequestWithQueryParam; diff --git a/packages/metro-config/src/assetPlugins/escapeAssetURLs.js b/packages/metro-config/src/assetPlugins/escapeAssetURLs.js new file mode 100644 index 0000000000..a9220fb173 --- /dev/null +++ b/packages/metro-config/src/assetPlugins/escapeAssetURLs.js @@ -0,0 +1,50 @@ +/** + * @typedef {import("metro").AssetData} AssetData; + * @typedef {import("metro-config").ConfigT} ConfigT; + * @typedef {import("metro-config").Middleware} Middleware; + * + * @typedef {import("metro/private/Server").default & { + * _config?: ConfigT; + * }} Server; + */ + +/** + * Metro doesn't support assets in a monorepo setup. When the app requests + * assets at URLs such as `/assets/../../../node_modules/react-native/<...>`, + * the URL will be resolved to `/node_modules/react-native/<...>` and Metro will + * fail to resolve them. The workaround is to replace `..` with something else + * so the URL doesn't collapse when resolved, then restore them in + * `server.enhanceMiddleware`. + * + * For more details, see https://github.com/facebook/metro/issues/290. + * + * @param {import("type-fest").Writable} assetData + * @returns {AssetData} + */ +function assetPlugin(assetData) { + assetData.httpServerLocation = assetData.httpServerLocation.replaceAll( + "../", + "@@/" + ); + return assetData; +} + +/** + * This middleware restores `..` in asset URLs. + * + * @param {Middleware} middleware + * @param {Server} _server + * @returns {import("connect").NextHandleFunction} + */ +function enhanceMiddleware(middleware, _server) { + return (req, res, next) => { + const { url } = req; + if (url && url.startsWith("/assets/")) { + req.url = url.replaceAll("@@/", "../"); + } + return middleware(req, res, next); + }; +} + +module.exports = assetPlugin; +module.exports.enhanceMiddleware = enhanceMiddleware; diff --git a/packages/metro-config/src/assetPlugins/rewriteAssetURLs.js b/packages/metro-config/src/assetPlugins/rewriteAssetURLs.js new file mode 100644 index 0000000000..34b455860f --- /dev/null +++ b/packages/metro-config/src/assetPlugins/rewriteAssetURLs.js @@ -0,0 +1,29 @@ +/** + * @typedef {import("metro").AssetData} AssetData; + */ + +/** + * Metro doesn't support assets in a monorepo setup. When the app requests + * assets at URLs such as `/assets/../../../node_modules/react-native/<...>`, + * the URL will be resolved to `/node_modules/react-native/<...>` and Metro will + * fail to resolve them. + * + * In 0.67, they introduced a query parameter, `unstable_path`, specifically to + * handle such cases. + * + * For more details, see https://github.com/facebook/metro/issues/290. + * + * @param {import("type-fest").Writable} assetData + * @returns {AssetData} + */ +module.exports = function (assetData) { + const prefix = "/assets/../"; + const url = assetData.httpServerLocation; + if (url.startsWith(prefix)) { + assetData.httpServerLocation = url.replace( + prefix, + "/assets?unstable_path=../" + ); + } + return assetData; +}; diff --git a/packages/metro-config/src/index.js b/packages/metro-config/src/index.js index ac589f8de1..9b80cb8893 100644 --- a/packages/metro-config/src/index.js +++ b/packages/metro-config/src/index.js @@ -293,6 +293,50 @@ function supportsAssetPathQueryParam(projectRoot) { return Number(major) * 1000 + Number(minor) >= 67; } +/** + * @param {string} projectRoot + * @param {InputConfig} inputConfig + * @returns {MetroConfig} + */ +function additionalConfig(projectRoot, inputConfig) { + const blockList = exclusionList([], projectRoot); + + /** @type {import("type-fest").WritableDeep} */ + const transformer = { + getTransformOptions: async () => ({ + transform: { + experimentalImportSupport: false, + inlineRequires: false, + }, + }), + }; + + /** @type {import("type-fest").Writable} */ + const config = { + resolver: { + resolverMainFields: ["react-native", "browser", "main"], + blacklistRE: blockList, // For Metro < 0.60 + blockList, // For Metro >= 0.60 + }, + transformer, + watchFolders: inputConfig.watchFolders ?? defaultWatchFolders(), + }; + + if (supportsAssetPathQueryParam(projectRoot)) { + transformer.assetPlugins = [ + require.resolve("./assetPlugins/rewriteAssetURLs.js"), + ]; + } else { + const { enhanceMiddleware } = require("./assetPlugins/escapeAssetURLs.js"); + config.server = { enhanceMiddleware }; + transformer.assetPlugins = [ + require.resolve("./assetPlugins/escapeAssetURLs.js"), + ]; + } + + return config; +} + module.exports = { defaultWatchFolders, excludeExtraCopiesOf, @@ -309,43 +353,16 @@ module.exports = { const projectRoot = inputConfig.projectRoot || process.cwd(); const { mergeConfig } = requireModuleFromMetro("metro-config", projectRoot); - const assetPlugins = require("./assetPluginForMonorepos"); const { getDefaultConfig } = require("./defaultConfig"); - const blockList = exclusionList([], projectRoot); const customBlockList = inputConfig.resolver && (inputConfig.resolver.blockList || inputConfig.resolver.blacklistRE); - const server = supportsAssetPathQueryParam(projectRoot) - ? { - enhanceMiddleware: assetPlugins.rewriteRelativePathsAsQueryParam, - rewriteRequestUrl: assetPlugins.rewriteRequestWithQueryParam, - } - : { - enhanceMiddleware: assetPlugins.escapeRelativePaths, - }; - /** @type {MetroConfig[]} */ const [defaultConfig, ...configs] = [ ...getDefaultConfig(projectRoot, platform), - { - resolver: { - resolverMainFields: ["react-native", "browser", "main"], - blacklistRE: blockList, // For Metro < 0.60 - blockList, // For Metro >= 0.60 - }, - server, - transformer: { - getTransformOptions: async () => ({ - transform: { - experimentalImportSupport: false, - inlineRequires: false, - }, - }), - }, - watchFolders: inputConfig.watchFolders ?? defaultWatchFolders(), - }, + additionalConfig(projectRoot, inputConfig), { ...inputConfig, resolver: { diff --git a/packages/metro-config/test/assetPluginForMonorepos.test.ts b/packages/metro-config/test/assetPlugins/escapeAssetURLs.test.ts similarity index 57% rename from packages/metro-config/test/assetPluginForMonorepos.test.ts rename to packages/metro-config/test/assetPlugins/escapeAssetURLs.test.ts index 2d856d78d8..2a8da3bfd7 100644 --- a/packages/metro-config/test/assetPluginForMonorepos.test.ts +++ b/packages/metro-config/test/assetPlugins/escapeAssetURLs.test.ts @@ -4,11 +4,12 @@ import type Server from "metro/private/Server"; import { equal } from "node:assert/strict"; import type { IncomingMessage, ServerResponse } from "node:http"; import { describe, it } from "node:test"; -import assetPlugin from "../src/assetPluginForMonorepos.js"; +import { + enhanceMiddleware, + default as escapeAssetURL, +} from "../../src/assetPlugins/escapeAssetURLs.js"; describe("assetPluginForMonorepos/escapeRelativePaths", () => { - const { escapeRelativePaths } = assetPlugin; - const cases = [ ["/assets/./node_modules", "/assets/./node_modules"], ["/assets/../node_modules", "/assets/@@/node_modules"], @@ -22,7 +23,7 @@ describe("assetPluginForMonorepos/escapeRelativePaths", () => { it("escapes `..` in URLs", () => { for (const [input, output] of cases) { const assetData = { httpServerLocation: input } as AssetData; - equal(assetPlugin(assetData).httpServerLocation, output); + equal(escapeAssetURL(assetData).httpServerLocation, output); } }); @@ -39,7 +40,7 @@ describe("assetPluginForMonorepos/escapeRelativePaths", () => { const incoming = { url: input } as IncomingMessage; const response = {} as ServerResponse; - escapeRelativePaths(middleware, server)( + enhanceMiddleware(middleware, server)( incoming, response, () => undefined @@ -47,27 +48,3 @@ describe("assetPluginForMonorepos/escapeRelativePaths", () => { } }); }); - -describe("assetPluginForMonorepos/rewriteRequestWithQueryParam", () => { - const { rewriteRequestWithQueryParam } = assetPlugin; - - const cases = [ - ["/assets/./node_modules", "/assets/./node_modules"], - ["/assets/../node_modules", "/assets?unstable_path=../node_modules"], - ["/assets/../../node_modules", "/assets?unstable_path=../../node_modules"], - [ - "/assets/node_modules/../../react-native", - "/assets/node_modules/../../react-native", - ], - [ - "/assets/local/path/with/nested/assets/../../react-native", - "/assets/local/path/with/nested/assets/../../react-native", - ], - ] as const; - - it("rewrites request URLs with relative paths", () => { - for (const [input, output] of cases) { - equal(rewriteRequestWithQueryParam(input), output); - } - }); -}); diff --git a/packages/metro-config/test/assetPlugins/rewriteAssetURLs.test.ts b/packages/metro-config/test/assetPlugins/rewriteAssetURLs.test.ts new file mode 100644 index 0000000000..87a2fe3911 --- /dev/null +++ b/packages/metro-config/test/assetPlugins/rewriteAssetURLs.test.ts @@ -0,0 +1,27 @@ +import type { AssetData } from "metro"; +import { deepEqual } from "node:assert/strict"; +import { describe, it } from "node:test"; +import rewriteRequest from "../../src/assetPlugins/rewriteAssetURLs.js"; + +describe("assetPluginForMonorepos/rewriteRequestWithQueryParam", () => { + const cases = [ + ["/assets/./node_modules", "/assets/./node_modules"], + ["/assets/../node_modules", "/assets?unstable_path=../node_modules"], + ["/assets/../../node_modules", "/assets?unstable_path=../../node_modules"], + [ + "/assets/node_modules/../../react-native", + "/assets/node_modules/../../react-native", + ], + [ + "/assets/local/path/with/nested/assets/../../react-native", + "/assets/local/path/with/nested/assets/../../react-native", + ], + ] as const; + + it("rewrites request URLs with relative paths", () => { + for (const [input, output] of cases) { + const assetData = { httpServerLocation: input } as AssetData; + deepEqual(rewriteRequest(assetData), { httpServerLocation: output }); + } + }); +}); diff --git a/packages/metro-config/test/index.test.ts b/packages/metro-config/test/index.test.ts index 87483f0a9e..bd95122db4 100644 --- a/packages/metro-config/test/index.test.ts +++ b/packages/metro-config/test/index.test.ts @@ -1,11 +1,8 @@ import { deepEqual, equal, fail, match, ok, throws } from "node:assert/strict"; import * as fs from "node:fs"; +import { createRequire } from "node:module"; import * as path from "node:path"; -import { afterEach, describe, it } from "node:test"; -import { - rewriteRelativePathsAsQueryParam, - rewriteRequestWithQueryParam, -} from "../src/assetPluginForMonorepos.js"; +import { after, afterEach, before, describe, it } from "node:test"; import metroConfigModule from "../src/index.js"; const currentWorkingDir = process.cwd(); @@ -357,10 +354,21 @@ describe("exclusionList()", () => { }); describe("makeMetroConfig()", () => { + const globalRequire = global.require; + const { exclusionList, makeMetroConfig } = metroConfigModule; const projectRoot = path.resolve("../test-app"); + before(() => { + // @ts-expect-error Tests are run in ESM mode + global.require = createRequire(new URL("../src/index.js", import.meta.url)); + }); + + after(() => { + global.require = globalRequire; + }); + it("returns a default Metro config", async () => { const config = makeMetroConfig({ projectRoot }); @@ -411,9 +419,9 @@ describe("makeMetroConfig()", () => { deepEqual(config.resolver.blacklistRE, blockList); deepEqual(config.resolver.blockList, blockList); - equal(config.server.enhanceMiddleware, rewriteRelativePathsAsQueryParam); - equal(config.server.rewriteRequestUrl, rewriteRequestWithQueryParam); - deepEqual(config.transformer.assetPlugins, []); + deepEqual(config.transformer.assetPlugins, [ + require.resolve("../src/assetPlugins/rewriteAssetURLs.js"), + ]); const opts = { dev: false, hot: true, platform: undefined } as const; const transformerOptions = await config.transformer.getTransformOptions( @@ -485,9 +493,9 @@ describe("makeMetroConfig()", () => { deepEqual(config.resolver.blacklistRE, blockList); deepEqual(config.resolver.blockList, blockList); - equal(config.server.enhanceMiddleware, rewriteRelativePathsAsQueryParam); - equal(config.server.rewriteRequestUrl, rewriteRequestWithQueryParam); - deepEqual(config.transformer.assetPlugins, []); + deepEqual(config.transformer.assetPlugins, [ + require.resolve("../src/assetPlugins/rewriteAssetURLs.js"), + ]); const opts = { dev: false, hot: true, platform: undefined } as const; const transformerOptions = await config.transformer.getTransformOptions( From b80ccd3d33270ed0ccf3c56ccf8d80b112fd376c Mon Sep 17 00:00:00 2001 From: Tommy Nguyen <4123478+tido64@users.noreply.github.com> Date: Wed, 7 Jan 2026 12:05:54 +0100 Subject: [PATCH 6/7] missed one more use in metro-service --- packages/metro-service/src/asset/default.ts | 5 ++++- packages/metro-service/src/asset/saveAssets.ts | 12 +++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/metro-service/src/asset/default.ts b/packages/metro-service/src/asset/default.ts index ebf215c938..0ccbd7d44c 100644 --- a/packages/metro-service/src/asset/default.ts +++ b/packages/metro-service/src/asset/default.ts @@ -8,7 +8,10 @@ export function getAssetDestPath(asset: PackagerAsset, scale: number): string { // Assets can have relative paths outside of the project root. // Replace `../` with `_` to make sure they don't end up outside of // the expected assets directory. - asset.httpServerLocation.substr(1).replaceAll("../", "_"), + asset.httpServerLocation + .substring(1) + .replace("?unstable_path=", "/") + .replaceAll("../", "_"), fileName ); } diff --git a/packages/metro-service/src/asset/saveAssets.ts b/packages/metro-service/src/asset/saveAssets.ts index 965c13cfda..a00c18d4e0 100644 --- a/packages/metro-service/src/asset/saveAssets.ts +++ b/packages/metro-service/src/asset/saveAssets.ts @@ -30,7 +30,17 @@ export function getSaveAssetsPlugin( const { default: saveAssets } = require( path.join(pluginPath, "dist", "commands", "bundle", "saveAssets.js") ); - return saveAssets; + const param = "?unstable_path="; + return (assets, ...args) => { + for (const asset of assets) { + const { httpServerLocation } = asset; + if (httpServerLocation.includes(param)) { + // @ts-expect-error Intentionally modifying a read-only property + asset.httpServerLocation = httpServerLocation.replace(param, "/"); + } + } + return saveAssets(assets, ...args); + }; } switch (platform) { From df9c55f798abcc9860c700aa8ced8810b1e976d2 Mon Sep 17 00:00:00 2001 From: Tommy Nguyen <4123478+tido64@users.noreply.github.com> Date: Thu, 8 Jan 2026 14:35:34 +0100 Subject: [PATCH 7/7] restore defaults --- .changeset/busy-ads-rescue.md | 16 ++++++- .../src/assetPlugins/escapeAssetURLs.js | 46 +++++++++---------- .../src/assetPlugins/rewriteAssetURLs.js | 3 +- packages/metro-config/src/index.js | 27 ++++------- .../test/assetPlugins/escapeAssetURLs.test.ts | 24 ++-------- .../assetPlugins/rewriteAssetURLs.test.ts | 2 +- packages/metro-config/test/index.test.ts | 4 +- 7 files changed, 54 insertions(+), 68 deletions(-) diff --git a/.changeset/busy-ads-rescue.md b/.changeset/busy-ads-rescue.md index 87dc95eaac..b69c20f93e 100644 --- a/.changeset/busy-ads-rescue.md +++ b/.changeset/busy-ads-rescue.md @@ -3,4 +3,18 @@ "@rnx-kit/metro-service": patch --- -Fixed assets outside of project root not rendering +Fixed assets outside of project root not rendering. This breaks release builds +so it must be manually enabled in `metro.config.js`: + +```diff +diff --git a/metro.config.js b/metro.config.js +index 000000000..000000000 100644 +--- a/metro.config.js ++++ b/metro.config.js +@@ -34,4 +34,5 @@ module.exports = makeMetroConfig({ + blacklistRE: blockList, + blockList, + }, ++ unstable_allowAssetsOutsideProjectRoot: true, + }); +``` diff --git a/packages/metro-config/src/assetPlugins/escapeAssetURLs.js b/packages/metro-config/src/assetPlugins/escapeAssetURLs.js index a9220fb173..2b27941ff5 100644 --- a/packages/metro-config/src/assetPlugins/escapeAssetURLs.js +++ b/packages/metro-config/src/assetPlugins/escapeAssetURLs.js @@ -1,20 +1,26 @@ /** * @typedef {import("metro").AssetData} AssetData; - * @typedef {import("metro-config").ConfigT} ConfigT; - * @typedef {import("metro-config").Middleware} Middleware; - * - * @typedef {import("metro/private/Server").default & { - * _config?: ConfigT; - * }} Server; */ +/** + * @param {string} str + * @param {string} searchValue + * @param {string} replaceValue + * @returns {string} + */ +function replaceString(str, searchValue, replaceValue) { + return str.startsWith("/assets/") + ? str.replaceAll(searchValue, replaceValue) + : str; +} + /** * Metro doesn't support assets in a monorepo setup. When the app requests * assets at URLs such as `/assets/../../../node_modules/react-native/<...>`, * the URL will be resolved to `/node_modules/react-native/<...>` and Metro will * fail to resolve them. The workaround is to replace `..` with something else * so the URL doesn't collapse when resolved, then restore them in - * `server.enhanceMiddleware`. + * `server.rewriteRequestUrl`. * * For more details, see https://github.com/facebook/metro/issues/290. * @@ -22,29 +28,19 @@ * @returns {AssetData} */ function assetPlugin(assetData) { - assetData.httpServerLocation = assetData.httpServerLocation.replaceAll( - "../", - "@@/" - ); + const url = assetData.httpServerLocation; + assetData.httpServerLocation = replaceString(url, "../", "@@/"); return assetData; } /** - * This middleware restores `..` in asset URLs. - * - * @param {Middleware} middleware - * @param {Server} _server - * @returns {import("connect").NextHandleFunction} + * Restores `..` in asset URLs. + * @param {string} url + * @returns {string} */ -function enhanceMiddleware(middleware, _server) { - return (req, res, next) => { - const { url } = req; - if (url && url.startsWith("/assets/")) { - req.url = url.replaceAll("@@/", "../"); - } - return middleware(req, res, next); - }; +function restoreAssetURL(url) { + return replaceString(url, "@@/", "../"); } module.exports = assetPlugin; -module.exports.enhanceMiddleware = enhanceMiddleware; +module.exports.restoreAssetURL = restoreAssetURL; diff --git a/packages/metro-config/src/assetPlugins/rewriteAssetURLs.js b/packages/metro-config/src/assetPlugins/rewriteAssetURLs.js index 34b455860f..fe29e369c2 100644 --- a/packages/metro-config/src/assetPlugins/rewriteAssetURLs.js +++ b/packages/metro-config/src/assetPlugins/rewriteAssetURLs.js @@ -9,7 +9,8 @@ * fail to resolve them. * * In 0.67, they introduced a query parameter, `unstable_path`, specifically to - * handle such cases. + * handle such cases. However, this isn't properly fleshed out and only works in + * server mode. Bundling with this plugin may cause issues with asset paths. * * For more details, see https://github.com/facebook/metro/issues/290. * diff --git a/packages/metro-config/src/index.js b/packages/metro-config/src/index.js index 9b80cb8893..c12e860465 100644 --- a/packages/metro-config/src/index.js +++ b/packages/metro-config/src/index.js @@ -3,7 +3,6 @@ const { findMetroPath, - getMetroVersion, requireModuleFromMetro, } = require("@rnx-kit/tools-react-native/metro"); const fs = require("node:fs"); @@ -12,7 +11,10 @@ const { applyExpoWorkarounds, isExpoConfig } = require("./expoConfig"); /** * @typedef {import("metro-config").MetroConfig} MetroConfig; - * @typedef {MetroConfig & { platform?: string; }} InputConfig; + * @typedef {MetroConfig & { + * platform?: string; + * unstable_allowAssetsOutsideProjectRoot?: boolean; + * }} InputConfig; */ /** Packages that must be resolved to one specific copy. */ @@ -281,18 +283,6 @@ function exclusionList(additionalExclusions = [], projectRoot = process.cwd()) { ]; } -/** - * Returns whether Metro supports the `unstable_path` query parameter. - * @param {string} projectRoot - * @returns {boolean} - */ -function supportsAssetPathQueryParam(projectRoot) { - // https://github.com/facebook/metro/commit/f3d1157bacc341dff82efea2f70b634141105fc0 - const version = getMetroVersion(projectRoot) || "0.0.0"; - const [major = 0, minor = 0] = version.split("."); - return Number(major) * 1000 + Number(minor) >= 67; -} - /** * @param {string} projectRoot * @param {InputConfig} inputConfig @@ -322,13 +312,16 @@ function additionalConfig(projectRoot, inputConfig) { watchFolders: inputConfig.watchFolders ?? defaultWatchFolders(), }; - if (supportsAssetPathQueryParam(projectRoot)) { + if (inputConfig.unstable_allowAssetsOutsideProjectRoot) { + // We currently cannot enable this by default because it affects the + // structure of the assets folder, breaking release builds. transformer.assetPlugins = [ require.resolve("./assetPlugins/rewriteAssetURLs.js"), ]; } else { - const { enhanceMiddleware } = require("./assetPlugins/escapeAssetURLs.js"); - config.server = { enhanceMiddleware }; + const { restoreAssetURL } = require("./assetPlugins/escapeAssetURLs.js"); + config.server = { rewriteRequestUrl: restoreAssetURL }; + transformer.assetPlugins = [ require.resolve("./assetPlugins/escapeAssetURLs.js"), ]; diff --git a/packages/metro-config/test/assetPlugins/escapeAssetURLs.test.ts b/packages/metro-config/test/assetPlugins/escapeAssetURLs.test.ts index 2a8da3bfd7..9615822175 100644 --- a/packages/metro-config/test/assetPlugins/escapeAssetURLs.test.ts +++ b/packages/metro-config/test/assetPlugins/escapeAssetURLs.test.ts @@ -1,15 +1,12 @@ import type { AssetData } from "metro"; -import type { Middleware } from "metro-config"; -import type Server from "metro/private/Server"; import { equal } from "node:assert/strict"; -import type { IncomingMessage, ServerResponse } from "node:http"; import { describe, it } from "node:test"; import { - enhanceMiddleware, default as escapeAssetURL, + restoreAssetURL, } from "../../src/assetPlugins/escapeAssetURLs.js"; -describe("assetPluginForMonorepos/escapeRelativePaths", () => { +describe("assetPlugins/escapeRelativePaths", () => { const cases = [ ["/assets/./node_modules", "/assets/./node_modules"], ["/assets/../node_modules", "/assets/@@/node_modules"], @@ -29,22 +26,7 @@ describe("assetPluginForMonorepos/escapeRelativePaths", () => { it("unescapes `..` in URLs", () => { for (const [output, input] of cases) { - const middleware: Middleware = (req: Middleware) => { - equal("url" in req && req.url, output); - return middleware; - }; - const server = { - _config: { transformer: { assetPlugins: [] } }, - } as unknown as Server; - - const incoming = { url: input } as IncomingMessage; - const response = {} as ServerResponse; - - enhanceMiddleware(middleware, server)( - incoming, - response, - () => undefined - ); + equal(restoreAssetURL(input), output); } }); }); diff --git a/packages/metro-config/test/assetPlugins/rewriteAssetURLs.test.ts b/packages/metro-config/test/assetPlugins/rewriteAssetURLs.test.ts index 87a2fe3911..08c7580593 100644 --- a/packages/metro-config/test/assetPlugins/rewriteAssetURLs.test.ts +++ b/packages/metro-config/test/assetPlugins/rewriteAssetURLs.test.ts @@ -3,7 +3,7 @@ import { deepEqual } from "node:assert/strict"; import { describe, it } from "node:test"; import rewriteRequest from "../../src/assetPlugins/rewriteAssetURLs.js"; -describe("assetPluginForMonorepos/rewriteRequestWithQueryParam", () => { +describe("assetPlugins/rewriteRequestWithQueryParam", () => { const cases = [ ["/assets/./node_modules", "/assets/./node_modules"], ["/assets/../node_modules", "/assets?unstable_path=../node_modules"], diff --git a/packages/metro-config/test/index.test.ts b/packages/metro-config/test/index.test.ts index bd95122db4..4c44dbcc84 100644 --- a/packages/metro-config/test/index.test.ts +++ b/packages/metro-config/test/index.test.ts @@ -420,7 +420,7 @@ describe("makeMetroConfig()", () => { deepEqual(config.resolver.blockList, blockList); deepEqual(config.transformer.assetPlugins, [ - require.resolve("../src/assetPlugins/rewriteAssetURLs.js"), + require.resolve("../src/assetPlugins/escapeAssetURLs.js"), ]); const opts = { dev: false, hot: true, platform: undefined } as const; @@ -494,7 +494,7 @@ describe("makeMetroConfig()", () => { deepEqual(config.resolver.blockList, blockList); deepEqual(config.transformer.assetPlugins, [ - require.resolve("../src/assetPlugins/rewriteAssetURLs.js"), + require.resolve("../src/assetPlugins/escapeAssetURLs.js"), ]); const opts = { dev: false, hot: true, platform: undefined } as const;