@dojo/cli
Version:
196 lines • 7.52 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const path_1 = require("path");
const chalk_1 = require("chalk");
const allCommands_1 = require("../allCommands");
const installableCommands_1 = require("../installableCommands");
const pkgDir = require('pkg-dir');
// exported for tests
exports.versionCurrentVersion = `
You are currently running @dojo/cli@{version}
`;
exports.versionNoRegisteredCommands = `
There are no registered commands available.`;
exports.versionNoVersion = chalk_1.default.yellow('package.json missing');
exports.versionRegisteredCommands = `
The currently installed commands are:
`;
const INBUILT_COMMAND_VERSION = '__IN_BUILT_COMMAND__';
function getLatestCommandVersions() {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const packagePath = pkgDir.sync(__dirname);
const packageJsonFilePath = path_1.join(packagePath, 'package.json');
const packageJson = require(packageJsonFilePath);
console.log(chalk_1.default.yellow('Fetching latest version information...'));
return yield installableCommands_1.getLatestCommands(packageJson.name);
});
}
/**
* Iterate through a ModuleVersions and output if the module can be updated to a later version.
* Version checks are async calls to npm - so module repository dependant for now.
*
* @param {ModuleVersion[]} moduleVersions
* @returns {{name, version, group}[]}
*/
function areCommandsOutdated(moduleVersions) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const latestCommands = yield getLatestCommandVersions();
const latestVersions = latestCommands.reduce((versions, { name, version }) => {
versions[name] = version;
return versions;
}, {});
return moduleVersions.map(({ name, version, group }) => {
const latest = latestVersions[name];
return { name, version, latest, group };
});
});
}
/**
* Is the command a built in command as opposed to an installed command
* @param commandPath path to the command module
* @returns {boolean}
*/
function isBuiltInCommand(commandPath) {
/*__dirname seems best as the only way to truly know if a command is built in, is by location.
* Since this module is a built in command, we can use our location.
* This was preferable to using packageDir and relative paths, because we may alter where we build to (_build/src...)
*/
return commandPath.startsWith(__dirname);
}
/**
* Create the stdout output
* @param myPackageDetails
* @param commandVersions
* @returns {string}
*/
function createOutput(myPackageDetails, commandVersions) {
let output = exports.versionCurrentVersion.replace('{version}', chalk_1.default.blue(myPackageDetails.version));
if (commandVersions.length) {
output += exports.versionRegisteredCommands;
output +=
'\n' +
commandVersions
.map((command) => {
return command.version === command.latest || command.latest === undefined
? ` ▹ ${command.name}@${chalk_1.default.blue(command.version)}`
: ` ▹ ${command.name}@${chalk_1.default.blue(command.version)} ${chalk_1.default.green(`(latest is ${command.latest})`)}`;
})
.join('\n') +
'\n';
}
else {
output += exports.versionNoRegisteredCommands;
}
return output;
}
function register(options) {
options('o', {
alias: 'outdated',
describe: 'Output a list of installed commands and check if any can be updated to a more recent stable version.',
demand: false,
type: 'boolean'
});
}
/**
* Read information about a package/module, if available, or return default values.
*
* @param {string} packageDir The directory containing the package.json file.
* @returns {{name: (any|string), version: any}}
*/
function readPackageDetails(packageDir) {
let data = {};
// rather than add another prop to Command, declare the command to be builtin by setting its version
if (isBuiltInCommand(packageDir)) {
data.version = INBUILT_COMMAND_VERSION;
}
else {
try {
data = require(path_1.join(packageDir, 'package.json'));
}
catch (e) {
data.name = packageDir;
data.version = exports.versionNoVersion;
}
}
return {
name: data.name,
version: data.version
};
}
/**
* Iterate through a CommandsMap and retrieve the module details of each module referenced in the
* CommandsMap. The returned list is sorted in alphabetical order, by group.
*
* @param {CommandsMap} commandsMap
* @returns {{name, version, group}[]}
*/
function buildVersions(groupMap) {
/*
* commandsMap comes in as a map of [command-name, command]. The command has a default command,
* the map will actually contain two entries for one command, on for the default command, one for the real,
* expanded, command.
*
* Loop over commandsMap and create a new map with one entry per command, then loop over each entry and extract
* the package details.
*/
const consolidatedCommands = [];
for (let [, commandMap] of groupMap.entries()) {
for (let [, value] of commandMap.entries()) {
consolidatedCommands.push([value.path, value.group]);
}
}
const versionInfo = consolidatedCommands
.map(([path, group]) => {
const { name, version } = readPackageDetails(path);
return {
name,
version,
group
};
})
.filter((val) => {
// remove inbuilt commands or commands that dont have a valid version in the package.json
return val.version !== exports.versionNoVersion && val.version !== INBUILT_COMMAND_VERSION;
})
.sort((a, b) => (a.group > b.group ? 1 : -1));
return versionInfo;
}
/**
* Returns a string describing the command group, module name, and module version of each
* command referenced in a specified CommandsMap. This is used to print the string.
*
* @param {CommandsMap} commandsMap maps of commands to output the versions for
* @param {boolean} checkOutdated should we check if there is a later stable version available for the command
* @returns {string} the stdout output
*/
function createVersionsString(groupMap, checkOutdated) {
const packagePath = pkgDir.sync(__dirname);
const myPackageDetails = readPackageDetails(packagePath); // fetch the cli's package details
const versions = buildVersions(groupMap);
if (checkOutdated) {
return areCommandsOutdated(versions).then((commandVersions) => createOutput(myPackageDetails, commandVersions), (err) => {
return `Something went wrong trying to fetch command versions: ${err.message}`;
});
}
else {
return Promise.resolve(createOutput(myPackageDetails, versions));
}
}
function run(helper, args) {
return allCommands_1.default()
.then((groupMap) => {
return createVersionsString(groupMap, args.outdated);
})
.then(console.log);
}
exports.default = {
name: '',
group: 'version',
description: 'provides version information for all installed commands and the cli itself',
register,
global: true,
installed: true,
run
};
//# sourceMappingURL=version.js.map