Skip to content

Commit f395792

Browse files
committed
feat: add helpers for getting RN path, version and platforms to simplify bundler plugin config
1 parent 21c6565 commit f395792

File tree

4 files changed

+96
-31
lines changed

4 files changed

+96
-31
lines changed

packages/config/src/lib/config.ts

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ export type PluginOutput = {
1010
export type PluginApi = {
1111
registerCommand: (command: CommandType) => void;
1212
getProjectRoot: () => string;
13+
getReactNativeVersion: () => string;
14+
getReactNativePath: () => string;
15+
getPlatforms: () => { [platform: string]: object };
1316
};
1417

1518
type PluginType = (args: PluginApi) => PluginOutput;
@@ -30,6 +33,8 @@ type CommandType = {
3033

3134
type ConfigType = {
3235
root?: string;
36+
reactNativeVersion?: string;
37+
reactNativePath?: string;
3338
plugins?: Record<string, PluginType>;
3439
platforms?: Record<string, PluginType>;
3540
commands?: Array<CommandType>;
@@ -41,13 +46,13 @@ type ConfigOutput = {
4146

4247
const extensions = ['.js', '.ts', '.mjs'];
4348

44-
const importUp = async <T>(dir: string, name: string): Promise<T> => {
49+
const importUp = async (dir: string, name: string): Promise<ConfigType> => {
4550
const filePath = path.join(dir, name);
4651

4752
for (const ext of extensions) {
4853
const filePathWithExt = `${filePath}${ext}`;
4954
if (fs.existsSync(filePathWithExt)) {
50-
let config: T;
55+
let config: ConfigType;
5156

5257
if (ext === '.mjs') {
5358
config = await import(filePathWithExt).then((module) => module.default);
@@ -58,6 +63,12 @@ const importUp = async <T>(dir: string, name: string): Promise<T> => {
5863

5964
return {
6065
root: dir,
66+
get reactNativePath() {
67+
return resolveReactNativePath(config.root || dir);
68+
},
69+
get reactNativeVersion() {
70+
return getReactNativeVersion(config.root || dir);
71+
},
6172
...config,
6273
};
6374
}
@@ -74,7 +85,7 @@ const importUp = async <T>(dir: string, name: string): Promise<T> => {
7485
export async function getConfig(
7586
dir: string = process.cwd()
7687
): Promise<ConfigOutput> {
77-
const config = await importUp<ConfigType>(dir, 'rnef.config');
88+
const config = await importUp(dir, 'rnef.config');
7889

7990
if (!config.root) {
8091
config.root = process.cwd();
@@ -85,6 +96,9 @@ export async function getConfig(
8596
config.commands = [...(config.commands || []), command];
8697
},
8798
getProjectRoot: () => config.root as string,
99+
getReactNativeVersion: () => config.reactNativeVersion as string,
100+
getReactNativePath: () => config.reactNativePath as string,
101+
getPlatforms: () => config.platforms as { [platform: string]: object },
88102
};
89103

90104
if (config.plugins) {
@@ -107,3 +121,26 @@ export async function getConfig(
107121

108122
return outputConfig;
109123
}
124+
125+
function getReactNativeVersion(root: string) {
126+
try {
127+
const require = createRequire(import.meta.url);
128+
return JSON.parse(
129+
fs.readFileSync(
130+
path.join(
131+
require.resolve('react-native', { paths: [root] }),
132+
'..',
133+
'package.json'
134+
),
135+
'utf-8'
136+
)
137+
).version;
138+
} catch {
139+
return 'unknown';
140+
}
141+
}
142+
143+
function resolveReactNativePath(root: string) {
144+
const require = createRequire(import.meta.url);
145+
return path.join(require.resolve('react-native', { paths: [root] }), '..');
146+
}

packages/plugin-metro/src/__tests__/pluginMetro.test.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
import { pluginMetro } from '../lib/pluginMetro.js';
22
import { expect, test } from 'vitest';
33

4-
const pluginApi = { registerCommand: vi.fn() };
4+
const pluginApi = {
5+
registerCommand: vi.fn(),
6+
getProjectRoot: vi.fn(),
7+
getReactNativePath: vi.fn(),
8+
getReactNativeVersion: vi.fn(),
9+
getPlatforms: vi.fn(),
10+
};
511

612
test('plugin is called with correct arguments and returns its name and description', () => {
7-
const plugin = pluginMetro({
8-
root: '/',
9-
reactNativeVersion: '0.77.0-rc.2',
10-
reactNativePath: '/path/to/react-native',
11-
platforms: {
12-
android: {},
13-
},
14-
})(pluginApi);
13+
const plugin = pluginMetro()(pluginApi);
1514

1615
expect(plugin).toMatchObject({
1716
name: 'plugin-metro',

packages/plugin-metro/src/lib/pluginMetro.ts

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,10 @@ import {
77
import { logger } from '@callstack/rnef-tools';
88

99
type PluginConfig = {
10-
root?: string;
11-
reactNativeVersion: string;
12-
reactNativePath: string;
13-
platforms: {
14-
[platformName: string]: {
15-
npmPackageName?: string;
16-
};
10+
reactNativeVersion?: string;
11+
reactNativePath?: string;
12+
platforms?: {
13+
[platformName: string]: object;
1714
};
1815
};
1916

@@ -60,15 +57,28 @@ type BundleCommandArgs = {
6057
};
6158

6259
export const pluginMetro =
63-
(pluginConfig: PluginConfig) =>
60+
(pluginConfig: PluginConfig = {}) =>
6461
(api: PluginApi): PluginOutput => {
6562
api.registerCommand({
6663
name: 'start',
6764
description: 'Starts Metro dev server.',
6865
// @ts-expect-error todo fix this
6966
action: (args: StartCommandArgs) => {
7067
const root = api.getProjectRoot();
71-
startCommand.func(undefined, { root, ...pluginConfig }, args);
68+
const reactNativeVersion = api.getReactNativeVersion();
69+
const reactNativePath = api.getReactNativePath();
70+
const platforms = api.getPlatforms();
71+
startCommand.func(
72+
undefined,
73+
{
74+
root,
75+
reactNativeVersion,
76+
reactNativePath,
77+
platforms,
78+
...pluginConfig,
79+
},
80+
args
81+
);
7282
},
7383
options: startCommand.options,
7484
});
@@ -86,7 +96,20 @@ export const pluginMetro =
8696
process.exit(1);
8797
}
8898
const root = api.getProjectRoot();
89-
bundleCommand.func(undefined, { root, ...pluginConfig }, args);
99+
const reactNativeVersion = api.getReactNativeVersion();
100+
const reactNativePath = api.getReactNativePath();
101+
const platforms = api.getPlatforms();
102+
bundleCommand.func(
103+
undefined,
104+
{
105+
root,
106+
reactNativeVersion,
107+
reactNativePath,
108+
platforms,
109+
...pluginConfig,
110+
},
111+
args
112+
);
90113
},
91114
options: bundleCommand.options,
92115
});

packages/plugin-repack/src/lib/pluginRepack.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,8 @@ import commands from '@callstack/repack/commands/rspack';
33
import { logger } from '@callstack/rnef-tools';
44

55
type PluginConfig = {
6-
root?: string;
7-
reactNativePath?: string;
8-
platforms: {
9-
[key: string]: {
10-
npmPackageName?: string;
11-
};
6+
platforms?: {
7+
[key: string]: object;
128
};
139
};
1410

@@ -24,14 +20,19 @@ const bundleCommand = commands.find(
2420
);
2521

2622
export const pluginRepack =
27-
(pluginConfig: PluginConfig) =>
23+
(pluginConfig: PluginConfig = {}) =>
2824
(api: PluginApi): PluginOutput => {
2925
api.registerCommand({
3026
name: 'start',
3127
description: 'Starts Re.Pack dev server.',
3228
action: (args) => {
3329
const root = api.getProjectRoot();
34-
startCommand.func(undefined, { root, ...pluginConfig }, args);
30+
const platforms = api.getPlatforms();
31+
startCommand.func(
32+
undefined,
33+
{ root, platforms, ...pluginConfig },
34+
args
35+
);
3536
},
3637
options: startCommand.options,
3738
});
@@ -48,7 +49,12 @@ export const pluginRepack =
4849
process.exit(1);
4950
}
5051
const root = api.getProjectRoot();
51-
bundleCommand.func(undefined, { root, ...pluginConfig }, args);
52+
const platforms = api.getPlatforms();
53+
bundleCommand.func(
54+
undefined,
55+
{ root, platforms, ...pluginConfig },
56+
args
57+
);
5258
},
5359
options: bundleCommand.options,
5460
});

0 commit comments

Comments
 (0)