From 010e3b138a9c3ac7196d1cb65170f96599545fe3 Mon Sep 17 00:00:00 2001 From: Matthieu Sieben Date: Tue, 23 Apr 2024 16:07:27 +0200 Subject: [PATCH] feat(dev): allow using @atproto packages from another directory --- metro.config.js | 40 ++++++++++++++++++++++++++++++++++++++++ webpack.config.js | 21 +++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/metro.config.js b/metro.config.js index a49d95f9aa..80d2e34baf 100644 --- a/metro.config.js +++ b/metro.config.js @@ -1,7 +1,47 @@ // Learn more https://docs.expo.io/guides/customizing-metro +const path = require('path') const {getDefaultConfig} = require('expo/metro-config') const cfg = getDefaultConfig(__dirname) +if (process.env.ATPROTO_ROOT) { + const atprotoRoot = path.resolve(process.cwd(), process.env.ATPROTO_ROOT) + + // Watch folders are used as roots for the virtual file system. Any file that + // needs to be resolved by the metro bundler must be within one of the watch + // folders. Since we will be resolving dependencies from the atproto packages, + // we need to add the atproto root to the watch folders so that the + cfg.watchFolders ||= [] + cfg.watchFolders.push(atprotoRoot) + + const resolveRequest = cfg.resolver.resolveRequest + cfg.resolver.resolveRequest = (context, moduleName, platform) => { + // Alias @atproto/* modules to the corresponding package in the atproto root + if (moduleName.startsWith('@atproto/')) { + const [, packageName] = moduleName.split('/', 2) + const packagePath = path.join(atprotoRoot, 'packages', packageName) + return context.resolveRequest(context, packagePath, platform) + } + + // Polyfills are added by the build process and are not actual dependencies + // of the @atproto/* packages. Resolve those from here. + if ( + moduleName.startsWith('@babel/') && + context.originModulePath.startsWith(atprotoRoot) + ) { + return { + type: 'sourceFile', + filePath: require.resolve(moduleName), + } + } + + return (resolveRequest || context.resolveRequest)( + context, + moduleName, + platform, + ) + } +} + cfg.resolver.sourceExts = process.env.RN_SRC_EXT ? process.env.RN_SRC_EXT.split(',').concat(cfg.resolver.sourceExts) : cfg.resolver.sourceExts diff --git a/webpack.config.js b/webpack.config.js index 6f1de3b8b7..5aa2d47f5b 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,3 +1,5 @@ +const fs = require('fs') +const path = require('path') const createExpoWebpackConfigAsync = require('@expo/webpack-config') const {withAlias} = require('@expo/webpack-config/addons') const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin') @@ -22,6 +24,25 @@ module.exports = async function (env, argv) { 'react-native$': 'react-native-web', 'react-native-webview': 'react-native-web-webview', }) + + if (process.env.ATPROTO_ROOT) { + const atprotoRoot = path.resolve(process.cwd(), process.env.ATPROTO_ROOT) + const atprotoPackages = path.join(atprotoRoot, 'packages') + + config = withAlias( + config, + Object.fromEntries( + fs + .readdirSync(atprotoPackages) + .map(pkgName => [pkgName, path.join(atprotoPackages, pkgName)]) + .filter(([_, pkgPath]) => + fs.existsSync(path.join(pkgPath, 'package.json')), + ) + .map(([pkgName, pkgPath]) => [`@atproto/${pkgName}`, pkgPath]), + ), + ) + } + config.module.rules = [ ...(config.module.rules || []), reactNativeWebWebviewConfiguration,