-
Notifications
You must be signed in to change notification settings - Fork 934
/
Copy pathindex.js
156 lines (135 loc) Β· 4.04 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import path from 'path';
import executeRule from '@commitlint/execute-rule';
import resolveExtends from '@commitlint/resolve-extends';
import cosmiconfig from 'cosmiconfig';
import {toPairs, merge, mergeWith, pick, startsWith} from 'lodash';
import resolveFrom from 'resolve-from';
import loadPlugin from './utils/loadPlugin';
const w = (a, b) => (Array.isArray(b) ? b : undefined);
const valid = input =>
pick(
input,
'extends',
'rules',
'plugins',
'parserPreset',
'formatter',
'ignores',
'defaultIgnores'
);
export default async (seed = {}, options = {cwd: process.cwd()}) => {
const loaded = await loadConfig(options.cwd, options.file);
const base = loaded.filepath ? path.dirname(loaded.filepath) : options.cwd;
// Merge passed config with file based options
const config = valid(merge({}, loaded.config, seed));
const opts = merge(
{extends: [], rules: {}, formatter: '@commitlint/format'},
pick(config, 'extends', 'plugins', 'ignores', 'defaultIgnores')
);
// Resolve parserPreset key when overwritten by main config
if (typeof config.parserPreset === 'string') {
const resolvedParserPreset = resolveFrom(base, config.parserPreset);
config.parserPreset = {
name: config.parserPreset,
path: resolvedParserPreset,
parserOpts: require(resolvedParserPreset)
};
}
// Resolve extends key
const extended = resolveExtends(opts, {
prefix: 'commitlint-config',
cwd: base,
parserPreset: config.parserPreset
});
const preset = valid(mergeWith(extended, config, w));
// Resolve parser-opts from preset
if (typeof preset.parserPreset === 'object') {
preset.parserPreset.parserOpts = await loadParserOpts(
preset.parserPreset.name,
preset.parserPreset
);
}
// Resolve config-relative formatter module
if (typeof config.formatter === 'string') {
preset.formatter =
resolveFrom.silent(base, config.formatter) || config.formatter;
}
// resolve plugins
preset.plugins = {};
if (config.plugins && config.plugins.length) {
config.plugins.forEach(pluginKey => {
loadPlugin(preset.plugins, pluginKey, process.env.DEBUG === 'true');
});
}
// Execute rule config functions if needed
const executed = await Promise.all(
['rules']
.map(key => {
return [key, preset[key]];
})
.map(async item => {
const [key, value] = item;
const executedValue = await Promise.all(
toPairs(value || {}).map(entry => executeRule(entry))
);
return [
key,
executedValue.reduce((registry, item) => {
const [key, value] = item;
registry[key] = value;
return registry;
}, {})
];
})
);
// Merge executed config keys into preset
return executed.reduce((registry, item) => {
const [key, value] = item;
registry[key] = value;
return registry;
}, preset);
};
async function loadConfig(cwd, configPath) {
const explorer = cosmiconfig('commitlint');
const explicitPath = configPath ? path.resolve(cwd, configPath) : undefined;
const explore = explicitPath ? explorer.load : explorer.search;
const searchPath = explicitPath ? explicitPath : cwd;
const local = await explore(searchPath);
if (local) {
return local;
}
return {};
}
async function loadParserOpts(parserName, pendingParser) {
// Await for the module, loaded with require
const parser = await pendingParser;
// Await parser opts if applicable
if (
typeof parser === 'object' &&
typeof parser.parserOpts === 'object' &&
typeof parser.parserOpts.then === 'function'
) {
return (await parser.parserOpts).parserOpts;
}
// Create parser opts from factory
if (
typeof parser === 'object' &&
typeof parser.parserOpts === 'function' &&
startsWith(parserName, 'conventional-changelog-')
) {
return await new Promise(resolve => {
parser.parserOpts((_, opts) => {
resolve(opts.parserOpts);
});
});
}
// Pull nested paserOpts, might happen if overwritten with a module in main config
if (
typeof parser === 'object' &&
typeof parser.parserOpts === 'object' &&
typeof parser.parserOpts.parserOpts === 'object'
) {
return parser.parserOpts.parserOpts;
}
return parser.parserOpts;
}