Skip to content

Commit 911dff8

Browse files
authored
feat: bump minimum Node version to 20.19 (#2799)
Also moves platform specific template config to their respective platform folders. This is part of an effort to move platform support out of the main package.
1 parent 2f86519 commit 911dff8

8 files changed

Lines changed: 120 additions & 62 deletions

File tree

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// @ts-check
2+
import * as nodefs from "node:fs";
3+
import * as path from "node:path";
4+
import { findFile } from "../scripts/helpers.js";
5+
import { generateAndroidManifest } from "./android-manifest.js";
6+
import { configureGradleWrapper } from "./gradle-wrapper.js";
7+
8+
/** @import { ProjectConfig, ProjectParams } from "../scripts/types.js"; */
9+
10+
/**
11+
* @returns {string | undefined}
12+
*/
13+
export function getAndroidPackageName() {
14+
return "com.microsoft.reacttestapp";
15+
}
16+
17+
/**
18+
* @param {string} projectRoot
19+
* @param {Required<ProjectConfig>["android"]} config
20+
* @returns {ProjectParams["android"] | undefined}
21+
*/
22+
export function configure(
23+
projectRoot,
24+
{ packageName, sourceDir },
25+
fs = nodefs
26+
) {
27+
const manifestPath = path.join(
28+
"app",
29+
"build",
30+
"generated",
31+
"rnta",
32+
"src",
33+
"main",
34+
"AndroidManifest.xml"
35+
);
36+
const appManifestPath = findFile("app.json", projectRoot, fs);
37+
if (appManifestPath) {
38+
const output = path.resolve(projectRoot, sourceDir, manifestPath);
39+
generateAndroidManifest(appManifestPath, output, fs);
40+
}
41+
42+
configureGradleWrapper(sourceDir, fs);
43+
44+
return {
45+
sourceDir,
46+
manifestPath,
47+
packageName: packageName || getAndroidPackageName(),
48+
};
49+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// @ts-check
2+
import * as nodefs from "node:fs";
3+
4+
/** @import { ProjectConfig, ProjectParams } from "../scripts/types.js"; */
5+
6+
/**
7+
* @param {string} _projectRoot
8+
* @param {Required<ProjectConfig>["ios"]} config
9+
* @returns {ProjectParams["ios"] | undefined}
10+
*/
11+
export function configure(_projectRoot, config, _fs = nodefs) {
12+
return config;
13+
}

packages/app/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"android/autolink.mjs",
4343
"android/gradle-wrapper.js",
4444
"android/support/src",
45+
"android/template.config.mjs",
4546
"common",
4647
"example/_gitignore",
4748
"example/android/gradle",
@@ -142,7 +143,7 @@
142143
}
143144
},
144145
"engines": {
145-
"node": ">=18.12"
146+
"node": ">=20.19.4"
146147
},
147148
"defaultPlatformPackages": {
148149
"android": "react-native",

packages/app/scripts/configure-projects.js

Lines changed: 14 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,15 @@
99
*/
1010
const nodefs = require("node:fs");
1111
const path = require("node:path");
12-
const { generateAndroidManifest } = require("../android/android-manifest");
13-
const { configureGradleWrapper } = require("../android/gradle-wrapper");
14-
const { findFile, findNearest, readTextFile } = require("./helpers");
12+
const {
13+
configure: configureAndroid,
14+
getAndroidPackageName,
15+
} = require("../android/template.config.mjs");
16+
const { configure: configureIOS } = require("../ios/template.config.mjs");
17+
const {
18+
configure: configureWindows,
19+
} = require("../windows/template.config.mjs");
20+
const { findNearest } = require("./helpers");
1521

1622
/**
1723
* Finds `react-native.config.[ts,mjs,cjs,js]`.
@@ -69,25 +75,6 @@ function findReactNativeConfig(fs = nodefs) {
6975
throw new Error("Failed to find `react-native.config.[ts,mjs,cjs,js]`");
7076
}
7177

72-
/**
73-
* @returns {string | undefined}
74-
*/
75-
function getAndroidPackageName() {
76-
return "com.microsoft.reacttestapp";
77-
}
78-
79-
/**
80-
* @param {string} solutionFile
81-
* @returns {ProjectParams["windows"]["project"]}
82-
*/
83-
function windowsProjectPath(solutionFile, fs = nodefs) {
84-
const sln = readTextFile(solutionFile, fs);
85-
const m = sln.match(
86-
/([^"]*?node_modules[/\\].generated[/\\]windows[/\\].*?\.vcxproj)/
87-
);
88-
return { projectFile: m ? m[1] : `(Failed to parse '${solutionFile}')` };
89-
}
90-
9178
/**
9279
* @param {ProjectConfig} configuration
9380
* @returns {Partial<ProjectParams>}
@@ -98,47 +85,15 @@ function configureProjects({ android, ios, windows }, fs = nodefs) {
9885
/** @type {Partial<ProjectParams>} */
9986
const config = {};
10087

88+
const projectRoot = path.dirname(reactNativeConfig);
10189
if (android) {
102-
const { packageName, sourceDir } = android;
103-
const manifestPath = path.join(
104-
"app",
105-
"build",
106-
"generated",
107-
"rnta",
108-
"src",
109-
"main",
110-
"AndroidManifest.xml"
111-
);
112-
const projectRoot = path.dirname(reactNativeConfig);
113-
const appManifestPath = findFile("app.json", projectRoot, fs);
114-
if (appManifestPath) {
115-
generateAndroidManifest(
116-
appManifestPath,
117-
path.resolve(projectRoot, sourceDir, manifestPath),
118-
fs
119-
);
120-
}
121-
122-
config.android = {
123-
sourceDir,
124-
manifestPath,
125-
packageName: packageName || getAndroidPackageName(),
126-
};
127-
128-
configureGradleWrapper(sourceDir, fs);
90+
config.android = configureAndroid(projectRoot, android, fs);
12991
}
130-
13192
if (ios) {
132-
config.ios = ios;
93+
config.ios = configureIOS(projectRoot, ios, fs);
13394
}
134-
135-
if (windows && fs.existsSync(windows.solutionFile)) {
136-
const { sourceDir, solutionFile } = windows;
137-
config.windows = {
138-
sourceDir,
139-
solutionFile: path.relative(sourceDir, solutionFile),
140-
project: windowsProjectPath(solutionFile, fs),
141-
};
95+
if (windows) {
96+
config.windows = configureWindows(projectRoot, windows, fs);
14297
}
14398

14499
return config;

packages/app/test/pack.test.mts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ describe("npm pack", () => {
102102
"android/support/build.gradle",
103103
"android/support/src/main/AndroidManifest.xml",
104104
"android/support/src/main/java/com/microsoft/reacttestapp/support/ReactTestAppLifecycleEvents.java",
105+
"android/template.config.mjs",
105106
"android/utils.gradle",
106107
"common/AppRegistry.cpp",
107108
"common/AppRegistry.h",
@@ -151,6 +152,7 @@ describe("npm pack", () => {
151152
"ios/localizations.mjs",
152153
"ios/pod_helpers.rb",
153154
"ios/privacyManifest.mjs",
155+
"ios/template.config.mjs",
154156
"ios/test_app.rb",
155157
"ios/use_react_native-0.71.rb",
156158
"ios/utils.mjs",
@@ -317,6 +319,7 @@ describe("npm pack", () => {
317319
"windows/Win32/targetver.h",
318320
"windows/app.mjs",
319321
"windows/project.mjs",
322+
"windows/template.config.mjs",
320323
"windows/uwp.mjs",
321324
"windows/win32.mjs",
322325
]);

packages/app/tsconfig.cjs.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"extends": "@rnx-kit/tsconfig/tsconfig.node.json",
2+
"extends": "@rnx-kit/tsconfig/tsconfig.nodenext.json",
33
"compilerOptions": {
44
"noEmit": true
55
},

packages/app/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"extends": "@rnx-kit/tsconfig/tsconfig.node.json",
2+
"extends": "@rnx-kit/tsconfig/tsconfig.nodenext.json",
33
"compilerOptions": {
44
"target": "esnext",
55
"allowImportingTsExtensions": true,
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// @ts-check
2+
import * as nodefs from "node:fs";
3+
import * as path from "node:path";
4+
import { readTextFile } from "../scripts/helpers.js";
5+
6+
/** @import { ProjectConfig, ProjectParams } from "../scripts/types.js"; */
7+
8+
/**
9+
* @param {string} solutionFile
10+
* @returns {ProjectParams["windows"]["project"]}
11+
*/
12+
function windowsProjectPath(solutionFile, fs = nodefs) {
13+
const sln = readTextFile(solutionFile, fs);
14+
const m = sln.match(
15+
/([^"]*?node_modules[/\\].generated[/\\]windows[/\\].*?\.vcxproj)/
16+
);
17+
return { projectFile: m ? m[1] : `(Failed to parse '${solutionFile}')` };
18+
}
19+
20+
/**
21+
* @param {string} _projectRoot
22+
* @param {Required<ProjectConfig>["windows"]} config
23+
* @returns {ProjectParams["windows"] | undefined}
24+
*/
25+
export function configure(
26+
_projectRoot,
27+
{ sourceDir, solutionFile },
28+
fs = nodefs
29+
) {
30+
return fs.existsSync(solutionFile)
31+
? {
32+
sourceDir,
33+
solutionFile: path.relative(sourceDir, solutionFile),
34+
project: windowsProjectPath(solutionFile, fs),
35+
}
36+
: undefined;
37+
}

0 commit comments

Comments
 (0)