Skip to content

Commit

Permalink
fix: update @react-native/ scoped packages to match version
Browse files Browse the repository at this point in the history
From 0.75 our @react-native/ dependencies must match the version of
react-native. Updated init to perform this on
@react-native-community/template.
  • Loading branch information
blakef committed Jun 19, 2024
1 parent 185f34b commit fba1546
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 9 deletions.
23 changes: 23 additions & 0 deletions packages/cli/src/commands/init/__tests__/editTemplate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
validatePackageName,
replaceNameInUTF8File,
updateDependencies,
normalizeReactNativeDeps,
} from '../editTemplate';
import semver from 'semver';

Expand Down Expand Up @@ -431,3 +432,25 @@ describe('replaceNameInUTF8File', () => {
expect(fsWriteFileSpy).toHaveBeenCalledTimes(0);
});
});

describe('normalizeReactNativeDeps', () => {
it('returns only @react-native/* dependencies updated to a specific version', () => {
const devDependencies = {
'@babel/core': '^7.20.0',
'@react-native/babel-preset': '0.75.0-main',
'@react-native/eslint-config': '0.75.0-main',
'@react-native/metro-config': '0.75.0-main',
'@react-native/typescript-config': '0.75.0-main',
'@types/react': '^18.2.6',
'@types/react-test-renderer': '^18.0.0',
eslint: '^8.19.0',
'react-test-renderer': '19.0.0-rc-fb9a90fa48-20240614',
};
expect(normalizeReactNativeDeps(devDependencies, '0.75.0')).toMatchObject({
'@react-native/babel-preset': '0.75.0',
'@react-native/eslint-config': '0.75.0',
'@react-native/metro-config': '0.75.0',
'@react-native/typescript-config': '0.75.0',
});
});
});
22 changes: 22 additions & 0 deletions packages/cli/src/commands/init/editTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,3 +307,25 @@ export async function changePlaceholderInTemplate({
}
}
}

type Packages = {
[pkgs: string]: string;
};

const REACT_NATIVE_SCOPE = '@react-native/';

/**
* Packages that are scoped under @react-native need a consistent version
*/
export function normalizeReactNativeDeps(
deps: Packages | undefined,
version: string,
): Packages {
const updated: Packages = {};
for (const key of Object.keys(deps ?? {}).filter((pkg) =>
pkg.startsWith(REACT_NATIVE_SCOPE),
)) {
updated[key] = version;
}
return updated;
}
39 changes: 30 additions & 9 deletions packages/cli/src/commands/init/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ import {
copyTemplate,
executePostInitScript,
} from './template';
import {changePlaceholderInTemplate, updateDependencies} from './editTemplate';
import {
changePlaceholderInTemplate,
updateDependencies,
normalizeReactNativeDeps,
} from './editTemplate';
import * as PackageManager from '../../tools/packageManager';
import banner from './banner';
import TemplateAndVersionError from './errors/TemplateAndVersionError';
Expand Down Expand Up @@ -293,13 +297,24 @@ async function createFromTemplate({
fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf8'),
);
if (templatePackageJson.dependencies?.['react-native'] === '1000.0.0') {
// Since 0.75

// Since 0.75, the version of all @react-native/ packages are pinned to the version of
// react native. Enforce this when updating versions.
const concreteVersion = await npmResolveConcreteVersion(
'react-native',
version,
);
updateDependencies({
dependencies: {
'react-native': await npmResolveConcreteVersion(
'react-native',
version,
'react-native': concreteVersion,
...normalizeReactNativeDeps(
templatePackageJson.dependencies,
concreteVersion,
),
},
devDependencies: {
...normalizeReactNativeDeps(
templatePackageJson.devDependencies,
concreteVersion,
),
},
});
Expand Down Expand Up @@ -484,20 +499,26 @@ async function createProject(
shouldBumpYarnVersion: boolean,
options: Options,
): Promise<TemplateReturnType> {
// Handle these cases (when community template is published and react-native
// doesn't have a template in 'react-native/template'):
// Handle these cases (when community template is published and react-native >= 0.75
//
// +==================================================================+==========+==============+
// | Arguments | Template | React Native |
// +==================================================================+==========+==============+
// | <None> | latest | latest |
// +------------------------------------------------------------------+----------+--------------+
// | --version 0.75.0 | latest | 0.75.0 |
// | --version 0.75.0 | 0.75.0 | 0.75.0 |
// +------------------------------------------------------------------+----------+--------------+
// | --template @react-native-community/template@0.75.1 | 0.75.1 | latest |
// +------------------------------------------------------------------+----------+--------------+
// | --template @react-native-community/template@0.75.1 --version 0.75| 0.75.1 | 0.75.x |
// +------------------------------------------------------------------+----------+--------------+
//
// 1. If you specify `--version 0.75.0` and `@react-native-community/template@0.75.0` is *NOT*
// published, then `init` will exit and suggest explicitly using the `--template` argument.
//
// 2. `--template` will always win over `--version` for the template.
//
// 3. For version < 0.75, the template ships with react-native.
const templateUri = await createTemplateUri(options, version);

return createFromTemplate({
Expand Down

0 comments on commit fba1546

Please sign in to comment.