monorepo-next
Version:
Detach monorepo packages from normal linking
104 lines (79 loc) • 2.92 kB
JavaScript
const path = require('path');
const writeJson = require('./json').write;
const semver = require('semver');
const buildDepGraph = require('./build-dep-graph');
const buildDAG = require('./build-dag');
const dependencyTypes = require('./dependency-types');
const {
getWorkspaceCwd,
} = require('./git');
function updateDependencyVersion(packageJson, name) {
for (let type of dependencyTypes) {
let deps = packageJson[type];
for (let _name in deps) {
if (_name !== name) {
continue;
}
deps[name] = deps[name].replace(/ +\|\| +[\d.]*-detached.*/, '');
break;
}
}
}
async function inquirerPrompt() {
const { default: inquirer } = await import('inquirer');
return inquirer.prompt(...arguments);
}
async function detach({
package: _package,
cwd = process.cwd(),
}) {
let myPackageJsonPath = path.join(cwd, 'package.json');
let myPackageJson = require(myPackageJsonPath);
let workspaceCwd = await getWorkspaceCwd(cwd);
let workspaceMeta = await buildDepGraph({ workspaceCwd });
if (_package) {
let otherPackageCwd = Object.values(workspaceMeta.packages).find(({ cwd }) => path.basename(cwd) === _package).cwd;
let otherPackageJsonPath = path.join(otherPackageCwd, 'package.json');
let otherPackageJson = require(otherPackageJsonPath);
updateDependencyVersion(myPackageJson, otherPackageJson.name);
} else {
let dag = buildDAG(workspaceMeta, myPackageJson.name);
let { major, minor, patch } = semver.parse(myPackageJson.version);
// don't mutate package.json until after DAG is built
myPackageJson.version = `${major}.${minor}.${patch}-detached`;
if (dag.node.dependents.length) {
// include space as to never match a similarly named package
let workspaceKey = 'Workspace Root';
let choices = dag.node.dependents.map(dependent => {
return dependent.node.packageName ?? path.basename(dependent.node.cwd);
});
let { answers } = await module.exports.inquirerPrompt([{
type: 'checkbox',
message: 'Would you like to attach any of these dependents to this newly detached package while you\'re at it?',
name: 'answers',
choices,
}]);
let dependents = answers.map(answer => {
// switch to key/value instead of array?
let isPackage = answer !== workspaceKey;
return dag.node.dependents.find(dependent => {
return isPackage ? dependent.node.packageName === answer : !dependent.node.isPackage;
});
});
// prevent loops
const attach = require('./attach');
for (let group of dependents) {
await attach({
package: path.basename(cwd),
cwd: group.node.cwd,
});
}
}
}
await writeJson(myPackageJsonPath, myPackageJson);
}
module.exports = detach;
Object.assign(module.exports, {
inquirerPrompt,
});
;