lerna-update-wizard
Advanced tools
Comparing version 0.9.1 to 0.9.2
@@ -6,3 +6,3 @@ { | ||
}, | ||
"version": "0.9.1", | ||
"version": "0.9.2", | ||
"main": "index.js", | ||
@@ -9,0 +9,0 @@ "license": "MIT", |
302
src/index.js
@@ -6,5 +6,10 @@ const path = require("path"); | ||
const globby = require("globby"); | ||
const semverCompare = require("semver-compare"); | ||
const perf = require("execution-time")(); | ||
const runCommand = require("./utils/runCommand"); | ||
const fileExists = require("./utils/fileExists"); | ||
const ui = require("./utils/ui"); | ||
const plural = require("./utils/plural"); | ||
const sanitizeGitBranchName = require("./utils/sanitizeGitBranchName"); | ||
@@ -132,10 +137,291 @@ inquirer.registerPrompt( | ||
return require(`./wizards/upgrade.js`)({ | ||
dependencyMap, | ||
projectName, | ||
projectDir, | ||
packages, | ||
resolve, | ||
flags, | ||
}); | ||
const allDependencies = Object.keys(dependencyMap); | ||
ui.log.write(`Starting update wizard for ${chalk.white.bold(projectName)}`); | ||
ui.log.write(""); | ||
const { targetDependency } = await inquirer.prompt([ | ||
{ | ||
type: "autocomplete", | ||
name: "targetDependency", | ||
message: "Select a dependency to upgrade:", | ||
pageSize: 15, | ||
source: (_ignore_, input) => { | ||
const itemize = value => ({ | ||
value, | ||
name: `${chalk.white(value)} ${chalk[dependencyMap[value].color]( | ||
`(${plural( | ||
"version", | ||
"versions", | ||
dependencyMap[value].versions.length | ||
)})` | ||
)}`, | ||
}); | ||
const sorter = flags.dedupe | ||
? (a, b) => | ||
dependencyMap[b].versions.length - | ||
dependencyMap[a].versions.length | ||
: undefined; | ||
let results = input | ||
? allDependencies | ||
.filter(name => new RegExp(input).test(name)) | ||
.sort(sorter) | ||
.map(itemize) | ||
: allDependencies.sort(sorter).map(itemize); | ||
if (input && !allDependencies.includes(input)) { | ||
results = [ | ||
...results, | ||
{ | ||
name: `${input} ${chalk.green.bold("[+ADD]")}`, | ||
value: input, | ||
}, | ||
]; | ||
} | ||
return Promise.resolve(results); | ||
}, | ||
}, | ||
]); | ||
const isNewDependency = !allDependencies.includes(targetDependency); | ||
const npmPackageInfoRaw = await runCommand( | ||
`npm info ${targetDependency} versions dist-tags --json`, | ||
{ | ||
startMessage: `Fetching package information for "${targetDependency}"`, | ||
logOutput: false, | ||
} | ||
); | ||
const npmPackageInfo = JSON.parse(npmPackageInfoRaw); | ||
if (npmPackageInfo.error) { | ||
ui.log.write( | ||
chalk.red.bold( | ||
`There was an error looking up "${targetDependency}" in NPM registry` | ||
) | ||
); | ||
process.exit(); | ||
} | ||
const { targetPackages } = await inquirer.prompt([ | ||
{ | ||
type: "checkbox", | ||
name: "targetPackages", | ||
message: "Select packages to affect:", | ||
pageSize: 15, | ||
choices: packages.map(({ config: { name: packageName } }) => { | ||
if (isNewDependency) { | ||
return { | ||
name: packageName, | ||
value: packageName, | ||
checked: false, | ||
}; | ||
} | ||
const { version, source } = | ||
dependencyMap[targetDependency].packs[packageName] || {}; | ||
const versionBit = version ? ` (${version})` : ""; | ||
const sourceBit = | ||
source === "devDependencies" ? chalk.white(" (dev)") : ""; | ||
return { | ||
name: `${packageName}${versionBit}${sourceBit}`, | ||
value: packageName, | ||
checked: !!version, | ||
}; | ||
}), | ||
}, | ||
]); | ||
const npmVersions = npmPackageInfo.versions.reverse(); | ||
const npmDistTags = npmPackageInfo["dist-tags"]; | ||
const highestInstalled = | ||
!isNewDependency && | ||
dependencyMap[targetDependency].versions.sort(semverCompare).pop(); | ||
const availableVersions = [ | ||
...Object.entries(npmDistTags).map(([tag, version]) => ({ | ||
name: `${version} ${chalk.bold(`#${tag}`)}`, | ||
value: version, | ||
})), | ||
!isNewDependency && { | ||
name: `${highestInstalled} ${chalk.bold("Highest installed")}`, | ||
value: highestInstalled, | ||
}, | ||
...npmVersions.filter( | ||
version => | ||
version !== highestInstalled && | ||
!Object.values(npmDistTags).includes(version) | ||
), | ||
].filter(Boolean); | ||
const { targetVersion } = await inquirer.prompt([ | ||
{ | ||
type: "list", | ||
name: "targetVersion", | ||
message: "Select version to install:", | ||
pageSize: 10, | ||
choices: availableVersions, | ||
}, | ||
]); | ||
perf.start(); | ||
let totalInstalls = 0; | ||
// Install process | ||
for (let depName of targetPackages) { | ||
const existingDependency = dependencyMap[targetDependency]; | ||
let source = "dependencies"; | ||
const dependencyManager = (await fileExists( | ||
resolve(projectDir, "yarn.lock") | ||
)) | ||
? "yarn" | ||
: "npm"; | ||
if (existingDependency && existingDependency.packs[depName]) { | ||
const { version, source: theSource } = | ||
existingDependency.packs[depName] || {}; | ||
source = theSource; | ||
if (version === targetVersion) { | ||
ui.log.write(""); | ||
ui.log.write(`Already installed (${targetVersion})`); | ||
ui.log.write(chalk.green(`${depName} ✓`)); | ||
ui.log.write(""); | ||
continue; | ||
} | ||
} else { | ||
const { targetSource } = await inquirer.prompt([ | ||
{ | ||
type: "list", | ||
name: "targetSource", | ||
message: `Select dependency installation type for "${depName}"`, | ||
pageSize: 3, | ||
choices: [ | ||
{ name: "dependencies" }, | ||
{ name: "devDependencies" }, | ||
dependencyManager === "yarn" && { name: "peerDependencies" }, | ||
].filter(Boolean), | ||
}, | ||
]); | ||
source = targetSource; | ||
} | ||
const { path: packageDir } = packages.find( | ||
({ config: { name } }) => name === depName | ||
); | ||
const sourceParam = { | ||
yarn: { | ||
devDependencies: "--dev", | ||
peerDependencies: "--peer", | ||
}, | ||
npm: { | ||
dependencies: "--save", | ||
devDependencies: "--save-dev", | ||
}, | ||
}[dependencyManager][source || "dependencies"]; | ||
const installCmd = (dependencyManager === "yarn" | ||
? ["yarn", "add", sourceParam, `${targetDependency}@${targetVersion}`] | ||
: ["npm", "install", sourceParam, `${targetDependency}@${targetVersion}`] | ||
).join(" "); | ||
await runCommand(`cd ${packageDir} && ${installCmd}`, { | ||
startMessage: `${chalk.white.bold(depName)}: ${installCmd}`, | ||
endMessage: chalk.green(`${depName} ✓`), | ||
logTime: true, | ||
}); | ||
totalInstalls++; | ||
} | ||
if (totalInstalls === 0) process.exit(); | ||
ui.log.write( | ||
chalk.bold(`Installed ${totalInstalls} packages in ${perf.stop().words}`) | ||
); | ||
const userName = ( | ||
(await runCommand("git config --get github.user", { logOutput: false })) || | ||
(await runCommand("whoami", { logOutput: false })) || | ||
"upgrade" | ||
) | ||
.split("\n") | ||
.shift(); | ||
const { | ||
shouldCreateGitBranch, | ||
shouldCreateGitCommit, | ||
gitBranchName, | ||
gitCommitMessage, | ||
} = await inquirer.prompt([ | ||
{ | ||
type: "confirm", | ||
name: "shouldCreateGitBranch", | ||
message: "Do you want to create a new git branch for the change?", | ||
}, | ||
{ | ||
type: "input", | ||
name: "gitBranchName", | ||
message: "Enter a name for your branch:", | ||
when: ({ shouldCreateGitBranch }) => shouldCreateGitBranch, | ||
default: sanitizeGitBranchName( | ||
`${userName}/${targetDependency}-${targetVersion}` | ||
), | ||
}, | ||
{ | ||
type: "confirm", | ||
name: "shouldCreateGitCommit", | ||
message: "Do you want to create a new git commit for the change?", | ||
}, | ||
{ | ||
type: "input", | ||
name: "gitCommitMessage", | ||
message: "Enter a git commit message:", | ||
when: ({ shouldCreateGitCommit }) => shouldCreateGitCommit, | ||
default: `Upgrade dependency: ${targetDependency}@${targetVersion}`, | ||
}, | ||
]); | ||
if (shouldCreateGitBranch) { | ||
const createCmd = `git checkout -b ${gitBranchName}`; | ||
await runCommand(`cd ${projectDir} && ${createCmd}`, { | ||
startMessage: `${chalk.white.bold(projectName)}: ${createCmd}`, | ||
endMessage: chalk.green(`Branch created ✓`), | ||
}); | ||
} | ||
if (shouldCreateGitCommit) { | ||
const subMessage = targetPackages | ||
.reduce((prev, depName) => { | ||
const { version: fromVersion } = dependencyMap[targetDependency].packs[ | ||
depName | ||
]; | ||
if (fromVersion === targetVersion) return prev; | ||
return fromVersion | ||
? [...prev, `* ${depName}: ${fromVersion} → ${targetVersion}`] | ||
: [...prev, `* ${depName}: ${targetVersion}`]; | ||
}, []) | ||
.join("\n"); | ||
const createCmd = `git add . && git commit -m '${gitCommitMessage}' -m '${subMessage}'`; | ||
await runCommand(`cd ${projectDir} && ${createCmd}`, { | ||
startMessage: `${chalk.white.bold(projectName)}: git add . && git commit`, | ||
endMessage: chalk.green(`Commit created ✓`), | ||
logOutput: false, | ||
}); | ||
} | ||
}; |
@@ -35,3 +35,3 @@ const { default: runProgram } = require("./utils/runProgram"); | ||
❯ treediff (1 version) | ||
tree + ADD NEW | ||
tree [+ADD] | ||
@@ -45,3 +45,3 @@ >>> input BACKSPACE | ||
❯ promise-react-component + ADD NEW | ||
❯ promise-react-component [+ADD] | ||
@@ -48,0 +48,0 @@ >>> input ENTER |
@@ -36,3 +36,3 @@ const { default: runProgram } = require("./utils/runProgram"); | ||
? Select a dependency to upgrade: tree | ||
❯ tree + ADD NEW | ||
❯ tree [+ADD] | ||
@@ -39,0 +39,0 @@ >>> input CTRL+C |
@@ -27,5 +27,7 @@ const { default: runProgram } = require("./utils/runProgram"); | ||
? Select a dependency to upgrade: (Use arrow keys or type to search) | ||
❯ lodash (2 versions) | ||
>>> input lodash | ||
? Select a dependency to upgrade: lodash | ||
❯ lodash (2 versions) | ||
@@ -35,2 +37,8 @@ | ||
/ Fetching package information for "lodash" | ||
>>> wait | ||
? Select packages to affect: (Press <space> to select, <a> to toggle all, <i> to | ||
invert selection) | ||
❯◯ sub-package-a | ||
@@ -37,0 +45,0 @@ ◉ sub-package-b (0.1.0) |
@@ -25,2 +25,4 @@ const match = ( | ||
const matchContext = [ | ||
buf[base - 7] && buf[base - 7], | ||
buf[base - 6] && buf[base - 6], | ||
buf[base - 5] && buf[base - 5], | ||
@@ -32,4 +34,4 @@ buf[base - 4] && buf[base - 4], | ||
] | ||
.filter(Boolean) | ||
.join("\n"); | ||
.join("\n") | ||
.trim(); | ||
@@ -36,0 +38,0 @@ const matchTarget = [...tar.map((_, idx) => buf[base + idx])] |
@@ -34,3 +34,3 @@ const unexpected = require("unexpected"); | ||
matchContext: | ||
"Lerna Update Wizard\nv0.9.0\n\x1b[2K\x1b[G\x1b[2K\x1b[GStarting update wizard for project-a\n\x1b[2K\x1b[G", | ||
"\x1b[2K\x1b[G\nLerna Update Wizard\nv0.9.0\n\n\x1b[2K\x1b[G\x1b[2K\x1b[GStarting update wizard for project-a\n\x1b[2K\x1b[G", | ||
} | ||
@@ -37,0 +37,0 @@ ); |
@@ -25,3 +25,3 @@ const chalk = require("chalk"); | ||
const run = (proc, { type, value, maxWait = 5 }, onStdOut) => | ||
const run = (proc, { type, value, maxWait = 8 }, onStdOut) => | ||
new Promise(async (resolve, reject) => { | ||
@@ -28,0 +28,0 @@ if (!proc) return resolve(); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
175478
27
10
1338