Skip to content

Commit

Permalink
feat(cli): specify dependency types as options
Browse files Browse the repository at this point in the history
Closes #10
  • Loading branch information
JamieMason committed Oct 28, 2018
1 parent 75e3de9 commit ec5ef6b
Show file tree
Hide file tree
Showing 28 changed files with 443 additions and 830 deletions.
23 changes: 2 additions & 21 deletions src/bin-fix-mismatches.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,6 @@
#!/usr/bin/env node

import chalk from 'chalk';
import program = require('commander');
import _ = require('lodash');
import { relative } from 'path';
import { OPTION_SOURCES } from './constants';
import { setVersionsToNewestMismatch } from './manifests';
import { run } from './fix-mismatches';

const collect = (value: string, values: string[] = []) => values.concat(value);

program
.option(OPTION_SOURCES.spec, OPTION_SOURCES.description, collect)
.parse(process.argv);

const sources: string[] =
program.source && program.source.length
? program.source
: OPTION_SOURCES.default;

setVersionsToNewestMismatch(...sources).then((descriptors) => {
_.each(descriptors, (descriptor) => {
console.log(chalk.blue(`./${relative('.', descriptor.path)}`));
});
});
run(program);
23 changes: 2 additions & 21 deletions src/bin-format.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,6 @@
#!/usr/bin/env node

import chalk from 'chalk';
import program = require('commander');
import _ = require('lodash');
import { relative } from 'path';
import { OPTION_SOURCES } from './constants';
import { format } from './manifests';
import { run } from './format';

const collect = (value: string, values: string[] = []) => values.concat(value);

program
.option(OPTION_SOURCES.spec, OPTION_SOURCES.description, collect)
.parse(process.argv);

const sources: string[] =
program.source && program.source.length
? program.source
: OPTION_SOURCES.default;

format(...sources).then((descriptors) => {
_.each(descriptors, (descriptor) => {
console.log(chalk.blue(`./${relative('.', descriptor.path)}`));
});
});
run(program);
26 changes: 2 additions & 24 deletions src/bin-list-mismatches.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,6 @@
#!/usr/bin/env node

import chalk from 'chalk';
import program = require('commander');
import _ = require('lodash');
import { OPTION_SOURCES } from './constants';
import { getMismatchedVersions } from './manifests';
import { run } from './list-mismatches';

const collect = (value: string, values: string[] = []) => values.concat(value);

program
.option(OPTION_SOURCES.spec, OPTION_SOURCES.description, collect)
.parse(process.argv);

const sources: string[] =
program.source && program.source.length
? program.source
: OPTION_SOURCES.default;

getMismatchedVersions(...sources).then((versionByName) => {
_.each(versionByName, (versions, name) => {
console.log(chalk.yellow(name), chalk.dim(versions.join(', ')));
});

if (versionByName.length) {
process.exit(1);
}
});
run(program);
26 changes: 2 additions & 24 deletions src/bin-list.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,6 @@
#!/usr/bin/env node

import chalk from 'chalk';
import program = require('commander');
import _ = require('lodash');
import { OPTION_SOURCES } from './constants';
import { getVersions } from './manifests';
import { run } from './list';

const collect = (value: string, values: string[] = []) => values.concat(value);

program
.option(OPTION_SOURCES.spec, OPTION_SOURCES.description, collect)
.parse(process.argv);

const sources: string[] =
program.source && program.source.length
? program.source
: OPTION_SOURCES.default;

getVersions(...sources).then((versionByName) => {
_.each(versionByName, (versions, name) => {
if (versions.length > 1) {
console.log(chalk.yellow(name), chalk.dim(versions.join(', ')));
} else {
console.log(chalk.blue(name), chalk.dim(versions[0]));
}
});
});
run(program);
25 changes: 2 additions & 23 deletions src/bin-set-semver-ranges.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,6 @@
#!/usr/bin/env node

import chalk from 'chalk';
import program = require('commander');
import _ = require('lodash');
import { relative } from 'path';
import { OPTION_SEMVER_RANGE, OPTION_SOURCES } from './constants';
import { setVersionRange } from './manifests';
import { run } from './set-semver-ranges';

const collect = (value: string, values: string[] = []) => values.concat(value);

program
.option(OPTION_SEMVER_RANGE.spec, OPTION_SEMVER_RANGE.description)
.option(OPTION_SOURCES.spec, OPTION_SOURCES.description, collect)
.parse(process.argv);

const semverRange: string = program.semverRange || OPTION_SEMVER_RANGE.default;
const sources: string[] =
program.source && program.source.length
? program.source
: OPTION_SOURCES.default;

setVersionRange(semverRange, ...sources).then((descriptors) => {
_.each(descriptors, (descriptor) => {
console.log(chalk.blue(`./${relative('.', descriptor.path)}`));
});
});
run(program);
19 changes: 2 additions & 17 deletions src/bin.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,6 @@
#!/usr/bin/env node

import program = require('commander');
import {
FIX_MISMATCHES,
FORMAT,
LIST,
LIST_MISMATCHES,
SET_SEMVER_RANGES,
VERSION
} from './constants';
import { run } from './syncpack';

program
.version(VERSION)
.command(FIX_MISMATCHES.command, FIX_MISMATCHES.description)
.command(FORMAT.command, FORMAT.description)
.command(LIST.command, LIST.description, { isDefault: true })
.command(LIST_MISMATCHES.command, LIST_MISMATCHES.description)
.command(SET_SEMVER_RANGES.command, SET_SEMVER_RANGES.description);

program.parse(process.argv);
run(program);
15 changes: 15 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,18 @@ export const OPTION_SOURCES = {
description: 'glob pattern for package.json files to read from',
spec: '-s, --source [pattern]'
};

export const OPTIONS_PROD = {
description: 'include dependencies',
spec: '-p, --prod'
};

export const OPTIONS_DEV = {
description: 'include devDependencies',
spec: '-d, --dev'
};

export const OPTIONS_PEER = {
description: 'include peerDependencies',
spec: '-P, --peer'
};
58 changes: 58 additions & 0 deletions src/fix-mismatches.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import chalk from 'chalk';
import { CommanderStatic } from 'commander';
import _ = require('lodash');
import { relative } from 'path';
import {
OPTION_SOURCES,
OPTIONS_DEV,
OPTIONS_PEER,
OPTIONS_PROD
} from './constants';
import { collect } from './lib/collect';
import { getDependencyTypes } from './lib/get-dependency-types';
import { getPackages } from './lib/get-packages';
import { getMismatchedVersionsByName } from './lib/get-versions-by-name';
import { getNewest } from './lib/version';
import { writeJson } from './lib/write-json';

export const run = async (program: CommanderStatic) => {
program
.option(OPTION_SOURCES.spec, OPTION_SOURCES.description, collect)
.option(OPTIONS_PROD.spec, OPTIONS_PROD.description)
.option(OPTIONS_DEV.spec, OPTIONS_DEV.description)
.option(OPTIONS_PEER.spec, OPTIONS_PEER.description)
.parse(process.argv);

const dependencyTypes = getDependencyTypes(program);
const pkgs = await getPackages(program);
const mismatchedVersionsByName = getMismatchedVersionsByName(
dependencyTypes,
pkgs
);

Object.entries(mismatchedVersionsByName).forEach(([name, versions]) => {
const newest = getNewest(versions);
if (typeof newest === 'string') {
pkgs.forEach(({ data, path }) => {
dependencyTypes.forEach((type) => {
if (data[type] && data[type][name] && data[type][name] !== newest) {
console.log(
relative(process.cwd(), path),
name,
data[type][name],
'->',
newest
);
data[type][name] = newest;
}
});
});
}
});

await Promise.all(pkgs.map(({ data, path }) => writeJson(path, data)));

_.each(pkgs, (pkg) => {
console.log(chalk.blue(`./${relative('.', pkg.path)}`));
});
};
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { getUntidyManifest } from '../../../test/fixtures';
import { shuffleObject } from '../../../test/helpers';
import { SORT_FIRST } from '../../constants';
import { IManifest } from '../../typings';
import { manifestData } from './index';
import { getUntidyManifest } from '../test/fixtures';
import { shuffleObject } from '../test/helpers';
import { SORT_FIRST } from './constants';
import { IManifest } from './typings';
import { manifestData } from './manifests/manifest-data';

describe('format', () => {
let results: IManifest[];
Expand Down
93 changes: 93 additions & 0 deletions src/format.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import chalk from 'chalk';
import { CommanderStatic } from 'commander';
import _ = require('lodash');
import { relative } from 'path';
import { OPTION_SOURCES, SORT_AZ, SORT_FIRST } from './constants';
import { collect } from './lib/collect';
import { getPackages } from './lib/get-packages';
import { writeJson } from './lib/write-json';
import { IManifest } from './typings';

export const run = async (program: CommanderStatic) => {
const shortenBugs = (manifest: IManifest): IManifest => {
if (
manifest.bugs &&
typeof manifest.bugs === 'object' &&
manifest.bugs.url
) {
return {
...manifest,
bugs: manifest.bugs.url
};
}
return manifest;
};

const shortenRepository = (manifest: IManifest): IManifest => {
if (
manifest.repository &&
typeof manifest.repository === 'object' &&
manifest.repository.url &&
manifest.repository.url.indexOf('github.com') !== -1
) {
return {
...manifest,
repository: manifest.repository.url.split('github.com/')[1]
};
}
return manifest;
};

const sortObject = (obj: IManifest) =>
_(obj)
.entries()
.sortBy('0')
.reduce((next, [key, value]) => ({ ...next, [key]: value }), {});

const sortValue = (value: any) =>
_.isArray(value)
? value.slice(0).sort()
: _.isObject(value)
? sortObject(value)
: value;

const sortManifest = (manifest: IManifest): IManifest => {
const [first, rest] = _(manifest)
.entries()
.sortBy('0')
.partition(([key, value]) => SORT_FIRST.indexOf(key) !== -1)
.value();

const firstSorted = [...first].sort(
([keyA], [keyB]) => SORT_FIRST.indexOf(keyA) - SORT_FIRST.indexOf(keyB)
);

const restSorted = _(rest)
.map(([key, value]) => [
key,
SORT_AZ.indexOf(key) !== -1 ? sortValue(value) : value
])
.value();

return _([...firstSorted, ...restSorted]).reduce(
(obj, [key, value]) => ({ ...obj, [key]: value }),
{} as IManifest
);
};

program
.option(OPTION_SOURCES.spec, OPTION_SOURCES.description, collect)
.parse(process.argv);

const pkgs = await getPackages(program);

await Promise.all(
pkgs.map(({ data, path }) =>
writeJson(path, sortManifest(shortenBugs(shortenRepository(data))))
)
);

_.each(pkgs, (pkg) => {
console.log(chalk.blue(`./${relative('.', pkg.path)}`));
});
};
2 changes: 2 additions & 0 deletions src/lib/collect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const collect = (value: string, values: string[] = []) =>
values.concat(value);
15 changes: 15 additions & 0 deletions src/lib/get-dependency-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { CommanderStatic } from 'commander';
import { DEPENDENCY_TYPES } from '../constants';
import { IManifestKey } from '../typings';

export type GetDependencyTypes = (program: CommanderStatic) => IManifestKey[];

export const getDependencyTypes: GetDependencyTypes = (program) =>
program.prod || program.dev || program.peer
? DEPENDENCY_TYPES.filter(
(type) =>
(type === 'dependencies' && program.prod) ||
(type === 'devDependencies' && program.dev) ||
(type === 'peerDependencies' && program.peer)
)
: DEPENDENCY_TYPES;
20 changes: 20 additions & 0 deletions src/lib/get-packages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { CommanderStatic } from 'commander';
import fs = require('fs-extra');
import globby = require('globby');
import { OPTION_SOURCES } from '../constants';
import { IManifestDescriptor } from '../typings';

export const getSources = (program: CommanderStatic): string[] =>
program.source && program.source.length
? program.source
: OPTION_SOURCES.default;

export const getPackages = async (
program: CommanderStatic
): Promise<IManifestDescriptor[]> =>
Promise.all(
(await globby(getSources(program))).map(async (filePath) => ({
data: await fs.readJSON(filePath),
path: filePath
}))
);

0 comments on commit ec5ef6b

Please sign in to comment.