Skip to content

Commit b18a16e

Browse files
committed
feat: basic implementation of config command
1 parent 3ba8c11 commit b18a16e

File tree

9 files changed

+166
-94
lines changed

9 files changed

+166
-94
lines changed

@commitlint/cli/src/cli.js

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,34 @@ const pkg = require('../package');
88
const commands = require('./commands');
99

1010
const FORMATS = ['commitlint', 'json'];
11+
const COMMANDS = ['config'];
12+
13+
const HELP = `
14+
Commands
15+
commitlint lint commits, [input] reads from stdin if --edit, --from and --to are omitted
16+
17+
Options
18+
--cwd, -d directory to execute in, defaults to: process.cwd()
19+
--extends, -x array of shareable configurations to extend
20+
--format, -o format to use, defaults to "commitlint". available: "commitlint", "json"
21+
--parser-preset, -p configuration preset to use for conventional-commits-parser
22+
--quiet, -q toggle console output
23+
24+
commitlint
25+
--color, -c toggle colored output, defaults to: true
26+
--edit, -e read last commit message from the specified file or falls back to ./.git/COMMIT_EDITMSG
27+
--from, -f lower end of the commit range to lint; applies if edit=false
28+
--to, -t upper end of the commit range to lint; applies if edit=false
29+
30+
Usage
31+
$ echo "some commit" | commitlint
32+
$ commitlint --to=master
33+
$ commitlint --from=HEAD~1
34+
`;
1135

1236
const cli = meow(
1337
{
14-
help: `
15-
Commands
16-
commitlint lint commits, [input] reads from stdin if --edit, --from and --to are omitted
17-
18-
Options
19-
--cwd, -d directory to execute in, defaults to: process.cwd()
20-
--extends, -x array of shareable configurations to extend
21-
--format, -o formatter to use, defaults to "commitlint". available: "commitlint", "json"
22-
--parser-preset, -p configuration preset to use for conventional-commits-parser
23-
--quiet, -q toggle console output
24-
25-
commitlint
26-
--color, -c toggle colored output, defaults to: true
27-
--edit, -e read last commit message from the specified file or falls back to ./.git/COMMIT_EDITMSG
28-
--from, -f lower end of the commit range to lint; applies if edit=false
29-
--to, -t upper end of the commit range to lint; applies if edit=false
30-
31-
Usage
32-
$ echo "some commit" | commitlint
33-
$ commitlint --to=master
34-
$ commitlint --from=HEAD~1
35-
`,
38+
help: HELP,
3639
description: `${pkg.name}@${pkg.version} - ${pkg.description}`
3740
},
3841
{
@@ -60,7 +63,18 @@ const cli = meow(
6063
quiet: false
6164
},
6265
unknown(arg) {
63-
console.log(`unknown flags: ${arg}`);
66+
if (COMMANDS.includes(arg)) {
67+
return;
68+
}
69+
70+
console.log(HELP);
71+
72+
if (!arg.startsWith('-') && !COMMANDS.includes(arg)) {
73+
console.log(`<command> must be on of: [config], received "${arg}"`);
74+
} else {
75+
console.log(`unknown flags: ${arg}`);
76+
}
77+
6478
process.exit(1);
6579
}
6680
}
@@ -86,8 +100,28 @@ async function main(options) {
86100
const raw = Array.isArray(options.input) ? options.input : [];
87101
const [command] = raw;
88102

103+
const flags = normalizeFlags(options.flags);
104+
89105
if (!command) {
90-
return commands.lint(raw, normalizeFlags(options.flags));
106+
return commands.lint(raw, flags);
107+
}
108+
109+
switch (command) {
110+
case 'config':
111+
return commands.config(raw, {
112+
cwd: flags.cwd,
113+
extends: flags.extends,
114+
format: flags.format,
115+
parserPreset: flags.parserPreset
116+
});
117+
default: {
118+
const err = new Error(
119+
`<command> must be on of: [config], received "${command}"`
120+
);
121+
err.help = true;
122+
err.type = pkg.name;
123+
throw err;
124+
}
91125
}
92126
}
93127

@commitlint/cli/src/cli.test.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ test('should reprint input from stdin', async t => {
3232
t.true(actual.stdout.includes('foo: bar'));
3333
});
3434

35+
test('should throw for unknown command', async t => {
36+
const cwd = await git.bootstrap('fixtures/empty');
37+
const actual = await cli(['foo'], {cwd})();
38+
t.is(actual.code, 1);
39+
t.true(
40+
actual.stdout.includes('<command> must be on of: [config], received "foo"')
41+
);
42+
});
43+
3544
test('should produce no success output with --quiet flag', async t => {
3645
const cwd = await git.bootstrap('fixtures/empty');
3746
const actual = await cli(['--quiet'], {cwd})('foo: bar');
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const core = require('@commitlint/core');
2+
const getSeed = require('./get-seed').getSeed;
3+
4+
module.exports.config = config;
5+
6+
async function config(_, flags) {
7+
const loaded = await core.load(getSeed(flags), {cwd: flags.cwd});
8+
switch (flags.format) {
9+
case 'commitlint':
10+
return console.log(loaded);
11+
case 'json':
12+
return console.log(JSON.stringify(loaded));
13+
default: {
14+
const err = new Error(`unknown format: ${flags.format}`);
15+
err.type = 'commitlint';
16+
err.help = true;
17+
throw err;
18+
}
19+
}
20+
}

@commitlint/cli/src/commands/lint.js renamed to @commitlint/cli/src/commands/cmd-lint.js

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ async function lint(rawInput, flags) {
3333
}
3434

3535
const loaded = await core.load(getSeed(flags), {cwd: flags.cwd});
36-
const parserOpts = selectParserOpts(loaded.parserPreset);
37-
const opts = parserOpts ? {parserOpts} : undefined;
3836

3937
const results = await all(messages, async msg => {
4038
return {
41-
report: await core.lint(msg, loaded.rules, opts),
39+
report: await core.lint(msg, loaded.rules, {
40+
parserOpts: loaded.parserPreset.opts
41+
}),
4242
input: msg
4343
};
4444
});
@@ -92,20 +92,6 @@ function error(message, opts = {}) {
9292
return err;
9393
}
9494

95-
function selectParserOpts(parserPreset) {
96-
if (typeof parserPreset !== 'object') {
97-
return undefined;
98-
}
99-
100-
const opts = parserPreset.opts;
101-
102-
if (typeof opts !== 'object') {
103-
return undefined;
104-
}
105-
106-
return opts.parserOpts;
107-
}
108-
10995
function checkFromStdin(input, flags) {
11096
return input.length === 0 && !checkFromRepository(flags);
11197
}

@commitlint/cli/src/commands/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
module.exports = {
2-
lint: require('./lint').lint
2+
config: require('./cmd-config').config,
3+
lint: require('./cmd-lint').lint
34
};

@commitlint/core/src/library/resolve-extends.js

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ import resolveFrom from 'resolve-from';
55
import {merge, omit} from 'lodash';
66

77
// Resolve extend configs
8-
export default function resolveExtends(config = {}, context = {}) {
8+
export default async function resolveExtends(config = {}, context = {}) {
99
const {extends: e} = config;
10-
const extended = loadExtends(config, context).reduceRight(
10+
11+
const extended = (await loadExtends(config, context)).reduceRight(
1112
(r, c) => merge(r, omit(c, 'extends')),
1213
e ? {extends: e} : {}
1314
);
@@ -23,8 +24,38 @@ export default function resolveExtends(config = {}, context = {}) {
2324
}
2425

2526
// (any, string, string, Function) => any[];
26-
function loadExtends(config = {}, context = {}) {
27-
return (config.extends || []).reduce((configs, raw) => {
27+
async function loadExtends(config = {}, context = {}) {
28+
return (config.extends || []).reduce(async (configs, raw) => {
29+
const load = context.require || require;
30+
const resolved = resolveConfig(raw, context);
31+
const c = load(resolved);
32+
const cwd = path.dirname(resolved);
33+
34+
const ctx = merge({}, context, {cwd});
35+
36+
if (
37+
!context.parserPreset &&
38+
typeof c === 'object' &&
39+
typeof c.parserPreset === 'string'
40+
) {
41+
const resolvedParserPreset = resolveFrom(cwd, c.parserPreset);
42+
43+
const parserPreset = {
44+
name: c.parserPreset,
45+
path: `./${path.relative(process.cwd(), resolvedParserPreset)}`
46+
.split(path.sep)
47+
.join('/'),
48+
opts: (await require(resolvedParserPreset)).parserOpts
49+
};
50+
51+
ctx.parserPreset = parserPreset;
52+
config.parserPreset = parserPreset;
53+
}
54+
55+
return [...configs, c, ...(await loadExtends(c, ctx))];
56+
}, Promise.resolve([]));
57+
58+
/* Return (config.extends || []).reduce((configs, raw) => {
2859
const load = context.require || require;
2960
const resolved = resolveConfig(raw, context);
3061
const c = load(resolved);
@@ -60,7 +91,7 @@ function loadExtends(config = {}, context = {}) {
6091
}
6192
6293
return [...configs, c, ...loadExtends(c, ctx)];
63-
}, []);
94+
}, []); */
6495
}
6596

6697
function getId(raw = '', prefix = '') {
@@ -80,7 +111,11 @@ function resolveConfig(raw, context = {}) {
80111
const legacy = getId(raw, 'conventional-changelog-lint-config');
81112
const resolved = resolve(legacy, context);
82113
console.warn(
83-
`Resolving ${raw} to legacy config ${legacy}. To silence this warning raise an issue at 'npm repo ${legacy}' to rename to ${id}.`
114+
`Resolving ${raw} to legacy config ${
115+
legacy
116+
}. To silence this warning raise an issue at 'npm repo ${
117+
legacy
118+
}' to rename to ${id}.`
84119
);
85120
return resolved;
86121
}

0 commit comments

Comments
 (0)