Skip to content
Merged
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
73 changes: 43 additions & 30 deletions tools/generators/dependency-mismatch/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ describe('dependency-mismatch generator', () => {
});
await generator(appTree);

const packageJson: PackageJson = await readTargetPackageJson();
const packageJson: PackageJson = readTargetPackageJson();
expect(packageJson.dependencies).toMatchInlineSnapshot(`
Object {
"@proj/react-theme": "^9.0.1",
}
`);
});

it('should also fix dev dependencies', async () => {
it('should fix dev dependencies', async () => {
const { readPackageJson: readTargetPackageJson } = setupDummyPackage(appTree, {
name: 'public-docsite-v9',
version: '9.0.0',
Expand All @@ -61,15 +61,15 @@ describe('dependency-mismatch generator', () => {
});
await generator(appTree);

const packageJson: PackageJson = await readTargetPackageJson();
const packageJson: PackageJson = readTargetPackageJson();
expect(packageJson.devDependencies).toMatchInlineSnapshot(`
Object {
"@proj/react-theme": "^9.0.1",
}
`);
});

it('should also fix peer dependencies', async () => {
it('should fix peer dependencies', async () => {
const { readPackageJson: readTargetPackageJson } = setupDummyPackage(appTree, {
name: 'public-docsite-v9',
version: '9.0.0',
Expand All @@ -89,7 +89,7 @@ describe('dependency-mismatch generator', () => {
});
await generator(appTree);

const packageJson: PackageJson = await readTargetPackageJson();
const packageJson: PackageJson = readTargetPackageJson();
expect(packageJson.peerDependencies).toMatchInlineSnapshot(`
Object {
"@proj/react-theme": "^9.0.1",
Expand Down Expand Up @@ -125,7 +125,7 @@ describe('dependency-mismatch generator', () => {
});
await generator(appTree);

const packageJson: PackageJson = await readTargetPackageJson();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

these awaits dont do anything as readTargetPackageJson is sync

const packageJson: PackageJson = readTargetPackageJson();
expect(packageJson.dependencies).toMatchInlineSnapshot(`
Object {
"@proj/react-select": "^9.0.0-beta.2",
Expand All @@ -134,7 +134,7 @@ describe('dependency-mismatch generator', () => {
`);
});

it('should run non-converged package', async () => {
it('should run on v8 packages', async () => {
const { readPackageJson: readTargetPackageJson } = setupDummyPackage(appTree, {
name: 'react',
version: '8.0.0',
Expand All @@ -154,43 +154,23 @@ describe('dependency-mismatch generator', () => {
});
await generator(appTree);

const packageJson: PackageJson = await readTargetPackageJson();
const packageJson: PackageJson = readTargetPackageJson();
expect(packageJson.dependencies).toMatchInlineSnapshot(`
Object {
"@proj/react-portal-compat-context": "^9.0.1",
}
`);
});

it('should ignore 3rd party packages/dependencies', async () => {
const { readPackageJson: readTargetPackageJson } = setupDummyPackage(appTree, {
name: 'react',
version: '8.0.0',
dependencies: {
[`@${workspaceNpmScope}/tslib`]: '^2.1.1',
},
devDependencies: {},
peerDependencies: {},
});

await generator(appTree);

const packageJson: PackageJson = await readTargetPackageJson();
expect(packageJson.dependencies).toMatchInlineSnapshot(`
Object {
"@proj/tslib": "^2.1.1",
}
`);
});

it('generator should not run on northstar packages', async () => {
it('should run on v0(northstar) packages changing only v9 deps', async () => {
const { readPackageJson: readTargetPackageJson } = setupDummyPackage(
appTree,
{
name: 'react-northstar',
version: '0.66.0',
dependencies: {
[`@${workspaceNpmScope}/dom-utilities`]: '^1.1.1',
[`@${workspaceNpmScope}/react-portal-compat-context`]: '^9.0.0',
},
devDependencies: {},
peerDependencies: {},
Expand All @@ -205,13 +185,46 @@ describe('dependency-mismatch generator', () => {
devDependencies: {},
peerDependencies: {},
});
setupDummyPackage(
appTree,
{
name: 'react-portal-compat-context',
version: '9.0.1',
dependencies: {},
devDependencies: {},
peerDependencies: {},
},
['vNext'],
);

await generator(appTree);

const packageJson: PackageJson = await readTargetPackageJson();
expect(packageJson.dependencies).toMatchInlineSnapshot(`
Object {
"@proj/dom-utilities": "^1.1.1",
"@proj/react-portal-compat-context": "^9.0.1",
}
`);
});

it('should ignore 3rd party packages/dependencies', async () => {
const { readPackageJson: readTargetPackageJson } = setupDummyPackage(appTree, {
name: 'react',
version: '8.0.0',
dependencies: {
[`@${workspaceNpmScope}/tslib`]: '^2.1.1',
},
devDependencies: {},
peerDependencies: {},
});

await generator(appTree);

const packageJson: PackageJson = readTargetPackageJson();
expect(packageJson.dependencies).toMatchInlineSnapshot(`
Object {
"@proj/tslib": "^2.1.1",
}
`);
});
Expand Down
45 changes: 32 additions & 13 deletions tools/generators/dependency-mismatch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,32 @@ import * as semver from 'semver';
import { Tree, formatFiles, updateJson, readJson, readProjectConfiguration } from '@nrwl/devkit';

import { getProjectConfig, getProjects, isPackageVersionPrerelease } from '../../utils';
import { PackageJson } from '../../types';
import type { PackageJson } from '../../types';

export default async function (tree: Tree) {
const projects = getProjects(tree);

projects.forEach((_project, projectName) => {
const config = getProjectConfig(tree, { packageName: projectName });

const { tags = [] } = readProjectConfiguration(tree, projectName);
// Ignore northstar packages
if (tags.includes('react-northstar')) {
return;
}
const scope = getProjectScope(config);

updateJson(tree, config.paths.packageJson, (packageJson: PackageJson) => {
if (packageJson.dependencies) {
packageJson.dependencies = getUpdatedDependencies(tree, packageJson.dependencies);
packageJson.dependencies = getUpdatedDependencies(tree, { dependencies: packageJson.dependencies, scope });
Copy link
Contributor Author

Choose a reason for hiding this comment

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

more args needed -> refactored to options pattern

}

if (packageJson.devDependencies) {
packageJson.devDependencies = getUpdatedDependencies(tree, packageJson.devDependencies);
packageJson.devDependencies = getUpdatedDependencies(tree, {
dependencies: packageJson.devDependencies,
scope,
});
}

if (packageJson.peerDependencies) {
packageJson.peerDependencies = getUpdatedDependencies(tree, packageJson.peerDependencies);
packageJson.peerDependencies = getUpdatedDependencies(tree, {
dependencies: packageJson.peerDependencies,
scope,
});
}

return packageJson;
Expand All @@ -46,7 +47,11 @@ function isProjectInWorkspace(tree: Tree, projectName: string) {
}
}

function getUpdatedDependencies(tree: Tree, dependencies: Record<string, string>) {
function getUpdatedDependencies(
tree: Tree,
options: { dependencies: Record<string, string>; scope: ReturnType<typeof getProjectScope> },
) {
const { dependencies, scope } = options;
return Object.entries(dependencies).reduce((acc, [dependencyName, versionRange]) => {
if (versionRange === '*') {
return acc;
Expand All @@ -62,9 +67,15 @@ function getUpdatedDependencies(tree: Tree, dependencies: Record<string, string>
return acc;
}

const shouldHaveCaret = !isPackageVersionPrerelease(minVersion.raw) || versionRange[0] === '^';

const depPackageConfig = getProjectConfig(tree, { packageName: dependencyName });
const depScope = getProjectScope(depPackageConfig);

const isNorthstarUnsupportedDepBump = scope.isReactNorthstarPackage && !depScope.isReactComponentsPackage;
if (isNorthstarUnsupportedDepBump) {
return acc;
}

const shouldHaveCaret = !isPackageVersionPrerelease(minVersion.raw) || versionRange[0] === '^';

acc[dependencyName] = `${shouldHaveCaret ? '^' : ''}${
readJson<PackageJson>(tree, depPackageConfig.paths.packageJson).version
Expand All @@ -73,3 +84,11 @@ function getUpdatedDependencies(tree: Tree, dependencies: Record<string, string>
return acc;
}, dependencies);
}

function getProjectScope(project: ReturnType<typeof getProjectConfig>) {
Copy link
Contributor

Choose a reason for hiding this comment

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

move this to utils?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah I was hesitant about that :D , we can do that later if we find shared usage for this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

will do a follow - normalizing all tags and tweaking this to utils

const tags = project.projectConfig.tags ?? [];
const isReactPackage = tags.includes('v8');
const isReactNorthstarPackage = tags.includes('react-northstar');
const isReactComponentsPackage = tags.includes('vNext');
return { isReactPackage, isReactNorthstarPackage, isReactComponentsPackage };
}
2 changes: 1 addition & 1 deletion tools/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ export function isPackageVersionConverged(versionString: string) {

export function isPackageVersionPrerelease(versionString: string) {
const version = semver.parse(versionString);
return version?.prerelease?.length && version?.prerelease?.length > 0;
return Boolean(version?.prerelease?.length && version?.prerelease?.length > 0);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

casted to explicitly return boolean instead of undefined/number/boolean

}

export function isPackageConverged(tree: Tree, project: ProjectConfiguration) {
Expand Down