Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/@rnw-scripts/integrate-rn/bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,12 @@
* @format
*/

// Ensure the package is built from latest source before running
const {execSync} = require('child_process');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an anti pattern.

Rather than doing this, we should just move to executing the TS directly. node 22 supports running ts scripts directly. So there is no need to compile integrate-rn at all. -- We should only be running tsc during build to do type checking.

execSync('npx tsc -p . --outDir lib-commonjs', {
cwd: __dirname,
stdio: 'inherit',
});

require('source-map-support').install();
require('./lib-commonjs/integrateRN.js');
10 changes: 7 additions & 3 deletions packages/@rnw-scripts/integrate-rn/src/integrateRN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ async function performSteps(newVersion: string) {
},
);

await funcStep('Upgrading out-of-date overrides', upgradePlatformOverrides);
await funcStep('Upgrading out-of-date overrides', () =>
upgradePlatformOverrides(newVersion),
);
await funcStep(
'Performing additional override validation',
validatePlatformOverrides,
Expand Down Expand Up @@ -103,13 +105,15 @@ async function isOverridePackage(pkg: NpmPackage): Promise<boolean> {
* Upgrade platform overrides in the repo to the current version of react
* native, disallowing files with conflicts to be written
*/
async function upgradePlatformOverrides(): Promise<StepResult> {
async function upgradePlatformOverrides(
newVersion: string,
): Promise<StepResult> {
const overridesWithConflicts: string[] = [];

for (const pkg of await enumerateOverridePackages()) {
const results = await upgradeOverrides(
path.join(pkg.path, 'overrides.json'),
{allowConflicts: false},
{reactNativeVersion: newVersion, allowConflicts: false},
);

overridesWithConflicts.push(
Expand Down
82 changes: 57 additions & 25 deletions packages/@rnw-scripts/integrate-rn/src/upgradeDependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,11 @@ export function calcPackageDependencies(
const newPackage: LocalPackageDeps = _.cloneDeep(pkg);

if (newPackage.outOfTreePlatform) {
syncReactNativeDependencies(newPackage, reactNativePackageDiff);
syncReactNativeDependencies(
newPackage,
reactNativePackageDiff,
newReactNativeVersion,
);
}

if (newPackage.dependencies && newPackage.dependencies['react-native']) {
Expand All @@ -261,6 +265,15 @@ export function calcPackageDependencies(
);
}

// All @react-native/* packages are published with matching nightly
// versions. Bump any that reference a nightly version across all packages.
if (newPackage.dependencies) {
newPackage.dependencies = bumpReactNativeNightlyDeps(
newPackage.dependencies,
newReactNativeVersion,
);
}

ensureValidReactNativePeerDep(newPackage, newReactNativeVersion);
ensureReactNativePeerDepsSatisfied(
newPackage,
Expand Down Expand Up @@ -307,13 +320,35 @@ function sortByKeys<T>(obj: Record<string, T>): Record<string, T> {
return _(obj).toPairs().sortBy(0).fromPairs().value();
}

/**
* All @react-native/* packages are published with matching nightly versions.
* Bump any @react-native/* dependency referencing a nightly version to the
* new nightly version.
*/
function bumpReactNativeNightlyDeps(
deps: Record<string, string>,
newReactNativeVersion: string,
): Record<string, string> {
if (!newReactNativeVersion.includes('nightly')) {
return deps;
}
const result = {...deps};
for (const [dep, version] of Object.entries(result)) {
if (dep.startsWith('@react-native/') && version.includes('nightly')) {
result[dep] = newReactNativeVersion;
}
}
return result;
}

/**
* Matches dependencies + peer dependencies of an out-of-tree platform to
* those used by react-native.
*/
function syncReactNativeDependencies(
pkg: LocalPackageDeps,
reactNativePackageDiff: PackageDiff,
newReactNativeVersion: string,
) {
// Because we host JS from RN core, we need to provide all of the
// dependencies and peerDependencies declared by react-native. Pick all of
Expand All @@ -323,10 +358,13 @@ function syncReactNativeDependencies(
Object.keys(pkg.dependencies || {}),
Object.keys(reactNativePackageDiff.oldPackage.dependencies || {}),
);
const newDeps = {
..._.pick(pkg.dependencies, extraDeps),
...reactNativePackageDiff.newPackage.dependencies,
} as Record<string, string>;
const newDeps = bumpReactNativeNightlyDeps(
{
..._.pick(pkg.dependencies, extraDeps),
...reactNativePackageDiff.newPackage.dependencies,
} as Record<string, string>,
newReactNativeVersion,
);
if (Object.keys(newDeps).length === 0) {
delete pkg.dependencies;
} else {
Expand Down Expand Up @@ -373,16 +411,13 @@ function syncDependencies(
...templateDiff.newPackage.devDependencies,
};

// below packages rely on internal builds upstream in their package.json but still publish a new matching nightly version. Update our package.json to the matching nightly version.
if (pkg[dependencyType]?.['@react-native/metro-config']) {
pkg[dependencyType]!['@react-native/metro-config'] = newReactNativeVersion;
}
if (pkg[dependencyType]?.['@react-native/metro-babel-transformer']) {
pkg[dependencyType]!['@react-native/metro-babel-transformer'] =
newReactNativeVersion;
}
if (pkg[dependencyType]?.['@react-native/babel-preset']) {
pkg[dependencyType]!['@react-native/babel-preset'] = newReactNativeVersion;
// All @react-native/* packages are published with matching nightly versions.
// Bump any that reference a nightly version to the new nightly version.
if (pkg[dependencyType]) {
pkg[dependencyType] = bumpReactNativeNightlyDeps(
pkg[dependencyType]!,
newReactNativeVersion,
);
}

for (const [dependency, version] of devDependencies) {
Expand Down Expand Up @@ -463,16 +498,13 @@ function ensureValidReactNativePeerDep(
newReactNativeVersion,
);

// below packages rely on internal builds upstream in their package.json but still publish a new matching nightly version. Update our package.json to the matching nightly version.
if (pkg.dependencies?.['@react-native/metro-config']) {
pkg.dependencies['@react-native/metro-config'] = newReactNativeVersion;
}
if (pkg.dependencies?.['@react-native/metro-babel-transformer']) {
pkg.dependencies['@react-native/metro-babel-transformer'] =
newReactNativeVersion;
}
if (pkg.dependencies?.['@react-native/babel-preset']) {
pkg.dependencies['@react-native/babel-preset'] = newReactNativeVersion;
// All @react-native/* packages are published with matching nightly versions.
// Bump any that reference a nightly version to the new nightly version.
if (pkg.dependencies) {
pkg.dependencies = bumpReactNativeNightlyDeps(
pkg.dependencies,
newReactNativeVersion,
);
}
}

Expand Down
Loading