Skip to content

Commit ca2ca0d

Browse files
committed
feat: bump minimum Node version to 20.19
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 411b336 commit ca2ca0d

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",
@@ -141,7 +142,7 @@
141142
}
142143
},
143144
"engines": {
144-
"node": ">=18.12"
145+
"node": ">=20.19.4"
145146
},
146147
"defaultPlatformPackages": {
147148
"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)