@zmotivat0r/mrepo
Version:
Awesome Typescript Monorepo Generator
247 lines • 12.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MainCommands = void 0;
const util_1 = require("@nestled/util");
const color = require("chalk");
const child_process_1 = require("child_process");
const getGitBranch = require("current-git-branch");
const emoji = require("node-emoji");
const constants_1 = require("../constants");
const helpers_1 = require("../helpers");
const utils_1 = require("../utils");
var AvailableCommands;
(function (AvailableCommands) {
AvailableCommands["CLEAN"] = "clean";
AvailableCommands["BUILD"] = "build";
AvailableCommands["TEST"] = "test";
AvailableCommands["LINK"] = "link";
AvailableCommands["UNLINK"] = "unlink";
AvailableCommands["RELEASE"] = "release";
})(AvailableCommands || (AvailableCommands = {}));
const RELEASE_SEMVER = ['patch', 'minor', 'major', 'prepatch', 'preminor', 'premajor', 'prerelease', 'select'];
const RELEASE_SEMVER_STR = RELEASE_SEMVER.join(', ');
class MainCommands {
static load(program, configFile) {
const packagesNames = configFile.workspace.packages.map((p) => p.name);
const packagesNamesStr = packagesNames.join(', ');
const { scope, name: workspaceName } = configFile.workspace;
program
.command(AvailableCommands.CLEAN)
.alias('c')
.arguments('[package]')
.description('Clean package(s)', {
package: `Package name, if specified. One of: ${packagesNamesStr}`,
})
.action((packageName) => runClean(packageName));
program
.command(AvailableCommands.BUILD)
.alias('b')
.arguments('[package]')
.option('--no-cache', 'Force build without cache comparison', false)
.description('Build package(s)', {
package: `Package name, if specified. One of: ${packagesNamesStr}`,
})
.action(async (packageName, options) => runBuild(packageName, options.cache));
program
.command(AvailableCommands.TEST)
.alias('t')
.arguments('[package]')
.description('Run tests for package(s)', {
package: `Package name, if specified. One of: ${packagesNamesStr}`,
})
.option('-f, --folder <value>', 'Tests folder', workspaceName)
.option('-s, --suite <value>', 'Test suite', '')
.option('-c, --config <value>', 'Jest config file', 'jest.config.js')
.option('--coverage', 'Run with coverage', false)
.option('--addCollectCoverageFrom <value>', 'Add collect coverage rules to defaults', '')
.option('--verbose', 'Run verbose', false)
.description('Test package(s)', {
package: `Package name, if specified. One of: ${packagesNamesStr}`,
})
.action((packageName, options) => runTest(packageName, options));
program
.command(AvailableCommands.LINK)
.alias('l')
.arguments('[package]')
.option('--build', 'Build before linking', false)
.description('Link package(s)', {
package: `Package name, if specified. One of: ${packagesNamesStr}`,
})
.action((packageName, options) => runLink(packageName, options));
program
.command(AvailableCommands.UNLINK)
.alias('u')
.arguments('[package]')
.description('Unlink package(s)', {
package: `Package name, if specified. One of: ${packagesNamesStr}`,
})
.action((packageName) => runUnlink(packageName));
program
.command(AvailableCommands.RELEASE)
.alias('r')
.arguments('<semver> value')
.option('--no-git-push', 'Skip git commit and push', false)
.option('--no-changelog', 'Skip changelog generation', false)
.option('--preid <value>', 'Prerelease identifier', 'alpha')
.option('--dist-tag <value>', 'Dist tag if Lerna version is "independent"', 'latest')
.option('--force-publish', 'Force packages release', false)
.description('Release package(s)', {
semver: `Package version semver type. One of: ${RELEASE_SEMVER_STR}`,
})
.action((semver, options) => runRelease(semver, options));
function runClean(packageName) {
const placesToRemove = ['lib', 'tsconfig.tsbuildinfo', 'node_modules', 'package-lock.json'];
const exec = (pName) => {
const p = `./${workspaceName}/${pName}/`;
utils_1.logger.info(AvailableCommands.CLEAN, `Cleaning ${color.italic.bold(pName)}`, emoji.get(':boom:'));
child_process_1.execSync(`npx rimraf ${placesToRemove.map((n) => p + n).join(' ')}`, { stdio: 'inherit' });
};
if (!packageName) {
packagesNames.forEach((pName) => {
exec(pName);
});
}
else {
validatePackageExist(packageName, packagesNames);
exec(packageName);
}
utils_1.logger.info(AvailableCommands.CLEAN, `Cleaning ${color.green('done')}`, emoji.get(':ok_hand:'));
}
async function runBuild(packageName, useCache = true) {
const exec = async (pName) => {
const hasCache = await helpers_1.hasCached(workspaceName, pName);
if (!useCache || !hasCache) {
utils_1.logger.info(AvailableCommands.BUILD, `Building ${color.italic.bold(pName)}`, emoji.get(':package:'));
child_process_1.execSync(`npx lerna run build --scope @${scope}/${pName}`, { stdio: 'inherit' });
await helpers_1.saveCache(workspaceName, pName);
}
else {
utils_1.logger.info(AvailableCommands.BUILD, `Package ${color.italic.bold(pName)} has been built already`, emoji.get(':ok_hand:'));
}
};
if (!packageName) {
for (let i = 0; i < packagesNames.length; i++) {
const pName = packagesNames[i];
await exec(pName);
}
}
else {
validatePackageExist(packageName, packagesNames);
exec(packageName);
}
utils_1.logger.info(AvailableCommands.BUILD, `Building ${color.green('done')}`, emoji.get(':ok_hand:'));
}
function runTest(packageName, options) {
const config = `-c=${options.config}`;
const coverage = options.coverage ? '--coverage' : '';
const verbose = options.verbose ? '--verbose' : '';
const suite = options.suite ? options.suite : '';
let where = '';
let collectCoverageFrom = '';
if (!packageName) {
utils_1.logger.info(AvailableCommands.TEST, 'Running tests', emoji.get(':zap:'));
where = `${options.folder}/*`;
}
else {
validatePackageExist(packageName, packagesNames);
utils_1.logger.info(AvailableCommands.TEST, `Running tests for ${color.italic.bold(packageName)}`, emoji.get(':zap:'));
where = `${options.folder}/${packageName}/${suite}`;
if (coverage) {
const addToRules = options.addCollectCoverageFrom ? options.addCollectCoverageFrom : '';
collectCoverageFrom = `--collectCoverageFrom='["${options.folder}/${packageName}/**/*.ts","!${options.folder}/${packageName}/**/*.d.ts","!${options.folder}/${packageName}/**/index.ts","!${options.folder}/${packageName}/**/*.interface.ts","!**/node_modules/**","!**/__stubs__/**","!**/__fixture__/**","!integration/*"${addToRules ? ',"' + addToRules.split(',').join('","') + '"' : ''}]'`;
}
}
const cmd = `npx jest --runInBand --detectOpenHandles ${config} ${where} ${coverage} ${collectCoverageFrom} ${verbose}`;
child_process_1.execSync(cmd, { stdio: 'inherit' });
utils_1.logger.info(AvailableCommands.TEST, `Running tests ${color.green('done')}`, emoji.get(':ok_hand:'));
}
function runLink(packageName, options) {
const exec = (pName) => {
utils_1.logger.info(AvailableCommands.LINK, `Linking ${color.italic.bold(pName)}`, emoji.get(':loudspeaker:'));
child_process_1.execSync(`cd ./${workspaceName}/${pName} && npm link`, { stdio: 'inherit' });
};
if (!packageName) {
if (options.build) {
runBuild(undefined, false);
}
packagesNames.forEach((pName) => {
exec(pName);
});
}
else {
validatePackageExist(packageName, packagesNames);
if (options.build) {
runBuild(packageName, false);
}
exec(packageName);
}
utils_1.logger.info(AvailableCommands.LINK, `Linking ${color.green('done')}`, emoji.get(':ok_hand:'));
}
function runUnlink(packageName) {
const exec = (pName) => {
utils_1.logger.info(AvailableCommands.UNLINK, `Unlinking ${color.italic.bold(pName)}`, emoji.get(':loudspeaker:'));
child_process_1.execSync(`cd ./${workspaceName}/${pName} && npm unlink`, { stdio: 'inherit' });
};
if (!packageName) {
packagesNames.forEach((pName) => {
exec(pName);
});
}
else {
exec(packageName);
}
utils_1.logger.info(AvailableCommands.UNLINK, `Unlinking ${color.green('done')}`, emoji.get(':ok_hand:'));
}
function runRelease(semver, options) {
utils_1.logger.info(AvailableCommands.RELEASE, 'Creating new release version(s)', emoji.get(':rocket:'));
const lernaFile = utils_1.loadLernaFile();
const isIndependent = lernaFile.version === 'independent';
const isCustomVersion = semver === 'select';
const semverStr = isCustomVersion ? '' : semver;
validateReleaseSemver(semver);
if (options.gitPush) {
validateReleaseGitBranch();
}
const preid = semver.startsWith('pre') ? `--preid ${options.preid}` : '';
const withChangelog = options.changelog && !isCustomVersion ? '--conventional-commits' : '';
const forcePublish = options.forcePublish ? '--force-publish' : '';
const lernaVersionCmd = `npx lerna version ${semverStr} --no-git-tag-version ${withChangelog} ${preid} ${forcePublish}`;
child_process_1.execSync(lernaVersionCmd, { stdio: 'inherit' });
if (isIndependent) {
child_process_1.execSync(`npx json -I -f ${process.cwd()}/lerna.json -e "this.distTag='${options.distTag}'"`);
child_process_1.execSync(`git add . && git commit -m "chore: release with --dist-tag=${options.distTag}"`);
}
else {
const updatedLernaFile = utils_1.loadLernaFile();
child_process_1.execSync(`git add . && git commit -m "chore: release v${updatedLernaFile.version}"`);
}
utils_1.logger.info(AvailableCommands.RELEASE, `Creating new release version(s) ${color.green('done')}`, emoji.get(':ok_hand:'));
}
function validatePackageExist(packageName, packagesNames) {
if (!util_1.isIn(packageName, packagesNames)) {
const msg = `${emoji.get(':flushed:')} Sorry, package ${color.bold(name)} hasn't been specified in ${color.bold(`${constants_1.CONFIG_FILE_NAME} -> workspace -> packages`)}`;
utils_1.logger.error('oops', msg);
throw new Error(msg);
}
}
function validateReleaseSemver(semver) {
if (!util_1.isIn(semver, RELEASE_SEMVER)) {
const msg = `${emoji.get(':flushed:')} Sorry, release version semver type must be one of ${color.bold(RELEASE_SEMVER_STR)}`;
utils_1.logger.error('oops', msg);
throw new Error(msg);
}
}
function validateReleaseGitBranch() {
const branch = getGitBranch({
altPath: process.cwd(),
});
if (!branch || !branch.startsWith('release')) {
const msg = `${emoji.get(':flushed:')} Sorry, release branch name should start with ${color.bold('release')}`;
utils_1.logger.error('oops', msg);
throw new Error(msg);
}
}
}
}
exports.MainCommands = MainCommands;
//# sourceMappingURL=main.commands.js.map