1 |
|
---|
2 | 'use strict'
|
---|
3 | const fs = require('fs')
|
---|
4 | const path = require('path')
|
---|
5 | const YError = require('./yerror')
|
---|
6 |
|
---|
7 | let previouslyVisitedConfigs = []
|
---|
8 |
|
---|
9 | function checkForCircularExtends (cfgPath) {
|
---|
10 | if (previouslyVisitedConfigs.indexOf(cfgPath) > -1) {
|
---|
11 | throw new YError(`Circular extended configurations: '${cfgPath}'.`)
|
---|
12 | }
|
---|
13 | }
|
---|
14 |
|
---|
15 | function getPathToDefaultConfig (cwd, pathToExtend) {
|
---|
16 | return path.resolve(cwd, pathToExtend)
|
---|
17 | }
|
---|
18 |
|
---|
19 | function applyExtends (config, cwd) {
|
---|
20 | let defaultConfig = {}
|
---|
21 |
|
---|
22 | if (config.hasOwnProperty('extends')) {
|
---|
23 | if (typeof config.extends !== 'string') return defaultConfig
|
---|
24 | const isPath = /\.json|\..*rc$/.test(config.extends)
|
---|
25 | let pathToDefault = null
|
---|
26 | if (!isPath) {
|
---|
27 | try {
|
---|
28 | pathToDefault = require.resolve(config.extends)
|
---|
29 | } catch (err) {
|
---|
30 | // most likely this simply isn't a module.
|
---|
31 | }
|
---|
32 | } else {
|
---|
33 | pathToDefault = getPathToDefaultConfig(cwd, config.extends)
|
---|
34 | }
|
---|
35 | // maybe the module uses key for some other reason,
|
---|
36 | // err on side of caution.
|
---|
37 | if (!pathToDefault && !isPath) return config
|
---|
38 |
|
---|
39 | checkForCircularExtends(pathToDefault)
|
---|
40 |
|
---|
41 | previouslyVisitedConfigs.push(pathToDefault)
|
---|
42 |
|
---|
43 | defaultConfig = isPath ? JSON.parse(fs.readFileSync(pathToDefault, 'utf8')) : require(config.extends)
|
---|
44 | delete config.extends
|
---|
45 | defaultConfig = applyExtends(defaultConfig, path.dirname(pathToDefault))
|
---|
46 | }
|
---|
47 |
|
---|
48 | previouslyVisitedConfigs = []
|
---|
49 |
|
---|
50 | return Object.assign({}, defaultConfig, config)
|
---|
51 | }
|
---|
52 |
|
---|
53 | module.exports = applyExtends
|
---|