wallet-core/node_modules/hullabaloo-config-manager/lib/resolvePluginsAndPresets.js

134 lines
4.0 KiB
JavaScript
Raw Normal View History

2017-05-28 00:38:50 +02:00
'use strict'
const path = require('path')
const ExtendableError = require('es6-error')
const pkgDir = require('pkg-dir')
const resolveFrom = require('resolve-from')
class ResolveError extends ExtendableError {
constructor (source, kind, ref) {
super(`${source}: Couldn't find ${kind} ${JSON.stringify(ref)} relative to directory`)
this.source = source
this.ref = ref
this.isPlugin = kind === 'plugin'
this.isPreset = kind === 'preset'
}
}
function normalize (arr) {
if (!Array.isArray(arr)) return []
return arr.map(item => Array.isArray(item) ? item[0] : item)
}
function isFilePath (ref) {
return path.isAbsolute(ref) || ref.startsWith('./') || ref.startsWith('../')
}
function resolveName (name, fromDir, cache) {
if (cache.has(name)) return cache.get(name)
const filename = resolveFrom(fromDir, name)
cache.set(name, filename)
return filename
}
function resolvePackage (filename, fromFile) {
if (fromFile) return null
return pkgDir.sync(filename)
}
function resolvePluginsAndPresets (chains, sharedCache) {
const dirCaches = (sharedCache && sharedCache.pluginsAndPresets) || new Map()
const getCache = dir => {
if (dirCaches.has(dir)) return dirCaches.get(dir)
const cache = new Map()
dirCaches.set(dir, cache)
return cache
}
const byConfig = new Map()
for (const chain of chains) {
for (const config of chain) {
if (byConfig.has(config)) continue
const plugins = new Map()
const presets = new Map()
byConfig.set(config, { plugins, presets })
const fromDir = config.dir
const cache = getCache(fromDir)
const resolve = (kind, ref) => {
const possibleNames = []
if (isFilePath(ref)) {
possibleNames.push({ fromFile: true, name: ref })
} else {
if (kind === 'plugin') {
// Expand possible plugin names, see
// https://github.com/babel/babel/blob/510e93b2bd434f05c816fe6639137b35bac267ed/packages/babel-core/src/helpers/get-possible-plugin-names.js
// Babel doesn't expand scoped plugin references. @ is only valid at
// the start of a package name, so disregard refs that would result
// in `babel-plugin-@scope/name`.
if (!ref.startsWith('@')) {
const name = `babel-plugin-${ref}`
possibleNames.push({ fromFile: false, name })
}
} else {
// Expand possible preset names, see
// https://github.com/babel/babel/blob/510e93b2bd434f05c816fe6639137b35bac267ed/packages/babel-core/src/helpers/get-possible-preset-names.js
if (ref.startsWith('@')) {
const matches = /^(@.+?)\/([^/]+)(.*)/.exec(ref)
const scope = matches[1]
const partialName = matches[2]
const remainder = matches[3]
const name = `${scope}/babel-preset-${partialName}${remainder}`
possibleNames.push({ fromFile: false, name })
} else {
const name = `babel-preset-${ref}`
possibleNames.push({ fromFile: false, name })
}
}
possibleNames.push({ fromFile: false, name: ref })
}
let entry = null
for (const possibility of possibleNames) {
const filename = resolveName(possibility.name, fromDir, cache)
if (filename) {
const fromPackage = resolvePackage(filename, possibility.fromFile)
entry = { filename, fromPackage }
break
}
}
if (!entry) {
throw new ResolveError(config.source, kind, ref)
}
if (kind === 'plugin') {
plugins.set(ref, entry)
} else {
presets.set(ref, entry)
}
}
for (const ref of normalize(config.options.plugins)) {
resolve('plugin', ref)
}
for (const ref of normalize(config.options.presets)) {
resolve('preset', ref)
}
}
}
return byConfig
}
module.exports = resolvePluginsAndPresets