aboutsummaryrefslogtreecommitdiff
path: root/node_modules/hullabaloo-config-manager
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2017-05-28 00:38:50 +0200
committerFlorian Dold <florian.dold@gmail.com>2017-05-28 00:40:43 +0200
commit7fff4499fd915bcea3fa93b1aa8b35f4fe7a6027 (patch)
tree6de9a1aebd150a23b7f8c273ec657a5d0a18fe3e /node_modules/hullabaloo-config-manager
parent963b7a41feb29cc4be090a2446bdfe0c1f1bcd81 (diff)
downloadwallet-core-7fff4499fd915bcea3fa93b1aa8b35f4fe7a6027.tar.xz
add linting (and some initial fixes)
Diffstat (limited to 'node_modules/hullabaloo-config-manager')
-rw-r--r--node_modules/hullabaloo-config-manager/LICENSE22
-rw-r--r--node_modules/hullabaloo-config-manager/README.md212
-rw-r--r--node_modules/hullabaloo-config-manager/index.js60
-rw-r--r--node_modules/hullabaloo-config-manager/lib/ResolvedConfig.js35
-rw-r--r--node_modules/hullabaloo-config-manager/lib/Verifier.js178
-rw-r--r--node_modules/hullabaloo-config-manager/lib/codegen.js64
-rw-r--r--node_modules/hullabaloo-config-manager/lib/collector.js332
-rw-r--r--node_modules/hullabaloo-config-manager/lib/currentEnv.js8
-rw-r--r--node_modules/hullabaloo-config-manager/lib/errors.js48
-rw-r--r--node_modules/hullabaloo-config-manager/lib/hashDependencies.js44
-rw-r--r--node_modules/hullabaloo-config-manager/lib/hashSources.js51
-rw-r--r--node_modules/hullabaloo-config-manager/lib/readSafe.js29
-rw-r--r--node_modules/hullabaloo-config-manager/lib/reduceChains.js158
-rw-r--r--node_modules/hullabaloo-config-manager/lib/resolvePluginsAndPresets.js133
l---------node_modules/hullabaloo-config-manager/node_modules/.bin/json51
-rw-r--r--node_modules/hullabaloo-config-manager/node_modules/md5-hex/browser.js10
-rw-r--r--node_modules/hullabaloo-config-manager/node_modules/md5-hex/index.js23
-rw-r--r--node_modules/hullabaloo-config-manager/node_modules/md5-hex/license21
-rw-r--r--node_modules/hullabaloo-config-manager/node_modules/md5-hex/package.json39
-rw-r--r--node_modules/hullabaloo-config-manager/node_modules/md5-hex/readme.md46
-rw-r--r--node_modules/hullabaloo-config-manager/package.json67
21 files changed, 1581 insertions, 0 deletions
diff --git a/node_modules/hullabaloo-config-manager/LICENSE b/node_modules/hullabaloo-config-manager/LICENSE
new file mode 100644
index 000000000..bf1b86df3
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/LICENSE
@@ -0,0 +1,22 @@
+MIT License
+
+Copyright (c) 2017 Mark Wubben <mark@novemberborn.net> (novemberborn.net)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/hullabaloo-config-manager/README.md b/node_modules/hullabaloo-config-manager/README.md
new file mode 100644
index 000000000..ef2099bad
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/README.md
@@ -0,0 +1,212 @@
+# hullabaloo-config-manager
+
+Manages complex [Babel] config chains, avoiding duplicated work and enabling
+effective caching.
+
+> Hullabaloo: informal of "babel" (noun)
+>
+> A confused noise, typically that made by a number
+of voices: *the babel of voices on the road.*
+
+Use this package to resolve [Babel] config chains. The resulting options result
+in equivalent compilation behavior as if `babel-core` had resolved the config.
+
+A Node.js-compatible JavaScript module can be generated which exports a function
+that provides the options object, applicable for the current environment. This
+module can be written to disk and reused.
+
+Config sources and plugin and preset dependencies can be hashed and used as
+cache keys. The cache keys and generated module can be verified to avoid having
+to repeatedly resolve the config chains, and to be sure a previously
+transformation result can be reused.
+
+This module is used by [AVA].
+
+## Installation
+
+```console
+$ npm install --save hullabaloo-config-manager
+```
+
+## Usage
+
+```js
+const configManager = require('hullabaloo-config-manager')
+```
+
+## API
+
+### `currentEnv(): string`
+
+Returns the current environment value, just like `babel-core` would determine
+it.
+
+### `fromDirectory(dir: string, options?: {cache: Cache}): Promise<null | ResolvedConfig>`
+
+Asynchronously resolves config chains from the `dir` directory. If no config can
+be found the promise is resolved with `null`. Otherwise it is resolved with the
+[resulting config object](#resolvedconfig). The promise is rejected if
+[errors](#errors) occur.
+
+A `cache` object may be provided.
+
+### `createConfig(options: {options: BabelOptions, source: string, dir?: string, hash?: string, json5?: false}): Config`
+
+Creates and returns an in-memory [config object](#config). The first argument
+must be provided, and it must have a valid [`options` object](#babeloptions) and
+`source` value.
+
+If the `dir` value is not provided it's derived from the `source` value.
+Dependencies are resolved relative to this `dir`.
+
+If the config source does not exist on disk the `hash` value should be provided,
+otherwise hashes cannot be created for the config.
+
+The `json5` property can be set to `false` if the `options` object can be
+serialized using `JSON.stringify()`.
+
+Note that the `options` object is cloned (deeply) before use.
+
+### `fromConfig(baseConfig: Config, options?: {cache: Cache}): Promise<ResolvedConfig>`
+
+Asynchronously resolves config chains, starting with the `baseConfig`. The
+`baseConfig` must be created using the `createConfig()` method. The promise is
+resolved with the [resulting config object](#resolvedconfig). The promise is
+rejected if [errors](#errors) occur.
+
+A `cache` object may be provided.
+
+### `restoreVerifier(buffer: Buffer): Verifier`
+
+Deserializes a [`Verifier`](#verifier). The `buffer` should be created using
+`Verifier#toBuffer()`.
+
+### `prepareCache(): Cache`
+
+Creates a cache object that can be passed to the above functions. This may
+improve performance by avoiding repeatedly reading files from disk or computing
+hashes.
+
+---
+
+### `Config`
+
+Use `createConfig()` to create this object.
+
+#### `Config#extend(config: Config)`
+
+Extend the config with another config. Throws a `TypeError` if the config was
+created with an `extends` clause in its `options`. It throws an `Error` if it
+has already been extended.
+
+---
+
+### `BabelOptions`
+
+See <https://babeljs.io/docs/usage/api/#options>.
+
+---
+
+### `ResolvedConfig`
+
+Returned by `fromConfig()` and `fromDirectory()`.
+
+#### `ResolvedConfig#generateModule(): string`
+
+Generates a Node.js-compatible JavaScript module which exports a `getOptions()`
+function. This function returns a unique options object, applicable for the
+current environment, that can be passed to `babel-core` methods.
+
+This module needs to evaluated before the `getOptions()` method can be accessed.
+
+#### `ResolvedConfig#createVerifier(): Promise<Verifier>`
+
+Asynchronously hashes plugin and preset dependencies of the resolved config, as
+well as config sources, and resolves the promise with a [`Verifier`](#verifier)
+object.
+
+---
+
+### `Verifier`
+
+Use `restoreVerifier()` or `ResolvedConfig#createVerifier()` to create this
+object.
+
+#### `Verifier#cacheKeysForCurrentEnv(): {dependencies: string, sources: string}`
+
+Synchronously returns cache keys for the plugin and preset dependencies, and
+config sources, that are applicable to the current environment. Use these values
+to cache the result of `babel-core` transforms.
+
+#### `Verifier#verifyCurrentEnv(fixedHashes?: {sources: {[source: string]: string}}, cache?: Cache): Promise<{badDependency: true} | {missingSource: true} | {sourcesChanged: true} | {cacheKeys: {dependencies: string, sources: string}, dependenciesChanged: boolean, sourcesChanged: false, verifier: Verifier}>`
+
+Asynchronously verifies whether the config is still valid for the current
+environment.
+
+Provide `fixedHashes` if the verifier was derived from a created config with a
+fixed `hash` value. A `cache` object may also be provided.
+
+The promise is resolved with an object describing the verification result:
+
+* If the object has a `badDependency` property then a plugin or preset
+dependency could not be hashed, presumably because it no longer exists.
+
+* If it has a `missingSource` property then a config source no longer exists.
+
+* If its `sourcesChanged` property is `true` then config sources have changed
+and the config is no longer valid.
+
+* If its `dependenciesChanged` property is `true` then plugin or preset
+dependencies have changed, but the config itself is still valid. The `verifier`
+property holds a new `Verifier` object which takes the new dependencies into
+account. The `cacheKeys` property contains the same result as calling
+`Verifier#cacheKeysForCurrentEnv()` on the returned `verifier`.
+
+* If its `sourcesChanged` and `dependenciesChanged` properties are both `false`
+then the config is valid and cache keys won't have changed. The `verifier`
+property holds the same `Verifier` object. The `cacheKeys` properties contains
+the same result as calling `Verifier#cacheKeysForCurrentEnv()`.
+
+#### `Verifier#toBuffer()`
+
+Serializes the verifier state into a `Buffer` object. Use `restoreVerifier()`
+to deserialize.
+
+---
+
+### Errors
+
+Error constructors are not publicly available, but errors can be identified by
+their `name` property.
+
+#### `BadDependencyError`
+
+Used when a plugin or preset dependency couldn't be resolved. The corresponding
+package or file name is available through the `source` property. There may be
+another error with more details, available through the `parent` property.
+
+#### `ExtendsError`
+
+Used when an `extends` clause points at a non-existent file. The config file
+that contains the clause is available through the `source` property. The clause
+itself is available through the `clause` property. Has a `parent` property that
+contains a `NoSourceFile` error.
+
+#### `InvalidFileError`
+
+Used when a config file is invalid. The file path is available through the
+`source` property.
+
+#### `NoSourceFileError`
+
+Used when a file does not exist. The file path is available through the `source`
+property.
+
+#### `ParseError`
+
+Used when a config file cannot be parsed (this is different from it being
+invalid). The file path is available through the `source` property. The parsing
+error is available through the `parent` property.
+
+[AVA]: https://ava.li/
+[Babel]: https://babeljs.io/
diff --git a/node_modules/hullabaloo-config-manager/index.js b/node_modules/hullabaloo-config-manager/index.js
new file mode 100644
index 000000000..4e10228e7
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/index.js
@@ -0,0 +1,60 @@
+'use strict'
+
+const path = require('path')
+
+const cloneDeep = require('lodash.clonedeep')
+
+const collector = require('./lib/collector')
+const currentEnv = require('./lib/currentEnv')
+const ResolvedConfig = require('./lib/ResolvedConfig')
+const Verifier = require('./lib/Verifier')
+
+function createConfig (options) {
+ if (!options || !options.options || !options.source) {
+ throw new TypeError("Expected 'options' and 'source' options")
+ }
+ if (typeof options.options !== 'object' || Array.isArray(options.options)) {
+ throw new TypeError("'options' must be an actual object")
+ }
+
+ const source = options.source
+ const dir = options.dir || path.dirname(source)
+ const hash = options.hash || null
+ const json5 = options.json5 !== false
+ const babelOptions = cloneDeep(options.options)
+
+ return new collector.Config(dir, null, hash, json5, babelOptions, source)
+}
+exports.createConfig = createConfig
+
+exports.currentEnv = currentEnv
+
+function fromConfig (baseConfig, options) {
+ options = options || {}
+ return collector.fromConfig(baseConfig, options.cache)
+ .then(chains => new ResolvedConfig(chains, options.cache))
+}
+exports.fromConfig = fromConfig
+
+function fromDirectory (dir, options) {
+ options = options || {}
+ return collector.fromDirectory(dir, options.cache)
+ .then(chains => chains && new ResolvedConfig(chains, options.cache))
+}
+exports.fromDirectory = fromDirectory
+
+function prepareCache () {
+ return {
+ dependencyHashes: new Map(),
+ fileExistence: new Map(),
+ files: new Map(),
+ pluginsAndPresets: new Map(),
+ sourceHashes: new Map()
+ }
+}
+exports.prepareCache = prepareCache
+
+function restoreVerifier (buffer) {
+ return Verifier.fromBuffer(buffer)
+}
+exports.restoreVerifier = restoreVerifier
diff --git a/node_modules/hullabaloo-config-manager/lib/ResolvedConfig.js b/node_modules/hullabaloo-config-manager/lib/ResolvedConfig.js
new file mode 100644
index 000000000..07d5cd474
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/lib/ResolvedConfig.js
@@ -0,0 +1,35 @@
+'use strict'
+
+const codegen = require('./codegen')
+const reduceChains = require('./reduceChains')
+const Verifier = require('./Verifier')
+
+class ResolvedConfig {
+ constructor (chains, cache) {
+ this.cache = cache
+ this.babelrcDir = chains.babelrcDir
+
+ const reduced = reduceChains(chains, cache)
+ this.dependencies = reduced.dependencies
+ this.envNames = reduced.envNames
+ this.fixedSourceHashes = reduced.fixedSourceHashes
+ this.sources = reduced.sources
+ this.unflattenedDefaultOptions = reduced.unflattenedDefaultOptions
+ this.unflattenedEnvOptions = reduced.unflattenedEnvOptions
+ }
+
+ createVerifier () {
+ return Verifier.hashAndCreate(
+ this.babelrcDir,
+ this.envNames,
+ this.dependencies,
+ this.sources,
+ this.fixedSourceHashes,
+ this.cache)
+ }
+
+ generateModule () {
+ return codegen(this)
+ }
+}
+module.exports = ResolvedConfig
diff --git a/node_modules/hullabaloo-config-manager/lib/Verifier.js b/node_modules/hullabaloo-config-manager/lib/Verifier.js
new file mode 100644
index 000000000..267fcb2bb
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/lib/Verifier.js
@@ -0,0 +1,178 @@
+'use strict'
+
+const fs = require('fs')
+const path = require('path')
+
+const isEqual = require('lodash.isequal')
+const md5Hex = require('md5-hex')
+
+const currentEnv = require('./currentEnv')
+const hashDependencies = require('./hashDependencies')
+const hashSources = require('./hashSources')
+
+function ensureMissingBabelrcFile (file, cache) {
+ if (cache && cache.fileExistence && cache.fileExistence.has(file)) {
+ return cache.fileExistence.get(file)
+ }
+
+ const promise = new Promise((resolve, reject) => {
+ fs.access(file, err => {
+ if (err) {
+ if (err.code !== 'ENOENT') {
+ reject(err)
+ } else {
+ resolve(true)
+ }
+ } else {
+ resolve(false)
+ }
+ })
+ })
+
+ if (cache && cache.fileExistence) {
+ cache.fileExistence.set(file, promise)
+ }
+ return promise
+}
+
+class Verifier {
+ constructor (babelrcDir, envNames, dependencies, sources) {
+ Object.assign(this, { babelrcDir, envNames, dependencies, sources })
+ }
+
+ selectByEnv (arr, envName, mapFn) {
+ const selectDefault = !this.envNames.has(envName)
+ return arr
+ .filter(item => selectDefault ? item.default : item.envs.has(envName))
+ .map(mapFn || (item => item))
+ }
+
+ cacheKeysForCurrentEnv () {
+ const envName = currentEnv()
+ const getHash = item => item.hash
+
+ const dependencyHashes = this.selectByEnv(this.dependencies, envName, getHash)
+ const sourceHashes = this.selectByEnv(this.sources, envName, getHash)
+
+ return {
+ dependencies: md5Hex(dependencyHashes),
+ sources: md5Hex(sourceHashes)
+ }
+ }
+
+ verifyCurrentEnv (fixedHashes, cache) {
+ const envName = currentEnv()
+
+ const sourcesToHash = this.selectByEnv(this.sources, envName)
+ const expectedSourceHashes = sourcesToHash.map(item => item.hash)
+ const pendingSourceHashes = hashSources(sourcesToHash, fixedHashes && fixedHashes.sources, cache)
+
+ let checkedBabelrcFile = true
+ if (this.babelrcDir) {
+ const babelrcFile = path.join(this.babelrcDir, '.babelrc')
+ if (!sourcesToHash.some(item => item.source === babelrcFile)) {
+ checkedBabelrcFile = ensureMissingBabelrcFile(babelrcFile, cache)
+ }
+ }
+
+ const dependenciesToHash = this.selectByEnv(this.dependencies, envName)
+ const expectedDependencyHashes = dependenciesToHash.map(item => item.hash)
+ const pendingDependencyHashes = hashDependencies(dependenciesToHash, cache)
+
+ return Promise.all([
+ pendingSourceHashes,
+ checkedBabelrcFile
+ ])
+ .then(result => {
+ const sourceHashes = result[0]
+ const babelrcFileIsSame = result[1]
+
+ if (!babelrcFileIsSame || !isEqual(sourceHashes, expectedSourceHashes)) {
+ return { sourcesChanged: true }
+ }
+
+ return pendingDependencyHashes
+ .then(dependencyHashes => {
+ const dependenciesChanged = !isEqual(dependencyHashes, expectedDependencyHashes)
+
+ let verifier = this
+ if (dependenciesChanged) {
+ const dependencies = this.dependencies.map((item, index) => {
+ const hash = dependencyHashes[index]
+ return Object.assign({}, item, { hash })
+ })
+
+ verifier = new Verifier(this.babelrcDir, this.envNames, dependencies, this.sources)
+ }
+
+ return {
+ sourcesChanged: false,
+ dependenciesChanged,
+ cacheKeys: {
+ dependencies: md5Hex(dependencyHashes),
+ sources: md5Hex(sourceHashes)
+ },
+ verifier
+ }
+ })
+ })
+ .catch(err => {
+ if (err.name === 'NoSourceFileError') {
+ return {
+ missingSource: true
+ }
+ }
+
+ if (err.name === 'BadDependencyError') {
+ return {
+ badDependency: true
+ }
+ }
+
+ throw err
+ })
+ }
+
+ toBuffer () {
+ return Buffer.from(JSON.stringify({
+ babelrcDir: this.babelrcDir,
+ envNames: this.envNames,
+ dependencies: this.dependencies,
+ sources: this.sources
+ }, (key, value) => {
+ return key === 'envNames' || key === 'envs'
+ ? Array.from(value)
+ : value
+ }, 2))
+ }
+
+ static fromBuffer (buffer) {
+ const json = JSON.parse(buffer.toString('utf8'), (key, value) => {
+ return key === 'envNames' || key === 'envs'
+ ? new Set(value)
+ : value
+ })
+ return new this(json.babelrcDir, json.envNames, json.dependencies, json.sources)
+ }
+
+ static hashAndCreate (babelrcDir, envNames, dependencies, sources, fixedSourceHashes, cache) {
+ return Promise.all([
+ hashDependencies(dependencies, cache),
+ hashSources(sources, fixedSourceHashes, cache)
+ ])
+ .then(results => {
+ const dependencyHashes = results[0]
+ const sourceHashes = results[1]
+
+ dependencies.forEach((item, index) => {
+ item.hash = dependencyHashes[index]
+ })
+ sources.forEach((item, index) => {
+ item.hash = sourceHashes[index]
+ })
+
+ return new this(babelrcDir, envNames, dependencies, sources)
+ })
+ }
+}
+module.exports = Verifier
diff --git a/node_modules/hullabaloo-config-manager/lib/codegen.js b/node_modules/hullabaloo-config-manager/lib/codegen.js
new file mode 100644
index 000000000..0f95284d2
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/lib/codegen.js
@@ -0,0 +1,64 @@
+'use strict'
+
+const indentString = require('indent-string')
+const stringifyJson5 = require('json5').stringify
+
+function stringify (json5, value) {
+ return json5
+ ? stringifyJson5(value, null, 2)
+ : JSON.stringify(value, null, 2)
+}
+
+function generateFactory (unflattened, envName) {
+ const code = [`${envName ? '()' : 'envName'} => {`]
+
+ if (envName) {
+ const flattenedOptions = unflattened.reduceRight((prev, options) => {
+ options.env = {
+ [envName]: prev
+ }
+ return options
+ })
+ code.push(indentString(`return ${stringify(unflattened.json5, flattenedOptions)}`, 2))
+ } else {
+ const optionsCode = unflattened.reduceRight((prev, options, index) => {
+ const str = stringify(unflattened.json5, options)
+ if (!prev) return str
+
+ // reduceOptions ensures no options object is ever empty.
+ const lines = str.split('\n')
+ lines[lines.length - 2] += ','
+ lines[lines.length - 1] = indentString(`env: {\n [envName]: ${indentString(prev, 2).trimLeft()}\n}`, 2)
+ return lines.join('\n') + '\n}'
+ }, null)
+
+ code.push(indentString(`return ${optionsCode.trimLeft()}`, 2))
+ }
+
+ code.push('}')
+ return code.join('\n')
+}
+
+function codegen (resolvedConfig) {
+ const code = [`"use strict"
+
+const process = require("process")\n`]
+ code.push(`const defaultOptions = ${generateFactory(resolvedConfig.unflattenedDefaultOptions)}\n`)
+
+ code.push(`const envOptions = Object.create(null)\n`)
+ for (const envName of resolvedConfig.envNames) {
+ const unflattened = resolvedConfig.unflattenedEnvOptions.get(envName)
+ code.push(`envOptions[${JSON.stringify(envName)}] = ${generateFactory(unflattened, envName)}\n`)
+ }
+
+ code.push(`exports.getOptions = () => {
+ const envName = process.env.BABEL_ENV || process.env.NODE_ENV || "development"
+ return envName in envOptions
+ ? envOptions[envName]()
+ : defaultOptions(envName)
+}\n`)
+
+ return code.join('\n')
+}
+
+module.exports = codegen
diff --git a/node_modules/hullabaloo-config-manager/lib/collector.js b/node_modules/hullabaloo-config-manager/lib/collector.js
new file mode 100644
index 000000000..1a7414a87
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/lib/collector.js
@@ -0,0 +1,332 @@
+'use strict'
+
+const path = require('path')
+
+const parseJson5 = require('json5').parse
+
+const errors = require('./errors')
+const readSafe = require('./readSafe')
+
+function makeValid (source, options) {
+ // Arrays are never valid options.
+ if (Array.isArray(options)) throw new errors.InvalidFileError(source)
+
+ // Force options to be an object. Babel itself ignores falsy values when
+ // resolving config chains. Here such files still need to be included
+ // for cache busting purposes.
+ if (!options || typeof options !== 'object') return {}
+
+ return options
+}
+
+function parseFile (source, buffer) {
+ let options
+ try {
+ options = parseJson5(buffer.toString('utf8'))
+ } catch (err) {
+ throw new errors.ParseError(source, err)
+ }
+
+ return makeValid(source, options)
+}
+
+function parsePackage (source, buffer) {
+ let options
+ try {
+ const pkg = JSON.parse(buffer.toString('utf8'))
+ options = pkg && pkg.babel
+ } catch (err) {
+ throw new errors.ParseError(source, err)
+ }
+
+ return makeValid(source, options)
+}
+
+class Config {
+ constructor (dir, env, hash, json5, options, source) {
+ this.dir = dir
+ this.env = env
+ this.hash = hash
+ this.json5 = json5
+ this.options = options
+ this.source = source
+
+ this.babelrcPointer = null
+ this.envPointers = new Map()
+ this.extends = null
+ this.extendsPointer = null
+ }
+
+ copyWithEnv (env, options) {
+ return new this.constructor(this.dir, env, this.hash, this.json5, options, this.source)
+ }
+
+ extend (config) {
+ const clause = this.takeExtends()
+ if (clause) {
+ throw new TypeError(`Cannot extend config: there is an extends clause in the current options: ${clause}`)
+ }
+ if (this.extends) {
+ throw new Error('Cannot extend config: already extended')
+ }
+
+ this.extends = config
+ }
+
+ takeEnvs () {
+ const env = this.options.env
+ delete this.options.env
+
+ return env
+ ? new Map(
+ Object.keys(env)
+ .filter(Boolean)
+ .map(name => [name, env[name]]))
+ : new Map()
+ }
+
+ takeExtends () {
+ const clause = this.options.extends
+ delete this.options.extends
+ return clause
+ }
+}
+exports.Config = Config
+
+function resolveDirectory (dir, cache) {
+ const fileSource = path.join(dir, '.babelrc')
+ const packageSource = path.join(dir, 'package.json')
+
+ const fromFile = readSafe(fileSource, cache)
+ .then(contents => contents && {
+ json5: true,
+ parse () { return parseFile(fileSource, contents) },
+ source: fileSource
+ })
+
+ const fromPackage = readSafe(packageSource, cache)
+ .then(contents => contents && {
+ json5: false,
+ parse () { return parsePackage(packageSource, contents) },
+ source: packageSource
+ })
+
+ return fromFile
+ .then(fileResult => fileResult || fromPackage)
+ .then(result => {
+ // .babelrc or package.json files may not exist, and that's OK.
+ if (!result) return null
+
+ return new Config(dir, null, null, result.json5, result.parse(), result.source)
+ })
+}
+
+function resolveFile (source, cache) {
+ return readSafe(source, cache)
+ .then(contents => {
+ // The file *must* exist. Causes a proper error to be propagated to
+ // where "extends" directives are resolved.
+ if (!contents) throw new errors.NoSourceFileError(source)
+
+ return new Config(path.dirname(source), null, null, true, parseFile(source, contents), source)
+ })
+}
+
+class Chains {
+ constructor (babelrcDir, defaultChain, envChains) {
+ this.babelrcDir = babelrcDir
+ this.defaultChain = defaultChain
+ this.envChains = envChains
+ }
+
+ * [Symbol.iterator] () {
+ yield this.defaultChain
+ for (const chain of this.envChains.values()) {
+ yield chain
+ }
+ }
+}
+
+class Collector {
+ constructor (cache) {
+ this.cache = cache
+ this.configs = []
+ this.envNames = new Set()
+ this.pointers = new Map()
+ }
+
+ get initialConfig () {
+ return this.configs[0]
+ }
+
+ add (config) {
+ // Avoid adding duplicate configs. Note that configs that came from an
+ // "env" directive share their source with their parent config.
+ if (!config.env && this.pointers.has(config.source)) {
+ return Promise.resolve(this.pointers.get(config.source))
+ }
+
+ const pointer = this.configs.push(config) - 1
+ // Make sure not to override the pointer to an environmental
+ // config's parent.
+ if (!config.env) this.pointers.set(config.source, pointer)
+
+ const envs = config.takeEnvs()
+ const extendsClause = config.takeExtends()
+ const waitFor = []
+
+ if (config.extends) {
+ const promise = this.add(config.extends)
+ .then(extendsPointer => (config.extendsPointer = extendsPointer))
+ waitFor.push(promise)
+ } else if (extendsClause) {
+ const extendsSource = path.resolve(config.dir, extendsClause)
+
+ if (this.pointers.has(extendsSource)) {
+ // Point at existing config.
+ config.extendsPointer = this.pointers.get(extendsSource)
+ } else {
+ // Different configs may concurrently resolve the same extends source.
+ // While only one such resolution is added to the config list, this
+ // does lead to extra file I/O and parsing. Optimizing this is not
+ // currently considered worthwhile.
+ const promise = resolveFile(extendsSource, this.cache)
+ .then(parentConfig => this.add(parentConfig))
+ .then(extendsPointer => (config.extendsPointer = extendsPointer))
+ .catch(err => {
+ if (err.name === 'NoSourceFileError') {
+ throw new errors.ExtendsError(config.source, extendsClause, err)
+ }
+
+ throw err
+ })
+
+ waitFor.push(promise)
+ }
+ }
+
+ for (const pair of envs) {
+ const name = pair[0]
+ const options = pair[1]
+
+ this.envNames.add(name)
+ const promise = this.add(config.copyWithEnv(name, options))
+ .then(envPointer => config.envPointers.set(name, envPointer))
+ waitFor.push(promise)
+ }
+
+ return Promise.all(waitFor)
+ .then(() => pointer)
+ }
+
+ resolveChains (babelrcDir) {
+ if (this.configs.length === 0) return null
+
+ // Resolves a config chain, correctly ordering parent configs and recursing
+ // through environmental configs, while avoiding cycles and repetitions.
+ const resolveChain = (from, envName) => {
+ const chain = new Set()
+ const knownParents = new Set()
+
+ /* eslint-disable no-use-before-define */
+ const addWithEnv = config => {
+ // Avoid unnecessary work in case the `from` list contains configs that
+ // have already been added through an environmental config's parent.
+ if (chain.has(config)) return
+ chain.add(config)
+
+ if (config.envPointers.has(envName)) {
+ const pointer = config.envPointers.get(envName)
+ const envConfig = this.configs[pointer]
+ addAfterParents(envConfig)
+ }
+ }
+
+ const addAfterParents = config => {
+ // Avoid cycles by ignoring those parents that are already being added.
+ if (knownParents.has(config)) return
+ knownParents.add(config)
+
+ if (config.babelrcPointer !== null) {
+ const parent = this.configs[config.babelrcPointer]
+ addAfterParents(parent)
+ }
+ if (config.extendsPointer !== null) {
+ const parent = this.configs[config.extendsPointer]
+ addAfterParents(parent)
+ }
+
+ if (envName) {
+ addWithEnv(config)
+ } else {
+ chain.add(config)
+ }
+ }
+ /* eslint-enable no-use-before-define */
+
+ for (const config of from) {
+ if (envName) {
+ addWithEnv(config)
+ } else {
+ addAfterParents(config)
+ }
+ }
+
+ return chain
+ }
+
+ // Start with the first config. This is either the base config provided
+ // to fromConfig(), or the config derived from .babelrc / package.json
+ // found in fromDirectory().
+ const defaultChain = resolveChain([this.initialConfig])
+
+ // For each environment, augment the default chain with environmental
+ // configs.
+ const envChains = new Map(Array.from(this.envNames, name => {
+ return [name, resolveChain(defaultChain, name)]
+ }))
+
+ return new Chains(babelrcDir, defaultChain, envChains)
+ }
+}
+
+function fromConfig (baseConfig, cache) {
+ let babelrcConfig = null
+ for (let config = baseConfig; config; config = config.extends) {
+ if (config.options.babelrc === false) continue
+
+ if (babelrcConfig) {
+ throw new TypeError(`${config.source}: Cannot resolve babelrc option, already resolved by ${babelrcConfig.source}`)
+ }
+
+ babelrcConfig = config
+ }
+
+ const collector = new Collector(cache)
+ return Promise.all([
+ collector.add(baseConfig),
+ // Resolve the directory concurrently. Assumes that in the common case,
+ // the babelrcConfig doesn't extend from a .babelrc file while also leaving
+ // the babelrc option enabled. Worst case the resolved config is discarded
+ // as a duplicate.
+ babelrcConfig && resolveDirectory(babelrcConfig.dir, cache)
+ .then(parentConfig => {
+ if (!parentConfig) return
+
+ return collector.add(parentConfig)
+ .then(babelrcPointer => (babelrcConfig.babelrcPointer = babelrcPointer))
+ })
+ ])
+ .then(() => collector.resolveChains(babelrcConfig && babelrcConfig.dir))
+}
+exports.fromConfig = fromConfig
+
+function fromDirectory (dir, cache) {
+ dir = path.resolve(dir)
+
+ const collector = new Collector(cache)
+ return resolveDirectory(dir, cache)
+ .then(config => config && collector.add(config))
+ .then(() => collector.resolveChains(dir))
+}
+exports.fromDirectory = fromDirectory
diff --git a/node_modules/hullabaloo-config-manager/lib/currentEnv.js b/node_modules/hullabaloo-config-manager/lib/currentEnv.js
new file mode 100644
index 000000000..3717e3fca
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/lib/currentEnv.js
@@ -0,0 +1,8 @@
+'use strict'
+
+const env = require('process').env
+
+function currentEnv () {
+ return env.BABEL_ENV || env.NODE_ENV || 'development'
+}
+module.exports = currentEnv
diff --git a/node_modules/hullabaloo-config-manager/lib/errors.js b/node_modules/hullabaloo-config-manager/lib/errors.js
new file mode 100644
index 000000000..6ecc2e283
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/lib/errors.js
@@ -0,0 +1,48 @@
+'use strict'
+
+const ExtendableError = require('es6-error')
+
+class SourceError extends ExtendableError {
+ constructor (message, source, parent) {
+ super(`${source}: ${message}`)
+ this.source = source
+ this.parent = parent || null
+ }
+}
+exports.SourceError = SourceError
+
+class NoSourceFileError extends SourceError {
+ constructor (source) {
+ super('No such file', source)
+ }
+}
+exports.NoSourceFileError = NoSourceFileError
+
+class ParseError extends SourceError {
+ constructor (source, parent) {
+ super(`Error while parsing — ${parent.message}`, source, parent)
+ }
+}
+exports.ParseError = ParseError
+
+class InvalidFileError extends SourceError {
+ constructor (source) {
+ super('Not a proper configuration file', source)
+ }
+}
+exports.InvalidFileError = InvalidFileError
+
+class ExtendsError extends SourceError {
+ constructor (source, clause, parent) {
+ super(`Couldn't resolve extends clause: ${clause}`, source, parent)
+ this.clause = clause
+ }
+}
+exports.ExtendsError = ExtendsError
+
+class BadDependencyError extends SourceError {
+ constructor (source, parent) {
+ super("Couldn't resolve dependency", source, parent)
+ }
+}
+exports.BadDependencyError = BadDependencyError
diff --git a/node_modules/hullabaloo-config-manager/lib/hashDependencies.js b/node_modules/hullabaloo-config-manager/lib/hashDependencies.js
new file mode 100644
index 000000000..9587cee1e
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/lib/hashDependencies.js
@@ -0,0 +1,44 @@
+'use strict'
+
+const packageHash = require('package-hash')
+const md5Hex = require('md5-hex')
+
+const errors = require('./errors')
+const readSafe = require('./readSafe')
+
+function hashFile (filename, cache) {
+ return readSafe(filename, cache)
+ .then(contents => {
+ if (!contents) throw new errors.BadDependencyError(filename)
+
+ return md5Hex(contents)
+ })
+}
+
+function hashPackage (filename, fromPackage) {
+ return packageHash(`${fromPackage}/package.json`)
+ .catch(err => {
+ throw new errors.BadDependencyError(filename, err)
+ })
+}
+
+function hashDependency (filename, fromPackage, cache) {
+ if (cache && cache.dependencyHashes && cache.dependencyHashes.has(filename)) {
+ return cache.dependencyHashes.get(filename)
+ }
+
+ const promise = fromPackage
+ ? hashPackage(filename, fromPackage)
+ : hashFile(filename, cache)
+
+ if (cache && cache.dependencyHashes) {
+ cache.dependencyHashes.set(filename, promise)
+ }
+ return promise
+}
+
+function hashDependencies (dependencies, cache) {
+ const promises = dependencies.map(item => hashDependency(item.filename, item.fromPackage, cache))
+ return Promise.all(promises)
+}
+module.exports = hashDependencies
diff --git a/node_modules/hullabaloo-config-manager/lib/hashSources.js b/node_modules/hullabaloo-config-manager/lib/hashSources.js
new file mode 100644
index 000000000..e48660ea9
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/lib/hashSources.js
@@ -0,0 +1,51 @@
+'use strict'
+
+const path = require('path')
+
+const dotProp = require('dot-prop')
+const md5Hex = require('md5-hex')
+
+const errors = require('./errors')
+const readSafe = require('./readSafe')
+
+function hashSource (source, cache) {
+ if (cache && cache.sourceHashes && cache.sourceHashes.has(source)) {
+ return cache.sourceHashes.get(source)
+ }
+
+ const basename = path.basename(source)
+ const parts = basename.split('#')
+ const filename = parts[0]
+ const filepath = path.join(path.dirname(source), filename)
+
+ const pkgAccessor = filename === 'package.json'
+ ? parts[1] || 'babel'
+ : null
+
+ const promise = readSafe(filepath, cache)
+ .then(contents => {
+ if (!contents) throw new errors.NoSourceFileError(source)
+
+ if (!pkgAccessor) {
+ return md5Hex(contents)
+ }
+
+ const json = JSON.parse(contents.toString('utf8'))
+ const value = dotProp.get(json, pkgAccessor) || {}
+ return md5Hex(JSON.stringify(value))
+ })
+
+ if (cache && cache.sourceHashes) {
+ cache.sourceHashes.set(source, promise)
+ }
+ return promise
+}
+
+function hashSources (sources, fixedHashes, cache) {
+ const promises = sources.map(item => {
+ if (fixedHashes && fixedHashes.has(item.source)) return fixedHashes.get(item.source)
+ return hashSource(item.source, cache)
+ })
+ return Promise.all(promises)
+}
+module.exports = hashSources
diff --git a/node_modules/hullabaloo-config-manager/lib/readSafe.js b/node_modules/hullabaloo-config-manager/lib/readSafe.js
new file mode 100644
index 000000000..568258ac6
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/lib/readSafe.js
@@ -0,0 +1,29 @@
+'use strict'
+
+const gfs = require('graceful-fs')
+
+function readSafe (source, cache) {
+ if (cache && cache.files && cache.files.has(source)) {
+ return cache.files.get(source)
+ }
+
+ const promise = new Promise((resolve, reject) => {
+ gfs.readFile(source, (err, contents) => {
+ if (err) {
+ if (err.code === 'ENOENT') {
+ resolve(null)
+ } else {
+ reject(err)
+ }
+ } else {
+ resolve(contents)
+ }
+ })
+ })
+
+ if (cache && cache.files) {
+ cache.files.set(source, promise)
+ }
+ return promise
+}
+module.exports = readSafe
diff --git a/node_modules/hullabaloo-config-manager/lib/reduceChains.js b/node_modules/hullabaloo-config-manager/lib/reduceChains.js
new file mode 100644
index 000000000..33d4de881
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/lib/reduceChains.js
@@ -0,0 +1,158 @@
+'use strict'
+
+const cloneDeepWith = require('lodash.clonedeepwith')
+const merge = require('lodash.merge')
+
+const resolvePluginsAndPresets = require('./resolvePluginsAndPresets')
+
+function trackDependency (dependencies, filename, fromPackage, envName) {
+ if (dependencies.has(filename)) {
+ const existing = dependencies.get(filename)
+ if (envName) {
+ existing.envs.add(envName)
+ } else {
+ existing.default = true
+ }
+ return
+ }
+
+ const item = {
+ default: !envName,
+ envs: new Set(envName ? [envName] : []),
+ filename,
+ fromPackage
+ }
+ dependencies.set(filename, item)
+}
+
+function trackSource (sources, source, envName) {
+ if (sources.has(source)) {
+ const existing = sources.get(source)
+ if (envName) {
+ existing.envs.add(envName)
+ } else {
+ existing.default = true
+ }
+ return
+ }
+
+ const item = {
+ default: !envName,
+ envs: new Set(envName ? [envName] : []),
+ source
+ }
+ sources.set(source, item)
+}
+
+function createOptions (plugins, presets) {
+ const options = {}
+ if (plugins) options.plugins = plugins
+ // istanbul ignore else
+ if (presets) options.presets = presets
+ return options
+}
+
+function compressOptions (orderedOptions) {
+ const remaining = orderedOptions.slice(0, 1)
+ remaining[0].babelrc = false
+
+ for (let index = 1; index < orderedOptions.length; index++) {
+ const options = orderedOptions[index]
+ delete options.babelrc
+
+ const plugins = options.plugins
+ delete options.plugins
+
+ const presets = options.presets
+ delete options.presets
+
+ merge(remaining[0], options)
+
+ if (plugins || presets) {
+ remaining.push(createOptions(plugins, presets))
+ }
+ }
+
+ return remaining
+}
+
+function reduceOptions (chain, envName, pluginsAndPresets, dependencies, sources, fixedSourceHashes) {
+ let json5 = false
+
+ const orderedOptions = Array.from(chain, config => {
+ trackSource(sources, config.source, envName)
+ if (config.hash) {
+ fixedSourceHashes.set(config.source, config.hash)
+ }
+
+ if (config.json5) json5 = true
+
+ const lookup = pluginsAndPresets.get(config)
+ const mapPluginOrPreset = (getEntry, ref) => {
+ if (Array.isArray(ref)) {
+ return ref.length === 1
+ ? mapPluginOrPreset(getEntry, ref[0])
+ : [mapPluginOrPreset(getEntry, ref[0]), ref[1]]
+ }
+
+ const entry = getEntry(ref)
+ trackDependency(dependencies, entry.filename, entry.fromPackage, envName)
+ return entry.filename
+ }
+
+ return cloneDeepWith(config.options, (value, key, object) => {
+ if (object === config.options && (key === 'plugins' || key === 'presets')) {
+ const getEntry = ref => lookup[key].get(ref)
+ return Array.isArray(value)
+ ? value.map(ref => mapPluginOrPreset(getEntry, ref))
+ : []
+ }
+ })
+ })
+
+ const unflattenedOptions = compressOptions(orderedOptions)
+ unflattenedOptions.json5 = json5
+ return unflattenedOptions
+}
+
+function reduceChains (chains, cache) {
+ const pluginsAndPresets = resolvePluginsAndPresets(chains, cache)
+
+ const dependencies = new Map()
+ const envNames = new Set()
+ const fixedSourceHashes = new Map()
+ const sources = new Map()
+
+ const unflattenedDefaultOptions = reduceOptions(
+ chains.defaultChain, null, pluginsAndPresets, dependencies, sources, fixedSourceHashes
+ )
+
+ const unflattenedEnvOptions = new Map()
+ for (const pair of chains.envChains) {
+ const envName = pair[0]
+ const chain = pair[1]
+
+ envNames.add(envName)
+ unflattenedEnvOptions.set(
+ envName,
+ reduceOptions(chain, envName, pluginsAndPresets, dependencies, sources, fixedSourceHashes)
+ )
+ }
+
+ return {
+ dependencies:
+ Array.from(dependencies.keys())
+ .sort()
+ .map(filename => dependencies.get(filename)),
+ envNames,
+ fixedSourceHashes,
+ sources:
+ Array.from(sources.keys())
+ .sort()
+ .map(source => sources.get(source)),
+ unflattenedDefaultOptions,
+ unflattenedEnvOptions
+ }
+}
+
+module.exports = reduceChains
diff --git a/node_modules/hullabaloo-config-manager/lib/resolvePluginsAndPresets.js b/node_modules/hullabaloo-config-manager/lib/resolvePluginsAndPresets.js
new file mode 100644
index 000000000..b72ab4090
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/lib/resolvePluginsAndPresets.js
@@ -0,0 +1,133 @@
+'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
diff --git a/node_modules/hullabaloo-config-manager/node_modules/.bin/json5 b/node_modules/hullabaloo-config-manager/node_modules/.bin/json5
new file mode 120000
index 000000000..519e49ec8
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/node_modules/.bin/json5
@@ -0,0 +1 @@
+../../../json5/lib/cli.js \ No newline at end of file
diff --git a/node_modules/hullabaloo-config-manager/node_modules/md5-hex/browser.js b/node_modules/hullabaloo-config-manager/node_modules/md5-hex/browser.js
new file mode 100644
index 000000000..d6c2da0bf
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/node_modules/md5-hex/browser.js
@@ -0,0 +1,10 @@
+'use strict';
+const md5OMatic = require('md5-o-matic');
+
+module.exports = input => {
+ if (Array.isArray(input)) {
+ input = input.join('');
+ }
+
+ return md5OMatic(input);
+};
diff --git a/node_modules/hullabaloo-config-manager/node_modules/md5-hex/index.js b/node_modules/hullabaloo-config-manager/node_modules/md5-hex/index.js
new file mode 100644
index 000000000..82cfae306
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/node_modules/md5-hex/index.js
@@ -0,0 +1,23 @@
+'use strict';
+const crypto = require('crypto');
+
+module.exports = function (input) {
+ const hash = crypto.createHash('md5');
+
+ const update = buf => {
+ const inputEncoding = typeof buf === 'string' ? 'utf8' : undefined;
+ hash.update(buf, inputEncoding);
+ };
+
+ if (arguments.length > 1) {
+ throw new Error('Too many arguments. Try specifying an array.');
+ }
+
+ if (Array.isArray(input)) {
+ input.forEach(update);
+ } else {
+ update(input);
+ }
+
+ return hash.digest('hex');
+};
diff --git a/node_modules/hullabaloo-config-manager/node_modules/md5-hex/license b/node_modules/hullabaloo-config-manager/node_modules/md5-hex/license
new file mode 100644
index 000000000..654d0bfe9
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/node_modules/md5-hex/license
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/node_modules/hullabaloo-config-manager/node_modules/md5-hex/package.json b/node_modules/hullabaloo-config-manager/node_modules/md5-hex/package.json
new file mode 100644
index 000000000..a87ce154f
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/node_modules/md5-hex/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "md5-hex",
+ "version": "2.0.0",
+ "description": "Create a MD5 hash with hex encoding",
+ "license": "MIT",
+ "repository": "sindresorhus/md5-hex",
+ "author": {
+ "name": "Sindre Sorhus",
+ "email": "sindresorhus@gmail.com",
+ "url": "sindresorhus.com"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "scripts": {
+ "test": "xo && ava"
+ },
+ "files": [
+ "index.js",
+ "browser.js"
+ ],
+ "keywords": [
+ "hash",
+ "crypto",
+ "md5",
+ "hex",
+ "buffer",
+ "browser",
+ "browserify"
+ ],
+ "dependencies": {
+ "md5-o-matic": "^0.1.1"
+ },
+ "devDependencies": {
+ "ava": "*",
+ "xo": "*"
+ },
+ "browser": "browser.js"
+}
diff --git a/node_modules/hullabaloo-config-manager/node_modules/md5-hex/readme.md b/node_modules/hullabaloo-config-manager/node_modules/md5-hex/readme.md
new file mode 100644
index 000000000..630b31d0b
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/node_modules/md5-hex/readme.md
@@ -0,0 +1,46 @@
+# md5-hex [![Build Status](https://travis-ci.org/sindresorhus/md5-hex.svg?branch=master)](https://travis-ci.org/sindresorhus/md5-hex)
+
+> Create a MD5 hash with hex encoding
+
+*Please don't use MD5 hashes for anything sensitive!*
+
+Works in the browser too, when used with browserify/webpack.
+
+Checkout [`hasha`](https://github.com/sindresorhus/hasha) if you need something more flexible.
+
+
+## Install
+
+```
+$ npm install --save md5-hex
+```
+
+
+## Usage
+
+```js
+const fs = require('fs');
+const md5Hex = require('md5-hex');
+const buffer = fs.readFileSync('unicorn.png');
+
+md5Hex(buffer);
+//=> '1abcb33beeb811dca15f0ac3e47b88d9'
+```
+
+
+## API
+
+### md5Hex(input)
+
+#### input
+
+Type: `Buffer` `string` `Buffer[]` `string[]`
+
+Prefer buffers as they're faster to hash, but strings can be useful for small things.
+
+Pass an array instead of concatenating strings and/or buffers. The output is the same, but arrays do not incur the overhead of concatenation.
+
+
+## License
+
+MIT © [Sindre Sorhus](https://sindresorhus.com)
diff --git a/node_modules/hullabaloo-config-manager/package.json b/node_modules/hullabaloo-config-manager/package.json
new file mode 100644
index 000000000..9fa461714
--- /dev/null
+++ b/node_modules/hullabaloo-config-manager/package.json
@@ -0,0 +1,67 @@
+{
+ "name": "hullabaloo-config-manager",
+ "version": "1.0.1",
+ "description": "Manages complex Babel config chains, avoiding duplicated work and enabling effective caching",
+ "main": "index.js",
+ "files": [
+ "index.js",
+ "lib"
+ ],
+ "engines": {
+ "node": ">=4.5"
+ },
+ "scripts": {
+ "lint": "as-i-preach",
+ "test": "ava",
+ "posttest": "as-i-preach",
+ "coverage": "nyc npm test"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/novemberborn/hullabaloo-config-manager.git"
+ },
+ "keywords": [
+ "babel"
+ ],
+ "author": "Mark Wubben (https://novemberborn.net/)",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/novemberborn/hullabaloo-config-manager/issues"
+ },
+ "homepage": "https://github.com/novemberborn/hullabaloo-config-manager#readme",
+ "dependencies": {
+ "dot-prop": "^4.1.0",
+ "es6-error": "^4.0.2",
+ "graceful-fs": "^4.1.11",
+ "indent-string": "^3.1.0",
+ "json5": "^0.5.1",
+ "lodash.clonedeep": "^4.5.0",
+ "lodash.clonedeepwith": "^4.5.0",
+ "lodash.isequal": "^4.5.0",
+ "lodash.merge": "^4.6.0",
+ "md5-hex": "^2.0.0",
+ "package-hash": "^2.0.0",
+ "pkg-dir": "^1.0.0",
+ "resolve-from": "^2.0.0"
+ },
+ "devDependencies": {
+ "@novemberborn/as-i-preach": "^9.0.0",
+ "ava": "^0.19.0",
+ "babel-core": "^6.22.1",
+ "coveralls": "^2.11.16",
+ "fs-extra": "^2.0.0",
+ "lodash.ismatch": "^4.4.0",
+ "nyc": "^10.1.2",
+ "proxyquire": "^1.7.11",
+ "testdouble": "^2.1.2",
+ "unique-temp-dir": "^1.0.0"
+ },
+ "nyc": {
+ "reporter": [
+ "html",
+ "lcov",
+ "text"
+ ]
+ },
+ "standard-engine": "@novemberborn/as-i-preach"
+}