-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7defab3
commit 96b0404
Showing
5 changed files
with
179 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// @ts-check | ||
|
||
"use strict"; | ||
|
||
/** | ||
* @see https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module | ||
*/ | ||
exports.command = "add-caching"; | ||
|
||
exports.describe = "Interactive prompt to generate task runner configuration"; | ||
|
||
exports.builder = (yargs) => { | ||
return yargs; | ||
}; | ||
|
||
exports.handler = function handler(argv) { | ||
// eslint-disable-next-line global-require | ||
return require(".")(argv); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
// @ts-check | ||
|
||
"use strict"; | ||
|
||
const { Command } = require("@lerna/command"); | ||
const { writeJsonFile, readJsonFile, workspaceRoot, joinPathFragments } = require("@nrwl/devkit"); | ||
const inquirer = require("inquirer"); | ||
const log = require("npmlog"); | ||
|
||
module.exports = factory; | ||
|
||
function factory(argv) { | ||
return new AddCachingCommand(argv); | ||
} | ||
|
||
class AddCachingCommand extends Command { | ||
constructor(argv) { | ||
super(argv, { skipValidations: true }); | ||
} | ||
|
||
initialize() { | ||
if (this.options.useNx === false) { | ||
this.logger.error( | ||
"add-caching", | ||
"The `add-caching` command is only available when using the Nx task runner" | ||
); | ||
process.exit(1); | ||
} | ||
|
||
const packages = this.packageGraph?.rawPackageList || []; | ||
const uniqueScriptNames = new Set(); | ||
for (const pkg of packages) { | ||
for (const scriptName of Object.keys(pkg.scripts || {})) { | ||
uniqueScriptNames.add(scriptName); | ||
} | ||
} | ||
this.uniqueScriptNames = Array.from(uniqueScriptNames); | ||
} | ||
|
||
async execute() { | ||
this.logger.info( | ||
"add-caching", | ||
"Please answer the following questions about the scripts found in your workspace in order to generate task runner configuration" | ||
); | ||
process.stdout.write("\n"); | ||
|
||
log.pause(); | ||
|
||
const { targetDefaults } = await inquirer.prompt([ | ||
{ | ||
type: "checkbox", | ||
name: "targetDefaults", | ||
message: "Which of the following scripts need to be run in deterministic/topoglogical order?\n", | ||
choices: this.uniqueScriptNames, | ||
}, | ||
]); | ||
|
||
const { cacheableOperations } = await inquirer.prompt([ | ||
{ | ||
type: "checkbox", | ||
name: "cacheableOperations", | ||
message: | ||
"Which of the following scripts are cacheable? (Produce the same output given the same input)\n", | ||
choices: this.uniqueScriptNames, | ||
}, | ||
]); | ||
|
||
const scriptOutputs = {}; | ||
|
||
for (const scriptName of cacheableOperations) { | ||
// eslint-disable-next-line no-await-in-loop | ||
scriptOutputs[scriptName] = await inquirer.prompt([ | ||
{ | ||
type: "input", | ||
name: scriptName, | ||
message: `Where within a particular project directory does the "${scriptName}" script write its outputs?\n`, | ||
default: "dist", | ||
validate: (input) => { | ||
if (!input) { | ||
return "Please provide a project relative path"; | ||
} | ||
return true; | ||
}, | ||
}, | ||
]); | ||
} | ||
|
||
log.resume(); | ||
|
||
process.stdout.write("\n"); | ||
|
||
this.convertAnswersToNxConfig({ cacheableOperations, targetDefaults, scriptOutputs }); | ||
|
||
this.logger.success("add-caching", "Successfully updated task runner configuration in `nx.json`"); | ||
|
||
this.logger.info( | ||
"add-caching", | ||
"Learn more about task runner configuration here: https://lerna.js.org/docs/concepts/task-pipeline-configuration" | ||
); | ||
} | ||
|
||
convertAnswersToNxConfig(answers) { | ||
const nxJsonPath = joinPathFragments(workspaceRoot, "nx.json"); | ||
let nxJson = {}; | ||
try { | ||
nxJson = readJsonFile(nxJsonPath); | ||
} catch (e) {} | ||
|
||
nxJson.tasksRunnerOptions = nxJson.tasksRunnerOptions || {}; | ||
nxJson.tasksRunnerOptions.default = nxJson.tasksRunnerOptions.default || {}; | ||
nxJson.tasksRunnerOptions.default.runner = | ||
nxJson.tasksRunnerOptions.default.runner || "nx/tasks-runners/default"; | ||
nxJson.tasksRunnerOptions.default.options = nxJson.tasksRunnerOptions.default.options || {}; | ||
|
||
if (nxJson.tasksRunnerOptions.default.options.cacheableOperations) { | ||
this.logger.warn( | ||
"add-caching", | ||
"The `tasksRunnerOptions.default.cacheableOperations` property already exists in `nx.json` and will be overwritten by your answers" | ||
); | ||
} | ||
|
||
nxJson.tasksRunnerOptions.default.options.cacheableOperations = answers.cacheableOperations; | ||
|
||
if (nxJson.targetDefaults) { | ||
this.logger.warn( | ||
"add-caching", | ||
"The `targetDefaults` property already exists in `nx.json` and will be overwritten by your answers" | ||
); | ||
} | ||
|
||
nxJson.targetDefaults = nxJson.targetDefaults || {}; | ||
|
||
for (const scriptName of answers.targetDefaults) { | ||
nxJson.targetDefaults[scriptName] = nxJson.targetDefaults[scriptName] || {}; | ||
nxJson.targetDefaults[scriptName] = { dependsOn: [`^${scriptName}`] }; | ||
} | ||
|
||
for (const [scriptName, scriptAnswerData] of Object.entries(answers.scriptOutputs)) { | ||
nxJson.targetDefaults[scriptName] = nxJson.targetDefaults[scriptName] || {}; | ||
nxJson.targetDefaults[scriptName].outputs = [`{projectRoot}/${scriptAnswerData[scriptName]}`]; | ||
} | ||
|
||
writeJsonFile(nxJsonPath, nxJson); | ||
} | ||
|
||
// eslint-disable-next-line class-methods-use-this | ||
normalizePathInput(pathInput) { | ||
if (pathInput.startsWith("/")) { | ||
return pathInput.substring(1); | ||
} | ||
return pathInput; | ||
} | ||
} | ||
|
||
module.exports.AddCachingCommand = AddCachingCommand; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.