This commit is contained in:
Ken 2019-01-21 11:56:16 -08:00
Родитель 42065a394d
Коммит 9700d576b7
9 изменённых файлов: 148 добавлений и 55 удалений

Просмотреть файл

@ -1,8 +1,10 @@
import { task, option } from 'just-task';
import { addPackageTask } from '../tasks/addPackageTask';
import { upgradeRepoTask } from '../tasks/upgradeRepoTask';
module.exports = function() {
option('cwd');
option('name');
task('add-package', addPackageTask);
task('upgrade-repo', upgradeRepoTask);
};

Просмотреть файл

@ -0,0 +1,31 @@
import { paths } from 'just-scripts-utils';
import path from 'path';
import fse from 'fs-extra';
export function findMonoRepoRootPath() {
const { installPath } = paths;
let found = false;
let currentPath = installPath;
const { root } = path.parse(installPath);
while (!found && currentPath !== root) {
const packageJsonFile = path.join(currentPath, 'package.json');
const rushConfigFile = path.join(currentPath, 'rush.json');
// Determine the monorepo by either presence of rush.json or package.json that has a just.stack of just-stack-monorepo
if (fse.existsSync(rushConfigFile)) {
return currentPath;
} else if (fse.existsSync(packageJsonFile)) {
const packageJson = fse.readJsonSync(packageJsonFile);
const stack = packageJson.just && packageJson.just.stack;
if (stack === 'just-stack-monorepo') {
return currentPath;
}
}
currentPath = path.dirname(currentPath);
}
return null;
}

Просмотреть файл

@ -0,0 +1,37 @@
import semver from 'semver';
/**
* Merges an incoming package.json with an original semantically
* - merges dependencies and devDependencies for ranges that look like "^x.y.z" or "~x.y.z" or "x.y.z"
*
* @param original
* @param incoming
*/
export function mergePackageJson(original: any, incoming: any) {
const newPackageJson = { ...original };
if (original.just) {
const depTypes = ['dependencies', 'devDependencies'];
let packageJsonModified = false;
depTypes.forEach(devType => {
if (incoming[devType]) {
Object.keys(incoming[devType]).forEach(dep => {
const strippedOriginalVersion = original[devType][dep] ? original[devType][dep].replace(/^[~^]/, '') : '0.0.0';
const strippedIncomingVersion = incoming[devType][dep].replace(/^[~^]/, '');
// Modify the version if the range is comparable and is greater (skip mod if any space, >, < or = characters are present)
if (semver.gt(strippedIncomingVersion, strippedOriginalVersion) && !incoming[devType][dep].match(/[\s<>=]/)) {
newPackageJson[devType][dep] = incoming[devType][dep];
packageJsonModified = true;
}
});
}
});
if (packageJsonModified) {
return newPackageJson;
}
}
return original;
}

Просмотреть файл

@ -3,13 +3,11 @@ import { paths, logger, transform, rushAddPackage, rushUpdate, prettyPrintMarkdo
import prompts from 'prompts';
import fse from 'fs-extra';
import { argv } from 'just-task';
import { findMonoRepoRootPath } from '../package/findMonoRepoRootPath';
export async function addPackageTask() {
const args = argv();
if (args.cwd) {
process.chdir(args.cwd);
}
const rootPath = findMonoRepoRootPath();
const name =
args.name ||
@ -21,38 +19,40 @@ export async function addPackageTask() {
logger.info(`Creating a package called: ${name}`);
const { installPath } = paths;
if (rootPath) {
// TODO: do validation that the path is indeed a monorepo
// TODO: do validation that the path is indeed a monorepo
// TODO: autosuggest just-stack-* packages from npmjs.org
let response = await prompts({
type: 'select',
name: 'type',
message: 'What type of package to add to the repo?',
choices: [
{ title: 'Library', value: 'just-stack-single-lib' },
{ title: 'UI Fabric Web Application (React)', value: 'just-stack-uifabric' }
]
});
const packagePath = path.join(installPath, 'packages', name);
const templatePath = await downloadPackage(response.type);
if (templatePath) {
transform(templatePath, packagePath, {
name
// TODO: autosuggest just-stack-* packages from npmjs.org
let response = await prompts({
type: 'select',
name: 'type',
message: 'What type of package to add to the repo?',
choices: [
{ title: 'Library', value: 'just-stack-single-lib' },
{ title: 'UI Fabric Web Application (React)', value: 'just-stack-uifabric' }
]
});
rushAddPackage(name, installPath);
logger.info('Running rush update');
rushUpdate(installPath);
const packagePath = path.join(rootPath, 'packages', name);
const templatePath = await downloadPackage(response.type);
logger.info('All Set!');
if (templatePath) {
transform(templatePath, packagePath, {
name
});
const readmeFile = path.join(packagePath, 'README.md');
if (fse.existsSync(readmeFile)) {
logger.info('\n' + prettyPrintMarkdown(fse.readFileSync(readmeFile).toString()));
rushAddPackage(name, rootPath);
logger.info('Running rush update');
rushUpdate(rootPath);
logger.info('All Set!');
const readmeFile = path.join(packagePath, 'README.md');
if (fse.existsSync(readmeFile)) {
logger.info('\n' + prettyPrintMarkdown(fse.readFileSync(readmeFile).toString()));
}
}
} else {
logger.warn('Cannot determine the root path to the mono repo');
}
}

Просмотреть файл

@ -0,0 +1,20 @@
import fse from 'fs-extra';
import path from 'path';
import { upgradeStackPackageJsonFile } from './upgradeStackTask';
import { findMonoRepoRootPath } from '../package/findMonoRepoRootPath';
export async function upgradeRepoTask() {
const rootPath = findMonoRepoRootPath();
if (rootPath) {
process.chdir(rootPath);
const rushConfig = fse.readJsonSync(path.join(rootPath, 'rush.json'));
// uses Array.reduce to sequentially loop through promise
rushConfig.projects.reduce(async (previousPromise: Promise<void>, project: any) => {
await previousPromise;
const projectPath = path.join(rootPath, project.projectFolder);
return upgradeStackPackageJsonFile(projectPath);
}, Promise.resolve());
}
}

Просмотреть файл

@ -1,13 +1,19 @@
import fse from 'fs-extra';
import path from 'path';
import semver from 'semver';
import chalk from 'chalk';
import { logger } from 'just-task';
import { paths, downloadPackage, transform } from 'just-scripts-utils';
import { mergePackageJson } from '../package/mergePackageJson';
export async function upgradeStackTask() {
const { installPath, tempPath } = paths;
const packageJsonFile = path.join(installPath, 'package.json');
export function upgradeStackTask() {
const { installPath } = paths;
return upgradeStackPackageJsonFile(installPath);
}
export async function upgradeStackPackageJsonFile(projectPath: string) {
const packageJsonFile = path.join(projectPath, 'package.json');
const packageJson = fse.readJsonSync(packageJsonFile);
const { tempPath } = paths;
if (packageJson.just) {
const stack = packageJson.just.stack;
@ -16,32 +22,24 @@ export async function upgradeStackTask() {
if (stackPath) {
const templatePath = tempPath(packageJson.name);
transform(stackPath, templatePath, { name: packageJson.name });
// Update package.json deps
const stackPackageJson = fse.readJsonSync(path.join(templatePath, 'package.json'));
const depTypes = ['dependencies', 'devDependencies'];
let packageJsonModified = false;
depTypes.forEach(devType => {
if (stackPackageJson[devType]) {
Object.keys(stackPackageJson[devType]).forEach(dep => {
const strippedPackageVersion = packageJson[devType][dep] ? packageJson[devType][dep].replace(/^[~^]/, '') : '0.0.0';
const strippedStackPackageVersion = stackPackageJson[devType][dep].replace(/^[~^]/, '');
if (semver.gt(strippedStackPackageVersion, strippedPackageVersion)) {
logger.info(`Dependency ${dep} should be updated to ${stackPackageJson[devType][dep]}`);
packageJson[devType][dep] = stackPackageJson[devType][dep];
packageJsonModified = true;
}
});
}
});
// If modified, the reference would be different
const newPackageJson = mergePackageJson(packageJson, stackPackageJson);
if (packageJsonModified) {
fse.writeFileSync(packageJsonFile, JSON.stringify(packageJson, null, 2));
logger.info(`Checking if package ${packageJson.name} should be upgraded...`);
if (newPackageJson !== packageJson) {
logger.info(`Package ${chalk.cyan(packageJson.name)} is being upgraded.`);
fse.writeFileSync(packageJsonFile, JSON.stringify(newPackageJson, null, 2));
} else {
logger.info(`Package ${chalk.cyan(packageJson.name)} upgrade not needed.`);
}
} else {
logger.error(`Cannot read or retrieve the stack package.json for ${stack}`);
}
} else {
logger.info(`Package ${packageJson} does not have a "just" key. Not self-upgradeable through this task.`);
logger.info(`Package ${chalk.cyan(packageJson.name)} does not have a "just" key. Skipping upgrade.`);
}
}

Просмотреть файл

@ -9,7 +9,8 @@
"test": "node common/scripts/install-run-rush.js test",
"update": "node common/scripts/install-run-rush.js update",
"postinstall": "node common/scripts/install-run-rush.js install",
"add-package": "cd scripts && npm run add-package"
"add-package": "cd scripts && npm run add-package",
"upgrade-repo": "cd scripts && npm run upgrade-repo"
},
"just": {
"stack": "just-stack-monorepo"

Просмотреть файл

@ -6,6 +6,7 @@
"main": "index.js",
"scripts": {
"add-package": "just add-package --cwd ../",
"upgrade-repo": "just upgrade-repo --cwd ../",
"build": ""
},
"keywords": [],
@ -15,5 +16,8 @@
"just-task": ">=0.7.5 <1.0.0",
"just-task-preset": ">=0.6.5 <1.0.0",
"just-scripts": "^0.4.0"
},
"just": {
"stack": "just-stack-monorepo"
}
}

Просмотреть файл

@ -19,7 +19,7 @@
"dependencies": {
"react": "^16.7.0",
"react-dom": "^16.7.0",
"office-ui-fabric-react": "^6.128.0"
"office-ui-fabric-react": "^6.129.0"
},
"devDependencies": {
"@types/jest": "^23.3.13",