UNPKG

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