|
1 | 1 | import { getDefaultConfig, mergeConfig } from '@react-native/metro-config'; |
2 | 2 | import path from 'node:path'; |
3 | 3 | import { fileURLToPath } from 'node:url'; |
| 4 | + |
4 | 5 | const __filename = fileURLToPath(import.meta.url); |
5 | 6 | const __dirname = path.dirname(__filename); |
6 | 7 |
|
| 8 | +/** Monorepo root (parent of formulus) so Metro can resolve @ode/tokens and @ode/components */ |
| 9 | +const monorepoRoot = path.resolve(__dirname, '..'); |
| 10 | + |
| 11 | +/** |
| 12 | + * Force a single React/react-native instance so hooks work (avoids "Invalid hook call" / "useState of null"). |
| 13 | + * Without this, @ode/components would use its own node_modules/react and we'd have two React copies. |
| 14 | + */ |
| 15 | +const projectRoot = __dirname; |
| 16 | + |
| 17 | +/** |
| 18 | + * Force react and react-native to always resolve from the app's node_modules |
| 19 | + * (avoids incomplete copy in packages/components). react-native-svg only uses |
| 20 | + * extraNodeModules so Metro resolves its real entry (lib/commonjs/index.js). |
| 21 | + */ |
| 22 | +const forcedModules = { |
| 23 | + react: path.resolve(projectRoot, 'node_modules/react'), |
| 24 | + 'react-native': path.resolve(projectRoot, 'node_modules/react-native'), |
| 25 | +}; |
| 26 | +const extraModules = { |
| 27 | + ...forcedModules, |
| 28 | + 'react-native-svg': path.resolve( |
| 29 | + projectRoot, |
| 30 | + 'node_modules/react-native-svg', |
| 31 | + ), |
| 32 | +}; |
| 33 | + |
7 | 34 | /** |
8 | 35 | * Metro configuration |
9 | 36 | * https://reactnative.dev/docs/metro |
10 | 37 | * |
11 | 38 | * @type {import('@react-native/metro-config').MetroConfig} |
12 | 39 | */ |
13 | | -const config = {}; |
| 40 | +const config = { |
| 41 | + watchFolders: [monorepoRoot], |
| 42 | + resolver: { |
| 43 | + unstable_enableSymlinks: true, |
| 44 | + unstable_enablePackageExports: true, |
| 45 | + extraNodeModules: extraModules, |
| 46 | + resolveRequest(context, moduleName, platform) { |
| 47 | + if (forcedModules[moduleName]) { |
| 48 | + return { |
| 49 | + type: 'sourceFile', |
| 50 | + filePath: path.join(forcedModules[moduleName], 'index.js'), |
| 51 | + }; |
| 52 | + } |
| 53 | + return context.resolveRequest(context, moduleName, platform); |
| 54 | + }, |
| 55 | + }, |
| 56 | +}; |
14 | 57 |
|
15 | 58 | export default mergeConfig(getDefaultConfig(__dirname), config); |
0 commit comments