|   | 
| 'use strict' | 
| const fs = require('fs') | 
| const path = require('path') | 
| const YError = require('./yerror') | 
|   | 
| let previouslyVisitedConfigs = [] | 
|   | 
| function checkForCircularExtends (cfgPath) { | 
|   if (previouslyVisitedConfigs.indexOf(cfgPath) > -1) { | 
|     throw new YError(`Circular extended configurations: '${cfgPath}'.`) | 
|   } | 
| } | 
|   | 
| function getPathToDefaultConfig (cwd, pathToExtend) { | 
|   return path.resolve(cwd, pathToExtend) | 
| } | 
|   | 
| function applyExtends (config, cwd) { | 
|   let defaultConfig = {} | 
|   | 
|   if (config.hasOwnProperty('extends')) { | 
|     if (typeof config.extends !== 'string') return defaultConfig | 
|     const isPath = /\.json|\..*rc$/.test(config.extends) | 
|     let pathToDefault = null | 
|     if (!isPath) { | 
|       try { | 
|         pathToDefault = require.resolve(config.extends) | 
|       } catch (err) { | 
|         // most likely this simply isn't a module. | 
|       } | 
|     } else { | 
|       pathToDefault = getPathToDefaultConfig(cwd, config.extends) | 
|     } | 
|     // maybe the module uses key for some other reason, | 
|     // err on side of caution. | 
|     if (!pathToDefault && !isPath) return config | 
|   | 
|     checkForCircularExtends(pathToDefault) | 
|   | 
|     previouslyVisitedConfigs.push(pathToDefault) | 
|   | 
|     defaultConfig = isPath ? JSON.parse(fs.readFileSync(pathToDefault, 'utf8')) : require(config.extends) | 
|     delete config.extends | 
|     defaultConfig = applyExtends(defaultConfig, path.dirname(pathToDefault)) | 
|   } | 
|   | 
|   previouslyVisitedConfigs = [] | 
|   | 
|   return Object.assign({}, defaultConfig, config) | 
| } | 
|   | 
| module.exports = applyExtends |