feat(devkit): add a flag to keep existing versions when calling addDependenciesToPackageJson (#21123)

This commit is contained in:
Jack Hsu 2024-01-16 14:24:14 -05:00 committed by GitHub
parent f02492301a
commit 253c0ff2ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 72 additions and 22 deletions

View File

@ -1,6 +1,6 @@
# Function: addDependenciesToPackageJson
**addDependenciesToPackageJson**(`tree`, `dependencies`, `devDependencies`, `packageJsonPath?`): [`GeneratorCallback`](../../devkit/documents/GeneratorCallback)
**addDependenciesToPackageJson**(`tree`, `dependencies`, `devDependencies`, `packageJsonPath?`, `keepExistingVersions?`): [`GeneratorCallback`](../../devkit/documents/GeneratorCallback)
Add Dependencies and Dev Dependencies to package.json
@ -14,12 +14,13 @@ This will **add** `react` and `jest` to the dependencies and devDependencies sec
#### Parameters
| Name | Type | Description |
| :----------------- | :------------------------------------ | :---------------------------------------------------------------------- |
| `tree` | [`Tree`](../../devkit/documents/Tree) | Tree representing file system to modify |
| `dependencies` | `Record`\<`string`, `string`\> | Dependencies to be added to the dependencies section of package.json |
| `devDependencies` | `Record`\<`string`, `string`\> | Dependencies to be added to the devDependencies section of package.json |
| `packageJsonPath?` | `string` | Path to package.json |
| Name | Type | Description |
| :---------------------- | :------------------------------------ | :-------------------------------------------------------------------------- |
| `tree` | [`Tree`](../../devkit/documents/Tree) | Tree representing file system to modify |
| `dependencies` | `Record`\<`string`, `string`\> | Dependencies to be added to the dependencies section of package.json |
| `devDependencies` | `Record`\<`string`, `string`\> | Dependencies to be added to the devDependencies section of package.json |
| `packageJsonPath?` | `string` | Path to package.json |
| `keepExistingVersions?` | `boolean` | If true, prevents existing dependencies from being bumped to newer versions |
#### Returns

View File

@ -446,6 +446,29 @@ describe('addDependenciesToPackageJson', () => {
});
expect(installTask).toBeDefined();
});
it('should allow existing versions to be kept', () => {
writeJson(tree, 'package.json', {
dependencies: {
foo: '1.0.0',
},
});
addDependenciesToPackageJson(
tree,
{
foo: '2.0.0',
},
{},
undefined,
true
);
const result = readJson(tree, 'package.json');
expect(result.dependencies).toEqual({
foo: '1.0.0',
});
});
});
describe('ensurePackage', () => {

View File

@ -132,13 +132,15 @@ function updateExistingDependenciesVersion(
* @param dependencies Dependencies to be added to the dependencies section of package.json
* @param devDependencies Dependencies to be added to the devDependencies section of package.json
* @param packageJsonPath Path to package.json
* @param keepExistingVersions If true, prevents existing dependencies from being bumped to newer versions
* @returns Callback to install dependencies only if necessary, no-op otherwise
*/
export function addDependenciesToPackageJson(
tree: Tree,
dependencies: Record<string, string>,
devDependencies: Record<string, string>,
packageJsonPath: string = 'package.json'
packageJsonPath: string = 'package.json',
keepExistingVersions?: boolean
): GeneratorCallback {
const currentPackageJson = readJson(tree, packageJsonPath);
@ -155,6 +157,7 @@ export function addDependenciesToPackageJson(
// filtered dependencies should consist of:
// - dependencies of the same type that are not present
// by default, filtered dependencies also include these (unless keepExistingVersions is true):
// - dependencies of the same type that have greater version
// - specified dependencies of the other type that have greater version and are already installed as current type
filteredDependencies = {
@ -178,14 +181,25 @@ export function addDependenciesToPackageJson(
),
};
filteredDependencies = removeLowerVersions(
filteredDependencies,
currentPackageJson.dependencies
);
filteredDevDependencies = removeLowerVersions(
filteredDevDependencies,
currentPackageJson.devDependencies
);
if (keepExistingVersions) {
filteredDependencies = removeExistingDependencies(
filteredDependencies,
currentPackageJson.dependencies
);
filteredDevDependencies = removeExistingDependencies(
filteredDevDependencies,
currentPackageJson.devDependencies
);
} else {
filteredDependencies = removeLowerVersions(
filteredDependencies,
currentPackageJson.dependencies
);
filteredDevDependencies = removeLowerVersions(
filteredDevDependencies,
currentPackageJson.devDependencies
);
}
if (
requiresAddingOfPackages(
@ -227,12 +241,24 @@ function removeLowerVersions(
) {
return Object.keys(incomingDeps).reduce((acc, d) => {
if (
existingDeps?.[d] &&
!isIncomingVersionGreater(incomingDeps[d], existingDeps[d])
!existingDeps?.[d] ||
isIncomingVersionGreater(incomingDeps[d], existingDeps[d])
) {
return acc;
acc[d] = incomingDeps[d];
}
return { ...acc, [d]: incomingDeps[d] };
return acc;
}, {});
}
function removeExistingDependencies(
incomingDeps: Record<string, string>,
existingDeps: Record<string, string>
): Record<string, string> {
return Object.keys(incomingDeps).reduce((acc, d) => {
if (!existingDeps?.[d]) {
acc[d] = incomingDeps[d];
}
return acc;
}, {});
}

View File

@ -129,6 +129,6 @@ describe('monorepo generator', () => {
// Extracted base config files
expect(tree.exists('tsconfig.base.json')).toBeTruthy();
expect(tree.exists('jest.config.ts')).toBeTruthy();
expect(tree.exists('jest.preset.js')).toBeTruthy();
});
});

View File

@ -25,7 +25,7 @@ export function moveProjectFiles(
'.babelrc',
'.eslintrc.json',
'eslint.config.js',
/^jest\.config\.(app|lib)\.[jt]s$/,
/^jest\.config\.((app|lib)\.)?[jt]s$/,
'vite.config.ts',
/^webpack.*\.js$/,
'index.html', // Vite