167 lines
5.0 KiB
TypeScript
167 lines
5.0 KiB
TypeScript
import { readJson, updateJson } from './json';
|
|
import { installPackagesTask } from '../tasks/install-packages-task';
|
|
import type { Tree } from 'nx/src/config/tree';
|
|
import { GeneratorCallback } from 'nx/src/config/misc-interfaces';
|
|
|
|
/**
|
|
* Add Dependencies and Dev Dependencies to package.json
|
|
*
|
|
* For example:
|
|
* ```typescript
|
|
* addDependenciesToPackageJson(tree, { react: 'latest' }, { jest: 'latest' })
|
|
* ```
|
|
* This will **add** `react` and `jest` to the dependencies and devDependencies sections of package.json respectively.
|
|
*
|
|
* @param tree Tree representing file system to modify
|
|
* @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
|
|
* @returns Callback to install dependencies only if necessary. undefined is returned if changes are not necessary.
|
|
*/
|
|
export function addDependenciesToPackageJson(
|
|
tree: Tree,
|
|
dependencies: Record<string, string>,
|
|
devDependencies: Record<string, string>,
|
|
packageJsonPath: string = 'package.json'
|
|
): GeneratorCallback {
|
|
const currentPackageJson = readJson(tree, packageJsonPath);
|
|
|
|
if (
|
|
requiresAddingOfPackages(currentPackageJson, dependencies, devDependencies)
|
|
) {
|
|
updateJson(tree, packageJsonPath, (json) => {
|
|
json.dependencies = {
|
|
...(json.dependencies || {}),
|
|
...dependencies,
|
|
...(json.dependencies || {}),
|
|
};
|
|
json.devDependencies = {
|
|
...(json.devDependencies || {}),
|
|
...devDependencies,
|
|
...(json.devDependencies || {}),
|
|
};
|
|
json.dependencies = sortObjectByKeys(json.dependencies);
|
|
json.devDependencies = sortObjectByKeys(json.devDependencies);
|
|
|
|
return json;
|
|
});
|
|
}
|
|
return (): void => {
|
|
installPackagesTask(tree);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Remove Dependencies and Dev Dependencies from package.json
|
|
*
|
|
* For example:
|
|
* ```typescript
|
|
* removeDependenciesFromPackageJson(tree, ['react'], ['jest'])
|
|
* ```
|
|
* This will **remove** `react` and `jest` from the dependencies and devDependencies sections of package.json respectively.
|
|
*
|
|
* @param dependencies Dependencies to be removed from the dependencies section of package.json
|
|
* @param devDependencies Dependencies to be removed from the devDependencies section of package.json
|
|
* @returns Callback to uninstall dependencies only if necessary. undefined is returned if changes are not necessary.
|
|
*/
|
|
export function removeDependenciesFromPackageJson(
|
|
tree: Tree,
|
|
dependencies: string[],
|
|
devDependencies: string[],
|
|
packageJsonPath: string = 'package.json'
|
|
): GeneratorCallback {
|
|
const currentPackageJson = readJson(tree, packageJsonPath);
|
|
|
|
if (
|
|
requiresRemovingOfPackages(
|
|
currentPackageJson,
|
|
dependencies,
|
|
devDependencies
|
|
)
|
|
) {
|
|
updateJson(tree, packageJsonPath, (json) => {
|
|
for (const dep of dependencies) {
|
|
delete json.dependencies[dep];
|
|
}
|
|
for (const devDep of devDependencies) {
|
|
delete json.devDependencies[devDep];
|
|
}
|
|
json.dependencies = sortObjectByKeys(json.dependencies);
|
|
json.devDependencies = sortObjectByKeys(json.devDependencies);
|
|
|
|
return json;
|
|
});
|
|
}
|
|
return (): void => {
|
|
installPackagesTask(tree);
|
|
};
|
|
}
|
|
|
|
function sortObjectByKeys<T>(obj: T): T {
|
|
if (!obj || typeof obj !== 'object' || Array.isArray(obj)) {
|
|
return obj;
|
|
}
|
|
return Object.keys(obj)
|
|
.sort()
|
|
.reduce((result, key) => {
|
|
return {
|
|
...result,
|
|
[key]: obj[key],
|
|
};
|
|
}, {}) as T;
|
|
}
|
|
|
|
/**
|
|
* Verifies whether the given packageJson dependencies require an update
|
|
* given the deps & devDeps passed in
|
|
*/
|
|
function requiresAddingOfPackages(packageJsonFile, deps, devDeps): boolean {
|
|
let needsDepsUpdate = false;
|
|
let needsDevDepsUpdate = false;
|
|
|
|
packageJsonFile.dependencies = packageJsonFile.dependencies || {};
|
|
packageJsonFile.devDependencies = packageJsonFile.devDependencies || {};
|
|
|
|
if (Object.keys(deps).length > 0) {
|
|
needsDepsUpdate = Object.keys(deps).some(
|
|
(entry) => !packageJsonFile.dependencies[entry]
|
|
);
|
|
}
|
|
|
|
if (Object.keys(devDeps).length > 0) {
|
|
needsDevDepsUpdate = Object.keys(devDeps).some(
|
|
(entry) => !packageJsonFile.devDependencies[entry]
|
|
);
|
|
}
|
|
|
|
return needsDepsUpdate || needsDevDepsUpdate;
|
|
}
|
|
|
|
/**
|
|
* Verifies whether the given packageJson dependencies require an update
|
|
* given the deps & devDeps passed in
|
|
*/
|
|
function requiresRemovingOfPackages(
|
|
packageJsonFile,
|
|
deps: string[],
|
|
devDeps: string[]
|
|
): boolean {
|
|
let needsDepsUpdate = false;
|
|
let needsDevDepsUpdate = false;
|
|
|
|
packageJsonFile.dependencies = packageJsonFile.dependencies || {};
|
|
packageJsonFile.devDependencies = packageJsonFile.devDependencies || {};
|
|
|
|
if (deps.length > 0) {
|
|
needsDepsUpdate = deps.some((entry) => packageJsonFile.dependencies[entry]);
|
|
}
|
|
|
|
if (devDeps.length > 0) {
|
|
needsDevDepsUpdate = devDeps.some(
|
|
(entry) => packageJsonFile.devDependencies[entry]
|
|
);
|
|
}
|
|
|
|
return needsDepsUpdate || needsDevDepsUpdate;
|
|
}
|