nx/packages/workspace/src/utils/rules/rename-npm-packages.ts
Adam L Barrett 889b648886
Emotion upgrade for React and Next plugins (#4088)
* chore(react): update emotion to new versions and new package names on react plugin

* chore(nextjs): update emotion to latest version and the new package names

* feat(misc): have react and next plugin migrations update emotion imports

 * add renamePackageImports and renameNpmPackage rules to workspace utils
 * update migrations to update emotion imports to the new name and version
2020-11-27 13:32:42 -06:00

128 lines
3.4 KiB
TypeScript

import {
chain,
Rule,
noop,
Tree,
SchematicContext,
} from '@angular-devkit/schematics';
import {
addDepsToPackageJson,
updateJsonInTree,
readJsonInTree,
} from '../ast-utils';
import {
renamePackageImports,
PackageNameMapping,
} from './rename-package-imports';
import { formatFiles } from './format-files';
export interface PackageRenameMapping {
[packageName: string]: string | [newPackageName: string, version: string];
}
interface NormalizedRenameDescriptors {
packageName: string;
newPackageName: string;
version: string;
isDevDep: boolean;
inPackageJson: boolean;
}
const normalizeToDescriptors = (packageJson: any) => ([
packageName,
newPackageNameConfig,
]): NormalizedRenameDescriptors => {
const isDevDep =
!!packageJson.devDependencies && packageName in packageJson.devDependencies;
const inPackageJson =
(packageJson.dependencies && packageName in packageJson.dependencies) ||
isDevDep;
const newPackageName = Array.isArray(newPackageNameConfig)
? newPackageNameConfig[0]
: newPackageNameConfig;
const version =
Array.isArray(newPackageNameConfig) && newPackageNameConfig[1]
? newPackageNameConfig[1]
: isDevDep
? packageJson.devDependencies[packageName]
: packageJson.dependencies[packageName];
return {
packageName,
newPackageName,
version,
isDevDep,
inPackageJson,
};
};
/**
* Updates all the imports in the workspace, and adjust the package.json appropriately.
*
* @param packageNameMapping The packageNameMapping provided to the schematic
*/
export function renameNpmPackages(packageRenameMapping: PackageRenameMapping) {
return (tree: Tree, context: SchematicContext): Rule => {
const pkg = readJsonInTree(tree, 'package.json');
const renameDescriptors = Object.entries(packageRenameMapping).map(
normalizeToDescriptors(pkg)
);
// if you don't find the packageName in package.json abort
if (
renameDescriptors.filter(({ inPackageJson }) => inPackageJson).length ===
0
) {
return noop();
}
const packageNameMapping: PackageNameMapping = renameDescriptors.reduce(
(mapping, { packageName, newPackageName }) => {
mapping[packageName] = newPackageName;
return mapping;
},
{}
);
const depAdditions = renameDescriptors.reduce(
(mapping, { newPackageName, version, isDevDep }) => {
if (!isDevDep) {
mapping[newPackageName] = version;
}
return mapping;
},
{}
);
const devDepAdditions = renameDescriptors.reduce(
(mapping, { newPackageName, version, isDevDep }) => {
if (isDevDep) {
mapping[newPackageName] = version;
}
return mapping;
},
{}
);
return chain([
// rename all the imports before the package.json changes and we can't find the imports
renamePackageImports(packageNameMapping),
// add the new name at either the old version or a new version
addDepsToPackageJson(depAdditions, devDepAdditions),
// delete the old entry from the package.json
updateJsonInTree('package.json', (json) => {
renameDescriptors.forEach(({ packageName, isDevDep }) => {
if (isDevDep) {
delete json.devDependencies[packageName];
} else {
delete json.dependencies[packageName];
}
});
return json;
}),
formatFiles(),
]);
};
}