Skip to content

Commit 3fca9c7

Browse files
authored
fix: support more extensions when looking for react-native.config.* (#2430)
1 parent 0d6913a commit 3fca9c7

File tree

4 files changed

+94
-11
lines changed

4 files changed

+94
-11
lines changed

.github/actions/setup-toolchain/action.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ inputs:
1313
java-version:
1414
description: Desired Java version
1515
default: "17"
16+
node-version:
17+
description: Desired Node version
18+
default: "22"
1619
xcode-developer-dir:
1720
description: Set the path for the active Xcode developer directory
1821
runs:
@@ -72,7 +75,7 @@ runs:
7275
- name: Set up Node.js
7376
uses: actions/[email protected]
7477
with:
75-
node-version: "22"
78+
node-version: ${{ inputs.node-version }}
7679
cache: ${{ inputs.cache-npm-dependencies }}
7780
- name: Set up Xcode
7881
if: ${{ inputs.xcode-developer-dir != '' }}

.github/workflows/build.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@ jobs:
550550
uses: ./.github/actions/setup-toolchain
551551
with:
552552
platform: windows
553+
node-version: "22.13"
553554
- name: Set up react-native@canary
554555
if: ${{ github.event_name == 'schedule' }}
555556
uses: ./.github/actions/setup-react-native
@@ -606,6 +607,7 @@ jobs:
606607
uses: ./.github/actions/setup-toolchain
607608
with:
608609
platform: windows
610+
node-version: "22.13"
609611
- name: Initialize test app
610612
uses: ./.github/actions/init-test-app
611613
with:

scripts/configure-projects.js

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// @ts-check
22
"use strict";
33

4+
/** @import { ProjectConfig, ProjectParams } from "./types.js"; */
5+
46
/**
57
* This script (and its dependencies) currently cannot be converted to ESM
68
* because it is consumed in `react-native.config.js`.
@@ -19,7 +21,61 @@ const {
1921
v,
2022
} = require("./helpers");
2123

22-
/** @import { ProjectConfig, ProjectParams } from "./types.js"; */
24+
/**
25+
* Finds `react-native.config.[ts,mjs,cjs,js]`.
26+
*
27+
* @note A naive search on disk might yield false positives so we also try to
28+
* use the stack trace to find it. This currently works in Node (V8) and Bun
29+
* (JSC).
30+
*
31+
* @returns {string} Path to `react-native.config.[ts,mjs,cjs,js]`
32+
*/
33+
function findReactNativeConfig(fs = nodefs) {
34+
// stack[0] holds this file
35+
// stack[1] holds where this function was called
36+
// stack[2] holds the file we're interested in
37+
const position = 2;
38+
if (position < Error.stackTraceLimit) {
39+
const orig_prepareStackTrace = Error.prepareStackTrace;
40+
let stack;
41+
try {
42+
Error.prepareStackTrace = (_, stack) => stack;
43+
stack = new Error().stack;
44+
} finally {
45+
Error.prepareStackTrace = orig_prepareStackTrace;
46+
}
47+
48+
if (Array.isArray(stack)) {
49+
const callsite = stack[position];
50+
if (
51+
callsite &&
52+
typeof callsite === "object" &&
53+
"getFileName" in callsite
54+
) {
55+
const file = callsite.getFileName();
56+
if (path.basename(file).startsWith("react-native.config.")) {
57+
return file;
58+
}
59+
}
60+
}
61+
}
62+
63+
const configFiles = [
64+
"react-native.config.ts",
65+
"react-native.config.mjs",
66+
"react-native.config.cjs",
67+
"react-native.config.js",
68+
];
69+
70+
for (const file of configFiles) {
71+
const reactNativeConfig = findNearest(file, undefined, fs);
72+
if (reactNativeConfig) {
73+
return reactNativeConfig;
74+
}
75+
}
76+
77+
throw new Error("Failed to find `react-native.config.[ts,mjs,cjs,js]`");
78+
}
2379

2480
/**
2581
* Returns the version number of a React Native dependency.
@@ -94,14 +150,7 @@ function windowsProjectPath(solutionFile, fs = nodefs) {
94150
* @returns {Partial<ProjectParams>}
95151
*/
96152
function configureProjects({ android, ios, windows }, fs = nodefs) {
97-
const reactNativeConfig = findNearest(
98-
"react-native.config.js",
99-
undefined,
100-
fs
101-
);
102-
if (!reactNativeConfig) {
103-
throw new Error("Failed to find `react-native.config.js`");
104-
}
153+
const reactNativeConfig = findReactNativeConfig(fs);
105154

106155
/** @type {Partial<ProjectParams>} */
107156
const config = {};
@@ -154,5 +203,6 @@ function configureProjects({ android, ios, windows }, fs = nodefs) {
154203

155204
exports.configureProjects = configureProjects;
156205
exports.internalForTestingPurposesOnly = {
206+
findReactNativeConfig,
157207
getAndroidPackageName,
158208
};

test/configure-projects.test.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { deepEqual, equal, fail } from "node:assert/strict";
1+
import { deepEqual, equal, fail, ok, throws } from "node:assert/strict";
22
import * as nodefs from "node:fs";
33
import * as path from "node:path";
44
import { describe, it } from "node:test";
@@ -82,6 +82,34 @@ describe("configureProjects()", () => {
8282
});
8383
});
8484

85+
describe("findReactNativeConfig()", () => {
86+
const { findReactNativeConfig } = internalForTestingPurposesOnly;
87+
88+
const configFiles = [
89+
"react-native.config.ts",
90+
"react-native.config.mjs",
91+
"react-native.config.cjs",
92+
"react-native.config.js",
93+
];
94+
95+
it("throws if no config file is found", () => {
96+
throws(
97+
() => findReactNativeConfig({ ...nodefs, existsSync: () => false }),
98+
new Error("Failed to find `react-native.config.[ts,mjs,cjs,js]`")
99+
);
100+
});
101+
102+
for (const configFile of configFiles) {
103+
it(`finds '${configFile}'`, () => {
104+
const result = findReactNativeConfig({
105+
...nodefs,
106+
existsSync: (p) => typeof p === "string" && p.endsWith(configFile),
107+
});
108+
ok(result.endsWith(configFile));
109+
});
110+
}
111+
});
112+
85113
describe("getAndroidPackageName()", () => {
86114
const { getAndroidPackageName } = internalForTestingPurposesOnly;
87115

0 commit comments

Comments
 (0)