diff --git a/.eslintrc.js b/.eslintrc.js
index ffd3427..c5c80fc 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -7,6 +7,14 @@ module.exports = {
'jsdoc/require-param': 'error',
'jsdoc/require-param-description': 'error',
'jsdoc/require-returns-type': 'error',
+
+ // 'filenames/match-regex': [2, '^[a-z_]+[a-zA-Z_]+$', true],
+ // "filenames/match-exported": [2, [ null, "kebab", "snake" ] ],
+ // "filenames/match-exported": [ 2, null, "\\.react$" ],
+ // 'filenames/match-regex': 2,
+ // 'filenames/match-exported': 2,
+ // 'filenames/no-index': 2,
+
// 'inferno/display-name': 'OFF',
// 'inferno/display-no-depreciated': 'OFF',
},
diff --git a/Makefile b/Makefile
index 6e90b4f..d416f4b 100644
--- a/Makefile
+++ b/Makefile
@@ -41,6 +41,9 @@ lint:
docgen:
node build/cli --docs
+site:
+ node docs/_site/index.js
+
dox:
yarn run dox -- 'src/**/*.js' --layout markdown --output docs/bits/doxdox.md
@@ -58,6 +61,9 @@ babel:
tests:
yarn run test -- --notify
+frisbee:
+ cd _modules/frisbee && npm run test
+
testdist:
yarn run ava -- test/built.js --verbose
diff --git a/README.md b/README.md
index a3840d9..bbc790e 100644
--- a/README.md
+++ b/README.md
@@ -7,12 +7,11 @@
[](https://travis-ci.org/fluents/awesome-fluents)
[](https://coveralls.io/github/fluents/chain-able?branch=master)
[](https://www.codacy.com/app/aretecode/chain-able?utm_source=github.com&utm_medium=referral&utm_content=fluents/chain-able&utm_campaign=Badge_Grade)
-[](https://unpkg.com/chain-able@3.0.0)
+[](https://unpkg.com/chain-able@4.0.6)
+
[](https://github.com/fluents/awesome-fluents)
[](https://aretecode.github.io/chain-able-playground/)
-
-
[david-deps-img]: https://img.shields.io/badge/0-dependencies-blue.svg
[david-deps-url]: https://david-dm.org/fluents/chain-able
[chain-able-npm-image]: https://img.shields.io/npm/v/chain-able.svg
@@ -57,6 +56,8 @@
> interfaces that describe their intentions
+❗ chain-able now has a website!
+[🔗 chain-able.js.org](https://chain-able.js.org)
### 📦 install
@@ -65,6 +66,11 @@ yarn add chain-able
npm i chain-able --save
```
+#### cdn
+- _dev_ ``
+- _min_ ``
+
+
# 🏰 benefits
writing an api using chain-able means:
@@ -78,8 +84,8 @@ writing an api using chain-able means:
- [expressive, clearly communicative code][wiki]
- [runtime type validation][Schema]
-- [🔬 230+ tests][Tests] with [96%+ code coverage][cov]
-- ⚡ [performant & tiny][Src] `~7kb` _(gzip)_ [_300 byte_ minimal version available as snippet][snippet]
+- [🔬 300+ tests][Tests] with [96%+ code coverage][cov]
+- ⚡ [performant & tiny][Src] `~8kb` _(gzip)_ [_300 byte_ minimal version available as snippet][snippet]
more...
@@ -123,7 +129,6 @@ writing an api using chain-able means:
- [🏭 infinitely nestable understandable factories][FactoryChain]
- [▶️◀️ easy deep merging][MergeChain]
- [☮️ compatibility - typescript, nodejs, webpack, rollup, fusebox, babel, buble, amd][API]
-- ⚡ performant & tiny `~7kb` _(gzip)_ [_300 byte_ minimal version available as snippet][snippet]
@@ -140,4 +145,4 @@ writing an api using chain-able means:
- thanks to [Jon Schlinkert](https://github.com/jonschlinkert/kind-of) & [inferno](https://github.com/infernojs/inferno/blob/master/packages/inferno-shared/src/index.ts) for type checking inspirations
- transpiled with [buble](https://gitlab.com/Rich-Harris/buble)
- [Martin Fowler on FluentInterface](https://www.martinfowler.com/bliki/FluentInterface.html)
-
+- [ramda](https://github.com/ramda/ramda) & [lodash](https://github.com/lodash/lodash) for some well tested & documented utilities (currying, mapping)
diff --git a/_modules/_chain-able-md/package.json b/_modules/_chain-able-md/package.json
index 3b9c3de..d13bf2e 100644
--- a/_modules/_chain-able-md/package.json
+++ b/_modules/_chain-able-md/package.json
@@ -10,9 +10,6 @@
"babel-plugin-transform-flow-strip-types": "^6.22.0"
},
"dependencies": {
- "fliplog": "^1.0.4",
- "frisbee": "^1.5.0",
- "node-fetch": "^1.7.1",
- "xmlhttprequest": "^1.8.0"
+ "fliplog": "^1.0.4"
}
}
diff --git a/_modules/_chain-able-md/src/Frisbee.js b/_modules/_chain-able-md/src/Frisbee.js
deleted file mode 100644
index 61059e6..0000000
--- a/_modules/_chain-able-md/src/Frisbee.js
+++ /dev/null
@@ -1,440 +0,0 @@
-// eslint-disable-next-line
-'use strict'
-// frisbee
-// Copyright (c) 2015- Nick Baugh
-// MIT Licensed
-// * Author: [@niftylettuce](https://twitter.com/#!/niftylettuce)
-// * Source:
-// # frisbee
-
-const {Buffer} = require('buffer')
-const qs = require('qs')
-const isJSON = require('./isJSON')
-const {
- Chain,
- isFunction,
- isString,
- isObjPure,
- isReal,
- isUndefined,
- isObj,
- isArray,
- isNull,
- isNill,
- merge,
-} = require('./chains')
-
-const fetch = typeof window === 'object' ? window.fetch : global.fetch
-const mergeOpts = {clone: true}
-
-const validations = [
- // 0 fatal.fetch
- 'A global `fetch` method is required as either `window.fetch` ' +
- 'for browsers or `global.fetch` for node runtime environments. ' +
- 'Please add `require(\'isomorphic-fetch\')` before importing `frisbee`. ' +
- 'You may optionally `require(\'es6-promise\').polyfill()` before you ' +
- 'require `isomorphic-fetch` if you want to support older browsers.' +
- '\n\nFor more info: https://github.com/niftylettuce/frisbee#usage',
- // 1 validate.fatal.baseuri*
- 'baseURI option is required',
- // 2 validate.path.string
- '`path` must be a string',
- // 3 validate.opts.obj
- '`options` must be an object',
- // 4 validate.auth.keys
- 'auth option can only have two keys `[user, pass]`',
- // 5 validate.auth.user.string
- 'auth option `user` must be a string',
- // 6 validate.auth.pass.string
- 'auth option `pass` must be a string',
- // 7 validate.auth.jwt.string
- 'jwt token must be a string',
- `Invalid JSON received from`,
-]
-
-// @TODO could also just put strings here but then they are allocated each time
-// using `_` instead of dot for easier selection
-// could also assign to variables but array isn't so bad for order and the eyes and ease
-// smaller this way, but changes stack...
-const errMsg = msg => {
- if (msg === 'req_fetch') return validations[0]
- else if (msg === 'req_base') return validations[1]
- else if (msg === 'str_path') return validations[2]
- else if (msg === 'obj_opts') return validations[3]
- else if (msg === 'auth_keys') return validations[4]
- else if (msg === 'str_user') return validations[5]
- else if (msg === 'str_pass') return validations[6]
- else if (msg === 'str_jwt') return validations[7]
- else if (msg === 'json') return validations[8]
-}
-const throwWithMsg = msg => {
- throw new Error(errMsg(msg))
-}
-
-if (!fetch) throw new Error(errMsg('req_fetch'))
-
-const methods = ['get', 'head', 'post', 'put', 'del', 'options', 'patch']
-
-const respProperties = {
- readOnly: [
- 'headers',
- 'ok',
- 'redirected',
- 'status',
- 'statusText',
- 'type',
- 'url',
- 'bodyUsed',
- ],
- writable: ['useFinalURL'],
- callable: [
- 'clone',
- 'error',
- 'redirect',
- 'arrayBuffer',
- 'blob',
- 'formData',
- 'json',
- 'text',
- ],
-}
-
-const getContentType = headers => {
- if (isNill(headers)) {
- return null
- }
- else if (isFunction(headers.get)) {
- return headers.get('Content-Type') || headers.get('content-type')
- }
- else if (isObj(headers)) {
- return headers['Content-Type'] || headers['content-type']
- }
-}
-
-// determine whether we're returning text or json for body
-// or attempt to parse json body to use as error message
-async function parseFrisbeeResponseBody(res, contentTypeJSON) {
- if (contentTypeJSON) {
- if (isFunction(res.json)) {
- res.body = await res.json()
- }
- else {
- res.body = await res.text()
-
- // @NOTE good thing to test solidly
- if (isJSON(res.body)) {
- res.body = JSON.parse(res.body)
- }
- else {
- res.err = this.handleError('json')
- }
- }
- return res
- }
- else {
- res.body = await res.text()
- }
- return res
-}
-
-/* prettier-ignore */
-function formatFrisbeeResponseError(res, contentTypeJSON, baseURI) {
- res.err = new Error(res.statusText)
-
- // check if the response was JSON, and if so, better the error
- if (contentTypeJSON) {
- // @TODO Glazed?
- // attempt to use Glazed error messages
- if (isObj(res.body) && isString(res.body.message)) {
- res.err = new Error(res.body.message)
- }
- // attempt to utilize Stripe-inspired error messages
- else if (!(isArray(res.body) && isObj(res.body.error))) {
- if (res.body.error.message) res.err = new Error(res.body.error.message)
- if (res.body.error.stack) res.err.stack = res.body.error.stack
- if (res.body.error.code) res.err.code = res.body.error.code
- if (res.body.error.param) res.err.param = res.body.error.param
- }
- }
-}
-
-function createFrisbeeResponse(origResp) {
- const resp = {
- originalResponse: origResp,
- }
-
- respProperties.readOnly.forEach(prop =>
- Object.defineProperty(resp, prop, {
- value: origResp[prop],
- })
- )
-
- respProperties.writable.forEach(prop =>
- Object.defineProperty(resp, prop, {
- get() {
- return origResp[prop]
- },
- set(value) {
- origResp[prop] = value
- },
- })
- )
-
- let callable = null
- respProperties.callable.forEach(prop => {
- Object.defineProperty(resp, prop, {
- value: (
- (callable = origResp[prop]),
- isFunction(callable) && callable.bind(origResp)
- ),
- })
- })
-
- // easy vanilla access headers
- const headersObj = {}
- origResp.headers.forEach(pair => {
- headersObj[pair[0]] = pair[1]
- })
- Object.defineProperty(resp, 'headersObj', {
- value: headersObj,
- })
-
- return resp
-}
-
-// easy destructure err
-const fetchIt = async(url, opts) => {
- let error = null
- try {
- const result = await fetch(url, opts)
- return [error, result]
- }
- catch (e) {
- return [e, null]
- }
-}
-
-/* prettier-ignore */
-class Frisbee extends Chain {
- constructor(opts = {}) {
- super()
-
- this
- .extend(['headers', 'arrayFormat'])
- // .autoGetSet()
- // .getSet()
- // .build()
-
- .opts(opts)
- .headers(opts.headers)
- .arrayFormat(opts.arrayFormat || 'indices')
- .when(opts.auth, () => this.auth(opts.auth))
-
- // @default
- // wish you could make better stack traces once thrown? extend error??
- this.onError(function defaultErrorThrower(error) {
- console.log('throwing...')
- // throw error
- })
-
- // because conflicting names
- this._get = this.get.bind(this)
-
- methods.forEach(method => {
- this[method] = this._setup(method)
- })
-
- // already bound
- // this.httpGet = this._get
- // this._get = (arg1, arg2) => {
- // if (isUndefined(arg2))
- // }
- }
- opts(opts) {
- // validate
- if (!opts.baseURI) this.handleError('req_base')
- this.set('opts', opts)
- return this
- }
-
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Custom_Error_Types
- // can have arrays of handlers, middleware, this is baby steps
- onError(handler) {
- return this.set('onError', handler)
- }
- handleError(msg, data) {
- const error = new Error(msg)
- error.data = data
- console.log({data})
- throw error
-
- try {
- const error = new Error(msg)
- // newest at top, remove this line
- // error.stack = error.stack.split('\n')
- // error.stack.shift()
- // error.stack = error.stack.join('\n')
- const onerr = this._get('onError')
- onerr(error)
- }
- catch (e) {
- console.log({e})
- }
- console.log('wut in the fuck')
- // this._get('onError').call(this, error, this)
- }
-
- /**
- * @methodFactory
- * @method
- * @memberOf frisbee
- * @protected
- * @param {string} method enum
- * @return {Frisbee} @chainable
- */
- _setup(methodKeyword) {
- return (path = '/', options = {}) => {
- // validate ---
-
- // path must be string
- if (!isString(path)) this.handleError('str_path')
-
- // otherwise check if its an object
- if (!isObjPure(options)) this.handleError('obj_opts', options)
-
- // console.log('about to get', this)
- // require('fliplog').quick(this)
-
- // setup data ---
- const baseURI = this._get('opts').baseURI
-
- // swappable/placeholder var to use existing them update with merged
- let headers = this._get('headers')
-
- // --- here down is not tied to any instance ---
-
- // don't want to override param,
- // and it's easier to read as a descriptive variable
- // @NOTE would be a good transform
- const method =
- methodKeyword === 'del' ? 'DELETE' : methodKeyword.toUpperCase()
-
- // merge headers when we have them
- if (isObj(options) && options.headers) {
- headers = merge(headers, options.headers, mergeOpts)
- }
- const opts = merge(options, {headers, method}, mergeOpts)
-
- // remove any nil or blank headers
- // (e.g. to automatically set Content-Type with `FormData` boundary)
- Object.keys(opts.headers).forEach(key => {
- if (!isReal(opts.headers[key])) delete opts.headers[key]
- })
-
-
- /**
- * in order to support Android POST requests
- * we must allow an empty body to be sent
- * @see https://github.com/facebook/react-native/issues/4890
- */
- if (isUndefined(opts.body)) {
- if (opts.method === 'POST') opts.body = ''
- }
- else if (isObj(opts.body)) {
- if (opts.method === 'GET' || opts.method === 'DELETE') {
- path += `?${qs.stringify(opts.body, {arrayFormat: this._get('arrayFormat')})}`
- delete opts.body
- }
- // @TODO: better stringify here
- else {
- /*
- * @NOTE using caseless means checking
- * permutations of casings
- * encouraging bad practice
- * and doing a massive amount of loops
- * when it just simply isn't in the headers
- */
- const reqContentType = opts.headers ? getContentType(opts.headers) : false
-
- if (reqContentType && reqContentType.split(';')[0] === 'application/json') {
- try {
- opts.body = JSON.stringify(opts.body)
- }
- catch (err) {
- throw err
- }
- }
- }
- }
-
- // @TODO does this part here ever throw to wrap try catch?
- const dofetch = async() => {
- const [error, ogRes] = await fetchIt(baseURI + path, opts)
-
- // simple error
- if (!isNill(error)) {
- // @TODO @DEV
- console.log('has error', {error})
- return Promise.reject(error)
- }
-
- const res = createFrisbeeResponse(ogRes)
- const contentType = res.headers.get('Content-Type')
- const contentTypeJSON =
- isString(contentType) &&
- contentType.includes('application/json')
-
- await parseFrisbeeResponseBody(res, contentTypeJSON)
- if (!res.ok) formatFrisbeeResponseError(res, contentTypeJSON, baseURI)
-
- return Promise.resolve(res)
- }
-
- return dofetch()
- }
- }
-
- delAuth() {
- return this.delete('headers.Authorization')
- }
- setAuth(Authorization) {
- return this.set('headers.Authorization', Authorization)
- }
-
- auth(creds) {
- // if it has :, split into array
- if (isString(creds)) {
- const index = creds.indexOf(':')
- if (index !== -1) {
- creds = [creds.substr(0, index), creds.substr(index + 1)]
- }
- }
-
- // @TODO this is no good...
- if (!isArray(creds)) creds = [].slice.call(arguments)
-
- // essentially padd out our credentials with empty
- if (creds.length === 0) creds = ['', '']
- else if (creds.length === 1) creds.push('')
- else if (creds.length !== 2) this.handleError('auth_keys')
-
- // @TODO can do 1 step further with validation as in split plugin
- if (!isString(creds[0])) this.handleError('str_user')
- if (!isString(creds[1])) this.handleError('str_pass')
-
- if (!creds[0] && !creds[1]) this.delAuth()
- else this.setAuth(`Basic ${new Buffer(creds.join(':')).toString('base64')}`)
-
- return this
- }
-
- jwt(token) {
- if (isNull(token)) return this.delAuth()
- else if (isString(token)) return this.setAuth(`Bearer ${token}`)
- else return this.handleError('str_jwt')
- }
-}
-
-module.exports = function Frisbees(opts) {
- return new Frisbee(opts)
-}
diff --git a/_modules/_chain-able-md/src/github.js b/_modules/_chain-able-md/src/github.js
index abcc847..a7bb8b0 100644
--- a/_modules/_chain-able-md/src/github.js
+++ b/_modules/_chain-able-md/src/github.js
@@ -3,7 +3,7 @@
// const {XMLHttpRequest} = require('xmlhttprequest')
global.fetch = require('node-fetch')
-var Frisbees = require('./Frisbee')
+var Frisbees = require('../../frisbee')
var log = require('fliplog')
log.registerCatch()
diff --git a/_modules/_chain-able-md/src/isJSON.js b/_modules/_chain-able-md/src/isJSON.js
deleted file mode 100644
index 565e8ee..0000000
--- a/_modules/_chain-able-md/src/isJSON.js
+++ /dev/null
@@ -1,130 +0,0 @@
-// https://bitsrc.io/amit/json/global/json-validator/code
-
-// const isString = require('./string')
-// const onlyLettersAndSpaces = /^([\sa-z]+)*$/gim
-
-// const regexp = /[\"|\{|\[|\}|]+/
-// const chars = ['[', '"', '{', ']', '}']
-// const nums = [91, 34]
-// const map = {
-// '"': 34,
-// '{': 123,
-// '}': 125,
-// ']': 93,
-// '[': 91,
-// }
-
-// these exist in /is
-var isArray = Array.isArray
-var isString = x => typeof x === 'string'
-var isNumber = x => typeof x === 'number'
-var toRegExp = str => new RegExp(str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'))
-var isTrue = x => x === true
-
-// @TODO everything like this
-// eslint-disable-next-line no-useless-escape
-var JSONAlphaOmega = x =>
- x === 93 || x === 91 || x === 125 || x === 123 || x === 34
-
-/* prettier-ignore */
-/**
- * @desc isOdd
- * @param {number | any} x value to check
- * @return {boolean} isOdd
- *
- * @see https://stackoverflow.com/questions/6211613/testing-whether-a-value-is-odd-or-even (smaller solution than original)
- * @extends isNumber
- * @alternate n % 2 === 0
- *
- * @example
- *
- * isOdd(1)
- * //=> true
- * isOdd(2)
- * //=> false
- */
-function isOdd(x) {
- return isNumber(x) && (x & 1)
-}
-
-// @TODO auto-curry
-function isAbove() {}
-function isBelow() {}
-function isBetween() {}
-
-/**
- * @desc isEven
- * @param {number | any} x value to check
- * @return {boolean} isEven
- *
- * @extends isOdd
- * @variations inverse
- *
- * @example
- *
- * isEven(1)
- * //=> false
- * isEven(2)
- * //=> true
- *
- * var rando = Math.floor(Math.random(0, 10000))
- * isEven(rando) !== isOdd(rando)
- * //=> true
- *
- */
-function isEven(x) {
- return !isOdd(x)
-}
-
-/**
- * @alias occurrs
- * @alias getIncludesCount
- *
- * @param {string | Array} haystack
- * @param {string | Matchable} needle
- * @return {number} occurrs/includes times/count
- */
-const getIncludesCount = (haystack, needle) => {
- if (isString(haystack)) {
- return haystack.split(needle).length - 1
- }
- else if (isArray(haystack)) {
- return haystack.filter(straw => toRegExp(needle).test(straw))
- }
-}
-
-function hasWith(x, fn, symbol) {
- if (isArray(symbol)) return symbol.map(s => hasWith(x, fn, s)).every(isTrue)
- else return fn(getIncludesCount(x.split(''), symbol))
-}
-
-/* prettier-ignore */
-/**
- * @desc isJSON, without tryCatch
- * @param {*} x value to check
- * @return {boolean} x isJSON
- *
- * @example
- * isJSON('{}')
- * // => true
- *
- * isJSON('')
- * // => false
- *
- * isJSON('[]')
- * // => true
- */
-function isJSON(x) {
- return isString(x) && x.split(',').every(subString => {
- const trimmed = subString.trim()
- const start = trimmed.charCodeAt(0)
- const end = trimmed.charCodeAt(trimmed.length - 1)
- return JSONAlphaOmega(start) && JSONAlphaOmega(end)
- })
-}
-
-function isJSONSafe(x) {
- return isJSON(x) && hasWith(x, isEven, ['[', ']', '{', '}', '"'])
-}
-
-module.exports = isJSON
diff --git a/_modules/_chain-able-md/test/index.js b/_modules/_chain-able-md/test/index.js
new file mode 100644
index 0000000..8315b1c
--- /dev/null
+++ b/_modules/_chain-able-md/test/index.js
@@ -0,0 +1,18 @@
+const todo = console.log
+
+todo('badge html output')
+todo('marked to html example')
+todo('frisbee in examples + isJSON in examples')
+todo('github api - can copy?')
+todo('isjson test')
+todo('find list of tags for md to loop thru')
+todo('pkgr')
+
+todo('there are not too many markdown places in docdown so use it there')
+
+todo(`make some reusable parts for string building
+ like the string chain had a few elements that
+ provided potential to do but was not created
+ for that purpose at all and had some technical debt`)
+
+todo('use it to make plugins')
diff --git a/_modules/_docdown/index.js b/_modules/_docdown/index.js
index 2361b0c..d483a6f 100755
--- a/_modules/_docdown/index.js
+++ b/_modules/_docdown/index.js
@@ -29,6 +29,7 @@ function docdown(options) {
style: 'default',
title: 'API documentation',
toc: 'properties',
+ metadata: true,
// @TODO
debug: false,
diff --git a/_modules/_docdown/lib/generator.js b/_modules/_docdown/lib/generator.js
index 3bebd1f..f3ce0ba 100644
--- a/_modules/_docdown/lib/generator.js
+++ b/_modules/_docdown/lib/generator.js
@@ -71,7 +71,10 @@ function escape(string) {
* @returns {string} Returns the member seperator.
*/
function getSeparator(entry) {
- return entry.isPlugin() ? '.prototype.' : '.'
+ return '.'
+
+ // @NOTE: removed this temporarily, is ugly
+ // return entry.isPlugin() ? '.prototype.' : '.'
}
/*----------------------------------------------------------------------------*/
@@ -92,6 +95,7 @@ function generateDoc(source, options) {
const byCategories = options.toc === 'categories'
const entries = getEntries(source)
const organized = {}
+ const useMetadata = options.metadata
const sortEntries = options.sort
const {style, url, files} = options
@@ -180,10 +184,34 @@ function generateDoc(source, options) {
// Start markdown for the entry.
const entryMarkdown = ['\n\n']
- const {linksToString, seeToString, makeTypes, makeTests} = maker(files, entry, entryMarkdown)
+ const {
+ linksToString,
+ seeToString,
+ makeTypes,
+ makeTests,
+ } = maker(files, entry, entryMarkdown)
+
+ // @NOTE: moved here to add as metadata to toc for search with data-* attr
+ const links = entry.getLink()
+ const see = entry.getSee()
+ const notes = entry.getNote()
+ const todos = entry.getTodo()
+ const sig = entry.getSig()
+ const symb = entry.getSymb()
+ const klass = entry.getClass()
+ const klassDesc = entry.getClassDesc()
+ const klassProps = entry.getClassProps()
+ const xtends = entry.getExtends()
+ const variation = entry.getVariation()
+ const description = entry.getDesc()
+ const hash = entry.getHash(style)
+ const call = entry.getCall()
+ const category = entry.getCategory()
+
const entryData = {
- call: entry.getCall(),
- category: entry.getCategory(),
+ call,
+ see,
+ category,
// eslint-disable-next-line no-template-curly-in-string
entryHref: '#${hash}',
entryLink: _.get(
@@ -192,12 +220,12 @@ function generateDoc(source, options) {
// eslint-disable-next-line no-template-curly-in-string
style === 'github' ? '' : '# '
),
- hash: entry.getHash(style),
+ hash,
member,
name,
separator,
+ description,
sourceHref: url + '#L' + entry.getLineNumber(),
-
sourceLink: '\n' + _.get(
options,
'sourceLink',
@@ -229,38 +257,43 @@ function generateDoc(source, options) {
}
)
- // Add the heading.
- entryMarkdown.push(
+ let entryLinkTemplate = ''
+ entryLinkTemplate += ''
+ entryLinkTemplate += ''
+ entryLinkTemplate += '${member}'
+ entryLinkTemplate += '${separator}'
+ entryLinkTemplate += '${call}'
+ entryLinkTemplate += '
\n'
+
+ const renderedHeading = interpolate(
+ // eslint-disable-next-line no-template-curly-in-string
+ entryLinkTemplate +
interpolate(
// eslint-disable-next-line no-template-curly-in-string
- '${entryLink}${member}${separator}${call}
\n' +
- interpolate(
- // eslint-disable-next-line no-template-curly-in-string
- _(['${sourceLink}', _.get(options, 'sublinks', []), '${tocLink}'])
- .flatten()
- .compact()
- .join(' '),
- entryData
- ).replace(/ {2,}/g, ' '),
+ _(['${sourceLink}', _.get(options, 'sublinks', []), '${tocLink}'])
+ .flatten()
+ .compact()
+ .join(' '),
entryData
- )
+ ).replace(/ {2,}/g, ' '),
+ entryData
)
+ // Add the heading.
+ entryMarkdown.push(renderedHeading)
+
// Add the description.
- entryMarkdown.push('\n' + entry.getDesc() + '\n')
+ entryMarkdown.push('\n' + description + '\n')
// ----- new -----
- const links = entry.getLink()
- const see = entry.getSee()
- const notes = entry.getNote()
- const todos = entry.getTodo()
- const sig = entry.getSig()
- const symb = entry.getSymb()
- const klass = entry.getClass()
- const klassDesc = entry.getClassDesc()
- const klassProps = entry.getClassProps()
- const xtends = entry.getExtends()
- const variation = entry.getVariation()
const news = {
see,
@@ -278,6 +311,7 @@ function generateDoc(source, options) {
// log.white('new').data(news).echo(false)
+ const h4 = '\n#### @'
const newsKeys = Object.keys(news)
newsKeys.forEach(key => {
const value = news[key]
@@ -308,7 +342,7 @@ function generateDoc(source, options) {
log.yellow('is @see').data(seeString).echo(false)
if (value.length !== 0) {
- entryMarkdown.push('\n### @' + key + ' \n')
+ entryMarkdown.push(h4 + key + ' \n')
entryMarkdown.push(seeString)
}
}
@@ -316,7 +350,7 @@ function generateDoc(source, options) {
entryMarkdown.push(value + ' ')
}
else if (key === 'extends') {
- const md = '\n### @' + key
+ const md = h4 + key
const augments = value
if (augments.length === 1) {
entryMarkdown.push(md)
@@ -334,7 +368,7 @@ function generateDoc(source, options) {
// log.cyan('\n### @' + key + ' \n').data({data: value, str}).echo(false)
if (str === ' ') return
- entryMarkdown.push('\n### @' + key + ' \n')
+ entryMarkdown.push(h4 + key + ' \n')
entryMarkdown.push(str)
}
// console.log('###H3: ' + key + ': ', news[key], news[key] + ' <- ')
@@ -344,7 +378,7 @@ function generateDoc(source, options) {
// Add optional since version.
const since = entry.getSince()
if (!_.isEmpty(since)) {
- entryMarkdown.push('#### Since', since, '')
+ entryMarkdown.push(h4 + 'Since', since, '')
}
// @TODO: needs comments not just tag
// var version = entry.getVersion()
@@ -353,7 +387,7 @@ function generateDoc(source, options) {
// }
// Add optional aliases.
- var aliases = entry.getAliases()
+ let aliases = entry.getAliases()
if (!_.isEmpty(aliases)) {
entryMarkdown.push(
'#### Aliases',
@@ -429,6 +463,7 @@ function generateDoc(source, options) {
examples.map(example => entryMarkdown.push('#### Example', example))
}
+
// ----
// End markdown for the entry.
@@ -469,8 +504,8 @@ function generateDoc(source, options) {
if (sortEntries && organized[group]) {
// Sort the TOC groups.
organized[group].sort(function(value, other) {
- var valMember = value.getMembers(0)
- var othMember = other.getMembers(0)
+ const valMember = value.getMembers(0)
+ const othMember = other.getMembers(0)
return util.compareNatural(
(valMember ? valMember + getSeparator(value) : '') + value.getName(),
@@ -479,6 +514,7 @@ function generateDoc(source, options) {
})
}
+ // -----------
// Add TOC entries for each category.
_.each(organized[group], function(entry) {
const member = entry.getMembers(0) || ''
@@ -489,6 +525,50 @@ function generateDoc(source, options) {
return
}
+ // @NOTE: added for metadata
+ const see = entry.getSee()
+ const notes = entry.getNote()
+ const todos = entry.getTodo()
+ const sig = entry.getSig()
+ const symb = entry.getSymb()
+ const klass = entry.getClass()
+ const klassDesc = entry.getClassDesc()
+ const klassProps = entry.getClassProps()
+ const xtends = entry.getExtends()
+ const description = entry.getDesc()
+ const call = entry.getCall()
+ const category = entry.getCategory()
+
+ const meta = `
+ ${(klass || '')}
+ ${(klassDesc || '')}
+ ${(xtends || '')}
+ ${(symb || '')}
+ ${(call || '')}
+ ${(sig || '')}
+ `.trim().replace(/\r\t/gmi, '')
+
+ // @TODO could do examples too...
+ const metadata = {
+ meta,
+ call,
+ category,
+ description,
+ name,
+ member,
+ see,
+ notes,
+ todos,
+ klassProps,
+ }
+
+ log.bold('toc').data({metadata}).echo()
+
+ const metaKeys = Object.keys(metadata)
+ metadata.all = {}
+ metaKeys.forEach(key => metadata.all[key] = metadata[key])
+
+
if (entry.isAlias()) {
// An alias has a more complex html structure.
const owner = entry.getOwner()
@@ -504,10 +584,13 @@ function generateDoc(source, options) {
)
}
else {
+ const metadataArg = useMetadata ? metadata : ''
+
// Add a simple TOC entry.
- tocMarkdown.push(
- '* ' + makeAnchor('#' + entry.getHash(style), '`' + title + '`')
- )
+ const hash = entry.getHash(style)
+ const anchor = makeAnchor('#' + hash, '`' + title + '`', metadataArg)
+ const tocEntry = '* ' + anchor
+ tocMarkdown.push(tocEntry)
}
})
diff --git a/_modules/_docdown/lib/md.js b/_modules/_docdown/lib/md.js
index b39034f..1d5eb47 100644
--- a/_modules/_docdown/lib/md.js
+++ b/_modules/_docdown/lib/md.js
@@ -6,10 +6,31 @@ const _ = require('lodash')
* @private
* @param {string} href The anchor href.
* @param {string} text The anchor text.
+ * @param {Object} [metadata] additional data for attriubutes
* @returns {string} Returns the anchor HTML.
*/
-function makeAnchor(href, text) {
- return '' + _.toString(text) + ''
+function makeAnchor(href, text, metadata = '') {
+ if (typeof metadata === 'object') {
+ let attrs = ''
+ for (let prop in metadata) {
+ let value = metadata[prop]
+ if (typeof value === 'object') value = JSON.stringify(value)
+ // keep whitespaces as underscores
+ value = value.replace(/\s+/, '_')
+ // strip everything not letters/nums
+ // value = value.replace(/[\W_]+/g, '')
+ value = value.replace(/[^a-z0-9]/gmi, ' ')
+ // trim empty lines
+ // value = value.replace(/\"/gmi, `'`)
+ value = value.replace(/\r|\n|\t|\s+/gmi, ' ').trim()
+
+ if (value === '') continue
+ attrs += ` data-${prop}="${value}" `
+ }
+ metadata = attrs
+ }
+
+ return `${_.toString(text)}`
}
const maker = (files, entry, entryMarkdown) => {
diff --git a/_modules/frisbee/eh.js b/_modules/frisbee/eh.js
new file mode 100644
index 0000000..03950b4
--- /dev/null
+++ b/_modules/frisbee/eh.js
@@ -0,0 +1,28 @@
+require('isomorphic-fetch')
+const log = require('fliplog')
+const Frisbee = require('./src/frisbee')
+require('./test-setup')
+
+global._server.start()
+
+async function eh() {
+ const api = new Frisbee(global._options)
+ const querystring = {
+ a: 'blue',
+ b: 'cyan',
+ c: 'pink',
+ }
+ const getRes = await api.get('/querystring', {
+ body: querystring,
+ })
+
+ console.log(typeof getRes.body)
+ console.log(getRes.body)
+
+ const delRes = await api.get('/querystring', {
+ body: querystring,
+ })
+ console.log(typeof delRes.body)
+ console.log(delRes.body)
+}
+eh()
diff --git a/_modules/frisbee/package.json b/_modules/frisbee/package.json
new file mode 100644
index 0000000..17ed34a
--- /dev/null
+++ b/_modules/frisbee/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "md-chain",
+ "scripts": {
+ "babs": "babel awesome-github.js > awesome-github-es6.js",
+ "build": "node js",
+ "test": "jest --verbose"
+ },
+ "jest": {
+ "setupTestFrameworkScriptFile": "./test-setup.js"
+ },
+ "devDependencies": {
+ "isomorphic-fetch": "*",
+ "express": "*",
+ "cors": "*",
+ "body-parser": "*",
+ "jest": "*"
+ },
+ "dependencies": {
+ "fliplog": "^1.0.4",
+ "qs": "*",
+ "frisbee": "^1.5.0",
+ "node-fetch": "^1.7.1",
+ "xmlhttprequest": "^1.8.0"
+ }
+}
diff --git a/_modules/frisbee/src/__tests__/node.test.js b/_modules/frisbee/src/__tests__/node.test.js
new file mode 100644
index 0000000..cb410eb
--- /dev/null
+++ b/_modules/frisbee/src/__tests__/node.test.js
@@ -0,0 +1,323 @@
+require('isomorphic-fetch')
+const log = require('fliplog')
+const Frisbee = require('../../src/frisbee')
+const { isError, isObj, isString, isNumber } = require('../chains')
+
+const standardMethods = ['get', 'post', 'put', 'del', 'patch']
+const methods = [].slice.call(standardMethods).concat(['head', 'options'])
+const server = global._server
+
+// log.registerCatch()
+
+// describe('node runtime', () => {
+let api
+
+// server.start()
+afterEach(() => server.start())
+beforeEach(() => server.stop())
+
+test('should have `fetch` defined', done => {
+ expect(fetch).toBeTruthy()
+ done()
+})
+
+//
+test('should throw an error if we fail to pass baseURI', done => {
+ // expect(new Frisbee).toThrow(new Error('baseURI option is required'));
+ expect(() => new Frisbee()).toThrow(/baseURI option is required/)
+ done()
+})
+
+test('should create Frisbee instance with all methods', done => {
+ console.log(global._options)
+ api = new Frisbee(global._options)
+ expect(isObj(api)).toBe(true)
+ methods.forEach(method => expect(typeof api[method]).toBe('function'))
+ done()
+})
+
+test('should throw errors for incorrect auth() usage', done => {
+ api = new Frisbee(global._options)
+ expect(() => api.auth({})).toThrow(/auth option `user` must be a string/)
+ expect(() => api.auth(new Array(3))).toThrow(
+ /auth option can only have two keys/
+ )
+ expect(() => api.auth([{}, ''])).toThrow(
+ /auth option `user` must be a string/
+ )
+ expect(() => api.auth(['', {}])).toThrow(
+ /auth option `pass` must be a string/
+ )
+ done()
+})
+
+test('should accept valid auth("user:pass") usage', done => {
+ api = new Frisbee(global._options)
+ const creds = 'foo:bar'
+ api.auth('foo:bar')
+ const basicAuthHeader = `Basic ${new Buffer(creds).toString('base64')}`
+ expect(api.headers.Authorization).toEqual(basicAuthHeader)
+ done()
+})
+
+test('should allow chaining of `auth` and an HTTP method', async done => {
+ api = new Frisbee(global._options)
+ try {
+ await api.auth('foo', 'bar').get('/')
+ }
+ catch (err) {
+ throw err
+ }
+ done()
+})
+
+test('should allow removal of auth() header', done => {
+ api = new Frisbee(global._options)
+
+ api.auth('foo')
+ // invalid auth
+ // expect(() => .toThrow(/user/)
+ api.auth()
+ expect(api.headers.Authorization).toBeFalsy()
+ done()
+})
+
+test(
+ 'should throw an error if we fail to pass a string `path`',
+ async done => {
+ api = new Frisbee(global._options)
+
+ try {
+ await api.get({})
+ }
+ catch (err) {
+ expect(err.message).toEqual('`path` must be a string')
+ }
+
+ done()
+ }
+)
+
+test('should throw an error if we fail to pass an object `options`', async done => {
+ api = new Frisbee(global._options)
+
+ try {
+ await api.get('', [])
+ }
+ catch (err) {
+ expect(err.message).toEqual('`options` must be an object')
+ }
+ try {
+ await api.get('', 1)
+ }
+ catch (err) {
+ expect(err.message).toEqual('`options` must be an object')
+ }
+ done()
+})
+
+test('should throw an error if we pass a non object `options`', async done => {
+ api = new Frisbee(global._options)
+ try {
+ await api.get('', false)
+ }
+ catch (err) {
+ expect(err.message).toEqual('`options` must be an object')
+ }
+ done()
+})
+
+test('should automatically set options to an empty object if not set', async done => {
+ api = new Frisbee(global._options)
+
+ try {
+ await api.get('')
+ }
+ catch (err) {
+ throw err
+ }
+
+ done()
+})
+
+standardMethods.forEach(method => {
+ const methodName = method === 'del' ? 'DELETE' : method.toUpperCase()
+
+ test(`should return 200 on ${methodName}`, async done => {
+ api = new Frisbee(global._options)
+
+ const opts = {}
+
+ if (method === 'post') opts.body = { foo: 'bar' }
+
+ try {
+ const res = await api[method]('/', opts)
+ expect(isObj(res)).toBe(true)
+ expect(isObj(res.body)).toBe(true)
+ }
+ catch (err) {
+ throw err
+ }
+
+ done()
+ })
+})
+
+standardMethods.forEach(method => {
+ const methodName = method === 'del' ? 'DELETE' : method.toUpperCase()
+
+ test(`should return 200 on ${methodName}`, async done => {
+ api = new Frisbee(global._options)
+
+ const opts = {}
+ if (method === 'post') opts.body = { foo: 'bar' }
+
+ try {
+ const res = await api[method]('/', opts)
+ expect(isObj(res)).toBe(true)
+ expect(isObj(res.body)).toBe(true)
+ }
+ catch (err) {
+ throw err
+ }
+
+ done()
+ })
+})
+
+test('should stringify querystring parameters for GET and DELETE requests', async done => {
+ api = new Frisbee(global._options)
+ const querystring = {
+ a: 'blue',
+ b: 'cyan',
+ c: 'pink',
+ }
+ const getRes = await api.get('/querystring', {
+ body: querystring,
+ })
+
+ expect(isObj(getRes.body)).toBe(true)
+ expect(getRes.body).toEqual(querystring)
+
+ const delRes = await api.get('/querystring', {
+ body: querystring,
+ })
+ expect(isObj(delRes.body)).toBe(true)
+ expect(delRes.body).toEqual(querystring)
+
+ done()
+})
+
+test('should stringify querystring parameters with arrayFormat for GET and DELETE requests', async done => {
+ api = new Frisbee(
+ Object.assign({}, global._options, { formatArray: 'brackets' })
+ )
+ const querystring = {
+ a: 'blue',
+ b: 'cyan',
+ c: 'pink',
+ d: ['1', '2', '3'],
+ }
+ const getRes = await api.get('/querystring', {
+ body: querystring,
+ })
+ expect(isObj(getRes.body)).toBe(true)
+ expect(getRes.body).toEqual(querystring)
+
+ const delRes = await api.get('/querystring', {
+ body: querystring,
+ })
+ expect(isObj(delRes.body)).toBe(true)
+ expect(delRes.body).toEqual(querystring)
+
+ done()
+})
+
+test('should URL encode querystring parameters for GET and DELETE requests', async done => {
+ api = new Frisbee(global._options)
+ const querystring = {
+ a: ' ',
+ b: '&foo&',
+ c: '$$%%%%',
+ }
+ const getRes = await api.get('/querystring', {
+ body: querystring,
+ })
+ expect(isObj(getRes.body)).toBe(true)
+ expect(getRes.body).toEqual(querystring)
+
+ const delRes = await api.del('/querystring', {
+ body: querystring,
+ })
+ expect(isObj(delRes.body)).toBe(true)
+ expect(delRes.body).toEqual(querystring)
+
+ done()
+})
+
+test('should return 404', async done => {
+ api = new Frisbee(global._options)
+ const res = await api.get('/404')
+ console.log('should return 404', { res, statusText: res.statusText })
+ console.log(res.statusText, 'statusText', res.statusText == 'Not Found')
+ // expect(isError(res.err)).toBe(true)
+ // expect(res.err.message).toEqual('Not Found')
+ expect(res.statusText).toEqual('Not Found')
+ done()
+})
+
+test('should return 404 with valid json', async done => {
+ api = new Frisbee(global._options)
+ const res = await api.get('/404-with-valid-json')
+ console.log('should return 404 with valid json', { res })
+
+ // expect(isError(res.err)).toBe(true)
+ // expect(res.err.message).toEqual('Bad Request')
+ expect(res.statusText).toEqual('Bad Request')
+ done()
+})
+
+test('should return 404 with invalid json', async done => {
+ api = new Frisbee(global._options)
+ try {
+ const res = await api.get('/404-with-invalid-json')
+ log.data(res).echo()
+ console.log(isError(res.err), res.err, 'isError___')
+ // expect(isError(res.err)).toBe(true)
+ expect(typeof (res.err)).toBe('object')
+ }
+ catch (e) {
+ log.data(e).red('e').echo()
+ }
+ // console.log('fetched, checking error message', res.err)
+ // invalid json response body at
+ // expect(res.err.message).toEqual(
+ // // @NOTE was Invalid JSON received from
+ // //
+ // `invalid json response body at ${global._options.baseURI}`
+ // )
+ done()
+})
+
+test('should return 404 with stripe error', async done => {
+ api = new Frisbee(global._options)
+ const res = await api.get('/404-with-stripe-error')
+ console.log('should return 404 with stripe error', res)
+ // expect(isError(res.err)).toBe(true)
+ expect(isString(res.err.message)).toBe(true)
+ // expect(isString(res.err.stack)).toBe(true)
+ // expect(isNumber(res.err.code)).toBe(true)
+ // expect(isString(res.err.param)).toBe('string')
+ done()
+})
+
+test('should return 400 with message', async done => {
+ api = new Frisbee(global._options)
+ const res = await api.get('/400-with-message')
+
+ // expect(isError(res.err)).toBe(true)
+ expect(res.body.message).toEqual('Oops!')
+ // expect(res.err.message).toEqual('Oops!')
+ done()
+})
+// })
diff --git a/_modules/frisbee/src/chains.js b/_modules/frisbee/src/chains.js
new file mode 100644
index 0000000..c116740
--- /dev/null
+++ b/_modules/frisbee/src/chains.js
@@ -0,0 +1,7 @@
+const Chainable = require('../../../src')
+const isJSON = require('../../../src/deps/is/JSON')
+
+Chainable.isJSON = Chainable.is.isJSON = isJSON
+Chainable.enhanceError = require('../../../src/deps/validators/error')
+
+module.exports = Chainable
diff --git a/_modules/frisbee/src/frisbee.js b/_modules/frisbee/src/frisbee.js
new file mode 100644
index 0000000..1caac02
--- /dev/null
+++ b/_modules/frisbee/src/frisbee.js
@@ -0,0 +1,710 @@
+// frisbee
+// Copyright (c) 2015- Nick Baugh
+// MIT Licensed
+// * Author: [@niftylettuce](https://twitter.com/#!/niftylettuce)
+// * Source:
+// # frisbee
+
+// eslint-disable-next-line
+'use strict'
+
+// https://davidwalsh.name/fetch
+
+const {Buffer} = require('buffer')
+const qs = require('qs')
+const {
+ Chain,
+ isFunction,
+ isString,
+ isObjPure,
+ isReal,
+ isUndefined,
+ isObj,
+ isArray,
+ isNull,
+ isNill,
+ isJSON,
+ merge,
+ encase,
+ enhanceError,
+} = require('./chains')
+
+const fetch = typeof window === 'object' ? window.fetch : global.fetch
+const mergeOpts = {clone: true}
+
+/* @TODO should wildcard fliplog in with logchain internal debugging for debug levels in dev build system thing */
+function isJSONSafe(json, debug = false) {
+ let valid = json
+ try {
+ valid = JSON.parse(json)
+ return valid
+ }
+ catch (e) {
+ if (debug === true) {
+ console.log('JSON is not JSON', e)
+ }
+ return false
+ }
+}
+
+// base URI for everything
+global._options = {
+ baseURI: 'http://localhost:8080',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json',
+ },
+}
+
+// scope the old function to the new one like .has .get since they are common
+// have a requireable fn
+//
+// @IMPORTANT TO UPGRADE THE EXPORTING SO EVERYTHING IS FLAT
+// NEEDS SOLID CHAIN-ABLE-FS
+function renameMethod(originalMethodName, newMethodName) {
+ this[newMethodName] = this[originalMethodName]
+}
+
+const validations = [
+ // 0 fatal.fetch
+ 'A global `fetch` method is required as either `window.fetch` ' +
+ 'for browsers or `global.fetch` for node runtime environments. ' +
+ 'Please add `require(\'isomorphic-fetch\')` before importing `frisbee`. ' +
+ 'You may optionally `require(\'es6-promise\').polyfill()` before you ' +
+ 'require `isomorphic-fetch` if you want to support older browsers.' +
+ '\n\nFor more info: https://github.com/niftylettuce/frisbee#usage',
+ // 1 validate.fatal.baseuri*
+ 'baseURI option is required',
+ // 2 validate.path.string
+ '`path` must be a string',
+ // 3 validate.opts.obj
+ '`options` must be an object',
+ // 4 validate.auth.keys
+ 'auth option can only have two keys `[user, pass]`',
+ // 5 validate.auth.user.string
+ 'auth option `user` must be a string',
+ // 6 validate.auth.pass.string
+ 'auth option `pass` must be a string',
+ // 7 validate.auth.jwt.string
+ 'jwt token must be a string',
+ `Invalid JSON received from`,
+]
+
+// @TODO could also just put strings here but then they are allocated each time
+// using `_` instead of dot for easier selection
+// could also assign to variables but array isn't so bad for order and the eyes and ease
+// smaller this way, but changes stack...
+const errMsg = msg => {
+ if (msg === 'req_fetch') return validations[0]
+ else if (msg === 'req_base') return validations[1]
+ else if (msg === 'str_path') return validations[2]
+ else if (msg === 'obj_opts') return validations[3]
+ else if (msg === 'auth_keys') return validations[4]
+ else if (msg === 'str_user') return validations[5]
+ else if (msg === 'str_pass') return validations[6]
+ else if (msg === 'str_jwt') return validations[7]
+ else if (msg === 'json') return validations[8]
+}
+const throwWithMsg = msg => {
+ throw new Error(errMsg(msg))
+}
+
+if (!fetch) throwWithMsg('req_fetch')
+
+const methods = ['get', 'head', 'post', 'put', 'del', 'options', 'patch']
+
+const respProperties = {
+ readOnly: [
+ 'headers',
+ 'ok',
+ 'redirected',
+ 'status',
+ 'statusText',
+ 'type',
+ 'url',
+ 'bodyUsed',
+ ],
+ writable: ['useFinalURL'],
+ callable: [
+ 'clone',
+ 'error',
+ 'redirect',
+ 'arrayBuffer',
+ 'blob',
+ 'formData',
+ 'json',
+ 'text',
+ ],
+}
+
+const getContentType = headers => {
+ if (isNill(headers)) {
+ return null
+ }
+ else if (isFunction(headers.get)) {
+ return headers.get('Content-Type') || headers.get('content-type')
+ }
+ else if (isObj(headers)) {
+ return headers['Content-Type'] || headers['content-type']
+ }
+}
+
+// @TODO could copy in the typed version to generate comments to generate docs too
+// and allows backwards parsing thinking for creating typedefs
+//
+// clone() - Creates a clone of a Response object.
+// error() - Returns a new Response object associated with a network error.
+// redirect() - Creates a new response with a different URL.
+// arrayBuffer() - Returns a promise that resolves with an ArrayBuffer.
+// blob() - Returns a promise that resolves with a Blob.
+// formData() - Returns a promise that resolves with a FormData object.
+// json() - Returns a promise that resolves with a JSON object.
+// text()
+
+// determine whether we're returning text or json for body
+// or attempt to parse json body to use as error message
+async function parseFrisbeeResponseBody(res, contentTypeJSON) {
+ // for (var originalProp in res.originalResponse) {
+ // // if (!isUndefined(res[originalProp])) {
+ // const has = originalProp in res
+ // if (has) continue
+ // Object.defineProperty(res, originalProp, Object.getOwnPropertyDescriptor(res.originalResponse, originalProp) || {})
+ // // }
+ // }
+ try {
+ if (contentTypeJSON) {
+ // console.log('is contentTypeJSON')
+ if (isFunction(res.json)) {
+ // console.log('is json on response')
+ try {
+ // @TODO encase()
+ res.body = await res.json()
+ }
+ catch (e) {
+ // console.log('errored parsing json on response', e)
+ // return e
+ res.err = e
+ res.originalResponse.statusText = e ? e.message : e
+
+ // res.originalResponse.err = e
+ // res.statusText = e.message
+ // console.log({res})
+ }
+ // console.log('parsed json on response, done')
+ }
+ else {
+ // console.log('is isFoshoJSON - calling text')
+
+ res.body = await res.text()
+ // console.log('is isFoshoJSON -pre')
+ const isFoshoJSON = isJSONSafe(res.body)
+ // console.log('is isFoshoJSON - pre parse')
+
+ // @TODO another fn here could do
+ // @NOTE good thing to test solidly
+ if (isJSON(res.body)) {
+ res.body = encase(JSON.parse(res.body)).onInvalid((error) => res.err = error)
+ // console.log('error?')
+ }
+ else {
+ // console.log('handling it, on own')
+ res.err = this.handleError('json')
+ }
+ }
+ return res
+ }
+ else {
+ // console.log('LAST ELSE')
+ res.body = await res.text()
+ }
+ }
+ catch (e) {
+ res.err = e
+ // console.log('ERROR PARSING', e)
+ }
+
+ // console.log('parsed response')
+ return res
+}
+
+/**
+ * @TODO needs more features that make axios viable
+ * easy middleware for local storage & jwt retry que
+ */
+
+/* prettier-ignore */
+function formatFrisbeeResponseError(res, contentTypeJSON, baseURI) {
+ // res.err = new Error(res.statusText)
+ const FrisbeeResponse = res
+ // new Response(res)
+
+ // type - basic, cors
+ // url
+ // useFinalURL - Boolean for if url is the final URL
+ // status - status code (ex: 200, 404, etc.)
+ // ok - Boolean for successful response (status in the range 200-299)
+ // statusText - status code (ex: OK)
+ // headers
+
+
+ // check if the response was JSON, and if so, better the error
+ if (contentTypeJSON) {
+ // @TODO Glazed?
+ // attempt to use Glazed error messages
+ if (isObj(FrisbeeResponse.body) && isString(FrisbeeResponse.body.message)) {
+ // @TODO these are the same...?
+ // FrisbeeResponse.err = new Error(FrisbeeResponse.body.message)
+ FrisbeeResponse.err = FrisbeeResponse.body
+ }
+ // attempt to utilize Stripe-inspired error messages
+ if (!(isArray(FrisbeeResponse.body) && isObj(FrisbeeResponse.body.error))) {
+ // was here
+ res.err = FrisbeeResponse.body.error
+ }
+ // if (isObj(res.err)) {
+ // if (res.err.message) res.err = new Error(res.err.message)
+ // if (res.err.stack) res.err.stack = (res.err.stack)
+ // if (res.err.code) res.err.code = (res.err.code)
+ // if (res.err.param) res.err.param = (res.err.param)
+ // }
+ }
+ return FrisbeeResponse
+}
+
+// enhanceError
+
+function createFrisbeeResponse(origResp) {
+ const resp = {
+ originalResponse: origResp,
+ }
+
+ // curry
+ // const define = (prop, value) => Object.defineProperty(resp, prop, value)
+
+ // console.log('creating frisbee response', {resp})
+
+ respProperties.readOnly.forEach(prop =>
+ Object.defineProperty(resp, prop, {
+ value: origResp[prop],
+ })
+ //&& console.log({ prop })
+ )
+
+ respProperties.writable.forEach(prop =>
+ Object.defineProperty(resp, prop, {
+ get() {
+ return origResp[prop]
+ },
+ set(value) {
+ origResp[prop] = value
+ },
+ })
+ //&& console.log({ prop })
+ )
+
+ let callable = null
+ respProperties.callable.forEach(prop => {
+ Object.defineProperty(resp, prop, {
+ // enumerable: true,
+ value: (
+ (callable = origResp[prop]),
+ isFunction(callable) && callable.bind(origResp)
+ ),
+ })
+ // && console.log({ prop })
+ })
+
+ // easy vanilla access headers
+ const headersObj = {}
+ origResp.headers.forEach(pair => {
+ headersObj[pair[0]] = pair[1]
+ })
+ Object.defineProperty(resp, 'headersObj', {
+ value: headersObj,
+ })
+
+ // const descriptors = obj => {
+ // const descs = []
+ // for (let prop in obj) {
+ // descs.push({ [prop]: Object.getOwnPropertyDescriptor(obj, prop) })
+ // }
+ // return descs
+ // }
+
+ // .body
+ // descriptors(resp.originalResponse).forEach(desc => {
+ // const prop = Object.keys(desc)[0]
+ // if (resp[prop]) return
+ // Object.defineProperty(resp, prop, desc[prop])
+ // console.log({ prop })
+ // })
+
+ // console.log('created frisbee response')
+ // console.log(descriptors(resp.originalResponse))
+
+ return resp
+}
+
+function copySetToMethodPlugin(name, parent) {
+ const copySetOntoMethod = arg => {
+ if (isUndefined(arg)) {
+ parent.get(name)
+ }
+ else {
+ parent.set(name, arg)
+ Object.assign(parent[name], arg)
+ }
+ return parent
+ }
+
+ // so we know if we defaulted them
+ copySetOntoMethod.copySetOntoMethod = true
+
+ return this.onSet(copySetOntoMethod)
+ .onGet(copySetOntoMethod)
+ .onCall(copySetOntoMethod)
+}
+
+const makeBody = () => {
+
+}
+const makeRequest = (url, opts) => {
+ const requestConfig = {
+ method: 'POST',
+ mode: 'cors',
+ redirect: 'follow',
+ headers: new Headers({
+ 'Content-Type': 'text/plain',
+ }),
+ }
+ Object.assign(requestConfig, opts)
+
+ return new Request(url, requestConfig)
+}
+
+
+/**
+ * @TODO formData (use util)
+ */
+// const blob = () => {
+// fetch('https://davidwalsh.name/submit', {
+// method: 'post',
+// body: new FormData(document.getElementById('comment-form'))
+// });
+//
+// .then(function(response) {
+// return response.blob();
+// })
+// .then(function(imageBlob) {
+// document.querySelector('img').src = URL.createObjectURL(imageBlob);
+// });
+// }
+
+// easy destructure err
+const fetchIt = async(url, opts) => {
+ let error = null
+ try {
+ const request = makeRequest(url, opts)
+ // console.log({request})
+ // url, opts
+ const result = await fetch(request)
+ // console.log(result)
+ return [error, result]
+ }
+ catch (e) {
+ return [e, null]
+ }
+}
+
+/* prettier-ignore */
+class Frisbee extends Chain {
+ constructor(opts = {}) {
+ //('frisbee'
+ super()
+
+ // because conflicting names
+ this._get = this.get.bind(this)
+
+ // @default
+ // wish you could make better stack traces once thrown? extend error??
+ this.onError(function defaultErrorThrower(error) {
+ console.log('throwing...', {error})
+ throw error
+ })
+
+ // try {
+ // this.method('_setup').encase().onInvalid((error) => {
+ // require('fliplog').quick(error)
+ // }).build()
+ // }
+ // catch (e) {
+ // console.log('ugh', e)
+ // }
+
+
+ this
+ .method('headers')
+ .plugin(copySetToMethodPlugin)
+ .build()
+ .extend(['arrayFormat'])
+ // .autoGetSet()
+ // .getSet()
+ // .build()
+
+ .auth(opts.auth)
+ .opts(opts)
+ .headers(opts.headers)
+ .arrayFormat(opts.arrayFormat || 'indices')
+ // .when(opts.auth, () => this.auth(opts.auth))
+
+ methods.forEach(method => {
+ this[method] = this._setup(method)
+ })
+
+ // already bound
+ // this.httpGet = this._get
+ // this._get = (arg1, arg2) => {
+ // if (isUndefined(arg2))
+ // }
+ }
+ opts(opts) {
+ // validate
+ if (!opts.baseURI) this.handleError('req_base')
+ this.set('opts', opts)
+ return this
+ }
+
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Custom_Error_Types
+ // can have arrays of handlers, middleware, this is baby steps
+ onError(handler) {
+ // console.log('onerror')
+ return this.set('onError', handler)
+ }
+ handleError(msg, data) {
+ const messageForIndex = isString(msg) ? errMsg(msg) : msg
+ // console.log('handleerror')
+ const errorPlus = new Error(messageForIndex)
+ errorPlus.data = data
+
+ // isError [object Object] FetchError {
+ // name: 'FetchError',
+ // message: 'invalid json response body at http://localhost:8080/404-with-invalid-json reason: Unexpected token o in JSON at position 1',
+ // type: 'invalid-json'
+
+ // console.log(error.message, error.stack)
+ // throw error
+
+
+ // try {
+ // const errorPlus = new Error(messageForIndex)
+ // newest at top, remove this line
+ // errorPlus.stack = errorPlus.stack.split('\n')
+ // errorPlus.stack.shift()
+ // errorPlus.stack = errorPlus.stack.join('\n')
+ // throw errorPlus
+ const onerr = this._get('onError')
+ // console.log({onerr})
+ // console.log(this.store)
+ onerr(errorPlus)
+ // }
+ // // when onerr throws an error
+ // catch (errorError) {
+ // console.log(errorError.message)
+ // console.log(errorError.stack)
+ // throw errorError
+ // }
+ // this._get('onError').call(this, error, this)
+ return errorPlus
+ }
+
+ /**
+ * @methodFactory
+ * @method
+ * @memberOf frisbee
+ * @protected
+ * @param {string} method enum
+ * @return {Frisbee} @chainable
+ */
+ _setup(methodKeyword) {
+ return (path = '/', options = {}) => {
+ // validate ---
+
+ // path must be string
+ if (!isString(path)) return this.handleError('str_path')
+
+ // otherwise check if its an object
+ if (!isObjPure(options)) return this.handleError('obj_opts', options)
+
+ // console.log('about to get', this)
+ // require('fliplog').quick(this)
+
+ // setup data ---
+ const {baseURI} = this._get('opts')
+
+ // swappable/placeholder var to use existing them update with merged
+ let headers = this._get('headers')
+
+ // console.log({baseURI, headers}, this)
+
+ // --- here down is not tied to any instance ---
+
+ // don't want to override param,
+ // and it's easier to read as a descriptive variable
+ // @NOTE would be a good transform
+ const method =
+ methodKeyword === 'del' ? 'DELETE' : methodKeyword.toUpperCase()
+
+ // merge headers when we have them
+ if (isObj(options) && options.headers) {
+ headers = merge(headers, options.headers, mergeOpts)
+ }
+ const opts = merge(options, {headers, method}, mergeOpts)
+
+ // remove any nil or blank headers
+ // (e.g. to automatically set Content-Type with `FormData` boundary)
+ Object.keys(opts.headers).forEach(key => {
+ if (!isReal(opts.headers[key])) delete opts.headers[key]
+ })
+
+
+ /**
+ * in order to support Android POST requests
+ * we must allow an empty body to be sent
+ * @see https://github.com/facebook/react-native/issues/4890
+ */
+ if (isUndefined(opts.body)) {
+ if (opts.method === 'POST') {
+ opts.body = ''
+ }
+ }
+ else if (isObj(opts.body)) {
+ if (opts.method === 'GET' || opts.method === 'DELETE') {
+ let qsOpts = null
+ if (this.has('arrayFormat')) {
+ qsOpts = {arrayFormat: this._get('arrayFormat')}
+ }
+
+ console.log('QS', qs.stringify(opts.body))
+
+ path += `?${qs.stringify(opts.body, qsOpts)}`
+ delete opts.body
+ }
+ // @TODO: better stringify here
+ else {
+ /*
+ * @NOTE using caseless means checking
+ * permutations of casings
+ * encouraging bad practice
+ * and doing a massive amount of loops
+ * when it just simply isn't in the headers
+ */
+ const reqContentType = opts.headers ? getContentType(opts.headers) : false
+
+ if (reqContentType && reqContentType.split(';')[0] === 'application/json') {
+ try {
+ opts.body = JSON.stringify(opts.body)
+ }
+ catch (err) {
+ this.handleError(err)
+ }
+ }
+ }
+ }
+
+ // @TODO does this part here ever throw to wrap try catch?
+ const dofetch = async() => {
+ // console.log('do fetch', {path, opts})
+
+ const [error, ogRes] = await fetchIt(baseURI + path, opts)
+
+ // console.log('do fetch - PASS')
+
+ // simple error
+ if (!isNill(error)) {
+ // @TODO @DEV
+ // console.log('has error', {error})
+ return this.handleError(error)
+ // return Promise.reject(error)
+ }
+
+ let res = createFrisbeeResponse(ogRes)
+ const contentType = res.headers.get('Content-Type')
+ const contentTypeJSON =
+ isString(contentType) &&
+ contentType.includes('application/json')
+
+ // console.log('enhanced contentType')
+ const encasedParse = encase(parseFrisbeeResponseBody)
+ res = await encasedParse(res, contentTypeJSON)
+
+ // console.log('parsed response body')
+
+ if (!res.ok) res = formatFrisbeeResponseError(res, contentTypeJSON, baseURI)
+
+ // console.log('formatted')
+
+ return Promise.resolve(res)
+ }
+
+ return dofetch()
+ }
+ }
+
+ /**
+ * @TODO have option to allow .setEh .getEh & access as normal properties so never `eh()`
+ */
+ delAuth() {
+ // @TODO this is kind of weird
+ delete this.headers.Authorization
+ return this.delete('headers.Authorization')
+ }
+ setAuth(Authorization) {
+ this.headers.Authorization = Authorization
+ return this.set('headers.Authorization', Authorization)
+ }
+
+ auth(creditStringOrArray) {
+ let creds = creditStringOrArray
+ console.log({creditStringOrArray})
+ // if it has :, split into array
+ if (isString(creds)) {
+ const index = creds.indexOf(':')
+ if (index !== -1) {
+ // aka creds.split(':')
+ creds = [creds.substr(0, index), creds.substr(index + 1)]
+ }
+ }
+
+ // @TODO argumentor undefined, else array
+ // @TODO this is no good...
+ if (!isArray(creds)) creds = [].slice.call(arguments)
+
+ // essentially padd out our credentials with empty
+ if (creds.length === 0) creds = ['', '']
+ else if (creds.length === 1) creds.push('')
+ else if (creds.length !== 2) this.handleError('auth_keys')
+ creds = creds.map(cred => (isReal(cred) ? cred : ''))
+
+ // console.log({creds})
+
+ // @TODO can do 1 step further with validation as in split plugin
+ if (!isString(creds[0])) this.handleError('str_user')
+ if (!isString(creds[1])) this.handleError('str_pass')
+
+ if (!creds[0] && !creds[1]) this.delAuth()
+ else this.setAuth(`Basic ${new Buffer(creds.join(':')).toString('base64')}`)
+
+ return this
+ }
+
+ jwt(token) {
+ if (isNull(token)) return this.delAuth()
+ else if (isString(token)) return this.setAuth(`Bearer ${token}`)
+ else return this.handleError('str_jwt')
+ }
+}
+
+module.exports = function Frisbees(opts) {
+ // console.log({opts})
+ return new Frisbee(opts)
+}
diff --git a/_modules/frisbee/src/index.js b/_modules/frisbee/src/index.js
new file mode 100644
index 0000000..8cf0a5d
--- /dev/null
+++ b/_modules/frisbee/src/index.js
@@ -0,0 +1 @@
+module.exports = require('./frisbee')
diff --git a/_modules/frisbee/test-setup.js b/_modules/frisbee/test-setup.js
new file mode 100644
index 0000000..147f6b1
--- /dev/null
+++ b/_modules/frisbee/test-setup.js
@@ -0,0 +1,103 @@
+const log = require('fliplog')
+const express = require('express')
+const cors = require('cors')
+const bodyParser = require('body-parser')
+
+const app = express()
+const extended = {extended: false}
+
+// log.registerCatch()
+app.use(cors())
+
+// parse application/x-www-form-urlencoded
+app.use(bodyParser.urlencoded(extended))
+
+// parse application/json
+app.use(bodyParser.json(extended))
+
+app.all('/', (req, res, next) => {
+ /*
+ // HEAD request body must be 0 in length
+ if (req.method === 'HEAD' || req.method === 'OPTIONS') {
+ res.send(200, '');
+ return;
+ }
+ */
+
+ res.json({
+ message: 'OK',
+ })
+})
+
+app.get('/400-with-message', (req, res, next) => {
+ res.status(400).json({message: 'Oops!'})
+})
+
+app.get('/querystring', (req, res, next) => {
+ res.json(req.query)
+})
+
+app.delete('/querystring', (req, res, next) => {
+ res.json(req.query)
+})
+
+app.get('/404', (req, res, next) => {
+ // console.log('404...', {req, res, next})
+ // throw new Error('404')
+ res.sendStatus(404)
+})
+
+app.get('/404-with-valid-json', (req, res, next) => {
+ res.set('Content-Type', 'application/json').status(400).send({foo: 'baz'})
+})
+
+app.get('/404-with-invalid-json', (req, res, next) => {
+ console.log('404')
+ res.set('Content-Type', 'application/json').status(404).send('foobaz')
+})
+
+app.get('/404-with-stripe-error', (req, res, next) => {
+ res.status(404).json({
+ error: {
+ message: 'Some error happened',
+ stack: {},
+ code: 23,
+ param: 'hello_world',
+ },
+ })
+})
+
+global.app = {}
+global._server = {
+ start() {
+ global.app = app.listen(8080)
+ },
+ stop() {
+ return global.app.close()
+ },
+}
+
+// base URI for everything
+global._options = {
+ baseURI: 'http://localhost:8080',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json',
+ },
+}
+
+// setup global chai methods
+// import chai from 'chai';
+// import dirtyChai from 'dirty-chai';
+// chai.config.includeStack = true;
+// chai.config.showDiff = true;
+// // chai.use(dirtyChai);
+// global.chai = chai;
+// global.AssertionError = chai.AssertionError;
+// global.Assertion = chai.Assertion;
+// global.expect = chai.expect;
+// global.assert = chai.assert;
+
+// setTimeout(() => {
+// global._server.close
+// }, 10000)
diff --git a/_modules/frisbee/yarn.lock b/_modules/frisbee/yarn.lock
new file mode 100644
index 0000000..477d231
--- /dev/null
+++ b/_modules/frisbee/yarn.lock
@@ -0,0 +1,2342 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+abab@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.3.tgz#b81de5f7274ec4e756d797cd834f303642724e5d"
+
+accepts@~1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca"
+ dependencies:
+ mime-types "~2.1.11"
+ negotiator "0.6.1"
+
+acorn-globals@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-3.1.0.tgz#fd8270f71fbb4996b004fa880ee5d46573a731bf"
+ dependencies:
+ acorn "^4.0.4"
+
+acorn@^4.0.4:
+ version "4.0.13"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787"
+
+ajv@^4.9.1:
+ version "4.11.8"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
+ dependencies:
+ co "^4.6.0"
+ json-stable-stringify "^1.0.1"
+
+align-text@^0.1.1, align-text@^0.1.3:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
+ dependencies:
+ kind-of "^3.0.2"
+ longest "^1.0.1"
+ repeat-string "^1.5.2"
+
+amdefine@>=0.0.4:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
+
+ansi-escapes@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
+
+ansi-regex@^2.0.0, ansi-regex@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+
+ansi-styles@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+
+ansi-styles@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.1.0.tgz#09c202d5c917ec23188caa5c9cb9179cd9547750"
+ dependencies:
+ color-convert "^1.0.0"
+
+anymatch@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507"
+ dependencies:
+ arrify "^1.0.0"
+ micromatch "^2.1.5"
+
+append-transform@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991"
+ dependencies:
+ default-require-extensions "^1.0.0"
+
+argparse@^1.0.7:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86"
+ dependencies:
+ sprintf-js "~1.0.2"
+
+arr-diff@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
+ dependencies:
+ arr-flatten "^1.0.1"
+
+arr-flatten@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
+
+array-equal@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
+
+array-flatten@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
+
+array-unique@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"
+
+arrify@^1.0.0, arrify@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
+
+asn1@~0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86"
+
+assert-plus@1.0.0, assert-plus@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
+
+assert-plus@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"
+
+async@^1.4.0:
+ version "1.5.2"
+ resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
+
+async@^2.1.4:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/async/-/async-2.5.0.tgz#843190fd6b7357a0b9e1c956edddd5ec8462b54d"
+ dependencies:
+ lodash "^4.14.0"
+
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+
+aws-sign2@~0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"
+
+aws4@^1.2.1:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
+
+babel-code-frame@^6.22.0:
+ version "6.22.0"
+ resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4"
+ dependencies:
+ chalk "^1.1.0"
+ esutils "^2.0.2"
+ js-tokens "^3.0.0"
+
+babel-core@^6.0.0, babel-core@^6.24.1:
+ version "6.25.0"
+ resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.25.0.tgz#7dd42b0463c742e9d5296deb3ec67a9322dad729"
+ dependencies:
+ babel-code-frame "^6.22.0"
+ babel-generator "^6.25.0"
+ babel-helpers "^6.24.1"
+ babel-messages "^6.23.0"
+ babel-register "^6.24.1"
+ babel-runtime "^6.22.0"
+ babel-template "^6.25.0"
+ babel-traverse "^6.25.0"
+ babel-types "^6.25.0"
+ babylon "^6.17.2"
+ convert-source-map "^1.1.0"
+ debug "^2.1.1"
+ json5 "^0.5.0"
+ lodash "^4.2.0"
+ minimatch "^3.0.2"
+ path-is-absolute "^1.0.0"
+ private "^0.1.6"
+ slash "^1.0.0"
+ source-map "^0.5.0"
+
+babel-generator@^6.18.0, babel-generator@^6.25.0:
+ version "6.25.0"
+ resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.25.0.tgz#33a1af70d5f2890aeb465a4a7793c1df6a9ea9fc"
+ dependencies:
+ babel-messages "^6.23.0"
+ babel-runtime "^6.22.0"
+ babel-types "^6.25.0"
+ detect-indent "^4.0.0"
+ jsesc "^1.3.0"
+ lodash "^4.2.0"
+ source-map "^0.5.0"
+ trim-right "^1.0.1"
+
+babel-helpers@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2"
+ dependencies:
+ babel-runtime "^6.22.0"
+ babel-template "^6.24.1"
+
+babel-jest@^20.0.3:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-20.0.3.tgz#e4a03b13dc10389e140fc645d09ffc4ced301671"
+ dependencies:
+ babel-core "^6.0.0"
+ babel-plugin-istanbul "^4.0.0"
+ babel-preset-jest "^20.0.3"
+
+babel-messages@^6.23.0:
+ version "6.23.0"
+ resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
+ dependencies:
+ babel-runtime "^6.22.0"
+
+babel-plugin-istanbul@^4.0.0:
+ version "4.1.4"
+ resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.4.tgz#18dde84bf3ce329fddf3f4103fae921456d8e587"
+ dependencies:
+ find-up "^2.1.0"
+ istanbul-lib-instrument "^1.7.2"
+ test-exclude "^4.1.1"
+
+babel-plugin-jest-hoist@^20.0.3:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-20.0.3.tgz#afedc853bd3f8dc3548ea671fbe69d03cc2c1767"
+
+babel-preset-jest@^20.0.3:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-20.0.3.tgz#cbacaadecb5d689ca1e1de1360ebfc66862c178a"
+ dependencies:
+ babel-plugin-jest-hoist "^20.0.3"
+
+babel-register@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.24.1.tgz#7e10e13a2f71065bdfad5a1787ba45bca6ded75f"
+ dependencies:
+ babel-core "^6.24.1"
+ babel-runtime "^6.22.0"
+ core-js "^2.4.0"
+ home-or-tmp "^2.0.0"
+ lodash "^4.2.0"
+ mkdirp "^0.5.1"
+ source-map-support "^0.4.2"
+
+babel-runtime@^6.22.0, babel-runtime@^6.9.2:
+ version "6.23.0"
+ resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b"
+ dependencies:
+ core-js "^2.4.0"
+ regenerator-runtime "^0.10.0"
+
+babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.25.0:
+ version "6.25.0"
+ resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.25.0.tgz#665241166b7c2aa4c619d71e192969552b10c071"
+ dependencies:
+ babel-runtime "^6.22.0"
+ babel-traverse "^6.25.0"
+ babel-types "^6.25.0"
+ babylon "^6.17.2"
+ lodash "^4.2.0"
+
+babel-traverse@^6.18.0, babel-traverse@^6.25.0:
+ version "6.25.0"
+ resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.25.0.tgz#2257497e2fcd19b89edc13c4c91381f9512496f1"
+ dependencies:
+ babel-code-frame "^6.22.0"
+ babel-messages "^6.23.0"
+ babel-runtime "^6.22.0"
+ babel-types "^6.25.0"
+ babylon "^6.17.2"
+ debug "^2.2.0"
+ globals "^9.0.0"
+ invariant "^2.2.0"
+ lodash "^4.2.0"
+
+babel-types@^6.18.0, babel-types@^6.25.0:
+ version "6.25.0"
+ resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.25.0.tgz#70afb248d5660e5d18f811d91c8303b54134a18e"
+ dependencies:
+ babel-runtime "^6.22.0"
+ esutils "^2.0.2"
+ lodash "^4.2.0"
+ to-fast-properties "^1.0.1"
+
+babylon@^6.17.2, babylon@^6.17.4:
+ version "6.17.4"
+ resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.4.tgz#3e8b7402b88d22c3423e137a1577883b15ff869a"
+
+balanced-match@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
+
+base64-js@^1.0.2:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886"
+
+bcrypt-pbkdf@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d"
+ dependencies:
+ tweetnacl "^0.14.3"
+
+body-parser@*:
+ version "1.17.2"
+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.17.2.tgz#f8892abc8f9e627d42aedafbca66bf5ab99104ee"
+ dependencies:
+ bytes "2.4.0"
+ content-type "~1.0.2"
+ debug "2.6.7"
+ depd "~1.1.0"
+ http-errors "~1.6.1"
+ iconv-lite "0.4.15"
+ on-finished "~2.3.0"
+ qs "6.4.0"
+ raw-body "~2.2.0"
+ type-is "~1.6.15"
+
+boom@2.x.x:
+ version "2.10.1"
+ resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f"
+ dependencies:
+ hoek "2.x.x"
+
+brace-expansion@^1.1.7:
+ version "1.1.8"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+braces@^1.8.2:
+ version "1.8.5"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7"
+ dependencies:
+ expand-range "^1.8.1"
+ preserve "^0.2.0"
+ repeat-element "^1.1.2"
+
+browser-resolve@^1.11.2:
+ version "1.11.2"
+ resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce"
+ dependencies:
+ resolve "1.1.7"
+
+bser@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/bser/-/bser-1.0.2.tgz#381116970b2a6deea5646dd15dd7278444b56169"
+ dependencies:
+ node-int64 "^0.4.0"
+
+bser@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719"
+ dependencies:
+ node-int64 "^0.4.0"
+
+buffer@^4.6.0:
+ version "4.9.1"
+ resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298"
+ dependencies:
+ base64-js "^1.0.2"
+ ieee754 "^1.1.4"
+ isarray "^1.0.0"
+
+builtin-modules@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
+
+bytes@2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339"
+
+callsites@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50"
+
+camelcase@^1.0.2:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
+
+camelcase@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
+
+caseless@^0.11.0:
+ version "0.11.0"
+ resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7"
+
+caseless@~0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
+
+center-align@^0.1.1:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad"
+ dependencies:
+ align-text "^0.1.3"
+ lazy-cache "^1.0.3"
+
+chain-able@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/chain-able/-/chain-able-3.0.0.tgz#dcffe8b04f3da210941a23843bc1332bb288ca9f"
+
+chalk@^1.1.0, chalk@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+ dependencies:
+ ansi-styles "^2.2.1"
+ escape-string-regexp "^1.0.2"
+ has-ansi "^2.0.0"
+ strip-ansi "^3.0.0"
+ supports-color "^2.0.0"
+
+ci-info@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.0.0.tgz#dc5285f2b4e251821683681c381c3388f46ec534"
+
+cliui@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1"
+ dependencies:
+ center-align "^0.1.1"
+ right-align "^0.1.1"
+ wordwrap "0.0.2"
+
+cliui@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
+ dependencies:
+ string-width "^1.0.1"
+ strip-ansi "^3.0.1"
+ wrap-ansi "^2.0.0"
+
+co@^4.6.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
+
+code-point-at@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
+
+color-convert@^1.0.0:
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a"
+ dependencies:
+ color-name "^1.1.1"
+
+color-name@^1.1.1:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+
+combined-stream@^1.0.5, combined-stream@~1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009"
+ dependencies:
+ delayed-stream "~1.0.0"
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+
+content-disposition@0.5.2:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
+
+content-type-parser@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/content-type-parser/-/content-type-parser-1.0.1.tgz#c3e56988c53c65127fb46d4032a3a900246fdc94"
+
+content-type@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.2.tgz#b7d113aee7a8dd27bd21133c4dc2529df1721eed"
+
+convert-source-map@^1.1.0, convert-source-map@^1.4.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5"
+
+cookie-signature@1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
+
+cookie@0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
+
+core-js@^2.4.0:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e"
+
+cors@*:
+ version "2.8.4"
+ resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.4.tgz#2bd381f2eb201020105cd50ea59da63090694686"
+ dependencies:
+ object-assign "^4"
+ vary "^1"
+
+cryptiles@2.x.x:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
+ dependencies:
+ boom "2.x.x"
+
+cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.2.tgz#b8036170c79f07a90ff2f16e22284027a243848b"
+
+"cssstyle@>= 0.2.37 < 0.3.0":
+ version "0.2.37"
+ resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-0.2.37.tgz#541097234cb2513c83ceed3acddc27ff27987d54"
+ dependencies:
+ cssom "0.3.x"
+
+dashdash@^1.12.0:
+ version "1.14.1"
+ resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
+ dependencies:
+ assert-plus "^1.0.0"
+
+debug@2.6.7:
+ version "2.6.7"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.7.tgz#92bad1f6d05bbb6bba22cca88bcd0ec894c2861e"
+ dependencies:
+ ms "2.0.0"
+
+debug@^2.1.1, debug@^2.2.0, debug@^2.6.3:
+ version "2.6.8"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
+ dependencies:
+ ms "2.0.0"
+
+decamelize@^1.0.0, decamelize@^1.1.1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+
+deep-is@~0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
+
+default-require-extensions@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8"
+ dependencies:
+ strip-bom "^2.0.0"
+
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+
+depd@1.1.0, depd@~1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3"
+
+destroy@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
+
+detect-indent@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
+ dependencies:
+ repeating "^2.0.0"
+
+diff@^3.2.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.0.tgz#056695150d7aa93237ca7e378ac3b1682b7963b9"
+
+ecc-jsbn@~0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505"
+ dependencies:
+ jsbn "~0.1.0"
+
+ee-first@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
+
+encodeurl@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20"
+
+encoding@^0.1.11:
+ version "0.1.12"
+ resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
+ dependencies:
+ iconv-lite "~0.4.13"
+
+errno@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d"
+ dependencies:
+ prr "~0.0.0"
+
+error-ex@^1.2.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc"
+ dependencies:
+ is-arrayish "^0.2.1"
+
+escape-html@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
+
+escape-string-regexp@^1.0.2:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+
+escodegen@^1.6.1:
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018"
+ dependencies:
+ esprima "^2.7.1"
+ estraverse "^1.9.1"
+ esutils "^2.0.2"
+ optionator "^0.8.1"
+ optionalDependencies:
+ source-map "~0.2.0"
+
+esprima@^2.7.1:
+ version "2.7.3"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
+
+esprima@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804"
+
+estraverse@^1.9.1:
+ version "1.9.3"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44"
+
+esutils@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
+
+etag@~1.8.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.0.tgz#6f631aef336d6c46362b51764044ce216be3c051"
+
+exec-sh@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.0.tgz#14f75de3f20d286ef933099b2ce50a90359cef10"
+ dependencies:
+ merge "^1.1.3"
+
+expand-brackets@^0.1.4:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
+ dependencies:
+ is-posix-bracket "^0.1.0"
+
+expand-range@^1.8.1:
+ version "1.8.2"
+ resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337"
+ dependencies:
+ fill-range "^2.1.0"
+
+express@*:
+ version "4.15.3"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.15.3.tgz#bab65d0f03aa80c358408972fc700f916944b662"
+ dependencies:
+ accepts "~1.3.3"
+ array-flatten "1.1.1"
+ content-disposition "0.5.2"
+ content-type "~1.0.2"
+ cookie "0.3.1"
+ cookie-signature "1.0.6"
+ debug "2.6.7"
+ depd "~1.1.0"
+ encodeurl "~1.0.1"
+ escape-html "~1.0.3"
+ etag "~1.8.0"
+ finalhandler "~1.0.3"
+ fresh "0.5.0"
+ merge-descriptors "1.0.1"
+ methods "~1.1.2"
+ on-finished "~2.3.0"
+ parseurl "~1.3.1"
+ path-to-regexp "0.1.7"
+ proxy-addr "~1.1.4"
+ qs "6.4.0"
+ range-parser "~1.2.0"
+ send "0.15.3"
+ serve-static "1.12.3"
+ setprototypeof "1.0.3"
+ statuses "~1.3.1"
+ type-is "~1.6.15"
+ utils-merge "1.0.0"
+ vary "~1.1.1"
+
+extend@~3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
+
+extglob@^0.3.1:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
+ dependencies:
+ is-extglob "^1.0.0"
+
+extsprintf@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550"
+
+fast-levenshtein@~2.0.4:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+
+fb-watchman@^1.8.0:
+ version "1.9.2"
+ resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-1.9.2.tgz#a24cf47827f82d38fb59a69ad70b76e3b6ae7383"
+ dependencies:
+ bser "1.0.2"
+
+fb-watchman@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58"
+ dependencies:
+ bser "^2.0.0"
+
+filename-regex@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
+
+fileset@^2.0.2:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0"
+ dependencies:
+ glob "^7.0.3"
+ minimatch "^3.0.3"
+
+fill-range@^2.1.0:
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723"
+ dependencies:
+ is-number "^2.1.0"
+ isobject "^2.0.0"
+ randomatic "^1.1.3"
+ repeat-element "^1.1.2"
+ repeat-string "^1.5.2"
+
+finalhandler@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.3.tgz#ef47e77950e999780e86022a560e3217e0d0cc89"
+ dependencies:
+ debug "2.6.7"
+ encodeurl "~1.0.1"
+ escape-html "~1.0.3"
+ on-finished "~2.3.0"
+ parseurl "~1.3.1"
+ statuses "~1.3.1"
+ unpipe "~1.0.0"
+
+find-up@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
+ dependencies:
+ path-exists "^2.0.0"
+ pinkie-promise "^2.0.0"
+
+find-up@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
+ dependencies:
+ locate-path "^2.0.0"
+
+fliplog@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/fliplog/-/fliplog-1.0.4.tgz#c66e064e1cb95473c0e037cb5855ab5da46b4441"
+ dependencies:
+ chain-able "3.0.0"
+
+for-in@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
+
+for-own@^0.1.4:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce"
+ dependencies:
+ for-in "^1.0.1"
+
+forever-agent@~0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
+
+form-data@~2.1.1:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1"
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.5"
+ mime-types "^2.1.12"
+
+forwarded@~0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.0.tgz#19ef9874c4ae1c297bcf078fde63a09b66a84363"
+
+fresh@0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.0.tgz#f474ca5e6a9246d6fd8e0953cfa9b9c805afa78e"
+
+frisbee@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/frisbee/-/frisbee-1.5.0.tgz#ae507b76f0fc092dfe208ced1513f2726cb555f5"
+ dependencies:
+ babel-runtime "^6.9.2"
+ buffer "^4.6.0"
+ caseless "^0.11.0"
+ qs "^6.2.0"
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+
+get-caller-file@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
+
+getpass@^0.1.1:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
+ dependencies:
+ assert-plus "^1.0.0"
+
+glob-base@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
+ dependencies:
+ glob-parent "^2.0.0"
+ is-glob "^2.0.0"
+
+glob-parent@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28"
+ dependencies:
+ is-glob "^2.0.0"
+
+glob@^7.0.3, glob@^7.0.5, glob@^7.1.1:
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.4"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+globals@^9.0.0:
+ version "9.18.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
+
+graceful-fs@^4.1.11, graceful-fs@^4.1.2:
+ version "4.1.11"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
+
+growly@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
+
+handlebars@^4.0.3:
+ version "4.0.10"
+ resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.10.tgz#3d30c718b09a3d96f23ea4cc1f403c4d3ba9ff4f"
+ dependencies:
+ async "^1.4.0"
+ optimist "^0.6.1"
+ source-map "^0.4.4"
+ optionalDependencies:
+ uglify-js "^2.6"
+
+har-schema@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
+
+har-validator@~4.2.1:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
+ dependencies:
+ ajv "^4.9.1"
+ har-schema "^1.0.5"
+
+has-ansi@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+ dependencies:
+ ansi-regex "^2.0.0"
+
+has-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
+
+hawk@~3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
+ dependencies:
+ boom "2.x.x"
+ cryptiles "2.x.x"
+ hoek "2.x.x"
+ sntp "1.x.x"
+
+hoek@2.x.x:
+ version "2.16.3"
+ resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
+
+home-or-tmp@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
+ dependencies:
+ os-homedir "^1.0.0"
+ os-tmpdir "^1.0.1"
+
+hosted-git-info@^2.1.4:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c"
+
+html-encoding-sniffer@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.1.tgz#79bf7a785ea495fe66165e734153f363ff5437da"
+ dependencies:
+ whatwg-encoding "^1.0.1"
+
+http-errors@~1.6.1:
+ version "1.6.1"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.1.tgz#5f8b8ed98aca545656bf572997387f904a722257"
+ dependencies:
+ depd "1.1.0"
+ inherits "2.0.3"
+ setprototypeof "1.0.3"
+ statuses ">= 1.3.1 < 2"
+
+http-signature@~1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
+ dependencies:
+ assert-plus "^0.2.0"
+ jsprim "^1.2.2"
+ sshpk "^1.7.0"
+
+iconv-lite@0.4.13:
+ version "0.4.13"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2"
+
+iconv-lite@0.4.15:
+ version "0.4.15"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb"
+
+iconv-lite@~0.4.13:
+ version "0.4.18"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2"
+
+ieee754@^1.1.4:
+ version "1.1.8"
+ resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2, inherits@2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+
+invariant@^2.2.0:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
+ dependencies:
+ loose-envify "^1.0.0"
+
+invert-kv@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
+
+ipaddr.js@1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.3.0.tgz#1e03a52fdad83a8bbb2b25cbf4998b4cffcd3dec"
+
+is-arrayish@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+
+is-buffer@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc"
+
+is-builtin-module@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
+ dependencies:
+ builtin-modules "^1.0.0"
+
+is-ci@^1.0.10:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.0.10.tgz#f739336b2632365061a9d48270cd56ae3369318e"
+ dependencies:
+ ci-info "^1.0.0"
+
+is-dotfile@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1"
+
+is-equal-shallow@^0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534"
+ dependencies:
+ is-primitive "^2.0.0"
+
+is-extendable@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
+
+is-extglob@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
+
+is-finite@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
+ dependencies:
+ number-is-nan "^1.0.0"
+
+is-fullwidth-code-point@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
+ dependencies:
+ number-is-nan "^1.0.0"
+
+is-glob@^2.0.0, is-glob@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
+ dependencies:
+ is-extglob "^1.0.0"
+
+is-number@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
+ dependencies:
+ kind-of "^3.0.2"
+
+is-number@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
+ dependencies:
+ kind-of "^3.0.2"
+
+is-posix-bracket@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
+
+is-primitive@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
+
+is-stream@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
+
+is-typedarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
+
+is-utf8@^0.2.0:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
+
+isarray@1.0.0, isarray@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+
+isobject@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
+ dependencies:
+ isarray "1.0.0"
+
+isomorphic-fetch@*:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
+ dependencies:
+ node-fetch "^1.0.1"
+ whatwg-fetch ">=0.10.0"
+
+isstream@~0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
+
+istanbul-api@^1.1.1:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.1.11.tgz#fcc0b461e2b3bda71e305155138238768257d9de"
+ dependencies:
+ async "^2.1.4"
+ fileset "^2.0.2"
+ istanbul-lib-coverage "^1.1.1"
+ istanbul-lib-hook "^1.0.7"
+ istanbul-lib-instrument "^1.7.4"
+ istanbul-lib-report "^1.1.1"
+ istanbul-lib-source-maps "^1.2.1"
+ istanbul-reports "^1.1.1"
+ js-yaml "^3.7.0"
+ mkdirp "^0.5.1"
+ once "^1.4.0"
+
+istanbul-lib-coverage@^1.0.1, istanbul-lib-coverage@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz#73bfb998885299415c93d38a3e9adf784a77a9da"
+
+istanbul-lib-hook@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.0.7.tgz#dd6607f03076578fe7d6f2a630cf143b49bacddc"
+ dependencies:
+ append-transform "^0.4.0"
+
+istanbul-lib-instrument@^1.4.2, istanbul-lib-instrument@^1.7.2, istanbul-lib-instrument@^1.7.4:
+ version "1.7.4"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.4.tgz#e9fd920e4767f3d19edc765e2d6b3f5ccbd0eea8"
+ dependencies:
+ babel-generator "^6.18.0"
+ babel-template "^6.16.0"
+ babel-traverse "^6.18.0"
+ babel-types "^6.18.0"
+ babylon "^6.17.4"
+ istanbul-lib-coverage "^1.1.1"
+ semver "^5.3.0"
+
+istanbul-lib-report@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#f0e55f56655ffa34222080b7a0cd4760e1405fc9"
+ dependencies:
+ istanbul-lib-coverage "^1.1.1"
+ mkdirp "^0.5.1"
+ path-parse "^1.0.5"
+ supports-color "^3.1.2"
+
+istanbul-lib-source-maps@^1.1.0, istanbul-lib-source-maps@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.1.tgz#a6fe1acba8ce08eebc638e572e294d267008aa0c"
+ dependencies:
+ debug "^2.6.3"
+ istanbul-lib-coverage "^1.1.1"
+ mkdirp "^0.5.1"
+ rimraf "^2.6.1"
+ source-map "^0.5.3"
+
+istanbul-reports@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.1.1.tgz#042be5c89e175bc3f86523caab29c014e77fee4e"
+ dependencies:
+ handlebars "^4.0.3"
+
+jest-changed-files@^20.0.3:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-20.0.3.tgz#9394d5cc65c438406149bef1bf4d52b68e03e3f8"
+
+jest-cli@^20.0.4:
+ version "20.0.4"
+ resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-20.0.4.tgz#e532b19d88ae5bc6c417e8b0593a6fe954b1dc93"
+ dependencies:
+ ansi-escapes "^1.4.0"
+ callsites "^2.0.0"
+ chalk "^1.1.3"
+ graceful-fs "^4.1.11"
+ is-ci "^1.0.10"
+ istanbul-api "^1.1.1"
+ istanbul-lib-coverage "^1.0.1"
+ istanbul-lib-instrument "^1.4.2"
+ istanbul-lib-source-maps "^1.1.0"
+ jest-changed-files "^20.0.3"
+ jest-config "^20.0.4"
+ jest-docblock "^20.0.3"
+ jest-environment-jsdom "^20.0.3"
+ jest-haste-map "^20.0.4"
+ jest-jasmine2 "^20.0.4"
+ jest-message-util "^20.0.3"
+ jest-regex-util "^20.0.3"
+ jest-resolve-dependencies "^20.0.3"
+ jest-runtime "^20.0.4"
+ jest-snapshot "^20.0.3"
+ jest-util "^20.0.3"
+ micromatch "^2.3.11"
+ node-notifier "^5.0.2"
+ pify "^2.3.0"
+ slash "^1.0.0"
+ string-length "^1.0.1"
+ throat "^3.0.0"
+ which "^1.2.12"
+ worker-farm "^1.3.1"
+ yargs "^7.0.2"
+
+jest-config@^20.0.4:
+ version "20.0.4"
+ resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-20.0.4.tgz#e37930ab2217c913605eff13e7bd763ec48faeea"
+ dependencies:
+ chalk "^1.1.3"
+ glob "^7.1.1"
+ jest-environment-jsdom "^20.0.3"
+ jest-environment-node "^20.0.3"
+ jest-jasmine2 "^20.0.4"
+ jest-matcher-utils "^20.0.3"
+ jest-regex-util "^20.0.3"
+ jest-resolve "^20.0.4"
+ jest-validate "^20.0.3"
+ pretty-format "^20.0.3"
+
+jest-diff@^20.0.3:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-20.0.3.tgz#81f288fd9e675f0fb23c75f1c2b19445fe586617"
+ dependencies:
+ chalk "^1.1.3"
+ diff "^3.2.0"
+ jest-matcher-utils "^20.0.3"
+ pretty-format "^20.0.3"
+
+jest-docblock@^20.0.3:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-20.0.3.tgz#17bea984342cc33d83c50fbe1545ea0efaa44712"
+
+jest-environment-jsdom@^20.0.3:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-20.0.3.tgz#048a8ac12ee225f7190417713834bb999787de99"
+ dependencies:
+ jest-mock "^20.0.3"
+ jest-util "^20.0.3"
+ jsdom "^9.12.0"
+
+jest-environment-node@^20.0.3:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-20.0.3.tgz#d488bc4612af2c246e986e8ae7671a099163d403"
+ dependencies:
+ jest-mock "^20.0.3"
+ jest-util "^20.0.3"
+
+jest-haste-map@^20.0.4:
+ version "20.0.4"
+ resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-20.0.4.tgz#653eb55c889ce3c021f7b94693f20a4159badf03"
+ dependencies:
+ fb-watchman "^2.0.0"
+ graceful-fs "^4.1.11"
+ jest-docblock "^20.0.3"
+ micromatch "^2.3.11"
+ sane "~1.6.0"
+ worker-farm "^1.3.1"
+
+jest-jasmine2@^20.0.4:
+ version "20.0.4"
+ resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-20.0.4.tgz#fcc5b1411780d911d042902ef1859e852e60d5e1"
+ dependencies:
+ chalk "^1.1.3"
+ graceful-fs "^4.1.11"
+ jest-diff "^20.0.3"
+ jest-matcher-utils "^20.0.3"
+ jest-matchers "^20.0.3"
+ jest-message-util "^20.0.3"
+ jest-snapshot "^20.0.3"
+ once "^1.4.0"
+ p-map "^1.1.1"
+
+jest-matcher-utils@^20.0.3:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-20.0.3.tgz#b3a6b8e37ca577803b0832a98b164f44b7815612"
+ dependencies:
+ chalk "^1.1.3"
+ pretty-format "^20.0.3"
+
+jest-matchers@^20.0.3:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/jest-matchers/-/jest-matchers-20.0.3.tgz#ca69db1c32db5a6f707fa5e0401abb55700dfd60"
+ dependencies:
+ jest-diff "^20.0.3"
+ jest-matcher-utils "^20.0.3"
+ jest-message-util "^20.0.3"
+ jest-regex-util "^20.0.3"
+
+jest-message-util@^20.0.3:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-20.0.3.tgz#6aec2844306fcb0e6e74d5796c1006d96fdd831c"
+ dependencies:
+ chalk "^1.1.3"
+ micromatch "^2.3.11"
+ slash "^1.0.0"
+
+jest-mock@^20.0.3:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-20.0.3.tgz#8bc070e90414aa155c11a8d64c869a0d5c71da59"
+
+jest-regex-util@^20.0.3:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-20.0.3.tgz#85bbab5d133e44625b19faf8c6aa5122d085d762"
+
+jest-resolve-dependencies@^20.0.3:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-20.0.3.tgz#6e14a7b717af0f2cb3667c549de40af017b1723a"
+ dependencies:
+ jest-regex-util "^20.0.3"
+
+jest-resolve@^20.0.4:
+ version "20.0.4"
+ resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-20.0.4.tgz#9448b3e8b6bafc15479444c6499045b7ffe597a5"
+ dependencies:
+ browser-resolve "^1.11.2"
+ is-builtin-module "^1.0.0"
+ resolve "^1.3.2"
+
+jest-runtime@^20.0.4:
+ version "20.0.4"
+ resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-20.0.4.tgz#a2c802219c4203f754df1404e490186169d124d8"
+ dependencies:
+ babel-core "^6.0.0"
+ babel-jest "^20.0.3"
+ babel-plugin-istanbul "^4.0.0"
+ chalk "^1.1.3"
+ convert-source-map "^1.4.0"
+ graceful-fs "^4.1.11"
+ jest-config "^20.0.4"
+ jest-haste-map "^20.0.4"
+ jest-regex-util "^20.0.3"
+ jest-resolve "^20.0.4"
+ jest-util "^20.0.3"
+ json-stable-stringify "^1.0.1"
+ micromatch "^2.3.11"
+ strip-bom "3.0.0"
+ yargs "^7.0.2"
+
+jest-snapshot@^20.0.3:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-20.0.3.tgz#5b847e1adb1a4d90852a7f9f125086e187c76566"
+ dependencies:
+ chalk "^1.1.3"
+ jest-diff "^20.0.3"
+ jest-matcher-utils "^20.0.3"
+ jest-util "^20.0.3"
+ natural-compare "^1.4.0"
+ pretty-format "^20.0.3"
+
+jest-util@^20.0.3:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-20.0.3.tgz#0c07f7d80d82f4e5a67c6f8b9c3fe7f65cfd32ad"
+ dependencies:
+ chalk "^1.1.3"
+ graceful-fs "^4.1.11"
+ jest-message-util "^20.0.3"
+ jest-mock "^20.0.3"
+ jest-validate "^20.0.3"
+ leven "^2.1.0"
+ mkdirp "^0.5.1"
+
+jest-validate@^20.0.3:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-20.0.3.tgz#d0cfd1de4f579f298484925c280f8f1d94ec3cab"
+ dependencies:
+ chalk "^1.1.3"
+ jest-matcher-utils "^20.0.3"
+ leven "^2.1.0"
+ pretty-format "^20.0.3"
+
+jest@*:
+ version "20.0.4"
+ resolved "https://registry.yarnpkg.com/jest/-/jest-20.0.4.tgz#3dd260c2989d6dad678b1e9cc4d91944f6d602ac"
+ dependencies:
+ jest-cli "^20.0.4"
+
+js-tokens@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
+
+js-yaml@^3.7.0:
+ version "3.9.0"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.0.tgz#4ffbbf25c2ac963b8299dc74da7e3740de1c18ce"
+ dependencies:
+ argparse "^1.0.7"
+ esprima "^4.0.0"
+
+jsbn@~0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
+
+jsdom@^9.12.0:
+ version "9.12.0"
+ resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-9.12.0.tgz#e8c546fffcb06c00d4833ca84410fed7f8a097d4"
+ dependencies:
+ abab "^1.0.3"
+ acorn "^4.0.4"
+ acorn-globals "^3.1.0"
+ array-equal "^1.0.0"
+ content-type-parser "^1.0.1"
+ cssom ">= 0.3.2 < 0.4.0"
+ cssstyle ">= 0.2.37 < 0.3.0"
+ escodegen "^1.6.1"
+ html-encoding-sniffer "^1.0.1"
+ nwmatcher ">= 1.3.9 < 2.0.0"
+ parse5 "^1.5.1"
+ request "^2.79.0"
+ sax "^1.2.1"
+ symbol-tree "^3.2.1"
+ tough-cookie "^2.3.2"
+ webidl-conversions "^4.0.0"
+ whatwg-encoding "^1.0.1"
+ whatwg-url "^4.3.0"
+ xml-name-validator "^2.0.1"
+
+jsesc@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
+
+json-schema@0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
+
+json-stable-stringify@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
+ dependencies:
+ jsonify "~0.0.0"
+
+json-stringify-safe@~5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
+
+json5@^0.5.0:
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
+
+jsonify@~0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
+
+jsprim@^1.2.2:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.0.tgz#a3b87e40298d8c380552d8cc7628a0bb95a22918"
+ dependencies:
+ assert-plus "1.0.0"
+ extsprintf "1.0.2"
+ json-schema "0.2.3"
+ verror "1.3.6"
+
+kind-of@^3.0.2:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
+ dependencies:
+ is-buffer "^1.1.5"
+
+kind-of@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57"
+ dependencies:
+ is-buffer "^1.1.5"
+
+lazy-cache@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
+
+lcid@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
+ dependencies:
+ invert-kv "^1.0.0"
+
+leven@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
+
+levn@~0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
+ dependencies:
+ prelude-ls "~1.1.2"
+ type-check "~0.3.2"
+
+load-json-file@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
+ dependencies:
+ graceful-fs "^4.1.2"
+ parse-json "^2.2.0"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+ strip-bom "^2.0.0"
+
+locate-path@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
+ dependencies:
+ p-locate "^2.0.0"
+ path-exists "^3.0.0"
+
+lodash@^4.14.0, lodash@^4.2.0:
+ version "4.17.4"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
+
+longest@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
+
+loose-envify@^1.0.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
+ dependencies:
+ js-tokens "^3.0.0"
+
+makeerror@1.0.x:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c"
+ dependencies:
+ tmpl "1.0.x"
+
+media-typer@0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
+
+merge-descriptors@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
+
+merge@^1.1.3:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da"
+
+methods@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
+
+micromatch@^2.1.5, micromatch@^2.3.11:
+ version "2.3.11"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
+ dependencies:
+ arr-diff "^2.0.0"
+ array-unique "^0.2.1"
+ braces "^1.8.2"
+ expand-brackets "^0.1.4"
+ extglob "^0.3.1"
+ filename-regex "^2.0.0"
+ is-extglob "^1.0.0"
+ is-glob "^2.0.1"
+ kind-of "^3.0.2"
+ normalize-path "^2.0.1"
+ object.omit "^2.0.0"
+ parse-glob "^3.0.4"
+ regex-cache "^0.4.2"
+
+mime-db@~1.27.0:
+ version "1.27.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1"
+
+mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.7:
+ version "2.1.15"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed"
+ dependencies:
+ mime-db "~1.27.0"
+
+mime@1.3.4:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53"
+
+minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+ dependencies:
+ brace-expansion "^1.1.7"
+
+minimist@0.0.8:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+
+minimist@^1.1.1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
+
+minimist@~0.0.1:
+ version "0.0.10"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
+
+mkdirp@^0.5.1:
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+ dependencies:
+ minimist "0.0.8"
+
+ms@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+
+natural-compare@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+
+negotiator@0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
+
+node-fetch@^1.0.1, node-fetch@^1.7.1:
+ version "1.7.1"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.1.tgz#899cb3d0a3c92f952c47f1b876f4c8aeabd400d5"
+ dependencies:
+ encoding "^0.1.11"
+ is-stream "^1.0.1"
+
+node-int64@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
+
+node-notifier@^5.0.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.1.2.tgz#2fa9e12605fa10009d44549d6fcd8a63dde0e4ff"
+ dependencies:
+ growly "^1.3.0"
+ semver "^5.3.0"
+ shellwords "^0.1.0"
+ which "^1.2.12"
+
+normalize-package-data@^2.3.2:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
+ dependencies:
+ hosted-git-info "^2.1.4"
+ is-builtin-module "^1.0.0"
+ semver "2 || 3 || 4 || 5"
+ validate-npm-package-license "^3.0.1"
+
+normalize-path@^2.0.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
+ dependencies:
+ remove-trailing-separator "^1.0.1"
+
+number-is-nan@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
+
+"nwmatcher@>= 1.3.9 < 2.0.0":
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.1.tgz#7ae9b07b0ea804db7e25f05cb5fe4097d4e4949f"
+
+oauth-sign@~0.8.1:
+ version "0.8.2"
+ resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
+
+object-assign@^4, object-assign@^4.1.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+
+object.omit@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
+ dependencies:
+ for-own "^0.1.4"
+ is-extendable "^0.1.1"
+
+on-finished@~2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
+ dependencies:
+ ee-first "1.1.1"
+
+once@^1.3.0, once@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ dependencies:
+ wrappy "1"
+
+optimist@^0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
+ dependencies:
+ minimist "~0.0.1"
+ wordwrap "~0.0.2"
+
+optionator@^0.8.1:
+ version "0.8.2"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
+ dependencies:
+ deep-is "~0.1.3"
+ fast-levenshtein "~2.0.4"
+ levn "~0.3.0"
+ prelude-ls "~1.1.2"
+ type-check "~0.3.2"
+ wordwrap "~1.0.0"
+
+os-homedir@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
+
+os-locale@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9"
+ dependencies:
+ lcid "^1.0.0"
+
+os-tmpdir@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
+
+p-limit@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc"
+
+p-locate@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
+ dependencies:
+ p-limit "^1.1.0"
+
+p-map@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.1.1.tgz#05f5e4ae97a068371bc2a5cc86bfbdbc19c4ae7a"
+
+parse-glob@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
+ dependencies:
+ glob-base "^0.3.0"
+ is-dotfile "^1.0.0"
+ is-extglob "^1.0.0"
+ is-glob "^2.0.0"
+
+parse-json@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
+ dependencies:
+ error-ex "^1.2.0"
+
+parse5@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/parse5/-/parse5-1.5.1.tgz#9b7f3b0de32be78dc2401b17573ccaf0f6f59d94"
+
+parseurl@~1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56"
+
+path-exists@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
+ dependencies:
+ pinkie-promise "^2.0.0"
+
+path-exists@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
+
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+
+path-parse@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1"
+
+path-to-regexp@0.1.7:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
+
+path-type@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
+ dependencies:
+ graceful-fs "^4.1.2"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+
+performance-now@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
+
+pify@^2.0.0, pify@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+
+pinkie-promise@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
+ dependencies:
+ pinkie "^2.0.0"
+
+pinkie@^2.0.0:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
+
+prelude-ls@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
+
+preserve@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
+
+pretty-format@^20.0.3:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-20.0.3.tgz#020e350a560a1fe1a98dc3beb6ccffb386de8b14"
+ dependencies:
+ ansi-regex "^2.1.1"
+ ansi-styles "^3.0.0"
+
+private@^0.1.6:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1"
+
+proxy-addr@~1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.4.tgz#27e545f6960a44a627d9b44467e35c1b6b4ce2f3"
+ dependencies:
+ forwarded "~0.1.0"
+ ipaddr.js "1.3.0"
+
+prr@~0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a"
+
+punycode@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
+
+qs@*, qs@^6.2.0:
+ version "6.5.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49"
+
+qs@6.4.0, qs@~6.4.0:
+ version "6.4.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
+
+randomatic@^1.1.3:
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c"
+ dependencies:
+ is-number "^3.0.0"
+ kind-of "^4.0.0"
+
+range-parser@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
+
+raw-body@~2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.2.0.tgz#994976cf6a5096a41162840492f0bdc5d6e7fb96"
+ dependencies:
+ bytes "2.4.0"
+ iconv-lite "0.4.15"
+ unpipe "1.0.0"
+
+read-pkg-up@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
+ dependencies:
+ find-up "^1.0.0"
+ read-pkg "^1.0.0"
+
+read-pkg@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
+ dependencies:
+ load-json-file "^1.0.0"
+ normalize-package-data "^2.3.2"
+ path-type "^1.0.0"
+
+regenerator-runtime@^0.10.0:
+ version "0.10.5"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658"
+
+regex-cache@^0.4.2:
+ version "0.4.3"
+ resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145"
+ dependencies:
+ is-equal-shallow "^0.1.3"
+ is-primitive "^2.0.0"
+
+remove-trailing-separator@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz#69b062d978727ad14dc6b56ba4ab772fd8d70511"
+
+repeat-element@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a"
+
+repeat-string@^1.5.2:
+ version "1.6.1"
+ resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
+
+repeating@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
+ dependencies:
+ is-finite "^1.0.0"
+
+request@^2.79.0:
+ version "2.81.0"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
+ dependencies:
+ aws-sign2 "~0.6.0"
+ aws4 "^1.2.1"
+ caseless "~0.12.0"
+ combined-stream "~1.0.5"
+ extend "~3.0.0"
+ forever-agent "~0.6.1"
+ form-data "~2.1.1"
+ har-validator "~4.2.1"
+ hawk "~3.1.3"
+ http-signature "~1.1.0"
+ is-typedarray "~1.0.0"
+ isstream "~0.1.2"
+ json-stringify-safe "~5.0.1"
+ mime-types "~2.1.7"
+ oauth-sign "~0.8.1"
+ performance-now "^0.2.0"
+ qs "~6.4.0"
+ safe-buffer "^5.0.1"
+ stringstream "~0.0.4"
+ tough-cookie "~2.3.0"
+ tunnel-agent "^0.6.0"
+ uuid "^3.0.0"
+
+require-directory@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
+
+require-main-filename@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
+
+resolve@1.1.7:
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
+
+resolve@^1.3.2:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5"
+ dependencies:
+ path-parse "^1.0.5"
+
+right-align@^0.1.1:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
+ dependencies:
+ align-text "^0.1.1"
+
+rimraf@^2.6.1:
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
+ dependencies:
+ glob "^7.0.5"
+
+safe-buffer@^5.0.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
+
+sane@~1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/sane/-/sane-1.6.0.tgz#9610c452307a135d29c1fdfe2547034180c46775"
+ dependencies:
+ anymatch "^1.3.0"
+ exec-sh "^0.2.0"
+ fb-watchman "^1.8.0"
+ minimatch "^3.0.2"
+ minimist "^1.1.1"
+ walker "~1.0.5"
+ watch "~0.10.0"
+
+sax@^1.2.1:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
+
+"semver@2 || 3 || 4 || 5", semver@^5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
+
+send@0.15.3:
+ version "0.15.3"
+ resolved "https://registry.yarnpkg.com/send/-/send-0.15.3.tgz#5013f9f99023df50d1bd9892c19e3defd1d53309"
+ dependencies:
+ debug "2.6.7"
+ depd "~1.1.0"
+ destroy "~1.0.4"
+ encodeurl "~1.0.1"
+ escape-html "~1.0.3"
+ etag "~1.8.0"
+ fresh "0.5.0"
+ http-errors "~1.6.1"
+ mime "1.3.4"
+ ms "2.0.0"
+ on-finished "~2.3.0"
+ range-parser "~1.2.0"
+ statuses "~1.3.1"
+
+serve-static@1.12.3:
+ version "1.12.3"
+ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.3.tgz#9f4ba19e2f3030c547f8af99107838ec38d5b1e2"
+ dependencies:
+ encodeurl "~1.0.1"
+ escape-html "~1.0.3"
+ parseurl "~1.3.1"
+ send "0.15.3"
+
+set-blocking@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
+
+setprototypeof@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04"
+
+shellwords@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.0.tgz#66afd47b6a12932d9071cbfd98a52e785cd0ba14"
+
+slash@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
+
+sntp@1.x.x:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198"
+ dependencies:
+ hoek "2.x.x"
+
+source-map-support@^0.4.2:
+ version "0.4.15"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1"
+ dependencies:
+ source-map "^0.5.6"
+
+source-map@^0.4.4:
+ version "0.4.4"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
+ dependencies:
+ amdefine ">=0.0.4"
+
+source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1:
+ version "0.5.6"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
+
+source-map@~0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d"
+ dependencies:
+ amdefine ">=0.0.4"
+
+spdx-correct@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40"
+ dependencies:
+ spdx-license-ids "^1.0.2"
+
+spdx-expression-parse@~1.0.0:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c"
+
+spdx-license-ids@^1.0.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57"
+
+sprintf-js@~1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+
+sshpk@^1.7.0:
+ version "1.13.1"
+ resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3"
+ dependencies:
+ asn1 "~0.2.3"
+ assert-plus "^1.0.0"
+ dashdash "^1.12.0"
+ getpass "^0.1.1"
+ optionalDependencies:
+ bcrypt-pbkdf "^1.0.0"
+ ecc-jsbn "~0.1.1"
+ jsbn "~0.1.0"
+ tweetnacl "~0.14.0"
+
+"statuses@>= 1.3.1 < 2", statuses@~1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e"
+
+string-length@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/string-length/-/string-length-1.0.1.tgz#56970fb1c38558e9e70b728bf3de269ac45adfac"
+ dependencies:
+ strip-ansi "^3.0.0"
+
+string-width@^1.0.1, string-width@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
+ dependencies:
+ code-point-at "^1.0.0"
+ is-fullwidth-code-point "^1.0.0"
+ strip-ansi "^3.0.0"
+
+stringstream@~0.0.4:
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
+
+strip-ansi@^3.0.0, strip-ansi@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+ dependencies:
+ ansi-regex "^2.0.0"
+
+strip-bom@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
+
+strip-bom@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
+ dependencies:
+ is-utf8 "^0.2.0"
+
+supports-color@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+
+supports-color@^3.1.2:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
+ dependencies:
+ has-flag "^1.0.0"
+
+symbol-tree@^3.2.1:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6"
+
+test-exclude@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.1.tgz#4d84964b0966b0087ecc334a2ce002d3d9341e26"
+ dependencies:
+ arrify "^1.0.1"
+ micromatch "^2.3.11"
+ object-assign "^4.1.0"
+ read-pkg-up "^1.0.1"
+ require-main-filename "^1.0.1"
+
+throat@^3.0.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/throat/-/throat-3.2.0.tgz#50cb0670edbc40237b9e347d7e1f88e4620af836"
+
+tmpl@1.0.x:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
+
+to-fast-properties@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
+
+tough-cookie@^2.3.2, tough-cookie@~2.3.0:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a"
+ dependencies:
+ punycode "^1.4.1"
+
+tr46@~0.0.3:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
+
+trim-right@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
+
+tunnel-agent@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
+ dependencies:
+ safe-buffer "^5.0.1"
+
+tweetnacl@^0.14.3, tweetnacl@~0.14.0:
+ version "0.14.5"
+ resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
+
+type-check@~0.3.2:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
+ dependencies:
+ prelude-ls "~1.1.2"
+
+type-is@~1.6.15:
+ version "1.6.15"
+ resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410"
+ dependencies:
+ media-typer "0.3.0"
+ mime-types "~2.1.15"
+
+uglify-js@^2.6:
+ version "2.8.29"
+ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
+ dependencies:
+ source-map "~0.5.1"
+ yargs "~3.10.0"
+ optionalDependencies:
+ uglify-to-browserify "~1.0.0"
+
+uglify-to-browserify@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
+
+unpipe@1.0.0, unpipe@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+
+utils-merge@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8"
+
+uuid@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"
+
+validate-npm-package-license@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
+ dependencies:
+ spdx-correct "~1.0.0"
+ spdx-expression-parse "~1.0.0"
+
+vary@^1, vary@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37"
+
+verror@1.3.6:
+ version "1.3.6"
+ resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c"
+ dependencies:
+ extsprintf "1.0.2"
+
+walker@~1.0.5:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"
+ dependencies:
+ makeerror "1.0.x"
+
+watch@~0.10.0:
+ version "0.10.0"
+ resolved "https://registry.yarnpkg.com/watch/-/watch-0.10.0.tgz#77798b2da0f9910d595f1ace5b0c2258521f21dc"
+
+webidl-conversions@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
+
+webidl-conversions@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.1.tgz#8015a17ab83e7e1b311638486ace81da6ce206a0"
+
+whatwg-encoding@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.1.tgz#3c6c451a198ee7aec55b1ec61d0920c67801a5f4"
+ dependencies:
+ iconv-lite "0.4.13"
+
+whatwg-fetch@>=0.10.0:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84"
+
+whatwg-url@^4.3.0:
+ version "4.8.0"
+ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-4.8.0.tgz#d2981aa9148c1e00a41c5a6131166ab4683bbcc0"
+ dependencies:
+ tr46 "~0.0.3"
+ webidl-conversions "^3.0.0"
+
+which-module@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
+
+which@^1.2.12:
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5"
+ dependencies:
+ isexe "^2.0.0"
+
+window-size@0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
+
+wordwrap@0.0.2:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
+
+wordwrap@~0.0.2:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
+
+wordwrap@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
+
+worker-farm@^1.3.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.4.1.tgz#a438bc993a7a7d133bcb6547c95eca7cff4897d8"
+ dependencies:
+ errno "^0.1.4"
+ xtend "^4.0.1"
+
+wrap-ansi@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
+ dependencies:
+ string-width "^1.0.1"
+ strip-ansi "^3.0.1"
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+
+xml-name-validator@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635"
+
+xmlhttprequest@^1.8.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc"
+
+xtend@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
+
+y18n@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
+
+yargs-parser@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a"
+ dependencies:
+ camelcase "^3.0.0"
+
+yargs@^7.0.2:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8"
+ dependencies:
+ camelcase "^3.0.0"
+ cliui "^3.2.0"
+ decamelize "^1.1.1"
+ get-caller-file "^1.0.1"
+ os-locale "^1.4.0"
+ read-pkg-up "^1.0.1"
+ require-directory "^2.1.1"
+ require-main-filename "^1.0.1"
+ set-blocking "^2.0.0"
+ string-width "^1.0.2"
+ which-module "^1.0.0"
+ y18n "^3.2.1"
+ yargs-parser "^5.0.0"
+
+yargs@~3.10.0:
+ version "3.10.0"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"
+ dependencies:
+ camelcase "^1.0.2"
+ cliui "^2.1.0"
+ decamelize "^1.0.0"
+ window-size "0.1.0"
diff --git a/_modules/lego-cli/async.js b/_modules/lego-cli/async.js
new file mode 100644
index 0000000..3ac9878
--- /dev/null
+++ b/_modules/lego-cli/async.js
@@ -0,0 +1 @@
+// https://github.com/MatAtBread/nodent-compiler/blob/master/lib/output.js
diff --git a/_modules/lego-cli/index.js b/_modules/lego-cli/index.js
new file mode 100644
index 0000000..8631cb1
--- /dev/null
+++ b/_modules/lego-cli/index.js
@@ -0,0 +1,54 @@
+// @TODO can also use `on-the-fly` to compile into a bundle on the fly
+
+// this file is just when using in dev mode so huge relative paths aren't required
+const {resolve} = require('path')
+const moduleAlias = require('module-alias')
+
+const res = rel => resolve(__dirname, rel)
+moduleAlias.addPath(res('../../../'))
+moduleAlias.addPath(res('../../'))
+moduleAlias.addPath(res('../../src'))
+moduleAlias.addPath(res('./node_modules'))
+
+// const CLI = require('fluent-cli')
+// const File = require('file-chain')
+
+const {exists, read, write} = require('flipfile')
+const Script = require('script-chain')
+const execa = require('execa')
+const find = require('chain-able-find')
+const fwf = require('funwithflags')
+const log = require('fliplog')
+const {Chain, isUndefined} = require('chain-able')
+const pkg = require('../../package.json')
+
+const deps = {
+ find,
+ execa,
+ Script,
+ // CLI,
+ resolve,
+ fwf,
+ log,
+ exists,
+ read,
+ write,
+ pkg,
+ Chain,
+ // File,
+ script: () => new Script(),
+}
+
+// @TODO: needs yarn-or-npm script
+/**
+ * @prop {string} dir directory to resolve everything to
+ * @type {ChainedMap}
+ */
+class AppCLI extends Chain {
+ dep(name) {
+ return isUndefined(name) ? deps : deps[name]
+ }
+ script() {
+ return new Script()
+ }
+}
diff --git a/_modules/lego-cli/plugins/ast/babel.js b/_modules/lego-cli/plugins/ast/babel.js
new file mode 100644
index 0000000..d2c7b42
--- /dev/null
+++ b/_modules/lego-cli/plugins/ast/babel.js
@@ -0,0 +1,17 @@
+module.exports = {
+ /**
+ * @since 0.0.1
+ * @tutorial https://github.com/babel
+ * @param {string} string code source
+ * @param {Object} [config=null] babel options
+ * @return {string} transformed babel output
+ */
+ babel(string, config = null) {
+ // return new Script().add().bin('babel').raw('src/ --out-dir dist').run()
+ const babel = require('babel-core')
+ // result = babel.transform(str, {allowReturnOutsideFunction: true});
+ const parsedAst = babel.parse(string, {allowReturnOutsideFunction: true})
+ const {code, map, ast} = babel.transformFromAst(parsedAst, string, config)
+ return code
+ },
+}
diff --git a/_modules/lego-cli/plugins/ast/buble.js b/_modules/lego-cli/plugins/ast/buble.js
new file mode 100644
index 0000000..6fb5bf5
--- /dev/null
+++ b/_modules/lego-cli/plugins/ast/buble.js
@@ -0,0 +1,13 @@
+module.exports = {
+ buble() {
+ const sourcemaps = true
+ const scripts = this.script()
+ .add()
+ .bin('buble')
+ .raw('-i dist')
+ .raw('-o dist')
+ .raw('--no forOf,dangerousForOf,computedProperty,spreadRest')
+ if (sourcemaps) scripts.raw('-m inline')
+ return scripts.run()
+ },
+}
diff --git a/_modules/lego-cli/plugins/ast/lebab.js b/_modules/lego-cli/plugins/ast/lebab.js
new file mode 100644
index 0000000..9464b80
--- /dev/null
+++ b/_modules/lego-cli/plugins/ast/lebab.js
@@ -0,0 +1,647 @@
+const {resolve} = require('path')
+const {execSync} = require('child_process')
+const log = require('fliplog')
+const lebab = require('lebab')
+const {read, write, del} = require('flipfile')
+const {GlobSync} = require('flipfile/glob')
+const ChainedMap = require('chain-able')
+
+/**
+ * @TODO:
+ * - [ ] should put the transformers as middleware
+ * - [ ] use file-chain now that it is extracted
+ * - [ ] run eslint on transformed files
+ */
+class File {
+ /**
+ * @param {Object} obj
+ */
+ constructor(obj) {
+ const {debug, abs} = obj
+ this.abs = abs
+ this._debug = !!debug
+ }
+
+ /**
+ * reads file
+ * @see File.contents
+ * @param {boolean} [force=false]
+ * @return {File}
+ */
+ load(force = false) {
+ if (this.contents !== undefined && force === false) {
+ return this
+ }
+
+ this.contents = read(this.abs)
+
+ log.blue('loaded content').data(this.abs, this.contents).echo(this._debug)
+
+ return this
+ }
+
+ del() {
+ del(this.abs)
+ return this
+ }
+
+ /**
+ * @return {File}
+ */
+ lebab() {
+ const features = ['let', 'arrow', 'commonjs', 'includes']
+ const {code, warnings} = lebab.transform(this.contents, features)
+
+ log.bold('label-ed').verbose().data({code, warnings}).echo(this._debug)
+
+ this.contents = code
+
+ return this
+ }
+
+ /**
+ * @param {string} from
+ * @param {string} to
+ * @return {File}
+ */
+ changeExtension(from, to) {
+ const abs = this.abs
+
+ this.abs = this.abs.replace(from, to).replace('//', '/')
+
+ log
+ .underline('changed path')
+ .data({from: abs, to: this.abs})
+ .echo(this._debug)
+
+ return this
+ }
+
+ /**
+ * @param {string} from
+ * @param {string} to
+ * @return {File}
+ */
+ changeDir(from, to) {
+ // const {input, temp} = dirs
+
+ const abs = this.abs
+
+ this.abs = this.abs.replace(from, to)
+ // const toDir = resolve(dir, './ts') .replace(dir, './')
+
+ log
+ .underline('changed dir')
+ .data({before: abs, after: this.abs, from, to})
+ .echo(this._debug)
+
+ return this
+ }
+
+ /**
+ * removes public/private/protected class properties
+ * since babel does not like them, currently
+ *
+ * @return {Magic}
+ */
+ removeModifiers() {
+ log.blue('data').verbose().data().echo(this._debug)
+
+ this.contents = this.contents.replace(
+ /( {0,4}public|private|protected )/gim,
+ ''
+ )
+
+ return this
+ }
+
+ /**
+ * @return {File}
+ */
+ write() {
+ const {abs, contents} = this
+
+ log.green('writing').data({abs, contents}).echo(this._debug)
+
+ write(abs, contents)
+
+ return this
+ }
+}
+
+class Magic extends ChainedMap {
+ /**
+ * @param {any} parent
+ */
+ constructor(parent) {
+ super(parent)
+
+ this.globs = {}
+
+ this.files = {
+ js: [],
+ other: [],
+ }
+
+ this.dirs = {}
+ this._debug = false
+ }
+
+ /**
+ * @param {Boolean} [should=true]
+ * @return {Magic}
+ */
+ debug(should = true) {
+ return this.set('debug', should)
+ }
+
+ /**
+ * @param {string} glob
+ * @return {Magic}
+ */
+ setGlob(glob) {
+ this.globs = {
+ glob,
+ opts: {stat: true, absolute: true},
+ }
+
+ return this
+ }
+
+ /**
+ * @param {Object} dirs
+ * @return {Magic}
+ */
+ setDirs(dirs) {
+ let {js, ts, temp, dist, dir} = dirs
+
+ // if not a single folder, split n pop
+ // if (js.includes('/')) js = js.split('/').pop()
+ // if (ts.includes('/')) ts = ts.split('/').pop()
+ // if (temp.includes('/')) temp = temp.split('/').pop()
+
+ // store on instance
+ this.dirs = {js, ts, temp, dir}
+
+ return this
+ }
+
+ /**
+ * @see Magic.files, Magic.globs, File
+ * @return {Magic}
+ */
+ gatherFiles() {
+ // extract variables
+ const {glob, opts} = this.globs
+
+ // do globbing
+ const found = new GlobSync(glob, opts).found
+
+ const debug = this.get('debug')
+
+ // add to instance
+ this.files = found.map(abs => new File({abs, debug}))
+
+ // const otherGlob = new GlobSync(other, opts).found
+ // other: otherGlob
+ // .filter(abs => !abs.includes('.js'))
+ // .map(abs => new File({abs, debug})),
+
+ return this
+ }
+
+ // --- handle
+
+ /**
+ * @see File.lebab
+ * @return {Magic}
+ */
+ lebab() {
+ this.files.forEach(file => {
+ file.load().lebab().write()
+ })
+
+ return this
+ }
+
+ /**
+ * @see Magic.gatherFiles, Magic.setDirs
+ * @return {Magic}
+ */
+ toTypeScript() {
+ // clean
+ execSync(`rm -f -r ${this.dirs.ts}/`, {stdio: 'inherit'})
+
+ // copy js dir to typescript dir
+ execSync(`cp -R -f ${this.dirs.js} ${this.dirs.ts}/`, {stdio: 'inherit'})
+
+ this.setGlob(this.dirs.ts + '/**/*.js')
+
+ return this
+ }
+ saveTypeScript() {
+ // then convert the js files
+ this.files.forEach(file => {
+ // file._debug = true
+ file
+ .load()
+ .del() // del .js, we already loaded contents
+ .changeExtension('.js', '.ts')
+ .write()
+ })
+ }
+
+ /**
+ * @see Magic.gatherFiles, Magic.setDirs
+ * @return {Magic}
+ */
+ toTemp() {
+ // clean
+ execSync(`rm -f -r ${this.dirs.temp}/`, {stdio: 'inherit'})
+
+ // copy ts dir to temp dir
+ execSync(`cp -R -f ${this.dirs.ts} ${this.dirs.temp}/`, {stdio: 'inherit'})
+
+ this.setGlob(this.dirs.temp + '/**/*.ts')
+
+ return this
+ }
+ saveTemp() {
+ this.files.forEach(file => {
+ file.load().del().changeExtension('.ts', '.js').removeModifiers().write()
+ })
+ return this
+ }
+}
+
+// @TODO: add options
+// @TODO: also add scripts with scriptflip...
+// const dirs = {
+// dir: __dirname,
+// js: 'test',
+// ts: 'typescript',
+// temp: 'temp',
+// dist: 'dist',
+// }
+
+const dirs = {
+ dir: __dirname,
+ ts: 'three/src',
+ temp: 'three/temp',
+ dist: 'three/dist',
+}
+
+let toTypescript = false
+let toTemp = false
+
+// toTypescript = true
+// toTemp = false
+
+if (toTypescript !== false) {
+ const magic = new Magic()
+
+ magic
+ .debug(false)
+ .setDirs(dirs)
+ .toTypeScript()
+ .gatherFiles()
+ .lebab()
+ .saveTypeScript()
+}
+
+if (toTemp !== false) {
+ const magic = new Magic()
+
+ magic.setDirs(dirs).toTemp().gatherFiles().saveTemp()
+}
+
+if (dirs.dist) {
+ const execa = require('execa')
+ execa('babel', [dirs.temp, '--out-dir=' + dirs.dist], {stdio: 'inherit'})
+}
+
+module.exports = Magic
+
+const {resolve} = require('path')
+const {execSync} = require('child_process')
+const log = require('fliplog')
+const lebab = require('lebab')
+const {read, write, del} = require('flipfile')
+const {GlobSync} = require('flipfile/glob')
+const ChainedMap = require('chain-able')
+
+/**
+ * @TODO:
+ * - [ ] should put the transformers as middleware
+ * - [ ] use file-chain now that it is extracted
+ * - [ ] run eslint on transformed files
+ */
+class File {
+ /**
+ * @param {Object} obj
+ */
+ constructor(obj) {
+ const {debug, abs} = obj
+ this.abs = abs
+ this._debug = !!debug
+ }
+
+ /**
+ * reads file
+ * @see File.contents
+ * @param {boolean} [force=false]
+ * @return {File}
+ */
+ load(force = false) {
+ if (this.contents !== undefined && force === false) {
+ return this
+ }
+
+ this.contents = read(this.abs)
+
+ log.blue('loaded content').data(this.abs, this.contents).echo(this._debug)
+
+ return this
+ }
+
+ del() {
+ del(this.abs)
+ return this
+ }
+
+ /**
+ * @return {File}
+ */
+ lebab() {
+ const features = ['let', 'arrow', 'commonjs', 'includes']
+ const {code, warnings} = lebab.transform(this.contents, features)
+
+ log.bold('label-ed').verbose().data({code, warnings}).echo(this._debug)
+
+ this.contents = code
+
+ return this
+ }
+
+ /**
+ * @param {string} from
+ * @param {string} to
+ * @return {File}
+ */
+ changeExtension(from, to) {
+ const abs = this.abs
+
+ this.abs = this.abs.replace(from, to).replace('//', '/')
+
+ log
+ .underline('changed path')
+ .data({from: abs, to: this.abs})
+ .echo(this._debug)
+
+ return this
+ }
+
+ /**
+ * @param {string} from
+ * @param {string} to
+ * @return {File}
+ */
+ changeDir(from, to) {
+ // const {input, temp} = dirs
+
+ const abs = this.abs
+
+ this.abs = this.abs.replace(from, to)
+ // const toDir = resolve(dir, './ts') .replace(dir, './')
+
+ log
+ .underline('changed dir')
+ .data({before: abs, after: this.abs, from, to})
+ .echo(this._debug)
+
+ return this
+ }
+
+ /**
+ * removes public/private/protected class properties
+ * since babel does not like them, currently
+ *
+ * @return {Magic}
+ */
+ removeModifiers() {
+ log.blue('data').verbose().data().echo(this._debug)
+
+ this.contents = this.contents.replace(
+ /( {0,4}public|private|protected )/gim,
+ ''
+ )
+
+ return this
+ }
+
+ /**
+ * @return {File}
+ */
+ write() {
+ const {abs, contents} = this
+
+ log.green('writing').data({abs, contents}).echo(this._debug)
+
+ write(abs, contents)
+
+ return this
+ }
+}
+
+class Magic extends ChainedMap {
+ /**
+ * @param {any} parent
+ */
+ constructor(parent) {
+ super(parent)
+
+ this.globs = {}
+
+ this.files = {
+ js: [],
+ other: [],
+ }
+
+ this.dirs = {}
+ this._debug = false
+ }
+
+ /**
+ * @param {Boolean} [should=true]
+ * @return {Magic}
+ */
+ debug(should = true) {
+ return this.set('debug', should)
+ }
+
+ /**
+ * @param {string} glob
+ * @return {Magic}
+ */
+ setGlob(glob) {
+ this.globs = {
+ glob,
+ opts: {stat: true, absolute: true},
+ }
+
+ return this
+ }
+
+ /**
+ * @param {Object} dirs
+ * @return {Magic}
+ */
+ setDirs(dirs) {
+ let {js, ts, temp, dist, dir} = dirs
+
+ // if not a single folder, split n pop
+ // if (js.includes('/')) js = js.split('/').pop()
+ // if (ts.includes('/')) ts = ts.split('/').pop()
+ // if (temp.includes('/')) temp = temp.split('/').pop()
+
+ // store on instance
+ this.dirs = {js, ts, temp, dir}
+
+ return this
+ }
+
+ /**
+ * @see Magic.files, Magic.globs, File
+ * @return {Magic}
+ */
+ gatherFiles() {
+ // extract variables
+ const {glob, opts} = this.globs
+
+ // do globbing
+ const found = new GlobSync(glob, opts).found
+
+ const debug = this.get('debug')
+
+ // add to instance
+ this.files = found.map(abs => new File({abs, debug}))
+
+ // const otherGlob = new GlobSync(other, opts).found
+ // other: otherGlob
+ // .filter(abs => !abs.includes('.js'))
+ // .map(abs => new File({abs, debug})),
+
+ return this
+ }
+
+ // --- handle
+
+ /**
+ * @see File.lebab
+ * @return {Magic}
+ */
+ lebab() {
+ this.files.forEach(file => {
+ file.load().lebab().write()
+ })
+
+ return this
+ }
+
+ /**
+ * @see Magic.gatherFiles, Magic.setDirs
+ * @return {Magic}
+ */
+ toTypeScript() {
+ // clean
+ execSync(`rm -f -r ${this.dirs.ts}/`, {stdio: 'inherit'})
+
+ // copy js dir to typescript dir
+ execSync(`cp -R -f ${this.dirs.js} ${this.dirs.ts}/`, {stdio: 'inherit'})
+
+ this.setGlob(this.dirs.ts + '/**/*.js')
+
+ return this
+ }
+ saveTypeScript() {
+ // then convert the js files
+ this.files.forEach(file => {
+ // file._debug = true
+ file
+ .load()
+ .del() // del .js, we already loaded contents
+ .changeExtension('.js', '.ts')
+ .write()
+ })
+ }
+
+ /**
+ * @see Magic.gatherFiles, Magic.setDirs
+ * @return {Magic}
+ */
+ toTemp() {
+ // clean
+ execSync(`rm -f -r ${this.dirs.temp}/`, {stdio: 'inherit'})
+
+ // copy ts dir to temp dir
+ execSync(`cp -R -f ${this.dirs.ts} ${this.dirs.temp}/`, {stdio: 'inherit'})
+
+ this.setGlob(this.dirs.temp + '/**/*.ts')
+
+ return this
+ }
+ saveTemp() {
+ this.files.forEach(file => {
+ file.load().del().changeExtension('.ts', '.js').removeModifiers().write()
+ })
+ return this
+ }
+}
+
+// @TODO: add options
+// @TODO: also add scripts with scriptflip...
+// const dirs = {
+// dir: __dirname,
+// js: 'test',
+// ts: 'typescript',
+// temp: 'temp',
+// dist: 'dist',
+// }
+
+const dirs = {
+ dir: __dirname,
+ ts: 'three/src',
+ temp: 'three/temp',
+ dist: 'three/dist',
+}
+
+let toTypescript = false
+let toTemp = false
+
+// toTypescript = true
+// toTemp = false
+
+if (toTypescript !== false) {
+ const magic = new Magic()
+
+ magic
+ .debug(false)
+ .setDirs(dirs)
+ .toTypeScript()
+ .gatherFiles()
+ .lebab()
+ .saveTypeScript()
+}
+
+if (toTemp !== false) {
+ const magic = new Magic()
+
+ magic.setDirs(dirs).toTemp().gatherFiles().saveTemp()
+}
+
+if (dirs.dist) {
+ const execa = require('execa')
+ execa('babel', [dirs.temp, '--out-dir=' + dirs.dist], {stdio: 'inherit'})
+}
+
+module.exports = Magic
diff --git a/_modules/lego-cli/plugins/ast/typescript.js b/_modules/lego-cli/plugins/ast/typescript.js
new file mode 100644
index 0000000..800d811
--- /dev/null
+++ b/_modules/lego-cli/plugins/ast/typescript.js
@@ -0,0 +1,25 @@
+module.exports = {
+ ts(TSC_SOURCE, TSC_OUT) {
+ const {read, write} = this.dep()
+ const ts = require('typescript')
+ const source = read(TSC_SOURCE)
+
+ let result = ts.transpileModule(source, {
+ compilerOptions: {module: ts.ModuleKind.CommonJS},
+ })
+ write(require.resolve(TSC_OUT), result.outputText)
+
+ console.log(JSON.stringify(result))
+ process.exit()
+ },
+ tsc(buildTests = false) {
+ const {script} = this.dep()
+
+ if (buildTests) {
+ const flags =
+ '--pretty --sourceMap --allowJs --project test --outDir test-dist'
+ return script('tsc', flags)
+ }
+ return script('tsc')
+ },
+}
diff --git a/_modules/lego-cli/plugins/bundle/browserify.js b/_modules/lego-cli/plugins/bundle/browserify.js
new file mode 100644
index 0000000..431d841
--- /dev/null
+++ b/_modules/lego-cli/plugins/bundle/browserify.js
@@ -0,0 +1,6 @@
+module.exports = {
+ name: 'browserify',
+ browserify() {
+ // browserify src -o dists/browserified/index.js
+ },
+}
diff --git a/_modules/lego-cli/plugins/bundle/optimizejs.js b/_modules/lego-cli/plugins/bundle/optimizejs.js
new file mode 100644
index 0000000..8626bc8
--- /dev/null
+++ b/_modules/lego-cli/plugins/bundle/optimizejs.js
@@ -0,0 +1,16 @@
+module.exports = {
+ name: 'optimizejs',
+
+ /**
+ * @since 0.0.1
+ * @tutorial https://github.com/nolanlawson/optimize-js
+ * @param {string} input
+ * @return {string} optimized output
+ */
+ optimize(input) {
+ const optimizeJs = require('optimize-js')
+ return optimizeJs(input, {
+ sourceMap: true,
+ })
+ },
+}
diff --git a/_modules/lego-cli/plugins/bundle/rollup.js b/_modules/lego-cli/plugins/bundle/rollup.js
new file mode 100644
index 0000000..35b5587
--- /dev/null
+++ b/_modules/lego-cli/plugins/bundle/rollup.js
@@ -0,0 +1,14 @@
+module.exports = {
+ name: 'rollup',
+
+ rollup(flags = '', ROLLUP_CONFIG_CLI) {
+ if (Array.isArray(flags)) return flags.map(flag => this.rollup(flag))
+ const config = ROLLUP_CONFIG_CLI
+ const {script} = this.dep()
+
+ return script('rollup', '-c ' + require.resolve(config) + ' ' + flags)
+ },
+ rollupNode(buildFile = './build', overrides = {}) {
+ return require(buildFile)(overrides)
+ },
+}
diff --git a/_modules/lego-cli/plugins/docs/README.md b/_modules/lego-cli/plugins/docs/README.md
new file mode 100644
index 0000000..5257695
--- /dev/null
+++ b/_modules/lego-cli/plugins/docs/README.md
@@ -0,0 +1 @@
+https://github.com/jsdoc3/jsdoc/issues/250
diff --git a/_modules/lego-cli/plugins/docs/doctrine.js b/_modules/lego-cli/plugins/docs/doctrine.js
new file mode 100644
index 0000000..c7ef175
--- /dev/null
+++ b/_modules/lego-cli/plugins/docs/doctrine.js
@@ -0,0 +1,165 @@
+var doctrineAPI = require('doctrine')
+
+var parsed = doctrineAPI.parse(
+ [
+ `
+ /**
+ * @classdesc this is to avoid circular requires
+ * because MergeChain & MethodChain extend this
+ * yet .method & .merge use those chains
+ *
+ * @since 4.0.0-alpha.1
+ * @inheritdoc
+ * @class ChainedMapBase
+ * @member ChainedMapBase
+ * @category Chainable
+ * @extends {Chainable}
+ * @type {Chainable}
+ *
+ * @types ChainedMapBase
+ * @tests ChainedMap
+ *
+ * @prop {Meta} meta
+ * @prop {Map} store
+ *
+ * {@link https://ponyfoo.com/articles/es6-maps-in-depth pony-map}
+ * {@link https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map mozilla-map}
+ * @see {@link pony-map}
+ * @see {@link mozilla-map}
+ *
+ * @see ChainedMap
+ * @see Chainable
+ * @see MergeChain
+ * @see MethodChain
+ * @see ChainedMap
+ *
+ */
+ `,
+ `
+ /**
+ * @param {*} x value
+ * @return {boolean} isDate
+ *
+ * @since 3.0.0
+ * @memberOf is
+ * @func isDate
+ *
+ * @example
+ *
+ * isDate(new Date())
+ * //=> true
+ * isDate(Date.now())
+ * //=> false
+ * isDate(1)
+ * //=> false
+ * isDate('')
+ * //=> false
+ *
+ * @example
+ *
+ * const e = {}
+ * eh[Symbol.toStringTag] = '[Object Date]'
+ * isDate(eh)
+ * //=> true
+ *
+ * @example
+ *
+ * class Eh extends Date()
+ * isDate(new Eh())
+ * //=> true
+ */
+ `,
+ // '/**',
+ // ' * This function comment is parsed by doctrine',
+ // ' * @param {{ok:String}} userName',
+ // '*/',
+ ].join('\n'),
+ {unwrap: true}
+)
+
+var ast = {
+ description: '/**',
+ tags: [
+ {
+ title: 'classdesc',
+ description:
+ 'this is to avoid circular requires\n because MergeChain & MethodChain extend this\n yet .method & .merge use those chains',
+ },
+ {title: 'since', description: '4.0.0-alpha.1'},
+ {title: 'inheritdoc', description: null},
+ {
+ title: 'class',
+ description: null,
+ type: null,
+ name: 'ChainedMapBase',
+ },
+ {
+ title: 'member',
+ description: null,
+ type: null,
+ name: 'ChainedMapBase',
+ },
+ {title: 'category', description: 'Chainable'},
+ {
+ title: 'extends',
+ description: null,
+ type: {type: 'NameExpression', name: 'Chainable'},
+ name: null,
+ },
+ {
+ title: 'type',
+ description: null,
+ type: {type: 'NameExpression', name: 'Chainable'},
+ },
+ {title: 'types', description: 'ChainedMapBase'},
+ {title: 'tests', description: 'ChainedMap'},
+ {
+ title: 'prop',
+ description: null,
+ type: {type: 'NameExpression', name: 'Meta'},
+ name: 'meta',
+ },
+ {
+ title: 'prop',
+ description:
+ '{@link https://ponyfoo.com/articles/es6-maps-in-depth pony-map}\n{@link https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map mozilla-map}',
+ type: {type: 'NameExpression', name: 'Map'},
+ name: 'store',
+ },
+ {title: 'see', description: '{@link pony-map}'},
+ {title: 'see', description: '{@link mozilla-map}'},
+ {title: 'see', description: 'ChainedMap'},
+ {title: 'see', description: 'Chainable'},
+ {title: 'see', description: 'MergeChain'},
+ {title: 'see', description: 'MethodChain'},
+ {title: 'see', description: 'ChainedMap\n\n/\n\n\n/**'},
+ {
+ title: 'param',
+ description: 'value',
+ type: {type: 'AllLiteral'},
+ name: 'x',
+ },
+ {
+ title: 'return',
+ description: 'isDate',
+ type: {type: 'NameExpression', name: 'boolean'},
+ },
+ {title: 'since', description: '3.0.0'},
+ {title: 'memberOf', description: 'is'},
+ {title: 'func', description: null, name: 'isDate'},
+ {
+ title: 'example',
+ description:
+ 'isDate(new Date())\n //=> true\n isDate(Date.now())\n //=> false\n isDate(1)\n //=> false\n isDate(\'\')\n //=> false',
+ },
+ {
+ title: 'example',
+ description:
+ 'const e = {}\n eh[Symbol.toStringTag] = \'[Object Date]\'\n isDate(eh)\n //=> true',
+ },
+ {
+ title: 'example',
+ description: 'class Eh extends Date()\n isDate(new Eh())\n //=> true\n/',
+ },
+ ],
+}
diff --git a/_modules/lego-cli/plugins/docs/dox.js b/_modules/lego-cli/plugins/docs/dox.js
new file mode 100644
index 0000000..5a3d7b6
--- /dev/null
+++ b/_modules/lego-cli/plugins/docs/dox.js
@@ -0,0 +1,53 @@
+// const dox = require('dox')
+const dox = require('../../../../_modules/_dox')
+const log = require('fliplog')
+
+const docblock = `
+/**
+ * @classdesc this is to avoid circular requires
+ * because MergeChain & MethodChain extend this
+ * yet .method & .merge use those chains
+ *
+ * @since 4.0.0-alpha.1
+ * @inheritdoc
+ * @class ChainedMapBase
+ * @member ChainedMapBase
+ * @category Chainable
+ * @extends {Chainable}
+ * @type {Chainable}
+ *
+ * @types ChainedMapBase
+ * @tests ChainedMap
+ *
+ * @prop {Meta} meta
+ * @prop {Map} store
+ *
+ * {@link https://ponyfoo.com/articles/es6-maps-in-depth pony-map}
+ * {@link https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map mozilla-map}
+ * @see {@link pony-map}
+ * @see {@link mozilla-map}
+ *
+ * @see ChainedMap
+ * @see Chainable
+ * @see MergeChain
+ * @see MethodChain
+ * @see ChainedMap
+ *
+ */
+// function eh() {}
+`
+
+/**
+ *
+ */
+function doxPlugin() {
+ const files = [docblock]
+ files.forEach(file => {
+ const obj = dox.parseComments(file)
+ log.json({obj}).echo()
+ })
+
+ return this
+}
+
+doxPlugin()
diff --git a/_modules/lego-cli/plugins/docs/doxdox.js b/_modules/lego-cli/plugins/docs/doxdox.js
new file mode 100644
index 0000000..78ce5bd
--- /dev/null
+++ b/_modules/lego-cli/plugins/docs/doxdox.js
@@ -0,0 +1,70 @@
+module.exports = {
+ /**
+ * https://github.com/nhnent/tui.jsdoc-template
+ * @param {Array} files
+ * @return {AppCli} @chainable
+ */
+ doxdox(files) {
+ console.log(
+ 'had issue with requiring absolute before, but should be fixed in latest'
+ )
+ console.log(
+ `doxdox 'src/**/*.js' --layout markdown --output docs/doxdox.md`
+ )
+ return this
+ // jsdoc2md --config=jsdoc.json
+ // jsdoc2md --source src --config=jsdoc.json
+ // https://github.com/jsdoc3/jsdoc/blob/master/lib/jsdoc/env.js
+ // https://github.com/jsdoc3/jsdoc/blob/master/cli.js
+ // jsdoc src --recurse --template='node_modules/tui-jsdoc-template' --destination='docgen' --readme='README.md' ENV.conf.plugins="['node_modules/jsdoc-babel', 'plugins/markdown']"
+ // jsdoc --include 'src' --recurse --template='node_modules/tui-jsdoc-template' --destination='docgen' --readme='README.md'
+ //
+ // --template 'node_modules/tui-jsdoc-template'
+ // jsdoc src --recurse --destination 'docgen'
+ //
+ // require('fliplog').trackConsole();
+ //
+ // * @module jsdoc/opts/args
+ // * @requires jsdoc/opts/argparser
+ //
+ //
+ // ./jsdoc/jsdoc src --recurse --destination 'docgen' --plugins "node_modules/jsdoc-babel,plugins/markdown"
+ // node ./node_modules/jsdoc/jsdoc src --recurse --destination 'docgen' --plugins "node_modules/jsdoc-babel,node_modules/jsdoc/plugins/markdown.js"
+
+ // const doxdox = require('doxdox')
+ const doxdox = require('../../../nofundocs/doxdox')
+ files = this.docFiles(files)
+
+ log
+ .data({
+ files,
+ config: {
+ // parser: 'dox',
+ // layout: 'Markdown',
+ pkg: this.pkgjson,
+ },
+ })
+ .echo()
+
+ log.white('files: ').data(files).echo()
+
+ // stupid paths
+ doxdox
+ .parseInputs(files, {
+ // parser: 'dox',
+ // layout: 'markdown',
+ parser: require.resolve('doxdox-parser-dox').replace(process.cwd(), ''),
+ layout: require
+ .resolve('doxdox-plugin-markdown')
+ .replace(process.cwd(), ''),
+ pkg: this.pkgjson,
+ })
+ .then(content => {
+ log.cyan('writing docs').echo()
+ log.white('content: ' + content).echo()
+ File.src('./docs/docs.md', this.dir).setContent(content).write()
+ })
+
+ return this
+ },
+}
diff --git a/_modules/lego-cli/plugins/docs/esdoc.js b/_modules/lego-cli/plugins/docs/esdoc.js
new file mode 100644
index 0000000..93f2487
--- /dev/null
+++ b/_modules/lego-cli/plugins/docs/esdoc.js
@@ -0,0 +1,9 @@
+module.exports = {
+ /**
+ * https://github.com/esdoc/esdoc
+ * https://github.com/jsdoc3/jsdoc/issues/833
+ * http://stackoverflow.com/questions/25314979/documenting-side-effects-of-javascript-methods
+ * https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler#nosideeffects-modifies-thisarguments
+ */
+ esdoc() {},
+}
diff --git a/_modules/lego-cli/plugins/docs/flowdoc.js b/_modules/lego-cli/plugins/docs/flowdoc.js
new file mode 100644
index 0000000..8ce76e8
--- /dev/null
+++ b/_modules/lego-cli/plugins/docs/flowdoc.js
@@ -0,0 +1,25 @@
+module.exports = {
+ name: 'flowdocs',
+ /**
+ * @since 0.0.1
+ * https://github.com/Kegsay/flow-jsdoc
+ * @desc jsdocs with flow support
+ * @param {Array} files
+ * @return {AppCli} @chainable
+ */
+ flowdocs(files) {
+ files = this.docFiles(files)
+
+ const babel = require('babel-core')
+ files.forEach(file => {
+ const {code} = babel.transform('code', {
+ plugins: ['jsdoc'],
+ })
+ const content = code
+
+ log.cyan('writing docs').echo()
+ log.white('content: ' + content).data(file).echo()
+ })
+ return this
+ },
+}
diff --git a/_modules/lego-cli/plugins/docs/jsdoc.js b/_modules/lego-cli/plugins/docs/jsdoc.js
new file mode 100644
index 0000000..ee56dd8
--- /dev/null
+++ b/_modules/lego-cli/plugins/docs/jsdoc.js
@@ -0,0 +1,26 @@
+module.exports = {
+ /**
+ * @since 0.0.1
+ * @see https://github.com/nhnent/tui.jsdoc-template
+ * @param {Array} files
+ * @return {AppCli} @chainable
+ */
+ jsdocs(files) {
+ files = this.docFiles(files)
+
+ const jsdoc = require('jsdoc-api')
+ let jsdocOpts = this.getPkg().jsdoc || this.getPkg().jsdocs
+
+ if (!jsdocOpts && exists(resolve(this.dir, './jsdoc.js'))) {
+ jsdocOpts = require(resolve(this.dir, './jsdoc.js')) // eslint-disable-line
+ }
+ if (!jsdocOpts && exists(resolve(this.dir, './jsdoc.json'))) {
+ jsdocOpts = require(resolve(this.dir, './jsdoc.json')) // eslint-disable-line
+ }
+
+ jsdocOpts.files = files
+ log.data({jsdocOpts}).text('jsdoc opts').echo()
+ jsdoc.explainSync(jsdocOpts)
+ return this
+ },
+}
diff --git a/_modules/lego-cli/plugins/docs/jsdoc2md.js b/_modules/lego-cli/plugins/docs/jsdoc2md.js
new file mode 100644
index 0000000..d8956c7
--- /dev/null
+++ b/_modules/lego-cli/plugins/docs/jsdoc2md.js
@@ -0,0 +1,16 @@
+module.exports = {
+ /**
+ * @since 0.0.1
+ * @param {Array} pattern array of glob patterns
+ * @return {AppCli} @chainable
+ */
+ jsdoc2md(pattern = ['disted/**/*.js']) {
+ const {log} = this.deps()
+ const jsdoc2md = require('jsdoc-to-markdown')
+
+ const docs = jsdoc2md.renderSync({files: pattern})
+ log.quick(docs)
+
+ return this
+ },
+}
diff --git a/_modules/lego-cli/plugins/docs/jsdox.js b/_modules/lego-cli/plugins/docs/jsdox.js
new file mode 100644
index 0000000..a926251
--- /dev/null
+++ b/_modules/lego-cli/plugins/docs/jsdox.js
@@ -0,0 +1,17 @@
+module.exports = {
+ /**
+ * @tutorial http://jsdox.org/
+ * @param {Array} files
+ * @return {AppCli} @chainable
+ */
+ jsdox(files) {
+ const jsdox = require('jsdox')
+
+ files.forEach(file => {
+ // , templateDir, cb, fileCb
+ jsdox.generateForDir(file, this.getPkg().folders.docs || 'docgen')
+ })
+
+ return this
+ },
+}
diff --git a/_modules/lego-cli/plugins/docs/tsdoc.js b/_modules/lego-cli/plugins/docs/tsdoc.js
new file mode 100644
index 0000000..666075d
--- /dev/null
+++ b/_modules/lego-cli/plugins/docs/tsdoc.js
@@ -0,0 +1,13 @@
+module.exports = {
+ /**
+ * @TODO `typedoc --exclude 'loader/LoaderAPI.ts' --target es6 --excludeExternals --includeDeclarations --out tsdox src`
+ * @since 0.0.1
+ * @see https://www.npmjs.com/package/tsd-jsdoc
+ * @see http://ts2jsdoc.js.org/
+ * @param {Array} files
+ * @return {AppCli} @chainable
+ */
+ tsdocs(files) {
+ return this
+ },
+}
diff --git a/_modules/lego-cli/plugins/fs/copy.js b/_modules/lego-cli/plugins/fs/copy.js
new file mode 100644
index 0000000..b6c7131
--- /dev/null
+++ b/_modules/lego-cli/plugins/fs/copy.js
@@ -0,0 +1,36 @@
+module.exports = {
+ /* prettier-ignore */
+ copy(root = false) {
+ const script = this.deps().script
+
+ // @TODO: dist & root (does it ever need to be in dist except for buble?)
+ const scripts = script()
+ .add()
+ .bin('flow-remove-types')
+ .raw('src/')
+ .flag('pretty')
+ .flag('quiet')
+ .flag('all')
+ .flag('out-dir')
+ .arg('./dist')
+
+ if (root) {
+ scripts
+ .add()
+ .bin('flow-remove-types')
+ .raw('src/'
+ .flag('pretty')
+ .flag('quiet')
+ .flag('all')
+ .flag('out-dir')
+ .arg('./')
+ }
+
+ scripts.remember = {
+ start() {},
+ finish() {},
+ }
+
+ scripts.toString()
+ }
+}
diff --git a/_modules/lego-cli/plugins/fs/find.js b/_modules/lego-cli/plugins/fs/find.js
new file mode 100644
index 0000000..c2b0678
--- /dev/null
+++ b/_modules/lego-cli/plugins/fs/find.js
@@ -0,0 +1,35 @@
+module.exports = {
+ /**
+ * @since 0.0.1
+ * @desc finds docfiles using a glob
+ * @param {Array} pattern array of glob patterns
+ * @return {Array} file
+ */
+ docFiles(pattern = ['disted/**/*.js']) {
+ const {log, globby, find} = this.deps()
+
+ if (Array.isArray(pattern) === false) {
+ // pattern = ['disted/**/*.js']
+ pattern = [pattern]
+ }
+ log.blue('docs pattern').json({pattern, dir: this.dir}).echo(true)
+
+ const files = globby.sync(pattern, {
+ cwd: this.dir,
+ absolute: true,
+ })
+
+ return files
+ },
+
+ /**
+ * @since 0.0.1
+ * @param {Array} pattern array of glob patterns
+ * @return {AppCli} @chainable
+ */
+ docs(pattern = ['disted/**/*.js']) {
+ this.doxdox([pattern])
+ // this.docFiles(pattern)
+ return this
+ },
+}
diff --git a/_modules/lego-cli/plugins/generate/doc-to-assert.js b/_modules/lego-cli/plugins/generate/doc-to-assert.js
new file mode 100644
index 0000000..ef89066
--- /dev/null
+++ b/_modules/lego-cli/plugins/generate/doc-to-assert.js
@@ -0,0 +1 @@
+// https://www.npmjs.com/package/jsdoc-to-assert
diff --git a/_modules/lego-cli/plugins/generate/dojo.js b/_modules/lego-cli/plugins/generate/dojo.js
new file mode 100644
index 0000000..1b9c32e
--- /dev/null
+++ b/_modules/lego-cli/plugins/generate/dojo.js
@@ -0,0 +1 @@
+// https://github.com/dojo/meta
diff --git a/_modules/lego-cli/plugins/generate/skeleton.js b/_modules/lego-cli/plugins/generate/skeleton.js
new file mode 100644
index 0000000..35439c2
--- /dev/null
+++ b/_modules/lego-cli/plugins/generate/skeleton.js
@@ -0,0 +1,21 @@
+module.exports = {
+ /**
+ * @since 0.0.1
+ * @desc regenerate interactively
+ * @return {AppCLI} @chainable
+ */
+ skeleton() {
+ const gen = require('../interactive/interactive')
+ gen(this.dir)
+ return this
+ },
+
+ /**
+ * @since 0.0.1
+ * @param {string} dir
+ * @return {AppCLI} @chainable
+ */
+ // static init(dir) {
+ // return new AppCLI(dir)
+ // }
+}
diff --git a/_modules/lego-cli/plugins/lint/autofix.js b/_modules/lego-cli/plugins/lint/autofix.js
new file mode 100644
index 0000000..41eb25d
--- /dev/null
+++ b/_modules/lego-cli/plugins/lint/autofix.js
@@ -0,0 +1,104 @@
+const {resolve} = require('path')
+const {read, write, isDir} = require('flipfile')
+const globby = require('globby')
+const log = require('fliplog')
+
+class CLI {
+ constructor(dir) {
+ this.dir = dir
+ }
+
+ find(pattern = ['src/**/*.js', '!node_modules']) {
+ this.found = globby.sync(pattern, {
+ cwd: this.dir,
+ absolute: true,
+ })
+ return this.found
+ }
+
+ mapFiles() {
+ const mapped = this.found
+ .map(abs => {
+ if (isDir(abs)) return null
+ return {
+ source: read(abs),
+ filename: abs,
+ }
+ })
+ .filter(file => file)
+ .map(file => ({source: this.prettier(file), abs: file.abs}))
+ .map(file => this.eslint(file))
+ log.quick(mapped)
+ }
+
+ eslint(file, config = require('../../.eslintrc.js')) {
+ const {source, filename} = file
+ const eslint = require('eslint')
+ const {linter} = eslint
+
+ const colored = log.colored(source, 'cyan')
+ log.cyan('before\n').data(colored).echo() // "var foo = bar;"
+
+ const messages = linter.verify(source, config, {filename})
+ const code = linter.getSourceCode()
+
+ log.yellow('messages').data(messages).echo()
+ if (!code || !code.text) {
+ log.red('could not handle this file ').data({filename}).echo()
+ return source
+ }
+ // log.yellow('code').fmtobj(code).echo()
+ log.blue(code.text).echo() // "var foo = bar;"
+ return code.text
+ }
+
+ /**
+ * @since 0.0.1
+ * @tutorial https://github.com/prettier/prettier
+ * @param {string} code
+ * @param {Object} [config=null] prettier options
+ * @return {string} prettified output
+ */
+ prettier(file, config = null) {
+ const {filename, source} = file
+ const prettier = require('prettier')
+
+ return prettier.format(source, {
+ // Indent lines with tabs
+ useTabs: false,
+
+ // Fit code within this line limit
+ printWidth: 80,
+
+ // Number of spaces it should use per tab
+ tabWidth: 2,
+
+ // If true, will use single instead of double quotes
+ singleQuote: true,
+
+ // Controls the printing of trailing commas wherever possible. Valid options:
+ // "none" - No trailing commas
+ // "es5" - Trailing commas where valid in ES5 (objects, arrays, etc)
+ // "all" - Trailing commas wherever possible (function arguments)
+ trailingComma: 'es5',
+
+ // Controls the printing of spaces inside object literals
+ bracketSpacing: true,
+
+ // If true, puts the `>` of a multi-line jsx element at the end of
+ // the last line instead of being alone on the next line
+ jsxBracketSameLine: false,
+
+ // Which parser to use. Valid options are "flow" and "babylon"
+ parser: 'babylon',
+
+ // Whether to add a semicolon at the end of every line (semi: true),
+ // or only at the beginning of lines that may introduce ASI failures (semi: false)
+ semi: false,
+ })
+ }
+}
+
+const cli = new CLI(resolve('../../'))
+cli.find()
+cli.mapFiles()
diff --git a/_modules/lego-cli/plugins/lint/prettier.js b/_modules/lego-cli/plugins/lint/prettier.js
new file mode 100644
index 0000000..348b536
--- /dev/null
+++ b/_modules/lego-cli/plugins/lint/prettier.js
@@ -0,0 +1,46 @@
+module.exports = {
+ /**
+ * @since 0.0.1
+ * @tutorial https://github.com/prettier/prettier
+ * @param {string} code
+ * @param {Object} [config=null] prettier options
+ * @return {string} prettified output
+ */
+ prettier(code, config = null) {
+ const prettier = require('prettier')
+
+ return prettier.format(code, {
+ // Indent lines with tabs
+ useTabs: false,
+
+ // Fit code within this line limit
+ printWidth: 80,
+
+ // Number of spaces it should use per tab
+ tabWidth: 2,
+
+ // If true, will use single instead of double quotes
+ singleQuote: true,
+
+ // Controls the printing of trailing commas wherever possible. Valid options:
+ // "none" - No trailing commas
+ // "es5" - Trailing commas where valid in ES5 (objects, arrays, etc)
+ // "all" - Trailing commas wherever possible (function arguments)
+ trailingComma: 'es5',
+
+ // Controls the printing of spaces inside object literals
+ bracketSpacing: true,
+
+ // If true, puts the `>` of a multi-line jsx element at the end of
+ // the last line instead of being alone on the next line
+ jsxBracketSameLine: false,
+
+ // Which parser to use. Valid options are "flow" and "babylon"
+ parser: 'babylon',
+
+ // Whether to add a semicolon at the end of every line (semi: true),
+ // or only at the beginning of lines that may introduce ASI failures (semi: false)
+ semi: false,
+ })
+ },
+}
diff --git a/_modules/lego-cli/plugins/make/Makefile.1 b/_modules/lego-cli/plugins/make/Makefile.1
new file mode 100644
index 0000000..31e74c4
--- /dev/null
+++ b/_modules/lego-cli/plugins/make/Makefile.1
@@ -0,0 +1,17 @@
+GITBOOK = node_modules/.bin/gitbook
+JSDOC = node_modules/.bin/jsdoc
+LESS = node_modules/.bin/lessc
+
+
+JSDOC_FILES := $(shell find jsdoc -type f | sort)
+LESS_FILES := $(shell find less -name '*.less' | sort)
+
+docs/%: $(VERSION)/docs/%
+ mkdir -p '$(@D)'
+ cp '$<' '$@'
+
+.PHONY: gitbook
+gitbook: check-version
+ $(GITBOOK) build manual './manual'
+ find './manual' -name '*.html' -print0 \
+ | xargs -0 perl -p -i -e 's/ data-revision="[^"]*"//g'
diff --git a/_modules/lego-cli/plugins/minify/butternut.js b/_modules/lego-cli/plugins/minify/butternut.js
new file mode 100644
index 0000000..f1bcba3
--- /dev/null
+++ b/_modules/lego-cli/plugins/minify/butternut.js
@@ -0,0 +1 @@
+// https://github.com/Rich-Harris/butternut
diff --git a/_modules/lego-cli/plugins/scripts/argv.js b/_modules/lego-cli/plugins/scripts/argv.js
new file mode 100644
index 0000000..38ab238
--- /dev/null
+++ b/_modules/lego-cli/plugins/scripts/argv.js
@@ -0,0 +1,52 @@
+const argvs = fwf(process.argv.slice(2))
+
+/**
+ * http://blog.millermedeiros.com/inline-docs/
+ * http://dailyjs.com/post/framework-part-46
+ * https://documentjs.com/docs/index.html (too old)
+ *
+ * @see https://github.com/yeoman/generator/blob/master/jsdoc.json
+ * @desc takes in argv, calls method on CLI
+ * @param {AppCli} cli
+ * @return {void}
+ * @type {Function}
+ */
+function handle(cli) {
+ log.registerCatch()
+
+ delete argvs._
+
+ const argv = Object.values(argvs)
+ const argk = Object.keys(argvs)
+
+ log.emoji('flag').cyan('argv/flags:').data(argvs).echo()
+
+ argk.forEach((method, i) => {
+ const val = argv[i]
+ log.emoji('phone').blue('cli: ' + method).data(val).echo(true)
+
+ if (cli[method]) {
+ cli[method](val, argvs)
+ }
+ else {
+ log.emoji('find').blue('no method for: ' + method).data(val).echo(true)
+ }
+ })
+}
+
+
+
+
+// --- docs ---
+
+
+
+
+/**
+ * @since 0.0.1
+ * @return {AppCli} @chainable
+ */
+handle() {
+ handle(this)
+ return this
+}
diff --git a/_modules/lego-cli/plugins/scripts/cmd.js b/_modules/lego-cli/plugins/scripts/cmd.js
new file mode 100644
index 0000000..0aaea89
--- /dev/null
+++ b/_modules/lego-cli/plugins/scripts/cmd.js
@@ -0,0 +1,11 @@
+module.exports = {
+ /**
+ * @since 0.0.1
+ * @param {ChainedMap | *} parent
+ */
+ constructor(parent) {
+ super(parent)
+
+ this.scriptChain = () => new Script()
+ },
+}
diff --git a/_modules/lego-cli/plugins/scripts/npm.js b/_modules/lego-cli/plugins/scripts/npm.js
new file mode 100644
index 0000000..378759a
--- /dev/null
+++ b/_modules/lego-cli/plugins/scripts/npm.js
@@ -0,0 +1,15 @@
+module.exports = {
+ /**
+ * @since 0.0.1
+ * @param {any} names npm scripts to run
+ * @return {CLI} @chainable
+ */
+ npm(names = null) {
+ const scripts = this.scriptChain().debug(false)
+
+ toarr(names).forEach(name => scripts.add().npm(name))
+ scripts.run()
+
+ return this
+ },
+}
diff --git a/_modules/lego-cli/plugins/scripts/open.js b/_modules/lego-cli/plugins/scripts/open.js
new file mode 100644
index 0000000..6d29164
--- /dev/null
+++ b/_modules/lego-cli/plugins/scripts/open.js
@@ -0,0 +1,6 @@
+module.exports = {
+ // https://github.com/sindresorhus/open-editor
+ openFile(files, editor = 'atom') {
+ require('open-editor')(files)
+ },
+}
diff --git a/_modules/lego-cli/plugins/scripts/pkg.js b/_modules/lego-cli/plugins/scripts/pkg.js
new file mode 100644
index 0000000..ad07582
--- /dev/null
+++ b/_modules/lego-cli/plugins/scripts/pkg.js
@@ -0,0 +1,33 @@
+module.exports = {
+ /**
+ * @since 0.0.1
+ * @desc requires pkgjson using this.dir
+ * @return {AppCLI} @chainable
+ */
+ setup() {
+ const pkgPath = resolve(this.dir, './package.json')
+
+ log.green('pkg: ').data({pkgPath, dir: this.dir}).echo(this.get('debug'))
+
+ // eslint-disable-next-line
+ this.pkgjson = require(pkgPath)
+
+ return this
+ },
+
+ /**
+ * @protected
+ * @since 0.0.1
+ * @see this.setup
+ * @desc regenerate interactively
+ * @return {AppCLI} @chainable
+ */
+ getPkg() {
+ if (!this.pkgjson) this.setup()
+
+ // defaults
+ if (!this.pkgjson) this.pkgjson.folders = {}
+
+ return this.pkgjson
+ },
+}
diff --git a/_modules/lego-cli/plugins/scripts/test.js b/_modules/lego-cli/plugins/scripts/test.js
new file mode 100644
index 0000000..f9c4a0c
--- /dev/null
+++ b/_modules/lego-cli/plugins/scripts/test.js
@@ -0,0 +1,6 @@
+module.exports = {
+ test(built = false) {
+ return script('ava', !built ? '--verbose' : 'test-dist/built.js')
+ // return script('test')
+ },
+}
diff --git a/_modules/lego-cli/plugins/scripts/yarn.js b/_modules/lego-cli/plugins/scripts/yarn.js
new file mode 100644
index 0000000..ac20470
--- /dev/null
+++ b/_modules/lego-cli/plugins/scripts/yarn.js
@@ -0,0 +1 @@
+console.log('todo')
diff --git a/build/README.md b/build/README.md
new file mode 100644
index 0000000..d92e6c0
--- /dev/null
+++ b/build/README.md
@@ -0,0 +1,19 @@
+ https://github.com/facebook/react/tree/master/scripts/rollup
+https://github.com/ramda/ramda/blob/master/scripts/build
+
+# two options:
+1. copy same folder structure
+2. custom copy, folders do not matter
+
+## copy same
+... .copy ha
+
+## custom copy
+1. find
+2. store metadata
+3. transform -
+ if function, use that,
+ if string,
+ if relative & isFilename, resolve filename
+ else if relative
+ else if absolute, use instead
diff --git a/build/cli.js b/build/cli.js
index 8a2eb45..bf9acbf 100644
--- a/build/cli.js
+++ b/build/cli.js
@@ -20,17 +20,22 @@ const fwf = require('funwithflags')
const Script = require('script-chain')
const log = require('fliplog')
const {read, write} = require('flipfile')
-const {del} = require('./util')
+const {del, _res} = require('./util')
// const docdown = require('docdown')
const {stripRollup} = require('./plugins/ast')
const find = require('chain-able-find')
+const {replace} = require('../src')
+// @TODO export more on /exports.js
+const dot = require('../src/deps/dot')
+const traverse = require('../src/deps/traverse')
+const uniq = require('../src/deps/array/uniq')
-const res = rel => resolve(__dirname, rel)
-const resRoot = rel => resolve(res('../'), rel)
+const res = _res(__dirname)
+const resRoot = _res('../')
// https://github.com/chalk/ansi-regex/blob/master/index.js
const ansiRegex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]/g
-const stripAnsi = str => str.replace(ansiRegex, '')
+const stripAnsi = replace(ansiRegex, '')
const timer = log.fliptime()
timer.start('cli')
@@ -151,9 +156,6 @@ const testFiles = find
.results()
const toRel = filepath => filepath.replace(root, '').replace(entry, '')
-const dot = require('../src/deps/dot')
-const traverse = require('../src/deps/traverse')
-const uniq = require('../src/deps/array/uniq')
const repoPath = 'https://github.com/fluents/chain-able/blob/master'
const repoDocPath =
diff --git a/build/easy-npm-files.js b/build/easy-npm-files.js
new file mode 100644
index 0000000..421ef97
--- /dev/null
+++ b/build/easy-npm-files.js
@@ -0,0 +1,510 @@
+// const ffs = require('../_modules/fluent-fs')
+const log = require('fliplog')
+const jetpack = require('fs-jetpack')
+const ConfigStore = require('configstore')
+const find = require('chain-able-find')
+const {_res} = require('./util')
+const {read, write} = require('flipfile')
+const {
+ curry,
+ not,
+ includes,
+ includesCount,
+ camelCase,
+ replace,
+ first,
+ isMatch,
+ isString,
+ isTrue,
+ isFunction,
+ isArray,
+ isEmpty,
+ remove,
+ reverse,
+ pipe,
+ toMatcher,
+ construct,
+ invoke,
+ hasOwnProperty,
+ toArr,
+ escapeDot,
+ includesAny,
+ includesAll,
+ all,
+ and,
+ firstToUpperCase,
+} = require('../index.all')
+const {
+ forEach,
+ wrapForEach,
+ replaceLast,
+ isNegative,
+ // find
+ findIndexAt,
+ findMatching,
+ findKey,
+ findValue,
+ findValues,
+ findFirstMatch,
+ // remap
+ remapKeys,
+ remapValues,
+ remapToMatch,
+} = require('./util/__fixme')
+const {
+ getFolderName, getFileName, getFolderAndFileName,
+} = require('./util/_filefolder')
+
+const has = x => includes('_', x)
+
+// includesAny('_', ['/', 'require'])
+// const hasRequire = and(includes('/'), includes('require'))
+// const hasRequire = and(includes('/'), includes('require'))
+const hasRequire = and(has('/'), has('require'))
+
+// log.quick(hasRequire, hasRequire(`require('./eh')`))
+// log.quick([hasRequire('/require'), hasRequire('require'), hasRequire('/'), hasRequire('/eh')])
+
+// SO EASY
+// ....... or ....... way better ....... just replace any `require('./')`
+
+
+// NOW
+// !!!!! SHOULD NOT TRANSFORM FILENAMES WITH THE FOLDERNAME === FILENAME
+// E.G. UTIL/UTIL, IS/IS!
+// ------- ugh forgot
+//
+// 0. [ ] !!!!!!!!! NEED TO READ CODE, AND CHANGE ALL KNOWN PATHS TO NEW OUTPUT
+// READ CONTENT
+// ITERATE THROUGH ABSOLUTE FILENAMES
+// USE IS_MATCH
+// E.G. ./deps/is/undefined
+// MATCH AGAINST FILE, PERMUTATE / IF NEEDED
+// RESOLVE TO ONE OF THE OUTPUT FILENAMES
+//
+//
+//
+// 1. [x] TOROOT
+// 2. [x] PUT IN KEY-VAL AS [FROM]: TO
+// 3. [x] SAVE FILE WITH FROM-TO AS .JSON
+// 4. [ ] READ .JSON
+// 5. [ ] DELETE FILES (IN CLI.JS)
+// 6. [x] DO A TEST RUN ON A SUBFOLDER
+// 7. [ ] !!! add aliases, so it gets copied to multiple output names
+
+// - [ ] could make docs expandable sections
+// - [ ] fix fuzzy search -> the `h2`s are always shown
+
+const entry = process.cwd()
+const cwd = process.cwd()
+const cwdRes = _res(cwd)
+const res = _res(__dirname)
+
+// @HACK @TODO just emulating
+// const resRoot = _res(res('../'))
+const resRoot = _res(res('./FAKEROOT'))
+
+// @TODO pipe?
+const src = cwdRes('./src')
+
+const defaultCopied = { /* ['absFrom']: 'absTo' */ }
+const store = new ConfigStore('easy-exports', {copied: defaultCopied})
+const fromToFilePath = res('./fromTo.json')
+
+const isRel = has('./')
+const isAbs = has('/Users')
+const isSrc = has('/src/')
+
+const toRoot = x => {
+ // @TODO relative-to
+ if (isSrc(x)) return resRoot('./' + x.split('/src/').pop())
+ else if (isAbs(x)) return x
+ else if (isRel(x)) return resRoot(x)
+ else return resRoot('./' + x)
+}
+
+// only copying .js ['!*package.json', '!*.DS_Store']
+const isNotIndex = not(has('index.js'))
+const isIzzez = has('/is/')
+
+const remapKeysToArr = remapKeys(toArr)
+const remapValuesToArr = remapValues(toArr)
+
+// when we have files with the same name, .onConflict, log?
+const found = find
+ .init()
+ .recursive(true)
+ .ignoreDirs(['ignant', 'node_modules'])
+ .abs(true)
+ .sync(true)
+ // all folders have a filename with the same name as the folder
+ // if they did not, we could also rename all index.js files
+ // , '!*index.js'
+ .matchFiles(['**/*.js'])
+ .find(src)
+ .results()
+ .filter(isNotIndex)
+ // .map(file => {
+ // return {
+ // og: file,
+ // remapped: file.replace(regex, dest),
+ // rel: file.replace(regex, '.'),
+ // }
+ // })
+ // .filter(file => {
+ // if (exists(file.remapped)) return false
+ //
+ // log.dim('copying:').data(file).echo(this.parent.debug)
+ // copied.push(file.rel)
+ //
+ // return true
+ // })
+ // .filter(uniq)
+
+
+const filesObj = {}
+const founds = wrapForEach(found)
+const hasDupeFileName = abs => {
+ // prop, pipe, lense?
+ const rel = filesObj[abs]
+ const rels = Object.values(filesObj)
+ const count = includesCount(rels, rel)
+ // console.log({[rel]: count})
+ if (count >= 2) {
+ console.log(count, abs)
+ }
+ return count >= 2
+}
+
+const transformFolderAndFileCamel = (abs, folder, filename) => {
+ const folderFile = folder + '/' + filename
+ const transformed = camelCase(folder + '_' + filename) + '.js'
+ return replace(folderFile, transformed, abs)
+}
+
+
+// @TODO either replaceLast, or toRel then replace
+const transformIzzes = (abs, folder, filename) => {
+ const fileName = getFileName(abs)
+ const transformedFileName = camelCase('is_' + fileName)
+ // @TODO: replaceLast (could .reverse.replace.reverse)
+ let transformedAbs = replaceLast(fileName, transformedFileName, abs)
+ return transformedAbs
+}
+
+// (x.includes('/deps/') ? x.split('/deps/').pop() : x.split('/src/').pop())
+// pipe(replace('/src/', '/'), replace('/deps/', '/'))
+const transformToFileName = x => x.split('/').pop()
+
+const transformSymbol = (abs, folder, fileName) => {
+ const beginning = abs.split(`/${folder}/`).shift()
+ return beginning + '/Symbol.' + firstToUpperCase(fileName) + '.js'
+}
+
+// @TODO !!!!!!!!!!!!!!!!!!! TRANSFORM, THIS-AS-A-CHAIN
+// key to matcher
+const map = {
+ // 'eh': 'eh',
+ '/conditional/all': 'all',
+ '/to/*.js': transformFolderAndFileCamel,
+ '/is/*.js': transformIzzes,
+ '/symbols/*.js': transformSymbol,
+ '*': transformToFileName,
+}
+
+// log.quick(findMatching('src/conditional/all'))
+
+// const firstIsFunction = pipe(first, isFunction)
+const firstIsFunction = x => isFunction(x[0])
+
+// (['.', '-', '_']).map(has)
+const isNotCamelCase = x =>
+ x.includes('.') || x.includes('-') || x.includes('_')
+
+const fromTo = {}
+
+const doubleExtHACK = has('.js.js')
+
+// isLast, isFirst ? kind of is .before .after if it's only flat...
+let remapped = founds
+ .forEach(abs => {
+ filesObj[abs] = getFileName(abs)
+ })
+ .map(abs => {
+ // start remap
+ let remappedAbs = fromTo[abs] || []
+ fromTo[abs] = remappedAbs
+ const alreadyHas = includes(remappedAbs)
+ const add = x => {
+ toArr(x).forEach(value => {
+ const rootValue = toRoot(value)
+ if (alreadyHas(rootValue)) return
+ // remappedAbs.push(value)
+ remappedAbs.push(rootValue)
+ })
+ remappedAbs.forEach((value, index) => {
+ remappedAbs[index] = toRoot(value)
+ if (doubleExtHACK(remappedAbs[index])) {
+ remappedAbs[index] = remappedAbs[index].split('.js').shift() + '.js'
+ }
+ })
+
+ // if (isNotCamelCase(x)) add(camelCase(escapeDot(x)))
+ }
+
+ // find if we need to remap and how we will do so
+ const matchFound = findMatching(map, abs)
+ if (matchFound) {
+ let [key, value, keys] = matchFound
+
+ // console.log('found matching', {abs, key, value, keys})
+ let [folderName, fileName] = getFolderAndFileName(abs)
+
+ if (isArray(value) && !isEmpty(value)) {
+ if (value.length > 1) {
+ value = value.map(x => (isString(x) ? replace(key, value) : x))
+
+ // @TODO was pipe, need best name
+ // what's the name for this? reducing with each value updating?
+ let transformed = abs
+ value.forEach(val => {
+ [folderName, fileName] = getFolderAndFileName(abs)
+ transformed = val(transformed, folderName, fileName)
+ })
+
+ add(transformed)
+ }
+ else if (firstIsFunction(value)) {
+ const transformed = value[0](abs, folderName, fileName)
+ add(transformed)
+ }
+ else {
+ console.log('first is not a function', {value: value[0]})
+ }
+ }
+ else {
+ const transformed = replace(key, value, abs)
+ add(transformed)
+ }
+ }
+ else if (isIzzez(abs)) {
+ const transformed = transformIzzes(abs)
+ add(transformed)
+ }
+ // @TODO default the one to use
+ else if (hasDupeFileName(abs)) {
+ const folderName = getFolderName(abs)
+ const fileName = getFileName(abs)
+ const folder_file = folderName + '_' + fileName
+ const folderWithSlashes = '/' + folderName + '/'
+ const beforeFolder = abs.split(folderWithSlashes).shift()
+ let transformed = beforeFolder + camelCase(folder_file)
+
+ // if (!transformedAbs.endsWith('js')) transformedAbs += '.js'
+ // console.log('hasDupe', {transformed})
+
+ add(transformed)
+ }
+ else {
+ add(abs)
+ }
+
+ const fileName = getFileName(abs)
+
+ // @TODO all snake & all camel
+ if (isNotCamelCase(fileName)) {
+ const beginning = abs.split(`/${fileName}`).shift()
+ let transformed = beginning + '/' + camelCase(fileName)
+ // let transformed = replace(fileName, camelCase(fileName), abs)
+ // log.data({transformed, camel: camelCase(fileName), fileName, abs}).echo()
+ add(transformed)
+ }
+
+ if (!hasDupeFileName(abs)) {
+ // add(abs) <- keeps nested folders which is meh
+ add(transformToFileName(abs))
+
+ const [folderName] = getFolderAndFileName(abs)
+ const [alpha, omega] = abs.split(folderName)
+ const transformed = alpha + omega
+ // add(transformed)
+ }
+
+ return remappedAbs
+ // return abs
+ })
+
+
+const fromToJSON = JSON.stringify(fromTo, null, 2)
+write(fromToFilePath, fromToJSON)
+
+// use when needed
+// const fromToRead = read.json(fromToFilePath)
+// log.quick(fromTo)
+
+// would just be .toMatcher...
+// const __map = (obj, transformer) => obj.map(transformer)
+// const _map = curry(2, __map)
+// const replaceAll = curry(3, (patterns, replacements, str) => {
+// _map(patterns)
+// }
+
+const remapRequire = contents => contents
+ .split('\n')
+ .map(line => {
+ // line.includes('/') && line.includes('require')
+ if (!hasRequire(line)) return line
+
+ const parts = line.split('=')
+ const name = parts.shift().trim()
+
+ // remove all initial dots, and the first slash
+ const sanitizeRequire = x => x.replace(/[.]/g, '').replace('/', '')
+
+ const requireReplacer = (match, p1, offset, string) => {
+ match = sanitizeRequire(match)
+
+ const findFrom = () => {
+ return Object.keys(fromTo).filter(x => {
+ const matches =
+ isMatch(match, x) ||
+ isMatch(x, match) ||
+ x.includes(match) ||
+ match.includes(x)
+
+ // if (!matches) log.quick(({x, match, matches}))
+
+ return matches
+ })
+ }
+
+ const requireFoundInFromTo = findFrom()
+ // log.data({requireFoundInFromTo}).echo()
+ return requireFoundInFromTo
+ // findMatching(map, match)
+ // return match
+ // p1 is nondigits, p2 digits, and p3 non-alphanumerics
+ // return [p1, p2, p3].join(' - ')
+ }
+
+ if (parts.length === 0) return line
+
+ const ogRequire = parts.pop().trim()
+
+ // @TODO right here can use a new name matching the parts, bingo bango bongo
+ const remappedRequire = ogRequire
+ .replace(`require('`, '')
+ .replace(')', '')
+ .replace(`'`, '')
+ .replace(/.*/, requireReplacer)
+ .split('/')
+ .pop()
+
+ const comment = `/* remapped from ${ogRequire} */`
+ return `${name} = require('./${remappedRequire}') ${comment}`
+ })
+ .join('\n')
+
+
+// @TODO file-chain better here
+Object.keys(fromTo).forEach(key => {
+ const fileNames = fromTo[key]
+
+ let contents = read(key)
+ contents = `/* FROM-TO: ${key.split('/chain-able/').pop()} */\n${contents}`
+ contents = remapRequire(contents)
+
+ log.bold(key).data(fileNames).echo()
+
+ fileNames.forEach(fileName => {
+ if (fileName.includes('/src/')) {
+ const bad = new Error(fileName)
+ log.red('bad filename').data(bad).echo()
+ return
+ }
+
+ // log.bold(fileName).echo()
+ // log.green(contents).echo()
+ // log.underline('__________ \n').echo()
+
+ // log.data({[fileName]: contents}).echo()
+ write(fileName, contents)
+ })
+})
+
+// remapped = remapValuesToArr(remapped)
+// remapped.forEach(transformed => log.bold(transformed).echo())
+// log.verbose(200).data({entry}).exit()
+
+
+// const from = 'foo_1'
+// const to = 'foo_final'
+//
+// // Copies files from folder foo_1 to foo_final, but overwrites in
+// // foo_final only files which are newer in foo_1.
+// jetpack.copy(from, to, {
+// overwrite: (srcInspectData, destInspectData) => {
+// console.log('had conflict')
+// return false
+// // return srcInspectData.modifyTime > destInspectData.modifyTime;
+// }
+// });
+
+// find.up
+// const res = _res(__dirname)
+// const resRoot = _res(entry)
+
+//
+//
+// ----- restructure for copying all to flat! ---
+//
+// // just have keyval map like I was doing with emoji
+// //
+// /// helpful for mapping all `toarr`
+// // MapValues of object
+// // MapKeys
+// // MapObjOrArr
+// //
+// // have each value be a string[], or Transformer which returns say
+// // function transformIs(folder, filename) {
+// // return folder + ucFirst(filename)
+// // }
+// // or false to ignore
+//
+// // string to upper how to do best?
+// // map string?
+// // finish !!!!!! chain-able-fs with data chains
+// //
+// const firstToUpper = str => str.charAt(0).toUpperCase() + str.slice(1)
+//
+// // treeshake should also add an index with EVERY FILE
+// // put as es6 exports.name
+// // then easy to remove unused exports
+//
+// // finish proxy example
+//
+// -------------------
+//
+// add test to `require` each file just for errors sake
+// add
+//
+//
+// -------------------
+//
+// perf
+// - argumentor
+// - gc
+// - obj-pooler?
+//
+//
+// arr/
+// - to-arr || to/arr -> **copy-as('to-arr)**
+// - concat
+//
+// // can also be `coerce`
+// to/
+//
+// traverse/
+// - index
+// - Traverse
+// - traversers
diff --git a/build/plugins/comments.js b/build/plugins/comments.js
new file mode 100644
index 0000000..65c3017
--- /dev/null
+++ b/build/plugins/comments.js
@@ -0,0 +1,22 @@
+const log = require('fliplog')
+
+function commentsPlugin(options = {}) {
+ return {
+ name: 'comments',
+ transform(code, id) {
+ if (id.includes('index.js')) return null
+ const parts = id.split('chain-able/')
+ if (parts.length <= 1) return null
+
+
+ const filename = parts.pop() || 'missing-filename'
+ const filenameComment = '/* ___filename___: ' + filename + ' */\n'
+ if (code.includes(filenameComment)) return null
+ console.log({filename})
+
+ return filenameComment + code
+ },
+ }
+}
+
+module.exports = options => commentsPlugin(options)
diff --git a/build/plugins/index.js b/build/plugins/index.js
index 1c9a390..3a1713c 100644
--- a/build/plugins/index.js
+++ b/build/plugins/index.js
@@ -5,6 +5,7 @@ const optimizejs = require('./optimizejs')
const filesize = require('./filesize')
const replace = require('./replace')
const falafelPlugin = require('./ast')
+const commentsPlugin = require('./comments')
module.exports = (version, options) => {
if (options.env === 'development') {
@@ -17,6 +18,8 @@ module.exports = (version, options) => {
const plugins = []
const add = plugin => plugins.push(plugin)
+ add(commentsPlugin(options))
+
if (options.falafel) add(falafelPlugin(options))
if (options.replace) add(replace(options))
diff --git a/build/plugins/uglify.js b/build/plugins/uglify.js
index ad3d4e7..6fecba5 100644
--- a/build/plugins/uglify.js
+++ b/build/plugins/uglify.js
@@ -5,7 +5,11 @@ const {minify} = require('uglify-es')
// https://github.com/mishoo/UglifyJS2#minify-options-structure
// should mangle...
module.exports = options => {
- const mangles = options.mangles === undefined ? true : options.mangles
+ let mangles = options.mangles === undefined ? true : options.mangles
+
+ // @TODO hard to keep it mangling top-level, so ugly with 1 letter fns
+ // mangles = false
+
const beautify = !!options.beautify
const uglifyOptions = {
@@ -49,10 +53,12 @@ module.exports = options => {
// @TODO:
// pure_funcs: true, side_effects: false,
- keep_fargs: beautify,
+
+ // @NOTE we need this one for fp/arity
+ keep_fargs: true,
+
keep_fnames: beautify, // for now
- // keep_fargs: false,
// keep_fnames: false, // for now
passes: 10,
},
diff --git a/build/size-over-time.txt b/build/size-over-time.txt
index 9cad971..11ee264 100644
--- a/build/size-over-time.txt
+++ b/build/size-over-time.txt
@@ -834,3 +834,243 @@ $ gzip-size "dists/umd/index.js" "--raw"
Done in 0.68s.
2017:15:07/12/17:19:15:45
---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+8774
+Done in 0.53s.
+2017:30:07/13/17:00:30:48
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+2357 <- traverser only (along with deps) (before any size optimization)
+Done in 0.56s.
+2017:55:07/13/17:03:55:41
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+2080 <- original traverse-js size (along with deps) (with all deopts)
+Done in 0.53s.
+2017:59:07/13/17:03:59:39
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+8780
+Done in 0.54s.
+2017:01:07/13/17:04:01:49
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+8835
+Done in 0.51s.
+2017:59:07/15/17:01:59:43
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9162
+Done in 0.61s.
+2017:34:07/16/17:19:34:30
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9161
+Done in 0.47s.
+2017:14:07/16/17:20:14:21
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9161
+Done in 0.55s.
+2017:51:07/17/17:20:51:34
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9161
+Done in 0.59s.
+2017:58:07/17/17:20:58:46
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9161
+Done in 0.56s.
+2017:23:07/17/17:21:23:44
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9161
+Done in 0.61s.
+2017:02:07/17/17:22:02:19
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9161
+Done in 0.58s.
+2017:48:07/18/17:00:48:19
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9161
+Done in 0.54s.
+2017:50:07/18/17:00:50:01
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9161
+Done in 0.55s.
+2017:50:07/18/17:00:50:43
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9161
+Done in 0.54s.
+2017:51:07/18/17:00:51:39
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9161
+Done in 0.54s.
+2017:52:07/18/17:00:52:12
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9161
+Done in 0.58s.
+2017:53:07/18/17:00:53:59
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9161
+Done in 0.54s.
+2017:54:07/18/17:00:54:51
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9161
+Done in 0.55s.
+2017:55:07/18/17:00:55:15
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9161
+Done in 0.58s.
+2017:55:07/18/17:00:55:52
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9161
+Done in 0.55s.
+2017:56:07/18/17:00:56:24
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9161
+Done in 0.70s.
+2017:57:07/18/17:00:57:27
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+12612 <- not uglified top level
+Done in 0.53s.
+2017:00:07/18/17:01:00:43
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9183 <- before trying curry in tryCatch
+Done in 0.49s.
+2017:27:07/18/17:15:27:26
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9219 <- with curry, sad
+Done in 0.57s.
+2017:28:07/18/17:15:28:24
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9216 <- currying tryCatch, so minor, why bigger for the other one? because they are both curried? sheesh
+Done in 0.56s.
+2017:30:07/18/17:15:30:38
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9371
+Done in 0.75s.
+2017:40:07/18/17:17:40:52
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9379
+Done in 0.62s.
+2017:34:07/19/17:19:34:43
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9379
+Done in 0.52s.
+2017:20:07/19/17:20:20:37
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9261
+Done in 0.56s.
+2017:55:07/19/17:21:55:07
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9303 <- refactor .equals
+Done in 0.58s.
+2017:36:07/20/17:02:36:25
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9308
+Done in 0.69s.
+2017:43:07/20/17:02:43:10
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9308
+Done in 0.54s.
+2017:54:07/20/17:02:54:35
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9308
+Done in 0.58s.
+2017:58:07/20/17:02:58:53
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9161 <- minor easy util usage (props in gc, remove if > 100 parents in traverse, remove isArray && !isArray since it is covered already, )
+Done in 0.54s.
+2017:21:07/20/17:03:21:48
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9153 <- more minor utils (or in str or num), rename .iteratee to .node, ternary in transform.remap
+Done in 0.62s.
+2017:12:07/20/17:18:12:51
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9153
+Done in 0.53s.
+2017:20:07/20/17:18:20:28
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9153
+Done in 0.59s.
+2017:24:07/20/17:18:24:16
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9153
+Done in 0.58s.
+2017:32:07/20/17:18:32:48
+---
+yarn run v0.27.5
+$ gzip-size "dists/umd/index.js" "--raw"
+9269
+Done in 0.54s.
+2017:38:07/22/17:03:38:19
+---
diff --git a/build/util/__fixme.js b/build/util/__fixme.js
new file mode 100644
index 0000000..22d1728
--- /dev/null
+++ b/build/util/__fixme.js
@@ -0,0 +1,203 @@
+const {
+ curry,
+ not,
+ includes,
+ includesCount,
+ camelCase,
+ replace,
+ first,
+ isMatch,
+ isString,
+ isTrue,
+ isFunction,
+ isArray,
+ isEmpty,
+ remove,
+ reverse,
+ pipe,
+ toMatcher,
+ construct,
+ invoke,
+ hasOwnProperty,
+ keysObjOrArray,
+} = require('../../index.all')
+
+const isNegative = x => x < 0
+
+// NEED TO HAVE .LAST_INDEX_OF CAN USE COUNT, SAME WAY, AND CPY FROM LODASH | RAMDA
+
+// whether to return the key along with value...
+// first, last, nth
+const _findAt = curry(3, (haystack, predicate, position) => {
+ let findings = []
+
+ // @TODO NOT SOLID
+ const hay = isArray(haystack) ? haystack : haystack.split(predicate)
+
+ // loop obj ugh
+ hay.forEach((needle, key) => {
+ if (isMatch(needle, predicate)) findings.push(needle)
+ // if (predicate(needle, key)) findings.push(needle)
+ })
+
+ if (isEmpty(findings)) return null
+ else if (isNegative(position)) return findings[findings.length - position]
+ else return findings[position]
+})
+
+// findIndexAt
+const findIndexAt = curry(3, (haystack, predicate, position) => {
+ const finding = _findAt(haystack, predicate, position)
+ return haystack.indexOf(finding)
+})
+
+// const replaceLast = findAt('_', '_', -1)
+// const replaceLast = (pattern, replacement, str) =>
+// pipe(reverse, replace(pattern, replacement), reverse)(str)
+
+const replaceLast = (pattern, replacement, str) => {
+ // const index = findIndexAt(str, pattern, -1)
+
+ // 1
+ // const pieces = str.split(pattern)
+ // const replaced = pieces.join(pattern)
+
+ // 2
+ const index = str.lastIndexOf(pattern)
+ const pre = str.substring(0, index)
+ const second = str.substring(index)
+ const replaced = pre + second.replace(pattern, replacement)
+ // console.log({index, pre, second, pattern, replaced})
+
+ // 3
+ // const strs = str.split(pattern)
+ // let replaced = ''
+ // strs.forEach((s, index) => {
+ // if (index === strs.length) replaced += s.replace(pattern)
+ // else replaced += s
+ // })
+
+ // const replaced = str.replace(toMatcher(pattern), replacement)
+
+ return replaced
+}
+
+// @TODO could also use for in
+const forOwn = curry(2, (array, iteratee) => {
+ const nodeIsArray = isArray(array)
+ let keys = keysObjOrArray(array)
+ let index = 0
+ while (index++ < keys.length - 1) {
+ const key = nodeIsArray ? keys[index] : keys[keys[index]]
+ iteratee(keys[index], key, index, array)
+ }
+ return array
+})
+
+// forEachChain
+const forEach = curry(2, (array, iteratee) => {
+ array.forEach(iteratee)
+ return array
+})
+const wrapForEach = (array) => {
+ return {forEach: forEach(array)}
+}
+
+
+// @TODO pure-function side-effect-free to return say an array
+// with them knowing the original index
+//
+// @TODO need to remap Map too... ugh
+const _remapKeys = (transform, obj, removeOld = true) => {
+ Object.keys(obj).forEach(oldKey => {
+ const newKey = transform(obj[oldKey])
+ obj[newKey] = obj[oldKey]
+ if (isTrue(removeOld)) remove(obj[oldKey])
+ })
+}
+const _remapValues = (transform, obj) => {
+ Object.keys(obj).forEach(key => obj[key] = transform(obj[key], key))
+}
+
+// value & values, key & keys, as obj or array... goodness
+//
+// match key, if match, use that transform (first one, condition/all as og name)
+const _findKey = (predicate, obj) => Object.keys(obj).filter(predicate).shift()
+const findKey = curry(2, _findKey)
+
+// @TODO NEED FINDVALUES TO PIPE ALL RESULTS
+const _findValue = (predicate, obj) => {
+ const keys = Object.keys(obj)
+ for (let index = 0; index < keys.length; index++) {
+ const key = keys[index]
+ const value = obj[key]
+ if (predicate(value, key)) return value
+ }
+ return false
+}
+const _findValues = (predicate, obj) => {
+ const keys = Object.keys(obj)
+ const valuesFound = []
+ for (let index = 0; index < keys.length; index++) {
+ const key = keys[index]
+ const value = obj[key]
+ if (predicate(value, key)) valuesFound.push(value)
+ }
+ return valuesFound
+}
+
+const findValue = curry(2, _findValue)
+const findValues = curry(2, _findValues)
+
+const remapKeys = curry(2, _remapKeys)
+const remapValues = curry(2, _remapValues)
+
+const remapToMatch = remapKeys(toMatcher)
+const findFirstMatch = pipe(isMatch, findValue)
+
+
+// @TODO now I have a use knowing it exists...
+// find(map, prop, isMatch)
+// findKey(map, isMatch)
+// Object.keys(map).filter(isMatch)
+// remapToMatch(map)
+
+const findMatching = (obj, query) => {
+ let lastKeyFound
+ let keys = []
+
+ const keyToMatcher = (val, key) => {
+ lastKeyFound = key
+ // console.log('does it match?', {query, val, key, isMatch: isMatch(query, key)})
+ if (isMatch(query, key)) {
+ keys.push(key)
+ return true
+ }
+ return false
+ }
+
+ const value = findValues(keyToMatcher, obj)
+
+ // console.log({value, keys}, 'finding matching...')
+ if (value.length) return [lastKeyFound, value, keys]
+ else return false
+}
+
+module.exports = {
+ forEach,
+ wrapForEach,
+ replaceLast,
+ isNegative,
+ // find
+ findIndexAt,
+ findMatching,
+ findKey,
+ findValue,
+ findValues,
+ findFirstMatch,
+ // remap
+ remapKeys,
+ remapValues,
+ remapToMatch,
+ forOwn,
+}
diff --git a/build/util/_filefolder.js b/build/util/_filefolder.js
new file mode 100644
index 0000000..051f9a7
--- /dev/null
+++ b/build/util/_filefolder.js
@@ -0,0 +1,23 @@
+const {basename} = require('path')
+
+const getFolderName = file => {
+ const fileParts = file.split('/')
+ fileParts.pop()
+ return fileParts.pop()
+}
+const getFileName = (file, withExt = false) => {
+ let filename = basename(file)
+
+ if (withExt === false && filename.includes('.')) {
+ filename = filename.split('.').shift()
+ }
+
+ return filename
+}
+const getFolderAndFileName = (abs, withExt = false) => {
+ const folder = getFolderName(abs, withExt)
+ const file = getFileName(abs, withExt)
+ return [folder, file, abs]
+}
+
+module.exports = {getFolderName, getFileName, getFolderAndFileName}
diff --git a/build/util/_res.js b/build/util/_res.js
new file mode 100644
index 0000000..4839703
--- /dev/null
+++ b/build/util/_res.js
@@ -0,0 +1,4 @@
+const {resolve} = require('path')
+const {curry} = require('../../')
+
+module.exports = curry(2, (dir, rel) => resolve(dir, rel))
diff --git a/build/util/_toRel.js b/build/util/_toRel.js
new file mode 100644
index 0000000..21e7651
--- /dev/null
+++ b/build/util/_toRel.js
@@ -0,0 +1,7 @@
+const {resolve} = require('path')
+const {curry} = require('../../')
+
+// replace()
+const toRel = (rootPath, filePath) => filePath.replace(rootPath, '')
+
+module.exports = curry(2, toRel)
diff --git a/build/util/index.js b/build/util/index.js
index b0c473b..836d4e3 100644
--- a/build/util/index.js
+++ b/build/util/index.js
@@ -1,4 +1,6 @@
module.exports = {
argv: require('./_args'),
del: require('./_delete'),
+ res: require('./_res'),
+ _res: require('./_res'),
}
diff --git a/dists/dev/index.js b/dists/dev/index.js
new file mode 100644
index 0000000..4f0e4ed
--- /dev/null
+++ b/dists/dev/index.js
@@ -0,0 +1,10130 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global.ChainAble = factory());
+}(this, (function () { 'use strict';
+
+ function unwrapExports (x) {
+ return x && x.__esModule ? x['default'] : x;
+ }
+
+ function createCommonjsModule(fn, module) {
+ return module = { exports: {} }, fn(module, module.exports), module.exports;
+ }
+
+ /* ___filename___: dist/deps/util/assign.js */
+ var assign = Object.assign;
+
+ /* ___filename___: dist/deps/is/undefined.js */
+ /**
+ * @desc Checks if `value` is `undefined`.
+ * @category Lang
+ *
+ * @param {*} x value
+ * @return {boolean} isUndefined
+ *
+ * @since 4.0.0-alpha.1
+ * @memberOf is
+ * @func isUndefined
+ *
+ * @see is/nullOrUndefined
+ * @see https://github.com/infernojs/inferno/blob/master/packages/inferno-shared/src/index.ts#L57
+ *
+ * @NOTE || typeof x === 'undefined'
+ *
+ * @example
+ *
+ * isUndefined(undefined)
+ * //=> true
+ * isUndefined(void 0)
+ * //=> true
+ *
+ * isUndefined(null)
+ * //=> false
+ * isUndefined(NaN)
+ * //=> false
+ * isUndefined({})
+ * //=> false
+ * isUndefined('')
+ * //=> false
+ * isUndefined(1)
+ * //=> false
+ * isUndefined(false)
+ * //=> false
+ *
+ */
+ var _undefined = function (x) { return x === undefined; };
+
+ /* ___filename___: dist/deps/symbols/iterator.js */
+ var iterator = Symbol.iterator;
+
+ // typeof Symbol !== 'undefined'
+ // ? Symbol.iterator
+ // : '@@iterator'
+
+ /* ___filename___: dist/deps/symbols/instance.js */
+ var instance = Symbol.hasInstance;
+
+ /* ___filename___: dist/deps/symbols/primitive.js */
+ var primitive = Symbol.toPrimitive;
+
+ /* ___filename___: dist/deps/is/prototypeOf.js */
+ var prototypeOf = function (obj, comparator) { return Object.prototype.isPrototypeOf.call(obj, comparator); };
+
+ /* ___filename___: dist/deps/is/toS.js */
+ /**
+ * The base implementation of `getTag` without fallbacks for buggy environments.
+ *
+ * @memberOf is
+ * @since 3.0.0
+ *
+ * @param {*} obj The value to `Object.prototype.toString.call(obj)`.
+ * @return {string} Returns the `toStringTag`.
+ *
+ * @see https://github.com/lodash/lodash/blob/master/.internal/baseGetTag.js
+ * @see https://github.com/jonschlinkert/kind-of
+ * @see https://github.com/substack/js-traverse/blob/master/index.js#L285
+ * @see http://luxiyalu.com/object-prototype-tostring-call/
+ *
+ * @TODO obj[Symbol.toStringTag]
+ *
+ * @example
+ *
+ * toS({})
+ * //=> '[Object object]'
+ *
+ * toS(function() {})
+ * //=> '[Object function]'
+ *
+ */
+ var toS = function (obj) { return Object.prototype.toString.call(obj); };
+
+ /* ___filename___: dist/deps/is/toS.js */
+
+ /* ___filename___: dist/deps/is/map.js */
+
+
+ /**
+ * @desc Checks if `value` is classified as a `Map` object.
+ * @param {*} x value
+ * @return {boolean} isMap
+ *
+ * @since 3.0.0
+ * @memberOf is
+ * @func isMap
+ * @see https://github.com/jonschlinkert/kind-of
+ *
+ * @example
+ *
+ * isMap(new Map())
+ * //=> true
+ * isMap(new Map.entries())
+ * //=> false
+ * isMap(new Set())
+ * //=> false
+ * isMap({})
+ * //=> false
+ * isMap('')
+ * //=> false
+ * isMap(1)
+ * //=> false
+ * isMap(new WeakMap)
+ * // => false
+ *
+ * @example
+ *
+ * const e = {}
+ * eh[Symbol.toStringTag] = '[object Map]'
+ * isMap(eh)
+ *
+ * @example
+ *
+ * class Eh extends Map()
+ * isMap(new Eh())
+ * //=> true
+ *
+ */
+ var map = function isMap(x) {
+ // return x instanceof Map ||
+ return toS(x) === '[object Map]'
+ };
+
+ /* ___filename___: dist/deps/is/set.js */
+
+
+ /**
+ * Checks if `value` is classified as a `Set` object.
+ *
+ * @since 4.3.0
+ * @category Lang
+ * @param {*} x The value to check.
+ * @return {boolean} Returns `true` if `value` is a set, else `false`.
+ *
+ * @example
+ *
+ * isSet(new Set)
+ * // => true
+ *
+ * isSet(new WeakSet)
+ * // => false
+ *
+ */
+ var set = function isSet(x) {
+ return x instanceof Set || toS(x) === '[object Set]'
+ // return toS(x) === '[object Set]'
+ };
+ // x instanceof Set ||
+
+ /* ___filename___: dist/deps/is/function.js */
+ /**
+ * Checks if `value` is classified as a `Function` object.
+ * @category Lang
+ *
+ * @param {*} x The value to check.
+ * @return {boolean} x isFunction
+ *
+ * @since 3.0.0
+ * @memberOf is
+ * @func isFunction
+ *
+ * @NOTE || x instanceof Function
+ *
+ * @polyfill safari=9
+ * The use of `Object#toString` avoids issues with the `typeof` operator
+ * in Safari 9 which returns 'object' for typed arrays and other constructors.
+ * there is no polyfill for this
+ * https://github.com/krambuhl/custom-event-polyfill/issues/2
+ * browser usage is < 0.3%, very edge case
+ *
+ * @example
+ *
+ * isFunction(function() {})
+ * //=> true
+ * isFunction(() => {})
+ * //=> true
+ * isFunction(new Function())
+ * //=> true
+ *
+ * isFunction(1)
+ * //=> false
+ * isFunction('')
+ * //=> false
+ * isFunction(/abc/)
+ * // => false
+ */
+ var _function = function isFunction(x) {
+ return typeof x === 'function'
+ };
+
+ /* ___filename___: dist/deps/is/stringPrimitive.js */
+
+
+ /**
+ * Checks if `value` is classified as a `String` **primitive**.
+ *
+ * @since 3.0.0
+ * @category Lang
+ * @memberOf is
+ * @param {*} x The value to check.
+ * @returns {boolean} Returns `true` if `value` is a string, else `false`.
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String
+ * @see https://github.com/lodash/lodash/blob/master/isString.js
+ * @see is/string
+ *
+ * @example
+ *
+ * isString('abc')
+ * // => true
+ *
+ * isString(new String('abc'))
+ * // => false
+ *
+ * isString(1)
+ * // => false
+ */
+ var stringPrimitive = function (x) { return typeof x === 'string'; };
+
+ /* ___filename___: dist/deps/is/stringPrimitive.js */
+
+ /* ___filename___: dist/deps/is/string.js */
+
+
+
+ /**
+ * Checks if `value` is classified as a `String` primitive or object.
+ *
+ * @since 3.0.0
+ * @category Lang
+ *
+ * @memberOf is
+ * @extends isStringPrimitive
+ * @variation also allows String objects
+ *
+ * @param {*} x The value to check.
+ * @return {boolean} Returns `true` if `value` is a string, else `false`.
+ *
+ * @see https://github.com/lodash/lodash/blob/master/isString.js
+ * @see isStringPrimitive
+ *
+ * @example
+ *
+ * isString('abc')
+ * // => true
+ *
+ * isString(new String('abc'))
+ * // => true
+ *
+ * isString(1)
+ * // => false
+ */
+ var string = function (x) { return stringPrimitive(x) || toS(x) === '[object String]'; };
+
+ /* ___filename___: dist/deps/is/false.js */
+ /**
+ * @param {*} x value
+ * @return {boolean} isFalse
+ *
+ * @since 4.0.0-alpha.1
+ * @memberOf is
+ * @func isFalse
+ *
+ * @example
+ *
+ * isFalse(false)
+ * //=> true
+ * isFalse(true)
+ * //=> false
+ * isFalse(0)
+ * //=> false
+ * isFalse('')
+ * //=> false
+ *
+ */
+ var _false = function isFalse(x) {
+ return x === false
+ };
+
+ /* ___filename___: dist/deps/util/noop.js */
+ /**
+ * @name noop
+ *
+ * @func
+ * @since 5.0.0
+ * @return {void}
+ *
+ * {@link https://github.com/sindresorhus/noop3 noop3}
+ * @see {@link noop3}
+ *
+ * @example
+ *
+ * noop
+ *
+ * @example
+ *
+ * noop()
+ *
+ */
+ var noop = function noop() { /* noop */ };
+
+ /* ___filename___: dist/deps/util/keys.js */
+ var keys = Object.keys;
+ // function keys(obj) {
+ // var res = []
+ // for (var key in obj)
+ // { res.push(key) }
+ // return res
+
+ /* ___filename___: dist/deps/util/assign.js */
+
+ /* ___filename___: dist/deps/define.js */
+
+
+ /**
+ * @desc default to configurable and enumerable, unless configured otherwise
+ * @since 4.0.0
+ *
+ * @param {Object} obj object to define on
+ * @param {Primitive} name property name to define
+ * @param {Object} descriptor object descriptor
+ * @return {void}
+ *
+ * @tutorial https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
+ *
+ * @example
+ *
+ * var desc = Object.getOwnPropertyDescriptor(obj, 'eh', {get: () => console.log('eh')})
+ *
+ */
+ var define = function(obj, name, descriptor) {
+ Object.defineProperty(
+ obj,
+ name,
+ assign(
+ {
+ configurable: true,
+ enumerable: true,
+ },
+ descriptor
+ )
+ );
+ };
+
+ /* ___filename___: dist/deps/ignored.js */
+ var ignored = function (key) { return key === 'parent' || key === 'store' || key === 'meta' || key === 'className'; };
+
+ // key === 'decorated' ||
+ // key === 'transformers' ||
+ // key === 'inspect' ||
+
+ /* ___filename___: dist/deps/env/dev.js */
+ /* istanbul ignore next: wip build */
+ var dev = process.env.NODE_ENV !== 'production';
+
+ /* ___filename___: dist/deps/symbols/iterator.js */
+
+ /* ___filename___: dist/deps/symbols/instance.js */
+
+ /* ___filename___: dist/deps/symbols/primitive.js */
+
+ /* ___filename___: dist/deps/is/prototypeOf.js */
+
+ /* ___filename___: dist/deps/is/map.js */
+
+ /* ___filename___: dist/deps/is/set.js */
+
+ /* ___filename___: dist/deps/is/undefined.js */
+
+ /* ___filename___: dist/deps/is/function.js */
+
+ /* ___filename___: dist/deps/is/string.js */
+
+ /* ___filename___: dist/deps/is/false.js */
+
+ /* ___filename___: dist/deps/util/noop.js */
+
+ /* ___filename___: dist/deps/util/keys.js */
+
+ /* ___filename___: dist/deps/define.js */
+
+ /* ___filename___: dist/deps/ignored.js */
+
+ /* ___filename___: dist/deps/env/dev.js */
+
+ /* ___filename___: dist/Chainable.js */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ // @TODO change from `||` to if else
+ var shouldClear = function (key, property) { return !ignored(key) &&
+ (map(property) || set(property) || (property && property.store)); };
+
+ var ComposeChainable = function (Target) {
+ /* istanbul ignore next: dev */
+ if (dev) {
+ if (!Target || !Target.prototype) {
+ console.log({Target: Target});
+ throw new TypeError('did not have a super class / target base')
+ }
+ }
+
+ /**
+ * @desc Trait class that can inherit any class passed into compose, extended by ChainedMap & ChainedSet
+ *
+ * @member Chainable
+ * @class Chainable
+ * @category Chainable
+ * @type {Chainable}
+ *
+ * @prop {Chainable | any} parent
+ * @prop {string} className
+ *
+ * {@link https://github.com/iluwatar/java-design-patterns/tree/master/chain chain-pattern}
+ * @see {@link chain-pattern}
+ *
+ * @see ChainedMap
+ * @see ChainedSet
+ *
+ * @tests Chainable
+ * @types Chainable
+ */
+ var Chainable = (function (Target) {
+ function Chainable(parent) {
+ Target.call(this);
+ if (parent) { this.parent = parent; }
+ this.className = this.constructor.name;
+ }
+
+ if ( Target ) Chainable.__proto__ = Target;
+ Chainable.prototype = Object.create( Target && Target.prototype );
+ Chainable.prototype.constructor = Chainable;
+
+ /**
+ * @desc Iterator for looping values in the store
+ *
+ * @memberOf Chainable
+ * @since 0.5.0
+ *
+ * @type {generator}
+ * @return {Object} {value: undefined | any, done: true | false}
+ *
+ * @NOTE assigned to a variable so buble ignores it
+ *
+ *
+ * @see https://github.com/sindresorhus/quick-lru/blob/master/index.js
+ * @see https://stackoverflow.com/questions/36976832/what-is-the-meaning-of-symbol-iterator-in-this-context
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator
+ * @see this.store
+ * @tests iteration
+ *
+ * @example
+ *
+ * const chain = new Chain().set('eh', 1)
+ * for (var [key, val] of chain) console.log({[key]: val})
+ * //=> {eh: 1}
+ *
+ * @example
+ *
+ * *[Symbol.iterator](): void { for (const item of this.store) yield item }
+ *
+ * @example
+ *
+ * const {ChainedSet} = require('chain-able')
+ * const set = new ChainedSet()
+ * set.add('eh')
+ *
+ * for (const arr of set) {
+ * const [key, val] = arr
+ *
+ * key
+ * //=> 0
+ *
+ * val
+ * //=> 'eh'
+ *
+ * arr.length
+ * //=> 2
+ * }
+ *
+ */
+ Chainable.prototype[iterator] = function () {
+ var values = this.values();
+ var size = this.store.size;
+ var entries = this.entries ? this.entries() : 0;
+ var keys$$1 = entries === 0 ? new Array(size) : keys(entries);
+
+ return {
+ i: 0,
+ next: function next() {
+ var i = this.i;
+ var key = i;
+ var val = values[i];
+ if (entries) { key = keys$$1[i]; }
+
+ // done - no more values, or iteration reached size
+ if ((_undefined(key) && _undefined(val)) || size <= i) {
+ return {value: undefined, done: true}
+ }
+
+ this.i++;
+
+ // return
+ return {value: [key, val], done: false}
+ },
+ }
+ };
+
+ /**
+ * @desc for ending nested chains
+ * @since 0.4.0
+ * @memberOf Chainable
+ *
+ * @return {Chainable | any}
+ *
+ * @see Chainable.parent
+ * @see FactoryChain
+ *
+ * @example
+ *
+ * const parent = 'eh'
+ * const child = newChain(parent)
+ * child.end()
+ * //=> 'eh'
+ *
+ */
+ Chainable.prototype.end = function end () {
+ return this.parent
+ };
+
+ /**
+ * @desc when the condition is true,
+ * trueBrancher is called,
+ * else, falseBrancher is called
+ *
+ * @memberOf Chainable
+ * @since 4.0.0 <- added string-as-has(condition)
+ * @since 2.0.0
+ *
+ * @param {boolean | string} condition when string, checks this.get
+ * @param {Function} [trueBrancher=Function] called when true
+ * @param {Function} [falseBrancher=Function] called when false
+ * @return {Chainable} @chainable
+ *
+ * @example
+ *
+ *
+ * const prod = process.env.NODE_ENV === 'production'
+ * chains.when(prod, c => c.set('prod', true), c => c.set('prod', false))
+ *
+ *
+ */
+ Chainable.prototype.when = function when (condition, trueBrancher, falseBrancher) {
+ if (condition) {
+ if (_function(trueBrancher)) {
+ if (string(condition)) {
+ if (this.get(condition)) {
+ trueBrancher(this);
+ }
+ }
+ else {
+ trueBrancher(this);
+ }
+ }
+ }
+ else if (_function(falseBrancher)) {
+ falseBrancher(this);
+ }
+
+ return this
+ };
+
+ /**
+ * @desc clears the map,
+ * goes through this properties,
+ * calls .clear if they are instanceof Chainable or Map
+ *
+ * @memberOf Chainable
+ * @since 4.0.0 (moved only to Chainable, added option to clear this keys)
+ * @since 0.4.0 (in ChainedMap)
+ * @since 0.3.0 (in Chainable)
+ *
+ * @param {boolean | undefined} [clearPropertiesThatAreChainLike=true] checks properties on the object, if they are `chain-like`, clears them as well
+ * @return {Chainable} @chainable
+ *
+ * @see https://github.com/fliphub/flipchain/issues/2
+ * @see ChainedSet
+ * @see ChainedMap
+ *
+ * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/clear map-clear}
+ * @see {@link map-clear}
+ *
+ * @example
+ *
+ * const chain = new Chain()
+ * chain.set('eh', 1)
+ * chain.entries()
+ * //=> {eh: 1}
+ * chain.clear()
+ * chain.entries()
+ * //=> {}
+ *
+ */
+ Chainable.prototype.clear = function clear (clearPropertiesThatAreChainLike) {
+ var this$1 = this;
+
+ this.store.clear();
+
+ if (_false(clearPropertiesThatAreChainLike)) { return this }
+
+ var keys$$1 = keys(this);
+ for (var k = 0; k < keys$$1.length; k++) {
+ var key = keys$$1[k];
+ var property = this$1[key];
+ if (shouldClear(key, property)) { this$1[key].clear(); }
+ }
+
+ return this
+ };
+
+ /**
+ * @desc calls .delete on this.store.map
+ * @since 0.3.0
+ * @memberOf Chainable
+ *
+ * @param {Primitive} key on a Map: key referencing the value. on a Set: the index
+ * @return {Chainable}
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/has
+ * @see ChainedSet
+ * @see ChainedMap
+ *
+ * @example
+ *
+ * const chain = new Chain()
+ * chain.set('eh', 1)
+ * chain.get('eh')
+ * // => 1
+ * chain.delete('eh', 1)
+ * chain.get('eh')
+ * // => undefined
+ *
+ */
+ Chainable.prototype.delete = function delete$1 (key) {
+ this.store.delete(key);
+ return this
+ };
+
+ /**
+ * @desc checks whether the store has a value for a given key
+ * @memberOf Chainable
+ * @since 0.3.0
+ *
+ * @param {any} keyOrValue key when Map, value when Set
+ * @return {boolean}
+ *
+ * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has map-has}
+ * @see {@link map-has}
+ *
+ * @example
+ *
+ * const chain = new Chain()
+ * chain.set('eh', 1).has('eh')
+ * //=> true
+ * chain.has('canada')
+ * //=> false
+ *
+ */
+ Chainable.prototype.has = function has (keyOrValue) {
+ return this.store.has(keyOrValue)
+ };
+
+ /**
+ * @desc spreads the entries from ChainedMap.store.values
+ * allocates a new array, adds the values from the iterator
+ *
+ * @memberOf Chainable
+ * @since 0.4.0
+ *
+ * @return {Array} toArr(this.store.values())
+ *
+ * @NOTE look at Chainable.constructor to ensure not to use `new Array...`
+ * @NOTE moved from ChainedMap and ChainedSet to Chainable @2.0.2
+ * @NOTE this was [...] & Array.from(this.store.values())
+ *
+ * {@link https://kangax.github.io/compat-table/es6/#test-Array_static_methods compat-array-static-methods}
+ * {@link https://stackoverflow.com/questions/20069828/how-to-convert-set-to-array set-to-array}
+ * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/values mozilla-map-values}
+ * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/values mozilla-set-values}
+ *
+ * @see {@link mozilla-map-values}
+ * @see {@link mozilla-set-values}
+ * @see {@link compat-array-static-methods}
+ * @see {@link set-to-array}
+ *
+ *
+ * @example
+ *
+ * const chain = new Chain()
+ * chain.set('eh', 1)
+ * chain.values()
+ * //=> [1]
+ *
+ */
+ Chainable.prototype.values = function values () {
+ var allocated = new Array(this.store.size);
+ var i = 0;
+ this.store.forEach(function (v) { return (allocated[i++] = v); });
+ return allocated
+ };
+
+ /**
+ * @desc symbol method for toString, toJSON, toNumber
+ * @memberOf Chainable
+ * @since 1.0.2
+ * @version 2
+ *
+ * @param {string} hint enum[default, string, number]
+ * @return {Primitive}
+ *
+ * {@link http://2ality.com/2015/09/well-known-symbols-es6.html#default-tostring-tags well-known-symbols-es6}
+ * @see {@link well-known-symbols-es6}
+ *
+ * @example
+ *
+ * const chain = new Chain()
+ * chain.toNumber = () => 1
+ * +chain;
+ * //=> 1
+ * chain + 1
+ * //=>
+ *
+ * @example
+ *
+ * const chain = new Chain()
+ * chain.toString = () => 'eh'
+ * chain + ''
+ * //=> 'eh'
+ *
+ */
+ Chainable.prototype[primitive] = function (hint) {
+ /* prettier-ignore */
+ /**
+ * hint === 'number'
+ * `s`tring is 115
+ * `n`umber is 110
+ * 110 & 4 = 1
+ * 115 & 4 = 0
+ *
+ * if (hint === 'string' && this.toJSON) return this.toJSON()
+ * else if (hint === 'number' && this.toNumber) return this.toNumber()
+ */
+ if (hint === 'number' && this.toNumber) { return this.toNumber() }
+
+ // hint === 'string'
+ if (this.toJSON) { return this.toJSON() }
+
+ // hint === 'default'
+ return this.toString()
+ };
+
+ return Chainable;
+ }(Target));
+
+ var ChainPrototype = Chainable.prototype;
+
+ /**
+ * @memberOf Chainable
+ * @name length
+ * @method length
+ * @readonly
+ * @since 0.5.0
+ * @see ChainedMap.store
+ * @return {number}
+ * @example for (var i = 0; i < chain.length; i++)
+ */
+ define(ChainPrototype, 'length', {
+ enumerable: false,
+ get: function get() {
+ return this.store.size
+ },
+ });
+ define(ChainPrototype, instance, {
+ enumerable: false,
+ value: function (instance$$1) { return instance$$1 && (prototypeOf(ChainPrototype, instance$$1) || instance$$1.store); },
+ });
+
+ return Chainable
+ };
+
+ // class {}
+ var c = ComposeChainable(noop);
+
+ /**
+ * @since 3.0.0
+ * @func
+ * @example
+ *
+ * class Target {}
+ * const TargetChain = Chainable.compose(Target)
+ * const chain = new TargetChain()
+ * chain instanceof Target
+ * //=> true
+ *
+ */
+ c.compose = ComposeChainable;
+
+ var Chainable = c;
+
+ /* ___filename___: dist/deps/is/objTypeof.js */
+ /**
+ * @param {*} x value
+ * @return {boolean} isObjLoose
+ *
+ * @since 3.0.0
+ * @memberOf is
+ * @func isObjLoose
+ * @see is/obj
+ * @see is/objWithKeys
+ * @see is/objStrict
+ * @see is/null
+ *
+ * @example
+ *
+ * isObjLoose(new Object())
+ * //=> true
+ * isObjLoose({})
+ * //=> true
+ * isObjLoose(Object.create(null))
+ * //=> true
+ * isObjLoose(null)
+ * //=> true
+ *
+ * isObjLoose(new Set())
+ * //=> false
+ * isObjLoose(function() {})
+ * //=> false
+ * isObjLoose('')
+ * //=> false
+ * isObjLoose(1)
+ * //=> false
+ *
+ */
+ var objTypeof = function (x) { return typeof x === 'object'; };
+
+ /* ___filename___: dist/deps/is/null.js */
+ /**
+ * @param {*} x value
+ * @return {boolean} isNull
+ *
+ * @since 3.0.0
+ * @memberOf is
+ * @func isNull
+ *
+ * @example
+ *
+ * isNull(null)
+ * //=> true
+ *
+ * isNull(undefined)
+ * //=> false
+ * isNull(void 0)
+ * //=> false
+ * isNull({})
+ * //=> false
+ * isNull('')
+ * //=> false
+ * isNull(1)
+ * //=> false
+ *
+ */
+ var _null = function (x) { return x === null; };
+
+ /* ___filename___: dist/deps/is/null.js */
+
+ /* ___filename___: dist/deps/is/nullOrUndefined.js */
+
+
+
+ /**
+ * @desc Checks if `value` is `null` or `undefined`.
+ * @alias isNil
+ * @category Lang
+ *
+ * @param {*} x value
+ * @return {boolean} isNullOrUndefined
+ *
+ * @since 4.0.0-alpha.1
+ * @memberOf is
+ * @func isNullOrUndefined
+ *
+ * @see is/null
+ * @see is/undefined
+ * @see https://github.com/infernojs/inferno/blob/master/packages/inferno-shared/src/index.ts#L23
+ *
+ * @example
+ *
+ * isNullOrUndefined(null)
+ * //=> true
+ * isNullOrUndefined(undefined)
+ * //=> true
+ * isNullOrUndefined(void 0)
+ * //=> true
+ *
+ * isNullOrUndefined(NaN)
+ * //=> false
+ * isNullOrUndefined({})
+ * //=> false
+ * isNullOrUndefined('')
+ * //=> false
+ * isNullOrUndefined(1)
+ * //=> false
+ * isNullOrUndefined(false)
+ * //=> false
+ *
+ */
+ var nullOrUndefined = function isNullOrUndef(x) {
+ return _undefined(x) || _null(x)
+ };
+
+ /* ___filename___: dist/deps/is/objTypeof.js */
+
+ /* ___filename___: dist/deps/is/nullOrUndefined.js */
+
+ /* ___filename___: dist/deps/is/objNotNull.js */
+
+
+
+ /**
+ * @param {*} x value
+ * @return {boolean} isObjStrict
+ *
+ * @since 3.0.0
+ * @memberOf is
+ * @func isObjStrict
+ * @see is/obj
+ * @see is/objWithKeys
+ * @see is/objTypeof
+ * @see is/null
+ * @see https://github.com/sindresorhus/is-obj/blob/master/index.js
+ * @TODO !Array.isArray
+ *
+ * @extends isObjTypeof
+ * @variation null will not count as an object
+ *
+ * @example
+ *
+ * isObjStrict(new Object())
+ * //=> true
+ * isObjStrict({})
+ * //=> true
+ * isObjStrict(Object.create(null))
+ * //=> true
+ * isObjStrict(null)
+ * //=> false
+ *
+ * isObjStrict(new Set())
+ * //=> false
+ * isObjStrict(function() {})
+ * //=> false
+ * isObjStrict('')
+ * //=> false
+ * isObjStrict(1)
+ * //=> false
+ *
+ */
+ var objNotNull = function (x) { return !nullOrUndefined(x) && objTypeof(x); };
+
+ /* ___filename___: dist/deps/is/array.js */
+ /**
+ * @func isArray
+ * @todo https://github.com/facebook/immutable-js/blob/master/src/utils/isArrayLike.js
+ * @see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
+ * @type {Function}
+ * @since 3.0.0
+ */
+ var array = Array.isArray;
+
+ // function isArray(xs) {
+ // return Object.prototype.toString.call(xs) === '[object Array]'
+ // }
+
+ /* ___filename___: dist/deps/is/true.js */
+ /**
+ * @param {*} x value
+ * @return {boolean} isTrue
+ *
+ * @since 4.0.0-alpha.1
+ * @memberOf is
+ * @func isTrue
+ *
+ * @example
+ *
+ * isTrue(true)
+ * //=> true
+ * isTrue(false)
+ * //=> false
+ * isTrue(1)
+ * //=> false
+ * isTrue('')
+ * //=> false
+ *
+ */
+ var _true = function (x) { return x === true; };
+
+ /* ___filename___: dist/deps/is/regexp.js */
+
+
+ /**
+ * Checks if `value` is classified as a `RegExp` object.
+ *
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} x The value to check.
+ * @return {boolean} Returns `true` if `value` is a regexp, else `false`.
+ * @see https://github.com/lodash/lodash/blob/master/isRegExp.js
+ *
+ * @example
+ *
+ * isRegExp(/abc/)
+ * // => true
+ *
+ * isRegExp('/abc/')
+ * // => false
+ *
+ */
+ var regexp = function (x) { return toS(x) === '[object RegExp]'; };
+ // obj instanceof RegExp ||
+
+ /* ___filename___: dist/deps/is/date.js */
+
+
+ /**
+ * @param {*} x value
+ * @return {boolean} isDate
+ *
+ * @since 3.0.0
+ * @memberOf is
+ * @func isDate
+ * @extends toS
+ *
+ * @example
+ *
+ * isDate(new Date())
+ * //=> true
+ * isDate(Date.now())
+ * //=> false
+ * isDate(1)
+ * //=> false
+ * isDate('')
+ * //=> false
+ *
+ * @example
+ *
+ * const e = {}
+ * eh[Symbol.toStringTag] = '[Object Date]'
+ * isDate(eh)
+ * //=> true
+ *
+ * @example
+ *
+ * class Eh extends Date()
+ * isDate(new Eh())
+ * //=> true
+ */
+ var date = function isDate(x) {
+ return toS(x) === '[object Date]'
+ // x instanceof Date ||
+ };
+
+ /* ___filename___: dist/deps/is/true.js */
+
+ /* ___filename___: dist/deps/is/boolean.js */
+
+
+
+
+ /**
+ * @desc Checks if `value` is classified as a boolean primitive or object.
+ * @category Lang
+ * @since 3.0.0
+ *
+ * @param {*} x value
+ * @return {boolean} isBoolean
+ *
+ * @extends isTrue
+ * @extends isFalse
+ * @see is/toS
+ * @memberOf is
+ * @func isBoolean
+ *
+ * @NOTE could also have typeof x === 'boolean' || (/true|false/).test(x)
+ *
+ * @example
+ *
+ * isBoolean(false)
+ * //=> true
+ * isBoolean(new Boolean(1))
+ * //=> true
+ * isBoolean(1)
+ * //=> false
+ * isBoolean('')
+ * //=> false
+ *
+ */
+ var boolean_1 = function isBoolean(x) {
+ return _true(x) || _false(x) || toS(x) === '[object Boolean]'
+ };
+
+ /* ___filename___: dist/deps/is/array.js */
+
+ /* ___filename___: dist/deps/util/simpleKindOf.js */
+
+
+
+ /* prettier-ignore */
+ /**
+ * @desc when Array -> 'array'
+ * when null -> 'null'
+ * else `typeof x`
+ * @param {any} x
+ * @return {string} type
+ */
+ var simpleKindOf = function (x) {
+ return array(x)
+ ? 'array'
+ : _null(x)
+ ? 'null'
+ : typeof x
+ };
+
+ /* ___filename___: dist/deps/conditional/includes/includes.js */
+ var includes = function (haystack, needle) { return haystack.includes(needle); };
+
+ /* ___filename___: dist/deps/conditional/includes/includes.js */
+
+ var index$4 = includes;
+
+ /* ___filename___: dist/deps/dopemerge/emptyTarget.js */
+
+
+ /**
+ * @desc make a new empty Array or Object for cloning
+ * @memberOf dopemerge
+ * @name emptyTarget
+ * @since 2.0.0
+ * @func
+ *
+ * @param {*} val array or object to return an empty one of
+ * @return {Object | Array} depending on the data type of val
+ *
+ * @example
+ *
+ * emptyTarget({eh: true})
+ * //=> {}
+ *
+ * emptyTarget([1])
+ * //=> []
+ *
+ */
+ var emptyTarget = function emptyTarget(val) {
+ return array(val) ? [] : {}
+ };
+
+ /* ___filename___: dist/deps/is/objNotNull.js */
+
+ /* ___filename___: dist/deps/is/regexp.js */
+
+ /* ___filename___: dist/deps/is/date.js */
+
+ /* ___filename___: dist/deps/is/boolean.js */
+
+ /* ___filename___: dist/deps/util/simpleKindOf.js */
+
+ /* ___filename___: dist/deps/dopemerge/emptyTarget.js */
+
+ /* ___filename___: dist/deps/dopemerge/dopemerge.js */
+ /* eslint complexity: "OFF" */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /**
+ * @desc 1: not null object
+ * 2: object toString is not a date or regex
+ *
+ * @category merge
+ * @memberOf dopemerge
+ *
+ * @since 2.0.0
+ * @param {*} x value to check
+ * @return {boolean}
+ *
+ * @example
+ *
+ * isMergeableObj({})
+ * //=> true
+ *
+ * isMergeableObj(Object.create(null))
+ * // => true
+ *
+ * isMergeableObj(new Date())
+ * //=> false
+ *
+ * isMergeableObj(/eh/)
+ * //=> false
+ *
+ */
+ function isMergeableObj(x) {
+ return objNotNull(x) && !regexp(x) && !date(x)
+ }
+
+ /**
+ * Defaults to `false`.
+ * If `clone` is `true` then both `x` and `y` are recursively cloned as part of the merge.
+ *
+ * @memberOf dopemerge
+ * @since 2.0.0
+ *
+ * @param {*} value value to clone if needed
+ * @param {DopeMergeOptions} optsArg dopemerge options, could contain .clone
+ * @return {Object | Array | any} cloned or original value
+ *
+ * @see emptyTarget
+ * @see isMergeableObj
+ *
+ * @example
+ *
+ * var obj = {eh: true}
+ *
+ * cloneIfNeeded(obj, {clone: true}) === obj
+ * //=> false
+ *
+ * cloneIfNeeded(obj, {clone: false}) === obj
+ * //=> true
+ *
+ */
+ function cloneIfNeeded(value, optsArg) {
+ return _true(optsArg.clone) && isMergeableObj(value)
+ ? deepmerge(emptyTarget(value), value, optsArg)
+ : value
+ }
+
+ /* prettier-ignore */
+ /**
+ * The merge will also merge arrays and array values by default.
+ * However, there are nigh-infinite valid ways to merge arrays,
+ * and you may want to supply your own.
+ * You can do this by passing an `arrayMerge` function as an option.
+ *
+ * @memberOf dopemerge
+ * @since 2.0.0
+ *
+ * @param {*} target array merged onto, could be emptyTarget if cloning
+ * @param {*} source original source array
+ * @param {*} optsArg dopemerge options
+ * @return {Array | *} merged array
+ *
+ * @example
+ *
+ * function concatMerge(destinationArray, sourceArray, options) {
+ * destinationArray
+ * //=> [1, 2, 3]
+ *
+ * sourceArray
+ * //=> [3, 2, 1]
+ *
+ * options
+ * //=> { arrayMerge: concatMerge }
+ *
+ * return destinationArray.concat(sourceArray)
+ * }
+ * merge([1, 2, 3], [3, 2, 1], { arrayMerge: concatMerge })
+ * //=> [1, 2, 3, 3, 2, 1]
+ *
+ */
+ function defaultArrayMerge(target, source, optsArg) {
+ var destination = target.slice();
+
+ for (var i = 0; i < source.length; i++) {
+ var v = source[i];
+ if (_undefined(destination[i])) {
+ destination[i] = cloneIfNeeded(v, optsArg);
+ }
+ else if (isMergeableObj(v)) {
+ destination[i] = deepmerge(target[i], v, optsArg);
+ }
+ // @see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_NOT
+ // === -1
+ // eslint-disable-next-line prefer-includes/prefer-includes
+ else if (!~target.indexOf(v)) {
+ destination.push(cloneIfNeeded(v, optsArg));
+ }
+ }
+ return destination
+ }
+
+ function mergeObj(target, source, optsArg) {
+ var destination = {};
+ if (isMergeableObj(target)) {
+ var targetKeys = keys(target);
+ for (var k = 0; k < targetKeys.length; k++) {
+ destination[targetKeys[k]] = cloneIfNeeded(target[targetKeys[k]], optsArg);
+ }
+ }
+ var sourceKeys = keys(source);
+ for (var s = 0; s < sourceKeys.length; s++) {
+ var key = sourceKeys[s];
+ if (!isMergeableObj(source[key]) || !target[key]) {
+ destination[key] = cloneIfNeeded(source[key], optsArg);
+ }
+ else {
+ destination[key] = deepmerge(target[key], source[key], optsArg);
+ }
+ }
+
+ return destination
+ }
+
+ function deepmerge(target, source, optsArg) {
+ if (array(source)) {
+ var arrayMerge = optsArg.arrayMerge;
+ return array(target)
+ ? arrayMerge(target, source, optsArg)
+ : cloneIfNeeded(source, optsArg)
+ }
+
+ // else
+ return mergeObj(target, source, optsArg)
+ }
+
+ /* prettier-ignore */
+ /**
+ * Merge the enumerable attributes of two objects deeply.
+ * Merge two objects `x` and `y` deeply, returning a new merged object with the
+ * elements from both `x` and `y`.
+ * If an element at the same key is present for both `x` and `y`, the value from
+ * `y` will appear in the result.
+ * Merging creates a new object, so that neither `x` or `y` are be modified.
+ * However, child objects on `x` or `y` are copied over -
+ * if you want to copy all values, you must pass `true` to the clone option.
+ *
+ *
+ * @member dopemerge
+ * @category merge
+ *
+ * @param {*} obj1 left
+ * @param {*} obj2 right
+ * @param {*} opts dopemerge options
+ * @return {Object | Array | any} merged
+ *
+ * {@link https://github.com/KyleAMathews/deepmerge deepmerge}
+ * @see {@link deepmerge}
+ *
+ * @types dopemerge
+ * @tests deepmerge
+ *
+ * @example
+ *
+ * var x = {
+ * foo: {bar: 3},
+ * array: [{
+ * does: 'work',
+ * too: [1, 2, 3],
+ * }],
+ * }
+ *
+ * var y = {
+ * foo: {baz: 4},
+ * quux: 5,
+ * array: [
+ * {
+ * does: 'work',
+ * too: [4, 5, 6],
+ * },
+ * {
+ * really: 'yes',
+ * },
+ * ],
+ * }
+ *
+ * var expected = {
+ * foo: {
+ * bar: 3,
+ * baz: 4,
+ * },
+ * array: [
+ * {
+ * does: 'work',
+ * too: [1, 2, 3, 4, 5, 6],
+ * },
+ * {
+ * really: 'yes',
+ * },
+ * ],
+ * quux: 5,
+ * }
+ *
+ * merge(x, y)
+ * //=> expected
+ *
+ */
+ function dopemerge(obj1, obj2, opts) {
+ // if they are identical, fastest === check
+ if (obj1 === obj2) {
+ return obj1
+ }
+
+ // setup options
+ var options = assign(
+ {
+ arrayMerge: defaultArrayMerge,
+ stringToArray: true,
+ boolToArray: false,
+ ignoreTypes: ['null', 'undefined'],
+ // debug: true,
+ },
+ opts || {}
+ );
+ var ignoreTypes = options.ignoreTypes;
+ var stringToArray = options.stringToArray;
+ var boolToArray = options.boolToArray;
+ var clone = options.clone;
+
+ // @NOTE: much better size but oh well
+ // const ignoreTypes = ['null', 'undefined']
+ // const stringToArray = true
+ // const boolToArray = false
+ // const clone = true
+
+ // check one then check the other
+ if (_true(index$4(ignoreTypes, simpleKindOf(obj1)))) {
+ return obj2
+ }
+ else if (_true(index$4(ignoreTypes, simpleKindOf(obj2)))) {
+ return obj1
+ }
+ else if (boolean_1(obj1) && boolean_1(obj2)) {
+ // @NOTE uglifier optimizes into a wicked ternary
+ return boolToArray ? [obj1, obj2] : obj2
+ }
+ else if (string(obj1) && string(obj2)) {
+ return stringToArray ? [obj1, obj2] : obj1 + obj2
+ }
+ else if (array(obj1) && string(obj2)) {
+ return (clone ? obj1.slice(0) : obj1).concat([obj2])
+ }
+ else if (string(obj1) && array(obj2)) {
+ return (clone ? obj2.slice(0) : obj2).concat([obj1])
+ }
+ else {
+ return deepmerge(obj1, obj2, options)
+ }
+ }
+
+ var dopemerge_1 = dopemerge;
+
+ /* ___filename___: dist/deps/dopemerge/dopemerge.js */
+
+ var index$2 = dopemerge_1;
+
+ /* ___filename___: dist/deps/util/from.js */
+ /**
+ * @tutorial https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from
+ * @see https://github.com/lodash/lodash/blob/master/.internal/setToArray.js
+ * ^ could use if needed
+ */
+ var from = Array.from;
+
+ /* ___filename___: dist/deps/util/from.js */
+
+ /* ___filename___: dist/deps/reduce/reduce.js */
+
+
+ /**
+ * @desc Map -> Object
+ * @since 4.0.0
+ *
+ * @param {Map} map map to reduce, calls entries, turns into an array, then object
+ * @return {Object} reduced object
+ *
+ * @see ArrayFrom
+ *
+ * @example
+ *
+ * var emptyMap = new Map()
+ * reduce(emptyMap)
+ * // => {}
+ *
+ * @example
+ *
+ * var map = new Map()
+ * map.set('eh', 1)
+ * reduce(map)
+ * // => {eh: 1}
+ *
+ */
+ var reduce = function (map) {
+ var reduced = {};
+
+ // only need to do this if we actually have values in our Map
+ if (map.size !== 0) {
+ reduced = from(map.entries()).reduce(function (acc, ref) {
+ var key = ref[0];
+ var value = ref[1];
+
+ acc[key] = value;
+ return acc
+ }, reduced);
+ }
+
+ return reduced
+ };
+
+ /* ___filename___: dist/deps/reduce/reduce.js */
+
+ var index$6 = reduce;
+
+ /* ___filename___: dist/deps/is/obj.js */
+
+
+
+
+ /**
+ * @func isObj
+ *
+ * Checks if `value` is the
+ * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
+ * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+ *
+ * @since 3.0.0
+ * @category Lang
+ *
+ * @param {*} value The value to check.
+ * @return {boolean} Returns `true` if `value` is an object, else `false`.
+ *
+ * @memberOf is
+ * @see http://stackoverflow.com/questions/34111902/why-do-lodashs-isobject-isplainobject-behave-differently-than-typeof-x
+ * @see https://github.com/lodash/lodash/blob/master/isObject.js
+ * @NOTE Object.prototype.toString.call(val) === '[object Object]'
+ *
+ * @example
+ *
+ * isObject({})
+ * // => true
+ *
+ * isObject([1, 2, 3])
+ * // => true
+ *
+ * isObject(Function)
+ * // => true
+ *
+ * isObject(null)
+ * // => false
+ *
+ */
+ var obj = function (x) { return !_null(x) && (objTypeof(x) || _function(x)); };
+
+ /* ___filename___: dist/deps/is/obj.js */
+
+ /* ___filename___: dist/deps/reduce/entries.js */
+
+
+
+
+
+
+ /**
+ * @desc recursively reduce maps and objects that include reducable data
+ * @since 4.0.0
+ *
+ * @sig reduced => object => isMap(object) -> reduced; merge(object, reduced)
+ *
+ * @param {Object | any} reduced merged object and reduced
+ * @return {Function} Function(values: Object)
+ *
+ * @see https://www.airpair.com/javascript/javascript-array-reduce
+ * @see ChainedMap
+ *
+ * @example
+ *
+ * const map = new Map()
+ * map.set('eh', true)
+ * const nested = new Map()
+ * nested.set('reduced', true)
+ *
+ * const chain = {
+ * entries() {
+ * return {
+ * nested: reduce(nested),
+ * key: true,
+ * }
+ * },
+ * }
+ * const reduced = reduce(map)
+ * reduceEntries(reduced)({chain})
+ * // => {
+ * eh: true,
+ * chain: {
+ * nested: {
+ * reduced: true,
+ * key: true,
+ * },
+ * },
+ * }
+ *
+ * @example
+ *
+ * const reducedIgnored = {
+ * canada: {
+ * store: chain,
+ * },
+ * }
+ * const ignored = reduceEntries(reduced)(reducedIgnored)
+ * //=> {
+ * eh: true,
+ * chain: {
+ * nested: {
+ * reduced: true,
+ * },
+ * key: true,
+ * },
+ * }
+ *
+ */
+ var entries = function (reduced) { return function (obj$$1) {
+ var keys$$2 = keys(obj$$1);
+
+ for (var k = 0; k < keys$$2.length; k++) {
+ var key = keys$$2[k];
+
+ if (ignored(key)) {
+ continue
+ }
+
+ var value = obj$$1[key];
+ if (obj(value) && _function(value.entries)) {
+ assign(reduced, {[key]: value.entries(true) || {}});
+ }
+ }
+
+ return reduced
+ }; };
+
+ /* ___filename___: dist/deps/is/iterator.js */
+
+
+ /**
+ * @param {*} x value
+ * @return {boolean} isIterator
+ *
+ * @since 3.0.0
+ * @memberOf is
+ * @func isIterator
+ * @see https://github.com/jonschlinkert/kind-of/pull/12
+ *
+ * @example
+ *
+ * isIterator(new Set().values())
+ * //=> true
+ * isIterator(new Map.entries())
+ * //=> true
+ * isIterator(new Map())
+ * //=> false
+ * isIterator('')
+ * //=> false
+ * isIterator(1)
+ * //=> false
+ *
+ * @example
+ *
+ * const e = {}
+ * eh[Symbol.toStringTag] = '[Map Iterator]'
+ * isIterator(eh)
+ * //=> true
+ * eh[Symbol.toStringTag] = '[Set Iterator]'
+ * isIterator(eh)
+ * //=> true
+ *
+ * @example
+ *
+ * class Eh extends Set()
+ * isIterator(new Eh().values())
+ * //=> true
+ *
+ */
+ // eslint-disable-next-line
+ var iterator$2 = function (x) { return ~toS(x).indexOf('Iterator'); };
+
+ /* ___filename___: dist/deps/is/iterator.js */
+
+ /* ___filename___: dist/deps/to-arr.js */
+
+
+
+
+
+
+
+ /**
+ * @desc anything into an array
+ * @sig * => Array
+ * @since 0.0.1
+ *
+ * @param {any} ar turn this into an array
+ * @return {Array} anything into an array
+ *
+ * @tests deps/to-arr
+ * @types deps
+ *
+ * @example
+ *
+ * toarr([])
+ * // => []
+ *
+ * toarr('')
+ * // => ['']
+ *
+ * toarr('1,2')
+ * // => ['1', '2']
+ *
+ * toarr('1,2')
+ * // => ['1', '2']
+ *
+ * const map = new Map()
+ * map.set('eh', true)
+ * const arr = toarr(map.entries())
+ * // => ['eh', true]
+ *
+ * const set = new Set()
+ * set.add('eh')
+ * set.add(true)
+ * const arr = toarr(map.entries())
+ * // => ['eh', true]
+ *
+ * toarr('').concat(toarr(false)).concat(toarr(null))
+ * // => ['', false, null]
+ *
+ */
+ var toArr = function(ar) {
+ // @NOTE: !'' === true
+ if (stringPrimitive(ar)) { return ar.includes(',') ? ar.split(',') : [ar] }
+ else if (!ar) { return [ar] }
+ else if (array(ar)) { return ar }
+ else if (set(ar) || map(ar) || ar.values) {
+ /**
+ * @desc when using `new Set().values`... no forEach o.o
+ * .values is also on `Object`...
+ */
+ return from(ar.values(ar))
+ }
+ else if (iterator$2(ar)) { return from(ar) }
+ else { return [ar] }
+ };
+
+ /* ___filename___: dist/deps/to-arr.js */
+
+ /* ___filename___: dist/deps/concat.js */
+
+
+ /**
+ * @desc conat two values, coerce to arrays
+ * @since 4.0.0
+ *
+ * @func
+ * @name concat
+ *
+ * @param {Array | *} one toArr1
+ * @param {Array | *} two toArr2
+ * @return {Array} [one, two]
+ *
+ * @example
+ *
+ * concat([1], [2]) //=> [1, 2]
+ * concat([1], 2) //=> [1, 2]
+ * concat(1, 2) //=> [1, 2]
+ * concat(new Set([1]), 2) //=> [1, 2]
+ *
+ * // kind of weird...
+ * concat(null, 2) //=> [2]
+ * concat(undefined, 2) //=> [2]
+ * concat(1, null) //=> [1, null]
+ *
+ */
+ var concat = function (one, two) { return toArr(one || []).concat(toArr(two)); };
+
+ /* ___filename___: dist/deps/fp/always.js */
+ /**
+ * Returns a function that always returns the given value. Note that for
+ * non-primitives the value returned is a reference to the original value.
+ *
+ * This function is known as `const`, `constant`, or `K` (for K combinator) in
+ * other languages and libraries.
+ *
+ * @alias always
+ * @alias constant
+ * @func
+ * @memberOf fp
+ * @since v5.0.0
+ * @category Function
+ * @sig a -> (* -> a)
+ *
+ * @param {*} value The value to wrap in a function
+ * @return {Function} A Function :: * -> val.
+ *
+ * @see https://github.com/ramda/ramda/issues/1038
+ * @see https://github.com/ramda/ramda/blob/master/src/always.js
+ *
+ * @example
+ *
+ * var t = always('Tee');
+ * t(); //=> 'Tee'
+ *
+ */
+
+ /* ___filename___: dist/deps/meta/transformers.js */
+ /* istanbul ignore next: wip build */
+ var transformers = process.env.NODE_ENV === 'production'
+ ? 'transformers'
+ : 'transformers';
+
+ /* ___filename___: dist/deps/meta/observers.js */
+ /* istanbul ignore next: wip build */
+ var observers = process.env.NODE_ENV === 'production'
+ ? 'observers'
+ : 'observers';
+
+ /* ___filename___: dist/deps/meta/shorthands.js */
+ /* istanbul ignore next: wip build */
+ var shorthands = process.env.NODE_ENV === 'production'
+ ? 'shorthands'
+ : 'shorthands';
+
+ /* ___filename___: dist/deps/meta/decorated.js */
+ /* istanbul ignore next: wip build */
+ var decorated = process.env.NODE_ENV === 'production'
+ ? 'decorated'
+ : 'decorated';
+
+ /* ___filename___: dist/deps/concat.js */
+
+ /* ___filename___: dist/deps/fp/always.js */
+
+ /* ___filename___: dist/deps/meta/transformers.js */
+
+ /* ___filename___: dist/deps/meta/observers.js */
+
+ /* ___filename___: dist/deps/meta/shorthands.js */
+
+ /* ___filename___: dist/deps/meta/decorated.js */
+
+ /* ___filename___: dist/deps/meta/meta.js */
+ // without it, the arguments & caller are uglier when drbugging
+
+
+
+
+
+
+
+
+
+
+
+
+
+ // will expand this later
+ var isInKeyMapAsSet = function (x) { return x === observers; };
+ var emptyArray = []; // always([])
+
+ // @NOTE: using `[]` deopts o.o
+ // eslint-disable-next-line
+ // this.shorthands = new Array()
+
+ /**
+ * @since 4.0.0
+ * @param {Chain} _this
+ * @return {Chain}
+ */
+ function getMeta(_this) {
+ // if we already have it, keep it
+ if (_this.meta) { return _this.meta }
+
+ // the store
+ // shorthands: key -> method
+ var store = {};
+
+ // --- uglifiable functions
+
+ /** @desc initialize the store maps when we need them */
+ /* prettier-ignore */
+ var ensureInitialized = function (name, value) {
+ if (!_undefined(store[name])) { return }
+
+ // if (
+ // name === TRANSFORMERS_KEY ||
+ // name === SHORTHANDS_KEY ||
+ // name === DECORATED_KEY
+ // ) {
+ // store[name] = new Map()
+ // }
+ // else
+ if (isInKeyMapAsSet(name)) {
+ store[name] = new Set();
+ }
+ else {
+ store[name] = new Map();
+ }
+ };
+
+ /**
+ * @since 4.0.0
+ * @param {Primitive} key
+ * @param {Primitive | undefined} [prop=undefined]
+ * @return {boolean}
+ */
+ var has = function (key, prop) {
+ if (_undefined(prop)) { return !!store[key].size }
+ else { return store[key].has(prop) }
+ };
+ /**
+ * @since 4.0.0
+ * @param {Primitive} key
+ * @param {Primitive | undefined} [prop=undefined]
+ * @return {any}
+ */
+ var get = function (key, prop) { return (has(key, prop) ? store[key].get(prop) : emptyArray); };
+
+ /**
+ * @since 4.0.0
+ * @param {Primitive} key
+ * @param {Primitive | undefined} [prop=undefined]
+ * @param {Primitive | undefined} [value=undefined]
+ * @return {void}
+ */
+ var set$$2 = function (key, prop, value) {
+ var storage = store[key];
+ // when it's a set, we have no `prop`, we just have .add
+ // so `prop = value` && `value = undefined`
+ if (set(storage)) {
+ storage.add(prop);
+ }
+ else {
+ // if (!has(key, prop)) return
+ var existing = storage.get(prop);
+ var val = concat(existing, value);
+ storage.set(prop, val);
+ }
+ };
+
+ /**
+ * @since 4.0.0
+ *
+ * @desc a single easily minifiable function,
+ * dynamically setting & getting depending on arguments
+ * to avoid nested property accessing
+ * only instantiating when values are **addded**
+ *
+ * @param {Primitive} key
+ * @param {Primitive | undefined} [prop=undefined]
+ * @param {undefined | any} [value=undefined] (when no value, it's a getter)
+ * @return {Array | Chain} depending on args
+ */
+ function meta(key, prop, value) {
+ if (process.env.NODE_ENV === 'DEBUG') {
+ console.log('USING META', {key: key, prop: prop, value: value});
+ }
+
+ /* prettier-ignore */
+ if (_undefined(value)) {
+ // when we want to just access the property, return an array
+ // @example `.meta('transformers')`
+ if (_undefined(prop)) {
+ if (_undefined(store[key])) { return emptyArray }
+ else { return store[key].size === 0 ? emptyArray : from(store[key].values()) }
+ }
+ // we have `key, prop`
+ //
+ // 1: should `prop` be a value, (isSet?)
+ else if (isInKeyMapAsSet(key)) {
+ ensureInitialized(key);
+ set$$2(key, prop);
+ }
+ // 2: prop is a key, we want to return the [..] for that specific property
+ // @example `.meta('transformers', 'eh')`
+ else if (_undefined(store[key])) { return emptyArray }
+ else { return toArr(get(key, prop)) }
+ }
+ // we have `key, prop, value`
+ else {
+ ensureInitialized(key);
+ // we have a value, let's add it
+ set$$2(key, prop, value);
+ }
+ return _this
+ }
+
+ // for debugging
+ meta.store = store;
+ // meta.debug = false
+
+ return meta
+ }
+
+ var meta = getMeta;
+
+ /* ___filename___: dist/deps/meta/meta.js */
+
+ var index$8 = meta;
+
+ /* ___filename___: dist/Chainable.js */
+
+ /* ___filename___: dist/deps/reduce/entries.js */
+
+ /* ___filename___: dist/ChainedMapBase.js */
+
+
+
+
+
+
+
+
+
+
+ /**
+ * this is to avoid circular requires
+ * because MergeChain & MethodChain extend this
+ * yet .method & .merge use those chains
+ * ...also, it serves as a non-references creator for extending new instances
+ * of Chainable, where it splits into (Map | Set) -> composed prototype decorators
+ *
+ *
+ * @file
+ * @since 4.0.0-alpha.1
+ * @inheritdoc
+ * @class ChainedMapBase
+ * @member ChainedMapBase
+ * @category Chainable
+ * @extends {Chainable}
+ * @type {Chainable}
+ *
+ * @types ChainedMapBase
+ * @tests ChainedMap
+ *
+ * @prop {Meta} meta meta fn
+ * @prop {Map} store main store
+ *
+ * {@link https://tc39.github.io/ecma262/#sec-map-objects emca-map}
+ * {@link https://ponyfoo.com/articles/es6-maps-in-depth pony-map}
+ * {@link https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map mozilla-map}
+ * @see {@link pony-map}
+ * @see {@link mozilla-map}
+ * @see {@link emca-map}
+ *
+ * @see ChainedMap
+ * @see Chainable
+ * @see MergeChain
+ * @see MethodChain
+ * @see ChainedMap
+ *
+ */
+
+ var ComposeChainedMapBase = function (Target) {
+ return (function (Target) {
+ function ChainedMapBase(parent) {
+ Target.call(this, parent);
+
+ this.store = new Map();
+ this.meta = index$8(this);
+ }
+
+ if ( Target ) ChainedMapBase.__proto__ = Target;
+ ChainedMapBase.prototype = Object.create( Target && Target.prototype );
+ ChainedMapBase.prototype.constructor = ChainedMapBase;
+
+ /**
+ * @desc tap a value with a function
+ * @modifies this.store.get(name)
+ * @memberOf ChainedMapBase
+ * @version 0.7.0
+ * @since 4.0.0-alpha.1 <- moved from transform & shorthands
+ *
+ * @param {string | any} name key to `.get`
+ * @param {Function} fn function to tap with
+ * @return {Chain} @chainable
+ *
+ * {@link https://github.com/sindresorhus/awesome-tap awesome-tap}
+ * {@link https://github.com/midknight41/map-factory map-factory}
+ * {@link https://github.com/webpack/tapable tapable}
+ * @see {@link tapable}
+ *
+ * @see ChainedMapBase.set
+ * @see ChainedMapBase.get
+ *
+ * @example
+ *
+ * chain
+ * .set('moose', {eh: true})
+ * .tap('moose', moose => {moose.eh = false; return moose})
+ * .get('moose')
+ *
+ * // => {eh: false}
+ *
+ * @example
+ *
+ * const entries = new Chain()
+ * .set('str', 'emptyish')
+ * .tap('str', str => str + '+')
+ * .set('arr', [1])
+ * .tap('arr', arr => arr.concat([2]))
+ * .entries()
+ *
+ * //=> {str: 'emptyish+', arr: [1, 2]}
+ *
+ */
+ ChainedMapBase.prototype.tap = function tap (name, fn) {
+ return this.set(name, fn(this.get(name), index$2))
+ };
+
+ /**
+ * @desc checks each property of the object
+ * calls the chains accordingly
+ *
+ * @memberOf ChainedMapBase
+ * @since 0.5.0
+ *
+ * @param {Object} obj object with functions to hydrate from
+ * @return {Chainable} @chainable
+ *
+ * @TODO could also add parsing stringified
+ *
+ * @example
+ *
+ * const from = new Chain().from({eh: true})
+ * const eh = new Chain().set('eh', true)
+ * eq(from, eh)
+ * // => true
+ *
+ */
+ ChainedMapBase.prototype.from = function from (obj) {
+ var this$1 = this;
+
+ var keys$$1 = keys(obj);
+
+ for (var k = 0; k < keys$$1.length; k++) {
+ var key = keys$$1[k];
+ var value = obj[key];
+ var fn = this$1[key];
+
+ if (fn && fn.merge) {
+ fn.merge(value);
+ }
+ else if (_function(fn)) {
+ fn.call(this$1, value);
+ }
+ else {
+ this$1.set(key, value);
+ }
+ }
+
+ return this
+ };
+
+ /**
+ * @desc shorthand methods, from strings to functions that call .set
+ * @since 0.4.0
+ * @memberOf ChainedMapBase
+ *
+ * @param {Array} methods decorates/extends an object with new shorthand functions to get/set
+ * @return {ChainedMapBase} @chainable
+ *
+ * @example
+ *
+ * const chain1 = new Chain()
+ * chain1.extend(['eh'])
+ *
+ * const chain2 = new Chain()
+ * chain2.eh = val => this.set('eh', val)
+ *
+ * eq(chain2.eh, chain1.eh)
+ * //=> true
+ *
+ */
+ ChainedMapBase.prototype.extend = function extend (methods) {
+ var this$1 = this;
+
+ methods.forEach(function (method) {
+ this$1.meta(shorthands, method);
+ this$1[method] = function (value) { return this$1.set(method, value); };
+ });
+ return this
+ };
+
+ /**
+ * @desc spreads the entries from ChainedMapBase.store (Map)
+ * return store.entries, plus all chain properties if they exist
+ *
+ * @memberOf ChainedMapBase
+ * @version 4.0.0 <- improved reducing
+ * @since 0.4.0
+ *
+ * @param {boolean} [chains=false] if true, returns all properties that are chains
+ * @return {Object} reduced object containing all properties from the store, and when `chains` is true, all instance properties, and recursive chains
+ *
+ * //
+ *
+ * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/entries mozilla-map-entries}
+ * @see {@link mozilla-map-entries}
+ *
+ * @example
+ *
+ * map.set('a', 'alpha').set('b', 'beta').entries()
+ * //=> {a: 'alpha', b: 'beta'}
+ *
+ */
+ ChainedMapBase.prototype.entries = function entries$$1 (chains) {
+ var reduced = index$6(this.store);
+ if (_undefined(chains)) { return reduced }
+
+ var reducer = entries(reduced);
+ reducer(this);
+ reducer(reduced);
+ return reduced
+ };
+
+ /**
+ * @desc get value for key path in the Map store
+ * ❗ `debug` is a special key and is *not* included into .store
+ * it goes onto .meta
+ *
+ * @memberOf ChainedMapBase
+ * @version 4.0.0 <- moved debug here
+ * @since 0.4.0
+ *
+ * @param {Primitive} key Primitive data key used as map property to reference the value
+ * @return {any} value in .store at key
+ *
+ * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get mozilla-map-get}
+ * @see {@link mozilla-map-get}
+ *
+ * @example
+ *
+ * const chain = new Chain()
+ * chain.set('eh', true)
+ * chain.get('eh')
+ * //=> true
+ *
+ * chain.get('nope')
+ * //=> undefined
+ *
+ */
+ ChainedMapBase.prototype.get = function get (key) {
+ if (key === 'debug') { return this.meta.debug }
+ return this.store.get(key)
+ };
+
+ /**
+ * @desc sets the value using the key on store
+ * adds or updates an element with a specified key and value
+ *
+ * @memberOf ChainedMapBase
+ * @since 0.4.0
+ *
+ * @param {Primitive} key Primitive to reference the value
+ * @param {any} value any data to store
+ * @return {ChainedMapBase} @chainable
+ *
+ * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/set mozilla-map-set}
+ *
+ * @see {@link mozilla-map-set}
+ * @see ChainedMapBase.store
+ *
+ * @example
+ *
+ * const chain = new Chain()
+ * chain.set('eh', true)
+ * chain.get('eh')
+ * //=> true
+ *
+ */
+ ChainedMapBase.prototype.set = function set (key, value) {
+ this.store.set(key, value);
+ return this
+ };
+
+ return ChainedMapBase;
+ }(Target))
+ };
+
+ /**
+ * @desc ChainedMapBase composer
+ * @alias ComposeMap
+ * @type {Composer}
+ * @method compose
+ * @memberOf ChainedMapBase
+ *
+ * @param {Class | Object | Composable} [Target=Chainable] class to extend
+ * @return {Class} ChainedMapBase
+ *
+ * @example
+ *
+ * const heh = class {}
+ * const composed = ChainedMapBase.compose(heh)
+ * const hehchain = new Composed()
+ * hehchain instanceof heh
+ * //=> true
+ *
+ */
+ var cmc = ComposeChainedMapBase(Chainable);
+ cmc.compose = ComposeChainedMapBase;
+
+ var ChainedMapBase = cmc;
+
+ /* ___filename___: dist/deps/env/debug.js */
+ var debug = process.env.NODE_ENV === 'debug'; // || process.env.DEBUG = true
+
+ /* ___filename___: dist/deps/util/keysObjOrArray.js */
+
+
+
+
+ /**
+ * Creates an array of the own enumerable property names of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects. See the
+ * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
+ * for more details.
+ *
+ * @since 0.1.0
+ * @category Object
+ *
+ * @param {Object} object The object to query.
+ * @return {Array} Returns the array of property names.
+ *
+ * @see deps/util/props
+ * @see values, valuesIn
+ * @see https://github.com/lodash/lodash/blob/master/.internal/getAllKeys.js
+ * @see https://github.com/lodash/lodash/blob/master/keys.js
+ * @TODO https://github.com/lodash/lodash/blob/master/.internal/arrayLikeKeys.js
+ *
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1
+ * this.b = 2
+ * }
+ *
+ * Foo.prototype.c = 3
+ *
+ * keys(new Foo)
+ * // => ['a', 'b'] (iteration order is not guaranteed)
+ *
+ * keys('hi')
+ * // => ['0', '1']
+ *
+ */
+
+ var zeroOneLength = function (obj$$2) { return (obj$$2.length > 1 ? obj$$2.length - 1 : obj$$2.length === 1 ? 1 : 0); };
+
+ var keysObjOrArray = function keys$$2(obj$$2) {
+ return array(obj$$2)
+ ? new Array(zeroOneLength(obj$$2))
+ : obj(obj$$2) ? keys(obj$$2) : []
+
+ // for (var key in obj) gathered.push(key)
+ // return gathered
+ };
+
+ /* ___filename___: dist/deps/util/keysObjOrArray.js */
+
+ /* ___filename___: dist/deps/is/empty.js */
+
+
+
+
+
+ /* prettier-ignore */
+ /**
+ * Returns `true` if the given value is its type's empty value;
+ * `false` otherwise.
+ *
+ * @func
+ * @memberOf is
+ * @since v0.1.0
+ * @category Logic
+ * @sig a -> Boolean
+ *
+ * @param {*} x value to check if empty
+ * @return {boolean}
+ *
+ * @see empty
+ * @see https://github.com/ramda/ramda/issues/1228
+ *
+ * @example
+ *
+ * isEmpty([1, 2, 3]); //=> false
+ * isEmpty([]); //=> true
+ * isEmpty(''); //=> true
+ * isEmpty(null); //=> false
+ * isEmpty({}); //=> true
+ * isEmpty({length: 0}); //=> false
+ *
+ */
+ var empty = function isEmpty(x) {
+ if (x === '') { return true }
+ else if (nullOrUndefined(x)) { return false }
+ else if (obj(x) || array(x)) { return keysObjOrArray(x).length === 0 }
+ else { return false }
+
+ // else return (
+ // // null|undefined = empty
+ // // isNullOrUndefined(x) ||
+ // // '' = empty
+ // // [] | {} = empty
+ // keys(x).length === 0
+ // )
+ };
+
+ /* ___filename___: dist/deps/is/error.js */
+
+
+ /**
+ * @param {*} x value
+ * @return {boolean} isError
+ *
+ * @since 4.0.0
+ * @memberOf is
+ * @func isError
+ *
+ * @example
+ *
+ * isError(new Error())
+ * //=> true
+ * isError(new Error().stack)
+ * //=> false
+ * isError(1)
+ * //=> false
+ * isError('')
+ * //=> false
+ *
+ * @example
+ *
+ * const e = {}
+ * eh[Symbol.toStringTag] = '[Object Error]'
+ * isError(eh)
+ * //=> true
+ *
+ * @example
+ *
+ * class Eh extends Error()
+ * isError(new Eh())
+ * //=> true
+ *
+ */
+ var error$1 = function isError(x) {
+ // console.log('isError', toS(x), x)
+ return toS(x) === '[object Error]'
+ // x instanceof Error ||
+ };
+
+ /* ___filename___: dist/deps/is/symbol.js */
+
+
+ /**
+ * Checks if `value` is classified as a `Symbol` primitive or object.
+ *
+ * @since 4.0.0
+ * @category Lang
+ * @memberOf is
+ *
+ * @param {*} value The value to check.
+ * @return {boolean} Returns `true` if `value` is a symbol, else `false`.
+ *
+ * @example
+ *
+ * isSymbol(Symbol.iterator)
+ * // => true
+ *
+ * isSymbol('abc')
+ * // => false
+ *
+ */
+ var symbol = function (x) { return toS(x) === '[object Symbol]'; };
+
+ /* ___filename___: dist/deps/is/async.js */
+
+
+ /**
+ * @category Lang
+ *
+ * @param {*} x value
+ * @return {boolean} isAsync
+ * @since 4.0.0-beta.2
+ *
+ * @memberOf is
+ * @func isAsync
+ *
+ * @example
+ *
+ * isAsync(async function() {})
+ * //=> true
+ * isAsync(new Promise(r => r()))
+ * //=> false
+ * isAsync({})
+ * //=> false
+ * isAsync(function() {})
+ */
+ var async = function isAsync(x) {
+ return toS(x) === '[object AsyncFunction]'
+ };
+
+ /* ___filename___: dist/deps/is/promise.js */
+
+
+ /**
+ * @desc is a Promise
+ * @param {*} x value
+ * @return {boolean} x isPromise
+ *
+ * @since 4.0.0-beta.2
+ * @memberOf is
+ * @func isPromise
+ *
+ * @see https://github.com/jonschlinkert/kind-of/blob/master/index.js#L66
+ * @see https://github.com/sindresorhus/promise-fun
+ *
+ * @example
+ *
+ * isPromise(new Promise(r => r))
+ * //=> true
+ * isPromise(async function() {})
+ * //=> false // on some environments, true
+ *
+ * isPromise({})
+ * //=> false
+ * isPromise(Object.create(null))
+ * //=> false
+ * isPromise(null)
+ * //=> false
+ * isPromise(new Set())
+ * //=> false
+ * isPromise(function() {})
+ * //=> false
+ * isPromise('')
+ * //=> false
+ * isPromise(1)
+ * //=> false
+ *
+ */
+ var promise = function (x) { return toS(x) === '[object Promise]'; };
+
+ /* ___filename___: dist/deps/is/async.js */
+
+ /* ___filename___: dist/deps/is/promise.js */
+
+ /* ___filename___: dist/deps/is/asyncish.js */
+
+
+
+ /**
+ * @desc async function or promise
+ * @category Lang
+ *
+ * @param {*} x value
+ * @return {boolean} x isAsyncish
+ * @since 4.0.0-beta.2
+ *
+ * @memberOf is
+ * @func isAsyncish
+ * @extends isAsyncish
+ * @extends isPromise
+ * @variation isAsyncish OR isPromise
+ *
+ * @example
+ *
+ * isAsyncish(async function() {})
+ * //=> true
+ * isAsyncish(new Promise(r => r()))
+ * //=> true
+ *
+ * isAsyncish({})
+ * //=> false
+ * isAsyncish(function() {})
+ */
+ var asyncish = function (x) { return async(x) || promise(x); };
+
+ /* ___filename___: dist/deps/is/numberPrimitive.js */
+ /**
+ * @param {*} x value
+ * @return {boolean} isNumberPrimitive
+ *
+ * @since 3.0.0
+ * @memberOf is
+ * @func isNumberPrimitive
+ * @see is/real
+ *
+ * @example
+ *
+ * isNumberPrimitive(1)
+ * //=> true
+ * isNumberPrimitive(Number(1))
+ * //=> true
+ * isNumberPrimitive(NaN)
+ * //=> true
+ * isNumberPrimitive(new Number(1))
+ * //=> false
+ *
+ * isNumberPrimitive(null)
+ * //=> false
+ * isNumberPrimitive(undefined)
+ * //=> false
+ * isNumberPrimitive(void 0)
+ * //=> false
+ * isNumberPrimitive({})
+ * //=> false
+ * isNumberPrimitive('')
+ * //=> false
+ * isNumberPrimitive(false)
+ * //=> false
+ *
+ */
+ var numberPrimitive = function (x) { return typeof x === 'number'; };
+
+ /* ___filename___: dist/deps/is/numberPrimitive.js */
+
+ /* ___filename___: dist/deps/is/primitive.js */
+
+
+
+
+
+ /**
+ * Checks if `value` is classified as a `String` **primitive**.
+ *
+ * @since 3.0.0
+ * @category Lang
+ * @memberOf is
+ * @param {*} x The value to check.
+ * @returns {boolean} Returns `true` if `value` is a string, else `false`.
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String
+ * @see https://github.com/lodash/lodash/blob/master/isString.js
+ * @see is/string
+ *
+ * @example
+ *
+ * isPrimitive('abc') // => true
+ * isPrimitive(new String('abc')) // => false
+ * isPrimitive(1) // => true
+ * isPrimitive([]) // => false
+ * isPrimitive('') // => true
+ * isPrimitive({}) // => false
+ *
+ */
+ var primitive$2 = function isPrimitive(node) {
+ return (
+ nullOrUndefined(node) ||
+ stringPrimitive(node) ||
+ numberPrimitive(node) ||
+ boolean_1(node) // isBooleanPrimitive
+ )
+ };
+
+ /* ___filename___: dist/deps/fp/isPlaceholder.js */
+ var isPlaceholder = function _isPlaceholder(x) {
+ return x === '_'
+ };
+
+ /* ___filename___: dist/deps/fp/arity.js */
+ /* istanbul ignore next: metadata, one is covered, all are covered */
+ /* prettier-ignore */
+ /**
+ * @desc just for `.length` of a function?
+ * @memberOf fp
+ *
+ * @since 5.0.0
+ * @param {number} n number of arguments
+ * @param {Function} fn function to wrap
+ * @return {Function} function with params
+ *
+ * @TODO keeping this means change uglify...
+ *
+ * @example
+ * const wan = one => console.log(one)
+ * arity(1, wan)
+ * => function(one => wan(one))
+ */
+ var arity = function _arity(n, fn) {
+ /* eslint-disable no-unused-vars */
+ if (n === 0) { return function() { return fn.apply(this, arguments) } }
+ else if (n === 1) { return function(a0) { return fn.apply(this, arguments) } }
+ else if (n === 2) { return function(a0, a1) { return fn.apply(this, arguments) } }
+ else if (n === 3) { return function(a0, a1, a2) { return fn.apply(this, arguments) } }
+ else if (n === 4) { return function(a0, a1, a2, a3) { return fn.apply(this, arguments) } }
+ else if (n === 5) { return function(a0, a1, a2, a3, a4) { return fn.apply(this, arguments) } }
+ else if (n === 6) { return function(a0, a1, a2, a3, a4, a5) { return fn.apply(this, arguments) } }
+ else if (n === 7) { return function(a0, a1, a2, a3, a4, a5, a6) { return fn.apply(this, arguments) } }
+ else if (n === 8) { return function(a0, a1, a2, a3, a4, a5, a6, a7) { return fn.apply(this, arguments) } }
+ else if (n === 9) { return function(a0, a1, a2, a3, a4, a5, a6, a7, a8) { return fn.apply(this, arguments) } }
+ else if (n === 10) { return function(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) { return fn.apply(this, arguments) } }
+ };
+
+ /* ___filename___: dist/deps/fp/isPlaceholder.js */
+
+ /* ___filename___: dist/deps/fp/arity.js */
+
+ /* ___filename___: dist/deps/fp/curry.js */
+
+
+
+
+ /**
+ * Returns a curried equivalent of the provided function, with the specified
+ * arity. The curried function has two unusual capabilities. First, its
+ * arguments needn't be provided one at a time. If `g` is `R.curryN(3, f)`, the
+ * following are equivalent:
+ *
+ * - `g(1)(2)(3)`
+ * - `g(1)(2, 3)`
+ * - `g(1, 2)(3)`
+ * - `g(1, 2, 3)`
+ *
+ * Secondly, the special placeholder value [`R.__`](#__) may be used to specify
+ * "gaps", allowing partial application of any combination of arguments,
+ * regardless of their positions. If `g` is as above and `_` is [`R.__`](#__),
+ * the following are equivalent:
+ *
+ * - `g(1, 2, 3)`
+ * - `g(_, 2, 3)(1)`
+ * - `g(_, _, 3)(1)(2)`
+ * - `g(_, _, 3)(1, 2)`
+ * - `g(_, 2)(1)(3)`
+ * - `g(_, 2)(1, 3)`
+ * - `g(_, 2)(_, 3)(1)`
+ *
+ * @func
+ * @memberOf fp
+ * @since v0.5.0
+ * @category Function
+ * @sig Number -> (* -> a) -> (* -> a)
+ *
+ * @param {Number} length The arity of the curried function.
+ * @param {Array} received An array of arguments received thus far.
+ * @param {Function} fn The function to curry.
+ * @return {Function} A new, curried function.
+ *
+ * @see R.curry
+ *
+ * @example
+ *
+ * var sumArgs = (...args) => R.sum(args);
+ *
+ * var curriedAddFourNumbers = R.curryN(4, sumArgs);
+ * var f = curriedAddFourNumbers(1, 2);
+ * var g = f(3);
+ * g(4); //=> 10
+ *
+ */
+ function _curryN(length, received, fn) {
+ return function() {
+ var arguments$1 = arguments;
+
+ var combined = [];
+ var argsIdx = 0;
+ var left = length;
+ var combinedIdx = 0;
+
+ while (combinedIdx < received.length || argsIdx < arguments.length) {
+ var result = (void 0);
+
+ if (
+ combinedIdx < received.length &&
+ (!isPlaceholder(received[combinedIdx]) || argsIdx >= arguments$1.length)
+ ) {
+ result = received[combinedIdx];
+ }
+ else {
+ result = arguments$1[argsIdx++];
+ // argsIdx += 1
+ }
+ combined[combinedIdx++] = result;
+ if (!isPlaceholder(result)) {
+ left -= 1;
+ }
+ // combinedIdx += 1
+ }
+ return left <= 0
+ ? fn.apply(this, combined)
+ : arity(left, _curryN(length, combined, fn))
+ }
+ }
+
+ /**
+ * Returns a curried equivalent of the provided function, with the specified
+ * arity. The curried function has two unusual capabilities. First, its
+ * arguments needn't be provided one at a time. If `g` is `R.curryN(3, f)`, the
+ * following are equivalent:
+ *
+ * - `g(1)(2)(3)`
+ * - `g(1)(2, 3)`
+ * - `g(1, 2)(3)`
+ * - `g(1, 2, 3)`
+ *
+ * Secondly, the special placeholder value [`R.__`](#__) may be used to specify
+ * "gaps", allowing partial application of any combination of arguments,
+ * regardless of their positions. If `g` is as above and `_` is [`R.__`](#__),
+ * the following are equivalent:
+ *
+ * - `g(1, 2, 3)`
+ * - `g(_, 2, 3)(1)`
+ * - `g(_, _, 3)(1)(2)`
+ * - `g(_, _, 3)(1, 2)`
+ * - `g(_, 2)(1)(3)`
+ * - `g(_, 2)(1, 3)`
+ * - `g(_, 2)(_, 3)(1)`
+ *
+ * @func
+ * @memberOf fp
+ * @since v0.5.0
+ * @category Function
+ * @sig Number -> (* -> a) -> (* -> a)
+ *
+ * @param {Number} length The arity for the returned function.
+ * @param {Function} fn The function to curry.
+ * @return {Function} A new, curried function.
+ *
+ * @see ramda
+ *
+ * @example
+ *
+ * var sumArgs = (...args) => R.sum(args);
+ *
+ * var curriedAddFourNumbers = R.curryN(4, sumArgs);
+ * var f = curriedAddFourNumbers(1, 2);
+ * var g = f(3);
+ * g(4); //=> 10
+ *
+ */
+ var curry = function curryN(length, fn) {
+ return arity(length, _curryN(length, [], fn))
+ };
+
+ /* ___filename___: dist/deps/fp/curry.js */
+
+ /* ___filename___: dist/deps/fp/prop.js */
+
+
+ /**
+ * Returns a function that when supplied an object returns the indicated
+ * property of that object, if it exists.
+ *
+ * @func
+ * @memberOf fp
+ * @since v5.0.0
+ * @category Object
+ * @sig s -> {s: a} -> a | Undefined
+ *
+ * @param {String} p The property name
+ * @param {Object} obj The object to query
+ * @return {*} The value at `obj.p`.
+ *
+ * @see R.path
+ *
+ * @example
+ *
+ * R.prop('x', {x: 100}); //=> 100
+ * R.prop('x', {}); //=> undefined
+ *
+ */
+ var prop = curry(2, function (p, obj) { return obj[p]; });
+
+ /* ___filename___: dist/deps/fp/prop.js */
+
+ /* ___filename___: dist/deps/util/length.js */
+
+
+ // reduces size by hundreds of bytes gzipped...
+ var length = prop('length');
+
+ /* ___filename___: dist/deps/util/length.js */
+
+ /* ___filename___: dist/deps/util/lengthMinusOne.js */
+
+
+ // lengthMinusOne
+ var lengthMinusOne = function (x) { return length(x) - 1; };
+
+ /* ___filename___: dist/deps/util/lengthMinusOne.js */
+
+ /* ___filename___: dist/deps/dot/segments.js */
+
+
+
+
+ var cache;
+
+ /**
+ * @name dotPropSegments
+ * @since 4.0.0
+ * @memberOf dot
+ *
+ * @param {string | Array} path dot-prop-path
+ * @return {Array} array path
+ *
+ * @example
+ *
+ * dotPropSegments('eh.oh') //=> ['eh', 'oh']
+ * dotPropSegments(['eh', 'oh']) //=> ['eh', 'oh']
+ * dotPropSegments('ehoh') //=> ['ehoh']
+ *
+ */
+ var segments = function (path) {
+ if (!cache) { cache = new Map(); }
+ if (cache.has(path)) { return cache.get(path) }
+ if (array(path)) { return path }
+
+ var pathArr = path.split('.');
+ var parts = [];
+
+ for (var i = 0; i < pathArr.length; i++) {
+ var p = pathArr[i];
+
+ /**
+ * @example 1
+ * '\.eh' -1 === '\\' (true)
+ * +1 !== undefined (true, eh)
+ *
+ * @example 2
+ * '.eh' -1 === '\\' (false, undefined)
+ * +1 !== undefined (true, eh)
+ *
+ * @example 3
+ * '\.' -1 === '\\' (true)
+ * +1 !== undefined (false, eh)
+ */
+ while (p[lengthMinusOne(p)] === '\\' && !_undefined(pathArr[i + 1])) {
+ p = p.slice(0, -1) + '.' + pathArr[++i];
+ }
+
+ parts.push(p);
+ }
+
+ cache.set(path, parts);
+ return parts
+ };
+
+ /* ___filename___: dist/deps/dot/dottable.js */
+
+
+
+
+ // const isDot = require('./is/dot')
+ // const isDottable = (obj, path) => isObj(obj) && isDot(path)
+ var dottable = function (obj$$2, path) { return (obj(obj$$2) && string(path)) || array(path); };
+
+ /* ___filename___: dist/deps/dot/segments.js */
+
+ /* ___filename___: dist/deps/dot/dottable.js */
+
+ /* ___filename___: dist/deps/dot/set.js */
+
+
+
+
+
+ var set$2 = function dotset(obj$$2, path, value) {
+ if (!dottable(obj$$2, path)) {
+ return
+ }
+
+ var pathArr = segments(path);
+
+ for (var i = 0; i < pathArr.length; i++) {
+ var p = pathArr[i];
+
+ if (!obj(obj$$2[p])) {
+ obj$$2[p] = {};
+ }
+
+ // isLast
+ if (i === lengthMinusOne(pathArr)) {
+ obj$$2[p] = value;
+ }
+
+ obj$$2 = obj$$2[p];
+ }
+ };
+
+ /* ___filename___: dist/deps/is/error.js */
+
+ /* ___filename___: dist/deps/traversers/copy.js */
+
+
+
+
+
+
+ /* prettier-ignore */
+ /**
+ * @desc copy any primitive value, part of clone
+ * @version 5.0.0
+ * @since 3.0.0
+ * @name copy
+ * @see clone
+ * @memberOf Traverse
+ *
+ * @param {*} src value to copy
+ * @return {*} copied
+ *
+ * @example
+ *
+ * copy(/eh/gmi) //=> new RegExp('eh', 'gmi')
+ * copy(new Error('eh')) // => new Error with copied stack + msg
+ * copy([1]) // => [1]
+ * copy({}) // => {}
+ *
+ */
+ var copy = function copy(src) {
+ if (objNotNull(src)) {
+ var dst;
+
+ // if (isPrimitive(src)) {
+ // if (isNullOrUndefined(src)) {
+ // dst = src
+ // }
+
+ // @TODO @IMPORTANT @FIXME @!IMPORTANT - COVER THIS OR NOT?
+ // for string value number boolean objects...
+ // if (isString(src)) {
+ // dst = src + ''
+ // }
+ // else if (isNumber(src)) {
+ // dst = src + 0
+ // }
+ // else if (isBoolean(src)) {
+ // dst = !!src
+ // }
+ // else
+
+ // lists... <- needs to have dot-prop support on Map/Set
+ // if (isMap(src)) {
+ // dst = new Map()
+ // const obj = reduce(src)
+ // // src.clear()
+ // ObjectKeys(obj).forEach(key => dst.set(key, obj[key]))
+ // return dst
+ // }
+ // else if (isSet(src)) {
+ // dst = new Set()
+ // // could clone here too
+ // const obj = toarr(src)
+ // // src.clear()
+ // obj.forEach(value => dst.add(value))
+ // return dst
+ // }
+
+ // ------
+ if (array(src)) {
+ dst = [];
+ }
+ // was new date(src.getTime())
+ // || isBoolean(src) || isNumber(src) || isString(src)
+ else if (date(src)) {
+ dst = new src.constructor(src.valueOf());
+ }
+ else if (regexp(src)) {
+ // dst = new RegExp(src)
+ dst = new RegExp(src.src, src.toString().match(/[^/]*$/)[0]);
+ dst.lastIndex = src.lastIndex;
+ }
+ else if (error$1(src)) {
+ dst = new Error(src.message);
+ dst.stack = src.stack;
+ }
+ else {
+ dst = Object.create(Object.getPrototypeOf(src));
+ }
+
+ // @TODO: copy descriptor
+ // eslint-disable-next-line
+ for (var prop in src) {
+ dst[prop] = src;
+ // const desc = Object.getOwnPropertyDescriptor(src, prop)
+ // Object.defineProperty(dst, prop, desc)
+ }
+ return dst
+ }
+ else {
+ // require('fliplog').red('is NOT OBJ').echo()
+ return src
+ }
+ };
+
+ /* ___filename___: dist/deps/is/enumerable.js */
+ var enumerable = function (obj, prop) { return Object.prototype.propertyIsEnumerable.call(obj, prop); };
+
+ /* ___filename___: dist/deps/is/enumerable.js */
+
+ /* ___filename___: dist/deps/dot/get.js */
+
+
+
+
+
+
+
+ /**
+ * @name dot.get
+ * @memberOf dot
+ * @func
+ * @since 3.0.0
+ * @extends dot/getPathSegments
+ *
+ * @param {Object} obj the object to retrieve the nested property from.
+ * @param {Dottable | string | Array} path dot-prop-path to use
+ * @param {*} fallback use when there is no value at specified path
+ * @return {*} value at path or fallback
+ *
+ * @example
+ *
+ * dot.get({a: {b: 2}}, 'a.b'); //=> 2
+ * dot.get({a: {b: 2}}, ['a', 'b']); //=> 2
+ * dot.get({c: {b: 2}}, ['a', 'b']); //=> undefined
+ *
+ */
+ var get = function(obj, path, fallback) {
+ if (!dottable(obj, path)) {
+ return _undefined(fallback) ? obj : fallback
+ }
+
+ var pathArr = segments(path);
+
+ for (var i = 0; i < pathArr.length; i++) {
+ if (!enumerable(obj, pathArr[i])) {
+ return fallback
+ }
+
+ obj = obj[pathArr[i]];
+
+ if (nullOrUndefined(obj)) {
+ /*
+ * `obj` is either `undefined` or `null` so we want to stop the loop, and
+ * if this is not the last bit of the path, and
+ * if it did't return `undefined`
+ * it would return `null` if `obj` is `null`
+ * but we want `get({foo: null}, 'foo.bar')` to equal `undefined`, or the supplied fallback, not `null`
+ */
+ if (i !== lengthMinusOne(pathArr)) {
+ return fallback
+ }
+
+ break
+ }
+ }
+
+ return obj
+ };
+
+ /* ___filename___: dist/deps/util/hasOwnProperty.js */
+ var hasOwnProperty_1 = function (haystack, needle) { return Object.prototype.hasOwnProperty.call(haystack, needle); };
+
+ // function(obj, key) {
+ // return key in obj
+ // }
+
+ /* ___filename___: dist/deps/util/hasOwnProperty.js */
+
+ /* ___filename___: dist/deps/traversers/eqValue.js */
+ // conditionals
+ /* eslint complexity: "OFF" */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ // const ENV_DEBUG = require('../env/debug')
+ var ENV_DEBUG$1 = true;
+
+ var isNotRealOrNotEqToString = function (x, y) { return !x || !y || x.toString() !== y.toString(); };
+
+ /* prettier-ignore */
+ /**
+ * @desc checks value equality, used by eq which compares all types
+ * @since 4.1.0
+ * @memberOf Traverse
+ * @protected
+ *
+ * @TODO !!!!!! USE ENUM FLAGS ON LOOSE TO ALLOW MORE CONFIG FOR ==, COMPARATOR, VALUEOF, walk proto (check ownProps...)...
+ *
+ * @param {*} x compare to y
+ * @param {*} y compare to x
+ * @param {boolean | number} [loose=false] use == checks when typof !=
+ * @return {boolean}
+ *
+ * @example
+ *
+ * eqValue(1, 1) //=> true
+ * eqValue('1', 1) //=> false
+ * eqValue('1', 1, true) //=> true
+ * eqValue({}, {}) //=> true
+ *
+ */
+ var eqValue = function eqValue(x, y, loose) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('eqValue', {x: x, y: y, loose: loose});
+ }
+
+ // if (x === y) {
+ // if (ENV_DEBUG) {
+ // console.log('===', {x, y})
+ // }
+ // // noop
+ // }
+ // else
+
+ if (nullOrUndefined(x) || nullOrUndefined(y)) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('null or undef !=', {x: x, y: y});
+ }
+
+ if (x !== y) {
+ return false
+ }
+ }
+ else if (typeof x !== typeof y) {
+ // eslint-disable-next-line
+ if (_true(loose) && x == y) {
+ // ignore
+ }
+ else {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('typeof !=', {x: x, y: y});
+ }
+
+ return false
+ }
+ }
+ // @TODO put this up first?
+ else if (toS(x) !== toS(y)) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('diff str types', {x: toS(x), y: toS(y)});
+ }
+
+ return false
+ }
+ else if (objNotNull(x)) {
+ // use .equals if the method exists
+ if (hasOwnProperty_1(x, 'equals')) {
+ return x.equals(y)
+ }
+
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('isObjNotNull', {x: x});
+ }
+
+ // if (isArray(x)) {
+ // if (x.length !== y.length) {
+ // return false
+ // }
+ // }
+
+ // @NOTE .toString will be covered for functions and regexes in objStrict
+ if (regexp(x) || regexp(y)) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('regexp', {x: x, y: y});
+ }
+
+ if (isNotRealOrNotEqToString(x, y)) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('regexp !=', {x: x, y: y});
+ }
+
+ return false
+ }
+ }
+ else if (date(x) || date(y)) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('dates', {x: x, y: y});
+ }
+
+ if (!date(x) || !date(y) || x.getTime() !== y.getTime()) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('!= dates', {x: x, y: y});
+ }
+
+ return false
+ }
+ }
+ else if (error$1(x) || error$1(y)) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('isError', {x: x, y: y});
+ }
+
+ if (!error$1(x) || !error$1(y) || x.stack !== y.stack) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('!= errors', {x: x, y: y});
+ }
+
+ return false
+ }
+ }
+ else if (array(x) && !array(y)) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('isArray(x) || isArray(y)!');
+ }
+
+ return false
+ }
+ else if (!array(x) && array(y)) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('!isArray(x) && isArray(y):');
+ }
+
+ return false
+ }
+
+ // @TODO considering, we already know it is not null & undefined
+ // if (isPrimitive(x) || isPrimitive(y)) {
+ // return x.valueOf() === y.valueOf()
+ // }
+
+ else {
+ // @TODO ObjectOrArrayKeys, but have to have else where they are both array
+ //
+ // @NOTE it will traverse through values if they are == here
+ var xKeys = keys(x);
+ var yKeys = keys(y).length;
+
+ // diff length
+ if (xKeys.length !== yKeys) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('!= obj key length', {xKeys: xKeys, yKeys: yKeys});
+ }
+
+ return false
+ }
+
+ for (var k = 0; k < xKeys.length; k++) {
+ if (!hasOwnProperty_1(y, xKeys[k])) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('!= obj property', {y: y, val: xKeys[k]});
+ }
+
+ return false
+ }
+ }
+ }
+ }
+ else if (toS(x) === toS(y) && x !== y) {
+ // isString(x) || isBoolean(x) || isNumber(x) || isIterator(x)
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('same str types - diff values', {s: toS(x), x: x, y: y});
+ }
+
+ return false
+ }
+ // // @TODO put this up first?
+ // else if (toS(x) !== toS(y)) {
+ // /* istanbul ignore next: dev */
+ // if (ENV_DEBUG) {
+ // console.log('diff str types', {x: toS(x), y: toS(y)})
+ // }
+ //
+ // return false
+ // }
+
+ // go deeper
+ else if (_function(x) || _function(y)) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('isFunction(x) && isFunction(y):');
+ console.log(x.toString());
+ console.log(y.toString());
+ }
+
+ if (isNotRealOrNotEqToString(x, y)) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('x.toString() !== y.toString()', x.toString() !== y.toString());
+ }
+ return false
+ }
+ else {
+ return true
+ }
+ }
+ // @TODO why?
+ else if (obj(x) && obj(y)) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('isObj(x) && isObj(y):');
+ }
+
+ return false
+ }
+ // else {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG$1) {
+ console.log('eqeqeq:', {[toS(x) + 'X']: x, [toS(y) + 'Y']: y});
+ }
+ return true
+ // }
+ };
+
+ /* ___filename___: dist/deps/dot/get.js */
+
+ /* ___filename___: dist/deps/is/empty.js */
+
+ /* ___filename___: dist/deps/env/debug.js */
+
+ /* ___filename___: dist/deps/traversers/eqValue.js */
+
+ /* ___filename___: dist/deps/traversers/_eq.js */
+ // conditionals
+ /* eslint complexity: "OFF" */
+
+ // const traverse = require('../traverse')
+
+
+
+
+
+
+
+ /* prettier-ignore */
+ /**
+ * @name eq
+ * @since 3.0.0
+ * @version 5.0.0
+ * @memberOf Traverse
+ *
+ * @see https://github.com/facebook/immutable-js/blob/master/src/utils/deepEqual.js
+ * @see https://github.com/substack/node-deep-equal
+ * @see http://ramdajs.com/docs/#equals
+ * @see https://lodash.com/docs/4.17.4#isEqual
+ * @see https://github.com/angular/angular.js/blob/master/src/Angular.js
+ *
+ * @param {Traverse} traverse traversejs
+ * @param {*} a compare to b
+ * @param {*} b compare to a
+ * @param {boolean} [loose] compare loosely
+ * @param {boolean} [scoped] doing a second pass, private
+ * @return {boolean} isEqual
+ *
+ * @extends eqValue
+ *
+ * @example
+ *
+ * eq(1, 1) //=> true
+ * eq(1, '1') //=> false
+ * eq(1, '1', true) //=> true
+ * eq([1], [1]) //=> true
+ *
+ */
+ var _eq = function (traverse) { return function eq(a, b, loose, stackA, stackB) {
+ if ( stackA === void 0 ) stackA = [];
+ if ( stackB === void 0 ) stackB = [];
+
+ /* istanbul ignore next: dev */
+ if (debug) {
+ console.log('\n');
+ }
+
+ var equal = true;
+ var node = b;
+ var nodes = [node];
+
+ var instance = traverse(a);
+
+ var notEqual = function () {
+ equal = false;
+ instance.stop();
+ };
+
+ /* istanbul ignore next: dev */
+ if (debug) {
+ console.log('eq?');
+ }
+
+ instance.forEach(function(key, y, traverser) {
+ // @NOTE do base comparisons on values that are not actually iteratable
+ // aka, .isRoot
+ if (_null(key)) {
+ // always-valid state opionion vs always-invalid
+ // so it only returns false when it is !== fosho
+ if (eqValue(node, y, loose) === false) { return notEqual() }
+ else { return }
+ }
+
+ /* istanbul ignore next: dev */
+ if (debug) {
+ console.log('eq: iterating:');
+ }
+
+ // could use it as a fallback if undefined && y !== undefined
+ // const xyz = get(b, traverser.path.join('.'), b)
+
+ var x = node;
+
+ // isNotLeafAndIsObj
+ if (objNotNull(node) && !empty(node)) {
+ /* istanbul ignore next: dev */
+ if (debug) {
+ console.log('is leaf, is not empty node, going deeper');
+ }
+
+ // so x is our current one,
+ // if node is not empty, use the key, push the value
+ // and when it is empty, and it is not a leaf but has nodes, pop back up
+ x = node[key];
+ nodes.push(x);
+ }
+
+ // ENV_DEBUG
+ // console.log({[key]: {x, xyz, y, nodes, path: traverser.path.join('.')}})
+
+ // for next loop!!!
+ if (!this.isLeaf && !empty(nodes)) {
+ /* istanbul ignore next: dev */
+ if (debug) {
+ console.log('is not leaf, has nodes stack, pop');
+ }
+ node = nodes.pop();
+ }
+
+ /* istanbul ignore next: dev */
+ if (debug) {
+ console.log({key: key, y: y, x: x, a: a, b: b});
+ }
+
+ var eqv = eqValue(x, y, loose);
+
+ /* istanbul ignore next: dev */
+ if (debug) {
+ console.log({eqv: eqv});
+ }
+
+ if (eqv === false) {
+ // equal
+ notEqual();
+ }
+ });
+
+ // cleanup
+ nodes = undefined;
+ node = undefined;
+
+ return equal
+ }; };
+
+ /* ___filename___: dist/deps/cache/pooler.js */
+ /* eslint consistent-this: ["error", "Klass"] */
+
+
+
+ /**
+ * @symb 🎱
+ * @member pooler
+ * @type {Object}
+ */
+ // const pooler = }}
+
+ /**
+ * @desc call destructor on a pooled instance, put it back in the pool
+ * @since 5.0.0
+ * @memberOf pooler
+ *
+ * @param {Object} instance call destructor
+ * @return {void}
+ *
+ * @example
+ *
+ * class Eh {}
+ * addPoolingTo(Eh)
+ * const eh = Eh.getPooled()
+ * eh.release()
+ *
+ */
+ function standardReleaser(instance) {
+ var Klass = this;
+
+ if (debug) {
+ if (instance instanceof Klass) {
+ throw new Error(
+ "Trying to release an instance\n into a pool of a different type."
+ )
+ }
+ }
+
+ instance.destructor();
+ if (Klass.instancePool.length < Klass.poolSize) {
+ Klass.instancePool.push(instance);
+ }
+ }
+
+ /**
+ * Static poolers. Several custom versions for each potential number of
+ * arguments. A completely generic pooler is easy to implement, but would
+ * require accessing the `arguments` object. In each of these, `this` refers to
+ * the Class itself, not an instance. If any others are needed, simply add them
+ * here, or in their own files.
+ *
+ * @since 5.0.0
+ * @memberOf pooler
+ *
+ * @param {Object} copyFieldsFrom obj with instance pool
+ * @return {Object} instance of Klass
+ *
+ * @example
+ *
+ * class Eh {}
+ * addPoolingTo(Eh)
+ * const eh = Eh.getPooled() //=> oneArgumentPooler(Eh)
+ * eh.release()
+ *
+ */
+ function oneArgumentPooler(copyFieldsFrom) {
+ var Klass = this;
+ if (Klass.instancePool.length) {
+ var instance = Klass.instancePool.pop();
+ Klass.call(instance, copyFieldsFrom);
+ return instance
+ }
+ else {
+ return new Klass(copyFieldsFrom)
+ }
+ }
+
+ var DEFAULT_POOL_SIZE = 10;
+ var DEFAULT_POOLER = oneArgumentPooler;
+
+ /**
+ * Augments `CopyConstructor` to be a poolable class, augmenting only the class
+ * itself (statically) not adding any prototypical fields. Any CopyConstructor
+ * you give this may have a `poolSize` property, and will look for a
+ * prototypical `destructor` on instances.
+ *
+ * @since 5.0.0
+ * @memberOf pooler
+ *
+ * @param {Function | Object} CopyConstructor Constructor that can be used to reset.
+ * @param {Function} pooler Customizable pooler.
+ * @return {Object} enhanced constructor, decorated with pooler
+ *
+ * @example
+ *
+ * class Eh {}
+ * addPoolingTo(Eh) // can optionally pass in pooler as second arg
+ * //=> Eh.instancePool = []
+ * //=> Eh.getPooled = pooler || singleArgumentPooler
+ * //=> Eh.poolSize = 10
+ * //=> Eh.release = standardReleaser
+ *
+ */
+ function addPoolingTo(CopyConstructor, pooler) {
+ // Casting as any so that flow ignores the actual implementation and trusts
+ // it to match the type we declared
+ var NewKlass = CopyConstructor;
+
+ NewKlass.instancePool = [];
+ NewKlass.getPooled = pooler || DEFAULT_POOLER;
+ if (!NewKlass.poolSize) { NewKlass.poolSize = DEFAULT_POOL_SIZE; }
+ NewKlass.release = standardReleaser;
+
+ return NewKlass
+ }
+
+ var pooler = addPoolingTo;
+
+ /* ___filename___: dist/deps/is/symbol.js */
+
+ /* ___filename___: dist/deps/is/asyncish.js */
+
+ /* ___filename___: dist/deps/is/primitive.js */
+
+ /* ___filename___: dist/deps/dot/set.js */
+
+ /* ___filename___: dist/deps/traversers/copy.js */
+
+ /* ___filename___: dist/deps/traversers/_eq.js */
+
+ /* ___filename___: dist/deps/cache/pooler.js */
+
+ /* ___filename___: dist/deps/traverse.js */
+ // conditionals
+ /* eslint complexity: "OFF" */
+
+ // inlined rollup
+ /* eslint import/max-dependencies: "OFF" */
+
+ // one file
+ /* eslint max-lines: "OFF" */
+
+ // debug conditionals
+ /* eslint max-depth: "OFF" */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ // const props = require('./util/props')
+
+ // const ENV_DEBUG = require('./env/debug')
+ // const ENV_DEBUG = true
+ var ENV_DEBUG = false;
+
+ function isIteratable(node) {
+ // ez ones
+ if (obj(node) || array(node)) { return true }
+
+ var notIteratable =
+ primitive$2(node) ||
+ regexp(node) ||
+ date(node) ||
+ symbol(node) ||
+ asyncish(node) ||
+ // isNative(node) ||
+ error$1(node);
+
+ if (notIteratable) { return false }
+ else { return true }
+
+ // if (isNullOrUndefined(node)) {
+ // }
+ // else if (isString(node)) {
+ // }
+ // else if (isNumber(node)) {
+ // }
+ // else if (isBoolean(node)) {
+ // }
+ // else if (isRegExp(node)) {
+ // }
+ // else if (isDate(node)) {
+ // }
+ // else if (isSymbol(node) || isAsyncish(node)) {
+ // }
+ // else if (isNative(node)) {
+ // }
+ // else {
+ // return true
+ // }
+ // return false
+ }
+
+ // function isSpecial(x) {
+ // // isPromise(x) ||
+ // return isSymbol(x) || isError(x) ||
+ // // || isGenerator(x)
+ // }
+
+ /**
+ * {@link https://github.com/wmira/object-traverse/blob/master/index.js }
+ * {@link https://www.npmjs.com/browse/keyword/traverse }
+ * {@link https://www.npmjs.com/package/tree-walk }
+ * {@link https://www.npmjs.com/package/1tree }
+ * {@link https://www.npmjs.com/package/pathway }
+ * {@link https://www.npmjs.com/package/@mojule/tree }
+ *
+ * --------------------
+ *
+ * if needed, clone
+ *
+ * first things to check are number/string/boolean/null/undefined
+ *
+ * then check non-iteratables
+ * symbol, promise,
+ *
+ * then check conversions
+ * - map, set
+ *
+ * then check empties
+ * - obj
+ * - fn
+ *
+ * -------
+ *
+ * numbers f-or first/last
+ * and as a sort of hash like
+ * 1 + 2 + 4 = ISLEAF & ISROOT ?
+ *
+ * Array
+ *
+ * Object Function Date Error Map Set
+ *
+ * String
+ * Number NaN Infinity
+ * Boolean
+ *
+ *
+ * null undefined
+ *
+ * Promise Symbol
+ *
+ * ----
+ *
+ * @emits before
+ * @emits pre
+ * @emits post
+ * @emits after
+ */
+
+ /**
+ * @class
+ * @desc Traverse class, pooled
+ * @alias IterAteOr
+ * @member Traverse
+ * @constructor
+ * @since 5.0.0
+ *
+ * @param {Traversable} iteratee value to iterate, clone, copy, check for eq
+ * @param {Object | undefined} [config] wip config for things such as events or configs
+ *
+ * @extends pooler
+ * @see traverse
+ * @TODO make this a trie OR a linked-list
+ *
+ * @example
+ *
+ * new Traverse([1])
+ * new Traverse([], {})
+ *
+ */
+ function Traverse(iteratee, config) {
+ // always cleared when done anyway
+ this.parents = new Set();
+
+ this.iteratee = iteratee;
+ this.parent = iteratee;
+ this.root = iteratee;
+ this.reset();
+
+ // to pass in the events (as commented below) without messing up scope?
+ // if (config.on) this.on = config.on
+ return this
+ }
+
+ Traverse.prototype.reset = function() {
+ this.path = [];
+ this.key = undefined;
+ this.isAlive = true;
+ this.isCircular = false;
+ this.isLeaf = false;
+ this.isRoot = true;
+
+ // iterates +1 so start at 0
+ this.depth = -1;
+ };
+
+ /**
+ * @desc find parent,
+ * is there a parent
+ * above the current depth
+ * with the same value,
+ * making it circular?
+ *
+ * @memberOf Traverse
+ * @since 5.0.0
+ * @private
+ *
+ * @param {number} depth current depth, to find parent >=
+ * @param {parent} value parent value to find
+ * @return {boolean} hasParent
+ *
+ * @example
+ *
+ * var obj = {eh: ['eh']}
+ * traverse(obj).addParent(0, obj)
+ *
+ */
+ Traverse.prototype.hasParent = function(depth, value) {
+ // or array
+ if (!obj(value)) { return false }
+ return this.parents.has(value)
+ };
+
+ /**
+ * @desc add parent, to prevent circular iterations
+ * @memberOf Traverse
+ * @since 5.0.0
+ * @private
+ *
+ * @param {number} depth current depth, to add parent to >=
+ * @param {parent} value parent value to add
+ * @return {void}
+ *
+ * @example
+ *
+ * var obj = {eh: ['eh']}
+ * traverse(obj).addParent(0, obj)
+ *
+ */
+ Traverse.prototype.addParent = function(depth, value) {
+ if (!obj(value)) { return }
+ if (this.parents.size >= 100) { this.clear(); }
+ this.parents.add(value);
+ };
+
+ /**
+ * @desc remove all parents, reset the map
+ *
+ * @memberOf Traverse
+ * @since 5.0.0
+ * @private
+ *
+ * @return {void}
+ *
+ * @example
+ *
+ * var obj = {eh: ['eh']}
+ * traverse(obj).forEach((key, value, t) => {
+ * t.parents
+ * //=> Set([obj])
+ * t.clear()
+ * t.parents
+ * //=> Set[]
+ * })
+ *
+ */
+ Traverse.prototype.clear = function() {
+ if (!_undefined(this.parents)) { this.parents.clear(); }
+ };
+
+ /**
+ * @memberOf Traverse
+ * @since 5.0.0
+ * @private
+ *
+ * @param {number} depth current depth, to find parents >=
+ * @param {parent} value parent value to remove
+ * @return {void}
+ *
+ * @example
+ *
+ * var obj = {eh: ['eh']}
+ * traverse(obj).removeParent(0, obj)
+ *
+ */
+ Traverse.prototype.removeParent = function(depth, value) {
+ this.parents.delete(value);
+ };
+
+ /**
+ * @desc this is the main usage of Traverse
+ * @memberOf Traverse
+ * @since 3.0.0
+ * @version 5.0.0
+ *
+ * @param {Function} cb callback for each iteration
+ * @return {*} mapped result or original value, depends how it is used
+ *
+ * @example
+ *
+ * traverse([1, 2, 3]).forEach((key, value) => console.log({[key]: value}))
+ * //=> {'0': 1}
+ * //=> {'1': 2}
+ * //=> {'2': 3}
+ *
+ */
+ Traverse.prototype.forEach = function iterateForEach(cb) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG) {
+ console.log('\n forEach \n');
+ }
+
+ var result = this.iterate(cb);
+
+ // TODO: HERE, WHEN THIS IS ADDED, CAN BREAK SOME TESTS? SCOPED PARENTS MAP?
+ Traverse.release(this);
+
+ return result
+ };
+
+ /**
+ * @desc stop the iteration
+ * @modifies this.isAlive = false
+ * @memberOf Traverse
+ *
+ * @return {void}
+ *
+ * @example
+ *
+ * traverse({eh: true, arr: []}).forEach((key, val, t) => {
+ * if (isArray(val)) this.stop()
+ * })
+ *
+ */
+ Traverse.prototype.stop = function stop() {
+ this.isAlive = false;
+ // this.release()
+ };
+
+ /**
+ * @TODO skip 1 branch
+ * @version 5.0.0
+ * @since 3.0.0
+ * @memberOf Traverse
+ *
+ * @return {void}
+ *
+ * @example
+ *
+ * traverse([1, 2, 3, [4]]).forEach((key, val, t) => {
+ * if (isArray(val)) t.skip()
+ * })
+ *
+ */
+ Traverse.prototype.skip = function skip() {
+ this.skipBranch = true;
+ };
+
+ /* prettier-ignore */
+ /**
+ * @TODO move into the wrapper? if perf allows?
+ *
+ * @desc checks whether a node is iteratable
+ * @modifies this.isIteratable
+ * @modifies this.isLeaf
+ * @modifies this.isCircular
+ *
+ * @memberOf Traverse
+ * @protected
+ *
+ * @param {*} node value to check
+ * @return {void}
+ *
+ * @example
+ *
+ * .checkIteratable({eh: true})
+ * //=> this.isLeaf = false
+ * //=> this.isCircular = false
+ * //=> this.isIteratable = true
+ *
+ * .checkIteratable({} || [])
+ * //=> this.isLeaf = true
+ * //=> this.isCircular = false
+ * //=> this.isIteratable = false
+ *
+ * var circular = {}
+ * circular.circular = circular
+ * .checkIteratable(circular)
+ * //=> this.isLeaf = false
+ * //=> this.isCircular = true
+ * //=> this.isIteratable = true
+ *
+ */
+ Traverse.prototype.checkIteratable = function check(node) {
+ this.isIteratable = isIteratable(node);
+ // just put these as an array?
+ if (_true(this.isIteratable)) {
+ // native = leaf if not root
+ this.isLeaf = false;
+ var path = this.path.join('.');
+
+
+ if (this.hasParent(path, node)) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG) {
+ console.log('circular___________', {node: node, path: this.path});
+ }
+ this.isCircular = true;
+ }
+ else {
+ this.addParent(path, node);
+ this.isCircular = false;
+ }
+
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG) {
+ // console.log('IS_CIRCULAR_JSON', isCircular(node), this.isCircular, node)
+ }
+ }
+ else {
+ // ---
+ this.isLeaf = true;
+ this.isCircular = false;
+ }
+ };
+
+ /* prettier-ignore */
+ /**
+ * Remove the current element from the output.
+ * If the node is in an Array it will be spliced off.
+ * Otherwise it will be deleted from its parent.
+ *
+ * @memberOf Traverse
+ * @version 5.0.0
+ * @since 2.0.0
+ *
+ * @param {undefined | Object} [arg] optional obj to use, defaults to this.iteratee
+ * @return {void}
+ *
+ * @example
+ *
+ * traverse([0]).forEach((key, val, it) => it.remove())
+ * //=> []
+ *
+ * traverse({eh: true}).forEach((key, val, it) => it.remove())
+ * //=> {}
+ *
+ * traverse({eh: true, str: 'stringy'}).forEach((key, val, it) => {
+ * if (!isString(val)) it.remove()
+ * })
+ * //=> {str: 'stringy'}
+ *
+ */
+ Traverse.prototype.remove = function removes(arg) {
+ if (_undefined(this.key)) { return }
+
+ var obj$$2 = arg || this.iteratee;
+
+ if (!obj(obj$$2)) { return }
+
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG) {
+ console.log('remove');
+ console.log({parent: this.parent, key: this.key, obj: obj$$2});
+ }
+
+ this.removeParent(obj$$2);
+
+ this.skip();
+
+ delete obj$$2[this.key];
+ delete this.parent[this.key];
+ // if (isObj(obj)) deleteFromObjOrArray(obj, this.key)
+ // else deleteFromObjOrArray(this.parent, this.key)
+ // deleteFromObjOrArray(this.parent, this.key)
+ // deleteFromObjOrArray(this.iteratee, this.key)
+
+ // if (isUndefined(obj)) {
+ // // throw new Error('why?')
+ // }
+ // else if (isArray(obj)) {
+ // /* istanbul ignore next: dev */
+ // if (ENV_DEBUG) {
+ // console.log('traverse:remove:array', obj, this.key)
+ // }
+ //
+ // obj.splice(this.key, 1)
+ // }
+ // else if (isObjNotNull(obj)) {
+ // /* istanbul ignore next: dev */
+ // if (ENV_DEBUG) {
+ // console.log('traverse:remove:obj', this.key)
+ // }
+ //
+ // delete obj[this.key]
+ // }
+ //
+ // if (isObjNotNull(this.parent)) {
+ // delete this.parent[this.key]
+ //
+ // /* istanbul ignore next: dev */
+ // if (ENV_DEBUG) {
+ // console.log('traverse:remove:parent', this.key)
+ // }
+ // }
+ // if (isObjNotNull(this.iteratee)) {
+ // delete this.iteratee[this.key]
+ //
+ // /* istanbul ignore next: dev */
+ // if (ENV_DEBUG) {
+ // console.log('traverse:remove:iteratee', this.key)
+ // }
+ // }
+
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG) {
+ console.log('traverse:remove:', this.key, {obj: obj$$2, iteratee: this.iteratee});
+ }
+ };
+
+ /**
+ * @desc update the value for the current key
+ * @version 5.0.0
+ * @since 2.0.0
+ * @memberOf Traverse
+ *
+ * @param {*} value this.iteratee[this.key] = value
+ * @return {void}
+ *
+ * @example
+ *
+ * traverse({eh: true})
+ * .forEach((key, val, traverser) => {
+ * if (this.isRoot) return
+ * traverser.update(false)
+ * })
+ * //=> {eh: false}
+ *
+ */
+ Traverse.prototype.update = function update(value) {
+ set$2(this.root, this.path, value);
+ };
+
+ /**
+ * @desc mark the iteration as done, clear the map
+ * @NOTE this recycles the instance in the pooler to re-use allocated objects
+ * @memberOf Traverse
+ * @private
+ * @since 5.0.0
+ *
+ * @return {void}
+ *
+ * @see Traverse.iterate
+ *
+ * @example
+ *
+ * traverse([]).destructor()
+ *
+ */
+ Traverse.prototype.destructor = function destructor() {
+ this.iteratee = undefined;
+ this.parent = undefined;
+ this.reset();
+
+ this.clear();
+ };
+
+ /* prettier-ignore */
+ /**
+ * @TODO handler for Set & Map so they can be skipped or traversed, for example when cloning...
+ * @TODO add hook to add custom checking if isIteratable
+ * @TODO deal with .isRoot if needed
+ * @TODO examples with clone and stop
+ *
+ * @memberOf Traverse
+ * @protected
+ * @sig on(key: null | Primitive, val: any, instance: Traverse): any
+ *
+ * @param {Function} on callback fn for each iteration
+ * @return {*} this.iteratee
+ *
+ * @example
+ *
+ * iterate([])
+ * //=> []
+ * //=> on(null, [])
+ *
+ * @example
+ *
+ * iterate([1])
+ * //=> [1]
+ * //=> on(null, [1])
+ * //=> on('1', 1)
+ *
+ * @example
+ *
+ * //primitive - same for any number, string, symbol, null, undefined
+ * iterate(Symbol('eh'))
+ * //=> Symbol('eh')
+ * //=> on(Symbol('eh'))
+ *
+ * @example
+ *
+ * var deeper = {eh: 'canada', arr: [{moose: true}, 0]}
+ * iterate(deeper)
+ * //=> deeper // returns
+ * //=> on(null, deeper, this) // root
+ *
+ * //=> on('eh', 'canada', this) // 1st branch
+ *
+ * //=> on('arr', [{moose: true}, 0], this)
+ * //=> on('arr.0', [{moose: true}], this)
+ * //=> on('arr.0.moose', true, this)
+ * //=> on('arr.1', [0], this)
+ *
+ *
+ */
+ Traverse.prototype.iterate = function iterate(on) {
+ var this$1 = this;
+
+ /* istanbul ignore next : dev */
+ if (ENV_DEBUG) {
+ // require('fliplog')
+ // .bold(this.path.join('.'))
+ // .data(parents.keys())
+ // .echo()
+ console.log('\n...iterate...\n');
+ }
+
+ if (this.isAlive === false) {
+ /* istanbul ignore next : dev */
+ if (ENV_DEBUG) {
+ console.log('DEAD');
+ }
+
+ return Traverse.release(this)
+ }
+
+ var node = this.iteratee;
+
+ // convert to iteratable
+ if (map(node)) {
+ node = index$6(node);
+ }
+ else if (set(node)) {
+ node = toArr(node);
+ }
+
+ // @TODO: maybe only right before sub-loop
+ this.addParent(this.depth, node);
+
+ var nodeIsArray = array(node);
+ var nodeIsObj = nodeIsArray || obj(node);
+
+ // ---
+
+ // @event
+ if (!_undefined(this.onBefore)) {
+ // eslint-disable-next-line no-useless-call
+ this.onBefore(this);
+ }
+
+ /* istanbul ignore next : dev */
+ if (ENV_DEBUG) {
+ // const str = require('pretty-format')({nodeIsObj, nodeIsArray, node})
+ // require('fliplog').verbose(1).data({nodeIsObj, nodeIsArray, node}).echo()
+ // console.log(node, parents)
+ // console.log(str)
+ console.log({nodeIsObj: nodeIsObj, nodeIsArray: nodeIsArray, node: node});
+ }
+
+ /**
+ * call as root, helpful when we
+ * - iterate something with no keys
+ * - iterate a non-iteratable (symbol, error, native, promise, etc)
+ */
+ if (_true(this.isRoot)) {
+ on.call(this, null, node, this);
+ this.isRoot = false;
+ }
+
+ var isObjOrArray = nodeIsArray || nodeIsObj;
+
+ // if (isObjOrArray) {
+ // // @event
+ // if (!isUndefined(this.onBefore)) {
+ // // eslint-disable-next-line no-useless-call
+ // this.onBefore(this)
+ // }
+ // }
+
+ // --------------------
+ // IF OBJWITHOUTKEYS, IF ARRAY WITHOUT LENGTH...
+ if (isObjOrArray && empty(node)) {
+ on.call(this, this.key, node, this);
+ this.iteratee = node;
+ }
+
+ // --------------------
+
+ else if (isObjOrArray) {
+ this.depth = this.path.length;
+
+ // @TODO SAFETY WITH `props(node)` <- fixes Error
+ var keys$$2 = nodeIsArray ? node : keys(node);
+
+ /* istanbul ignore next : dev */
+ if (ENV_DEBUG) {
+ console.log({keys: keys$$2});
+ // require('fliplog').verbose(1).data(this).echo()
+ }
+
+ // @event
+ // if (!isUndefined(this.onBefore)) this.onBefore()
+
+ // @NOTE: safety here
+ // this.checkIteratable(node)
+
+ // const last = keys[keys.length - 1]
+
+ // @loop
+ for (var key = 0; key < keys$$2.length; key++) {
+ // if (ENV_DEBUG)
+ // console.log('iterating:', {key})
+
+ // --- safety ---
+ if (this$1.isAlive === false) {
+ /* istanbul ignore next : dev */
+ if (ENV_DEBUG) {
+ console.log('DEAD');
+ }
+
+ return Traverse.release(this$1)
+ }
+
+ // @NOTE: look above add prev add parent
+ // addParent(this.depth, node)
+
+
+ // ----- setup our data ----
+
+ // to make it deletable
+ if (node !== this$1.iteratee) { this$1.parent = node; }
+
+ this$1.key = nodeIsArray ? key : keys$$2[key];
+ // this.isLast = key === last
+
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG) {
+ console.log('alive', this$1.key);
+ }
+
+ // @event
+ if (!_undefined(this$1.onPre)) {
+ // eslint-disable-next-line no-useless-call
+ this$1.onPre(this$1);
+ }
+
+
+ var value = node[this$1.key];
+
+ this$1.checkIteratable(value);
+ // addParent(value)
+ var pathBeforeNesting = this$1.path.slice(0);
+
+ // @NOTE: can go forward-backwards if this is after the nested iterating
+ this$1.path.push(this$1.key);
+ this$1.depth = this$1.path.length;
+
+ // ----- continue events, loop deeper when needed ----
+
+ // @NOTE since we check isAlive at the beginning of each loop
+ // could use .skip alongisde .stop
+ // @TODO @IMPORTANT @HACK @FIXME right here it should also handle the .stop
+ on.call(this$1, this$1.key, value, this$1);
+ if (_true(this$1.skipBranch)) {
+ this$1.skipBranch = false;
+ continue
+ }
+
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG) {
+ // require('fliplog').data(parents).echo()
+ // require('fliplog').data(this).echo()
+ }
+
+ // handle data
+ if (_true(this$1.isCircular)) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG) {
+ console.log('(((circular)))', this$1.key);
+ }
+
+ // on.call(this, this.key, value, this)
+ // this.path.pop()
+ this$1.path = pathBeforeNesting;
+
+ // this.isCircular = false
+ // break
+ continue
+ // return
+ }
+
+
+ // &&
+ if (_true(this$1.isIteratable)) {
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG) {
+ console.log('(((iteratable)))', this$1.key);
+ }
+
+ this$1.iteratee = value;
+ this$1.iterate(on);
+ this$1.path = pathBeforeNesting;
+ }
+
+ /* istanbul ignore next: dev */
+ if (ENV_DEBUG) {
+ if (this$1.isIteratable === false) {
+ console.log('not iteratable', this$1.key);
+ }
+
+ console.log('----------------- post ----------', node);
+ }
+
+ // @event
+ if (!_undefined(this$1.onPost)) {
+ // eslint-disable-next-line no-useless-call
+ this$1.onPost(this$1);
+ }
+
+ // cleanup, backup 1 level
+ this$1.path.pop();
+
+ this$1.removeParent(node);
+ }
+
+ // this.path.pop()
+ this.depth = this.path.length;
+ }
+ else {
+ // this.isLast = false
+ on.call(this, this.depth, node, this);
+ }
+
+ // @NOTE: careful
+ // removeParent(node)
+
+ // @NOTE: just for .after ?
+ this.iteratee = node;
+
+ // @event
+ if (!_undefined(this.onAfter)) {
+ // eslint-disable-next-line no-useless-call
+ this.onAfter(this);
+ }
+
+ this.path.pop();
+
+ return this.iteratee
+ };
+
+ // is smaller, but probably slower
+ // function onEvent(property) {
+ // return function(fn) {
+ // this[property] = function
+ // }
+ // }
+
+ // when it's some sort of itertable object, loop it further
+ // @TODO: need to handle these better without totally messing with bad scope
+ Traverse.prototype.pre = function(fn) {
+ this.onPre = fn;
+ };
+ Traverse.prototype.post = function(fn) {
+ this.onPost = fn;
+ };
+ Traverse.prototype.before = function(fn) {
+ this.onBefore = fn;
+ };
+ Traverse.prototype.after = function(fn) {
+ this.onAfter = fn;
+ };
+
+ // -----------------------
+
+ /**
+ * @TODO merge with dopemerge?
+ * @TODO needs tests converted back for this (observe tests do cover somewhat)
+ *
+ * @param {*} arg defaults to this.iteratee
+ * @return {*} cloned
+ *
+ * @example
+ *
+ * var obj = {}
+ * var cloned = traverse().clone(obj)
+ * obj.eh = true
+ * eq(obj, cloned)
+ * //=> false
+ *
+ */
+ Traverse.prototype.clone = clone;
+
+ /**
+ * @todo ugh, how to clone better with *recursive* objects?
+ * @param {any} src wip
+ * @return {any} wip
+ */
+ Traverse.prototype.copy = copy;
+
+ /**
+ * @desc clone any value
+ * @version 5.0.0
+ * @since 4.0.0
+ * @memberOf Traverse
+ * @extends copy
+ * @extends Traverse
+ *
+ * @param {*} arg argument to clone
+ * @return {*} cloned value
+ *
+ * @see dopemerge
+ * @example
+ *
+ * var obj = {eh: true}
+ * clone(obj) === obj //=> false
+ *
+ * var obj = {eh: true}
+ * var obj2 = clone(obj)
+ * obj.eh = false
+ * console.log(obj2.eh) //=> true
+ *
+ */
+ function clone(arg) {
+ var obj$$2 = _undefined(arg) ? this.iteratee : arg;
+ if (primitive$2(obj$$2)) { return obj$$2 }
+ var cloned = emptyTarget(obj$$2);
+ var current = cloned;
+
+ traverse(obj$$2).forEach(function (key, value, traverser) {
+ // t.isRoot
+ if (_null(key)) { return }
+
+ var copied = copy(value);
+ if (traverser.isCircular && array(value)) { copied = value.slice(0); }
+ set$2(current, traverser.path, copied);
+
+ // current[key] = traverser.copy(value)
+ // if (isObj(value)) current = current[key]
+ });
+
+ return cloned
+ }
+
+ // @TODO could just have traverse = Traverse.getPooled ?
+ pooler(Traverse);
+ function traverse(value) {
+ return Traverse.getPooled(value)
+ }
+
+ var traverse_1 = traverse;
+ var eq_1 = _eq(traverse);
+ var clone_1 = clone;
+ var copy_1 = copy;
+
+
+
+ traverse_1.eq = eq_1;
+ traverse_1.clone = clone_1;
+ traverse_1.copy = copy_1;
+
+ var index$10 = new Map();
+
+ /* ___filename___: dist/deps/traverse.js */
+
+ /* ___filename___: dist/deps/dot/paths.js */
+
+
+
+
+
+
+ var run = 0;
+
+ /* prettier-ignore */
+ /**
+ * @desc gathers dot.prop from any value, with a prefixed/base key
+ * @since 4.0.0
+ *
+ * @param {Primitive} key prefixing key for the paths, root path/key
+ * @param {Traversable} value traversable value to extract paths from
+ * @param {boolean | undefined} [longest] optionally filter to keep only longest/deepest paths
+ * @return {Array} paths[]
+ *
+ * @see deps/traverse
+ * @TODO should build a trie if doing this
+ * @NOTE had `onlyLongest` & `asString` but can just .join(',') to match
+ *
+ * @example
+ *
+ * dotPropPaths('', {oh: {eh: true}})
+ * //=> ['oh.eh']
+ *
+ * dotPropPaths('moose', {oh: {eh: true}})
+ * //=> ['moose.oh.eh']
+ *
+ */
+ var paths = function(key, value, longest) {
+ // if (cache.has(value)) return cache.get(value)
+
+ var paths = [];
+
+ /* istanbul ignore next: debug */
+ if (debug) {
+ console.log({value: value});
+ }
+
+ // gather all paths in the object
+ // filter to ensure only the longest paths are kept
+ //
+ // .map the paths to `dot-prop`,
+ // `matcher` takes in an array so it will work for all
+ traverse_1(value).forEach(function(x) {
+ // const currentPath = this.paths
+ var currentPath = this.path;
+
+ /* istanbul ignore next: debug */
+ if (debug) {
+ console.log('paths', run++, this.path);
+ }
+
+ // ignore
+ if (!currentPath) { return }
+ else if (!currentPath.length) { return }
+
+ // dot-prop the array of paths
+ // if we have a key, prefix it
+ paths.push(
+ (key ? key + '.' : '') +
+ (currentPath.join ? currentPath.join('.') : currentPath)
+ );
+ });
+
+ if (_true(longest)) {
+ // concat a string of all paths so we can unique each branch
+ // @example `canada.arr.0` vs `canada.arr`
+ paths = paths.filter(function (path) { return !paths.some(function (otherPath) { return otherPath !== path && index$4(otherPath, path); }
+ ); });
+ }
+
+ // cache.set(value, paths)
+
+ return paths
+ };
+
+ /* ___filename___: dist/deps/is/number.js */
+
+
+
+ /**
+ * @param {*} x value
+ * @return {boolean} isNumber
+ *
+ * @since 3.0.0
+ * @memberOf is
+ * @func isNumber
+ * @see is/real
+ * @extends numberPrimitive
+ * @variation also returns true for new Number object
+ *
+ * @see http://stackoverflow.com/questions/18082/validate-decimal-numbers-in-javascript-isnumeric
+ * @alternate !isNaN(parseFloat(n)) && isFinite(n)
+ *
+ * @example
+ *
+ * isNumber(1)
+ * //=> true
+ * isNumber(new Number(1))
+ * //=> true
+ * isNumber(Number(1))
+ * //=> true
+ * isNumber(NaN)
+ * //=> true
+ *
+ * isNumber(null)
+ * //=> false
+ * isNumber(undefined)
+ * //=> false
+ * isNumber(void 0)
+ * //=> false
+ * isNumber({})
+ * //=> false
+ * isNumber('')
+ * //=> false
+ * isNumber(false)
+ * //=> false
+ *
+ * @NOTE was not needed except for abstract ==
+ * const isObj = require('./obj')
+ * const isSymbol = require('./symbol')
+ * (isObj(x) || isSymbol(x)
+ * ? false
+ * : (/^0x[0-9a-f]+$/i).test(x) ||
+ * (/^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/).test(x))
+ *
+ */
+ var number = function (x) { return numberPrimitive(x) || toS(x) === '[object Number]'; };
+
+ /* ___filename___: dist/deps/is/number.js */
+
+ /* ___filename___: dist/deps/is/stringOrNumber.js */
+
+
+
+ /**
+ * Checks if `value` is classified as a `String` primitive or object.
+ *
+ * @since 3.0.0
+ * @category Lang
+ * @memberOf is
+ * @param {*} x The value to check.
+ * @return {boolean} Returns `true` if `value` is a string, else `false`.
+ *
+ * @see https://github.com/infernojs/inferno/blob/master/packages/inferno-shared/src/index.ts#L23
+ * @see https://github.com/lodash/lodash/blob/master/isString.js
+ *
+ * @example
+ *
+ * isString('abc')
+ * // => true
+ *
+ * isString(1)
+ * // => false
+ */
+ var stringOrNumber = function (x) { return string(x) || number(x); };
+
+ /* ___filename___: dist/deps/is/real.js */
+
+
+ /**
+ * @param {*} x value
+ * @return {boolean} isReal
+ *
+ * @since 3.0.0
+ * @memberOf is
+ * @func isReal
+ * @see is/null
+ * @see is/undefined
+ *
+ * @see http://2ality.com/2013/04/quirk-implicit-conversion.html
+ * @see https://javascriptrefined.io/nan-and-typeof-36cd6e2a4e43
+ * @see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/isNaN
+ *
+ * @NOTE eslint-disable-next-line no-self-compare
+ * && x !== x
+ *
+ * @extends isNullOrUndefined
+ * @variation *not* isNullOrUndefined && false for NaN
+ *
+ * @example
+ *
+ * isReal(null)
+ * //=> false
+ * isReal(void 0)
+ * //=> false
+ * const nan = Number(undefined)
+ * isReal(nan)
+ * //=> false
+ *
+ * isReal({eh: true})
+ * //=> true
+ * isReal({})
+ * //=> true
+ * isReal(Object)
+ * //=> true
+ * isReal([])
+ * //=> true
+ * isReal(new Set())
+ * //=> true
+ * isReal(function() {})
+ * //=> true
+ * isReal('')
+ * //=> true
+ * isReal(1)
+ * //=> true
+ *
+ */
+ var real = function (x) { return !nullOrUndefined(x) && !Number.isNaN(x); };
+
+ /* ___filename___: dist/deps/is/objPure.js */
+
+
+
+
+
+ /**
+ * @name isObjPure
+ * @memberOf is
+ * @alias isObjNotArrayOrFunction
+ * @since 3.0.0
+ *
+ *
+ * @param {*} x value to check
+ * @return {boolean} is obj & !null & !undefined & !array & !function
+ *
+ * @extends isArray
+ * @extends isObjTypeof
+ * @extends isNullOrUndefined
+ * @extends isFunction
+ *
+ * @example
+ *
+ * isObjPure(function() {})
+ * //=> false
+ * isObjPure(null)
+ * //=> false
+ * isObjPure([])
+ * //=> false
+ *
+ * isObjPure({})
+ * //=> true
+ *
+ */
+ var objPure = function (x) { return !nullOrUndefined(x) && !array(x) && !_function(x) && objTypeof(x); };
+
+ /* ___filename___: dist/deps/is/objWithKeys.js */
+
+
+
+ /**
+ * @TODO @NOTE need to be more careful, needs to check for vanilla objects, not native ones since e.g. Error has no keys
+ *
+ * @param {*} x value
+ * @return {boolean} isObjWithKeys
+ *
+ * @since 3.0.0
+ * @memberOf is
+ * @func isObjWithKeys
+ * @see is/obj
+ * @see is/objWithKeys
+ * @see is/objStrict
+ * @see is/null
+ *
+ * @extends isObj
+ * @variation Object.keys(obj).length !== 0
+ *
+ * @example
+ *
+ * isObjWithKeys({eh: true})
+ * //=> true
+ * isObjWithKeys({})
+ * //=> false
+ * isObjWithKeys(new Object())
+ * //=> false
+ * isObjWithKeys(Object.create(null))
+ * //=> false
+ * isObjWithKeys(null)
+ * //=> false
+ * isObjWithKeys(new Set())
+ * //=> false
+ * isObjWithKeys(function() {})
+ * //=> false
+ * isObjWithKeys('')
+ * //=> false
+ * isObjWithKeys(1)
+ * //=> false
+ *
+ */
+ var objWithKeys = function (val) { return obj(val) && keys(val).length !== 0; };
+
+ /* ___filename___: dist/deps/conditional/or.js */
+
+
+ /**
+ * @desc first fn || second fn, curried
+ * @name or
+ * @memberOf conditional
+ * @since 4.0.1
+ * @func
+ *
+ * @param {Function} left first fn
+ * @param {Function} right second fn
+ * @param {*} x value to pass into left & right, curried
+ * @return {boolean} one of the functions return truthy
+ *
+ * @example
+ * const {isTrue, isFalse} = require('chain-able')
+ *
+ * const either = or(isFalse, isTrue)
+ *
+ * either([true])
+ * //=> true
+ *
+ * either([new Boolean(true)])
+ * //=> false
+ *
+ * either([1])
+ * //=> false
+ *
+ * // because curried
+ * or(isTrue, isFalse, true) //=> true
+ *
+ */
+ var or = curry(3, function (left, right, x) { return left(x) || right(x); });
+
+ /* ___filename___: dist/deps/conditional/or.js */
+
+ /* ___filename___: dist/deps/is/matcher.js */
+
+
+
+
+ /**
+ * @func isMatcher
+ * @memberOf is
+ * @since 3.0.0
+ *
+ * @param {*} x value to check
+ * @return {boolean} isFunction || isRegExp
+ *
+ * @see is/regexp
+ * @see is/function
+ * @see conditionals/or
+ *
+ * @example
+ *
+ * isMatcher(/(.*)/)
+ * //=> true
+ *
+ * isMatcher(x => true)
+ * //=> true
+ *
+ * isMatcher(1)
+ * //=> false
+ * isMatcher('.*')
+ * //=> false
+ *
+ */
+ var matcher = or(_function, regexp); // x => isFunction(x) || isRegExp(x)
+ // x instanceof RegExp
+
+ /* ___filename___: dist/deps/is/objPure.js */
+
+ /* ___filename___: dist/deps/is/objWithKeys.js */
+
+ /* ___filename___: dist/deps/is/real.js */
+
+ /* ___filename___: dist/deps/is/matcher.js */
+
+ // dont need these yet
+
+
+ // const isClass = require('./class')
+ // const isEnumerable = require('./enumerable')
+ // const isMapish = require('./mapish')
+
+ /**
+ * @member is
+ * @types is
+ * @tests is/*
+ *
+ * @see https://github.com/lodash/lodash/issues/3237
+ * @type {Object}
+ */
+ var index$12 = {
+ isObjWithKeys: objWithKeys,
+ isObj: obj,
+ // isObject: isObj,
+ isObjPure: objPure,
+ isObjNotNull: objNotNull,
+ isFunction: _function,
+ isReal: real,
+ toS: toS,
+ isDate: date,
+ isRegExp: regexp,
+ isError: error$1,
+ isBoolean: boolean_1,
+ isNumber: number,
+ isString: string,
+ isMap: map,
+ isSet: set,
+ isSymbol: symbol,
+ isPrototypeOf: prototypeOf,
+ isArray: array,
+ // new
+ isIterator: iterator$2,
+ isUndefined: _undefined,
+ isNull: _null,
+ isNill: nullOrUndefined,
+ isTrue: _true,
+ isMatcher: matcher,
+ };
+
+ /* ___filename___: dist/deps/string/camelCase.js */
+ /* prettier-ignore */
+ /**
+ * @desc camelCase
+ * @since 0.2.0
+ * @symb 🐫
+ *
+ * @param {string} str string to turn into camelCase
+ * @return {string} camelCased string
+ *
+ * @tutorial https://github.com/substack/camelize/blob/master/test/camel.js
+ * @tutorial https://github.com/andrewplummer/Sugar/blob/9c018a257a38714b81f7df033b74d236dbf1e861/lib/string.js
+ * @tutorial http://stackoverflow.com/questions/2970525/converting-any-string-into-camel-case
+ * @tutorial https://github.com/sindresorhus/camelcase
+ * @see https://stackoverflow.com/questions/1533131/what-useful-bitwise-operator-code-tricks-should-a-developer-know-about
+ * @TODO s.charAt(0).toLowerCase() + string.slice(1)
+ *
+ * @types deps
+ * @tests deps/camelCase
+ *
+ * @example
+ *
+ * camelCase('snake_case')
+ * //=> 'snakeCase'
+ *
+ */
+ var camelCase = function (str) { return str
+ // spaces with underscore
+ .replace(/\s+/g, '_')
+ // < underscores & dashes until whitespace or end
+ // > .toUpperCase x & '_'
+ .replace(/[_.-](\w|$)/g, function (m, x) { return x.toUpperCase(); }); };
+
+ /* ___filename___: dist/deps/conditional/not.js */
+ /**
+ * @desc return a negated function
+ * @name not
+ * @memberOf conditional
+ * @since 4.0.1
+ * @func
+ *
+ * @param {Function} fn any function
+ * @return {Function} !Function
+ *
+ * @example
+ *
+ * const falsed = not(x => true)
+ * const trued = not(x => false)
+ *
+ * trued()
+ * //=> true
+ *
+ * falsed()
+ * //=> false
+ *
+ */
+ var not = function (fn) { return function (x) { return !fn(x); }; };
+
+ // function not(predicate) {
+ // return function() {
+ // return !predicate.apply(this, arguments)
+ // }
+ // }
+
+ /* ___filename___: dist/deps/conditional/and.js */
+ /**
+ * @desc first fn & second fn
+ * @name and
+ * @memberOf conditional
+ * @since 4.0.1
+ * @func
+ *
+ * @param {Function} left first fn
+ * @param {Function} right second fn
+ * @return {boolean} both functions return truthy
+ *
+ * @example
+ *
+ * const both = and(x => typeof x === 'boolean', x => x === true)
+ *
+ * both([true])
+ * //=> true
+ *
+ * both([false])
+ * //=> false
+ *
+ * both([1])
+ * //=> false
+ *
+ */
+ var and = function (left, right) { return function (x) { return left(x) && right(x); }; };
+
+ /* ___filename___: dist/deps/conditional/all.js */
+
+
+ /**
+ * map all values in an array to see if all match
+ * @memberOf conditional
+ *
+ * @since 4.0.1
+ * @param {Function} predicate match the value
+ * @param {Array} array to match against predicate
+ * @return {boolean} all match predicate
+ *
+ * @see fp/curry
+ *
+ * @example
+ *
+ * const allBoolean = all(x => typeof x === 'boolean'q)
+ *
+ * allBoolean([true])
+ * //=> true
+ *
+ * allBoolean([1])
+ * //=> false
+ *
+ */
+ var all = curry(2, function (predicate, arr) {
+ for (var i in arr) {
+ if (!predicate(arr[i])) { return false }
+ }
+ return true
+ });
+
+ var all_1 = all;
+
+ /* ___filename___: dist/deps/conditional/and.js */
+
+ /* ___filename___: dist/deps/conditional/all.js */
+
+ /* ___filename___: dist/deps/is/arrayOf.js */
+
+
+
+
+ /**
+ * @desc every item in an array matches predicate
+ * @since 4.0.0 was in validatorBuilder
+ * @version 5.0.0
+ *
+ * @param {Function} predicate test to pass on every item in an array
+ * @return {boolean} all match predicate
+ *
+ * @example
+ *
+ * isArrayOf(isTrue)([true, true]) //=> true
+ * isArrayOf(isEmpty)(['']) //=> true
+ *
+ * isArrayOf(isBoolean)([true, false, 1, 2, 0]) //=> false
+ * isArrayOf(isString)(['string', Number]) //=> false
+ *
+ */
+ var arrayOf = function isArrayOf(predicate) {
+ return and(array, all_1(predicate))
+ };
+
+ /* ___filename___: dist/deps/conditional/not.js */
+
+ /* ___filename___: dist/deps/is/notRealOrIsEmpty.js */
+
+
+
+
+
+ /**
+ * @SIZE: another 10bytes for these fns
+ * @name isNotRealOrIsEmpty
+ *
+ * @see is/isReal
+ * @see is/isEmpty
+ * @see conditional/and
+ * @see conditional/not
+ *
+ * @type {Function}
+ */
+ var notRealOrIsEmpty = and(not(real), empty);
+
+ /* ___filename___: dist/deps/fp/replace.js */
+
+
+ /**
+ * Replace a substring or regex match in a string with a replacement.
+ *
+ * @func
+ * @memberOf fp
+ * @since v5.0.0
+ * @category String
+ * @sig RegExp|String -> String -> String -> String
+ *
+ * @param {RegExp|String} pattern A regular expression or a substring to match.
+ * @param {String} replacement The string to replace the matches with.
+ * @param {String} str The String to do the search and replacement in.
+ * @return {String} The result.
+ *
+ * @see https://github.com/ramda/ramda/blob/master/src/replace.js
+ *
+ * @example
+ *
+ * replace('foo', 'bar', 'foo foo foo'); //=> 'bar foo foo'
+ * replace(/foo/, 'bar', 'foo foo foo'); //=> 'bar foo foo'
+ *
+ * // Use the "g" (global) flag to replace all occurrences:
+ * replace(/foo/g, 'bar', 'foo foo foo'); //=> 'bar bar bar'
+ *
+ */
+ var replace = curry(3, function replace(regex, replacement, str) {
+ return str.replace(regex, replacement)
+ });
+
+ /* ___filename___: dist/ChainedMapBase.js */
+
+ /* ___filename___: dist/deps/string/camelCase.js */
+
+ /* ___filename___: dist/deps/is/arrayOf.js */
+
+ /* ___filename___: dist/deps/is/notRealOrIsEmpty.js */
+
+ /* ___filename___: dist/deps/fp/replace.js */
+
+ /* ___filename___: dist/deps/validators/validatorBuilder.js */
+ /**
+ * @since 4.0.0 <- moved out of the store, into scoped
+ * @since 1.0.0
+ * @desc library of validators to use by name
+ * @modifies this.validators
+ * @param {Object} validators
+ */
+
+
+
+
+
+
+
+
+
+
+
+
+
+ var validators = new ChainedMapBase();
+
+ // eslint-disable-next-line
+ var stripArithmeticSymbols = replace(/[?\[\]!\|]/g, '');
+ var escapedKey = function (x) { return camelCase('is-' + x); };
+ var enummy = function (enums) { return function (x) { return enums === x || enums.includes(x); }; };
+
+ // @TODO: .remap!!!
+ // @TODO: can use these to return noops with error logging on development
+ var get$2 = function (key) { return validators.get(key) || validators.get(escapedKey(key)) || enummy(key); };
+ var has = function (key) { return validators.has(key) || validators.get(escapedKey(key)); };
+ var set$4 = function (key, value) { return validators.set(key, value); };
+ var doesNotHave = not(has);
+
+ /**
+ * @desc add custom types for validation
+ * @category types
+ * @category schema
+ * @types schema
+ *
+ * @since 4.0.0 <- used with schema, used in method chain
+ * @since 3.0.0 <- took out
+ * @since 1.0.0
+ *
+ * @param {Object} types custom Types
+ *
+ * @see deps/validators/validatorFactory
+ *
+ * @example
+ *
+ * addTypes({yaya: x => typeof x === 'string'})
+ *
+ * const chain = new Chain().methods('eh').type('yaya').build()
+ *
+ * chain.eh('good')
+ * //=> chain
+ *
+ * chain.eh(!!'throws')
+ * //=> TypeError(false != {yaya: x => typeof x === 'string'})
+ *
+ * @example
+ *
+ * const custom = {}
+ * custom.enums = enums => x => enums.includes(x)
+ * custom['*'] = x => true
+ * addTypes(custom)
+ * //-> void
+ *
+ * new Chain().methods('eh').type('*').build().eh
+ * //=> validateType(custom['*'])
+ *
+ */
+ var addTypes = function (types) { return validators.from(index$2(validators.entries(), types)); };
+
+ addTypes(index$12);
+
+ var includesAndOr = function (x) { return x.includes('|') || x.includes('&'); };
+
+ /**
+ * @memberOf schema
+ * @category types
+ *
+ * @param {string} fullKey a key with `|` and/or '&'
+ * @return {Function} validator
+ *
+ * @example
+ *
+ * const isStringOrNumber = typeListFactory('string|number')
+ *
+ * isStringOrNumber(1)
+ * //=> true
+ * isStringOrNumber('one')
+ * //=> true
+ * isStringOrNumber(Object)
+ * //=> false
+ *
+ */
+ function typeListFactory(fullKey) {
+ // already have it
+ if (has(fullKey)) {
+ return get$2(fullKey)
+ }
+
+ // get all types
+ var orTypes = fullKey.split('|');
+ var andTypes = fullKey.split('&');
+
+ // ensure we have all validators - sets up conditionals
+ for (var v = 0; v < orTypes.length; v++) {
+ builder(orTypes[v]);
+ }
+
+ // go through all valid options, if any are true, good to go
+ set$4(fullKey, function (x) {
+ for (var v = 0; v < orTypes.length; v++) {
+ if (get$2(orTypes[v])(x)) {
+ return true
+ }
+ }
+ return false
+ });
+
+ return get$2(fullKey)
+ }
+
+ // @TODO how to iterate properly with the bitwise fn + AND
+ // add another param? ignore overly complex |& things? just allow 1?
+ // just show how to use these shorthand fn builders
+
+ /**
+ * @desc transform arithmetic strings into types
+ * @since 4.0.0-alpha.1
+ * @category types
+ *
+ * @param {Matchable} fullKey arithmetic type key
+ * @return {Matchable} function to match with, with .inspect for easy debugging
+ *
+ * @types schema
+ * @test typed
+ * @test schema
+ * @see is
+ * @todo coercing values to certain types: arithmeticTypeFactory('')
+ *
+ * @example
+ *
+ * arithmeticTypeFactory('?string')
+ * //=> x => !isReal(x) || isString(x)
+ *
+ * @example
+ *
+ * arithmeticTypeFactory('?string|string[]')
+ * //=> x => isString(x) || isArrayOf(isString)(x)
+ *
+ * @example
+ *
+ * arithmeticTypeFactory('!string')
+ * //=> x => not(isString)(x)
+ *
+ * @example
+ *
+ * types.addTypes({star: x => true})
+ * arithmeticTypeFactory('object|function|star')
+ * //=> x => isObj(x) || isFunction(x) || isStar(x)
+ *
+ * @example
+ *
+ * arithmeticTypeFactory('===')
+ * //=> x => (['===']).includes(x)
+ */
+ function arithmeticTypeFactory(fullKey) {
+ var key = stripArithmeticSymbols(fullKey);
+ var fn = get$2(key);
+ var optionalType = "?" + key;
+ var typeOrArrayOrType = key + "[]";
+ var notType = "!" + key;
+
+ var isValidOrNotRealOrEmptyStr = or(fn, notRealOrIsEmpty);
+ var isValidOrArrayOfValid = or(fn, arrayOf(fn));
+ if (doesNotHave(optionalType)) {
+ set$4(optionalType, isValidOrNotRealOrEmptyStr);
+ }
+ if (doesNotHave(typeOrArrayOrType)) {
+ set$4(typeOrArrayOrType, isValidOrArrayOfValid);
+ }
+ if (doesNotHave(notType)) {
+ set$4(notType, not(fn));
+ }
+
+ return get$2(fullKey)
+ }
+
+ // ----
+ // ; function split
+ // ----
+
+ // v- annoying on comments with ifs
+ /* prettier-ignore */
+ /**
+ * @desc @pattern @builder -> builds using multiple factories depending on conditons
+ * or abstractFactory whatever
+ * opinionated: if it's a function, it's a validator...
+ *
+ * @category types
+ * @since 4.0.0
+ * @param {string | Function | Primitive} fullKey arithmetic key to the validator
+ * @return {Function} validator
+ *
+ * @see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Default_parameters
+ * @NOTE if/else is for uglifying ternaries, even though else if is not needed
+ * @NOTE if key is number, iterating the array
+ *
+ * @example
+ *
+ * // functionType
+ * const isString = x => typeof x === 'string'
+ * builder(isString)
+ * // => isString
+ *
+ * @example
+ *
+ * // stringType (built in, or custom-keyed validator, or eqeqeq)
+ * builder('string')
+ * // => isString
+ *
+ * const enummy = builder('enum')
+ * // => x => ['enum'].includes(x)
+ *
+ * @example
+ *
+ * // arithmeticType
+ * builder('string|string[]')
+ * // => isString || isArrayOf(isString)
+ *
+ */
+ function builder(fullKey) {
+ if (_function(fullKey)) {
+ /* istanbul ignore next: dev */
+ if (debug) {
+ console.log('functionType', {fullKey: fullKey});
+ }
+ return fullKey
+ }
+ else if (string(fullKey) && includesAndOr(fullKey)) {
+ /* istanbul ignore next: dev */
+ if (debug) {
+ console.log('andOrType', {fullKey: fullKey});
+ }
+ return typeListFactory(fullKey)
+ }
+ else {
+ /* istanbul ignore next: dev */
+ if (debug) {
+ console.log('arithmeticType', {fullKey: fullKey}, arithmeticTypeFactory(fullKey));
+ }
+ return arithmeticTypeFactory(fullKey)
+ }
+ }
+
+ builder.has = has;
+ builder.get = get$2;
+ builder.set = set$4;
+ builder.addTypes = addTypes; // was merge
+ builder.map = validators;
+ var validatorBuilder = builder;
+
+ /* ___filename___: dist/deps/dot/paths.js */
+
+ /* ___filename___: dist/deps/is/stringOrNumber.js */
+
+ /* ___filename___: dist/deps/validators/validatorBuilder.js */
+
+ /* ___filename___: dist/deps/validators/schemaBuilder.js */
+
+
+
+
+
+
+
+
+
+
+ var isNotNested = function (x) { return stringOrNumber(x) ||
+ boolean_1(x) ||
+ !real(x) ||
+ error$1(x) ||
+ regexp(x); };
+
+ var validateType = function (type, value, nestedSchema) {
+ var validator = nestedSchema || validatorBuilder(type);
+ return validator(value)
+ };
+
+ /**
+ * @desc pass the property & schema in, get a nestable typeValidator out
+ * @since 4.0.0-alpha.1
+ * @category types
+ * @category schema
+ *
+ * @param {Primitive} property property name of the currently nested schema
+ * @param {Schema | Type} nestedSchema a nested schema with Type validators, or a Type validator
+ * @return {Function} typeValidator
+ *
+ * @example
+ *
+ * // property name here is `dates`, then `created`, then `at`
+ * nestedSchema = {
+ * dates: {
+ * created: {
+ * at: 'date'
+ * }
+ * }
+ * }
+ *
+ * input = {
+ * dates: {
+ * created: {
+ * at: new Date()
+ * }
+ * }
+ * }
+ *
+ * input = new Date()
+ * input = {
+ * dates: {
+ * mismatch: true
+ * }
+ * }
+ *
+ */
+ var schemaFactory = function (property, nestedSchema) {
+ /**
+ * @desc build a recursive schema for all around runtime type safety
+ * @category types
+ * @category schema
+ * @memberOf schema
+ * @symb 🛂
+ * @since 4.0.0-beta.1
+ *
+ * @param {any} input the input to validate
+ * @return {boolean} valid
+ *
+ * @see is
+ *
+ * @example
+ *
+ * const typeValidator = schemaFactory('eh', x => typeof x === 'string')
+ *
+ * var isValid = typeValidator('stringy')
+ * //=> true
+ *
+ * var isValid = typeValidator(Number)
+ * //=> false
+ *
+ * @example
+ *
+ * const isNumber = x => typeof x === 'number'
+ * const typeValidator = schemaFactory('eh', {canada: 'number'})
+ *
+ * var isValid = typeValidator({canada: 1})
+ * //=> true
+ *
+ * var isValid = typeValidator({})
+ * //=> false
+ *
+ * var isValid = typeValidator({canada: false})
+ * //=> false
+ *
+ * var isValid = typeValidator(1)
+ * //=> false
+ *
+ */
+ function typeValidator(input) {
+ if (isNotNested(input)) {
+ // @@DEBUGGER
+ return validateType(property, input, nestedSchema)
+ }
+ var longestPaths = paths(false, input, true);
+
+ // @@DEBUGGER
+
+ for (var l = 0; l < longestPaths.length; l++) {
+ var fullPath = longestPaths[l] || property;
+ var type = get(nestedSchema, fullPath);
+ var value = get(input, fullPath.split('.'));
+
+ // @@DEBUGGER
+
+ if (!validateType(type, value)) {
+ // @@DEBUGGER
+ return false
+ }
+
+ // @@DEBUGGER
+ }
+ return true
+ }
+
+ /* istanbul ignore next: devs */
+ if (dev) {
+ typeValidator.inspect = function () { return ({property: property, nestedSchema: nestedSchema}); };
+ typeValidator.toString = function () { return JSON.stringify(typeValidator.inspect(), null, 2); };
+ }
+ return typeValidator
+ };
+ var schemaBuilder = schemaFactory;
+
+ /* ___filename___: dist/deps/validators/schemaBuilder.js */
+
+ /* ___filename___: dist/plugins/schema.js */
+ /* eslint complexity: "OFF" */
+
+ // util
+
+
+
+
+
+ var isFunction$1 = _undefined;
+ // logic
+
+
+
+ var SCHEMA_KEY = 'schema';
+
+ var isObjOrArray = function (x) { return (obj(x) && !isFunction$1(x)) || array(x); };
+
+ // const meta = require('../deps/meta')
+ // const or = require('../deps/conditional/or')
+ // const and = require('../deps/conditional/and')
+ // const not = require('../deps/conditional/not')
+ // const condition = Condition(Condition.is(isFunction).and().not(isObj)).or(isArray)
+ // const isObjNotFn = and(not(isFunction), isObj)
+ // const isObjOrArray = or(isObjNotFn, isArray)
+
+ /**
+ * @desc handles:
+ * 1. recursively building nestable schemas,
+ * 2. creating MethodChains for all types
+ * 3. carrying over the inheritable properties
+ * 4. @modifies @injects @decorates .add(customValidators)
+ * @pattern decorator...builder...plugin...
+ *
+ * @param {Schema} obj
+ * @return {MethodFactory} @chainable
+ */
+ var schema = function schema(obj$$2) {
+ var this$1 = this;
+
+ var parent = this.parent;
+ var ref = this.entries();
+ var onValid = ref.onValid;
+ var onInvalid = ref.onInvalid;
+ var define = ref.define;
+ var getSet = ref.getSet;
+ var keys$$2 = keys(obj$$2);
+
+ for (var k = 0; k < keys$$2.length; k++) {
+ var key = keys$$2[k];
+ var value = obj$$2[key];
+
+ // parent.method ? parent.method(key) :
+ var builder = this$1.newThis().name(key); // MethodChain
+
+ // @TODO: PLUCK METHOD FOR USING VALID KEYS
+ // @TODO:
+ // const entryKeys = ObjectKeys(entries)
+ // const entries = this.entries()
+ // for (let e = 0; e < entryKeys.length; e++) {
+ // const entryKey = entryKeys[e]
+ // const entry = entries[entryKey]
+ // builder[entryKey](entry)
+ // }
+ if (onInvalid) { builder.onInvalid(onInvalid); }
+ if (onValid) { builder.onValid(onValid); }
+ if (define) { builder.define(); }
+ if (getSet) { builder.getSet(); }
+
+ var type = value;
+ if (isObjOrArray(value)) {
+ // @@DEBUGGER
+
+ // could just assign to type
+ var traversableValidator = schemaBuilder(key, value);
+
+ if (dev) {
+ traversableValidator.schema = value;
+ }
+
+ type = traversableValidator;
+ }
+
+ // @HACK @FIXME @TODO: this should not happen,
+ // just when using babel and decorating not calling constructor...
+ // likely needs to `return this` on each?
+ // parent.store = parent.store || new Map()
+ // parent.meta = meta(parent)
+ if (parent.meta) {
+ parent.meta(SCHEMA_KEY, key, value);
+ }
+
+ builder.type(type).build();
+ }
+
+ return parent
+ };
+
+ /* ___filename___: dist/deps/encase/withSpecification.js */
+
+
+ /**
+ * @desc a special encased wrapper with no try catch but same api
+ * @name withSpecification
+ * @func
+ * @memberOf encase
+ * @since 4.0.0
+ *
+ * @param {Function} specification match
+ * @param {Function} call cb to determine valid or invalid
+ * @param {Function} onInvalid cb when invalid
+ * @param {Function} onInvalid cb when valid
+ * @return {Function} a lot of functions...
+ *
+ * @see fp/curry
+ *
+ * @example
+ * const onInvalid = console.error
+ * const onValid = console.debug
+ * const onCall = console.log
+ * const encased = withSpecification(x => true)(onCall)(onValid, onInvalid)
+ *
+ * encased(1, 2, 3) //=> onCall (did not throw)
+ */
+ var withSpecification = curry(4, function (specification, call, onInvalid, onValid) { return function (a, b, c) {
+ var result = call(a, b, c);
+ if (specification(result)) { return onInvalid(result) }
+ else { return onValid(result) }
+ }; });
+
+ /* ___filename___: dist/deps/validators/error.js */
+
+
+
+
+ /* istanbul ignore next: dev */
+ var thrower = function (error) { return function () {
+ if (dev) {
+ console.log(error);
+ }
+
+ throw error
+ }; };
+
+ /**
+ * @desc enhance an Error, enable rethrowing & better inspection
+ * @memberOf encase
+ * @category types
+ * @category encase
+ *
+ * @since 4.0.0-alpha.1
+ * @param {Primitive} method method being decorated
+ * @param {Type} type type to validate with
+ * @return {Function} function that returns a decorated TypeError with .inspect & metadata (arg, thrown, meta)
+ *
+ * @TODO js stringify if development
+ *
+ * @see MethodChain
+ * @see validators/schemaBuilder
+ * @see validators/validatorBuilder
+ * @see plugins/encase
+ *
+ * @example
+ * const badValidator = x => {
+ * if (x === 'bad') {
+ * throw new Error('bad!')
+ * }
+ * }
+ * const enhancer = enhanceError('eh', badValidator)
+ *
+ * // called by plugins/encase when throws or invalid
+ * let error
+ * let arg = 'bad'
+ * try {
+ * error = badValidator(arg)
+ * }
+ * catch (e) {
+ * error = enhancer(arg, e, {metadata: true})
+ * }
+ *
+ * console.log(error)
+ * //=> {[eh]: { type: badValidator, arg: 'bad', json, str, rethrow }}
+ * //=> console.log on DEVELOPMENT
+ */
+ var error$3 = function (method, type) { return function (arg, thrown, meta) {
+ var argToString = toS(arg);
+ var data = {
+ [method]: {
+ type: type,
+ arg: {
+ val: arg,
+ str: argToString,
+ json: JSON.stringify(arg),
+ },
+ },
+ };
+
+ var error = assign(
+ new TypeError((argToString + " != " + type)),
+ data,
+ meta
+ );
+
+ // put it back in its place
+ if (thrown && thrown.message) { error.message += thrown.message; }
+ if (thrown && thrown.stack) { error.stack = thrown.stack; }
+
+ /* istanbul ignore next: dev */
+ if (dev) {
+ // since we are just inspecting the metadata on dev
+ error.inspect = function () {
+ var devMsg = 'inspecting on development';
+ var thrownMsg = "thrown: " + thrown;
+ var eMsg = "compare: " + (error.message);
+ var errorName = "name: " + (error.name);
+ var argMsg = "arg: " + arg + ";\nstr: " + (toS(
+ arg
+ )) + " " + (typeof arg) + ";\njson: " + (JSON.stringify(arg));
+ var typeMsg = "type: " + type;
+ var stackMsg = 'stack: ' + error.stack;
+ var dashMsg = "-----";
+ var msg = "\n" + dashMsg + " " + devMsg + " " + dashMsg + "\n";
+ if (meta) { msg += "meta: " + (JSON.stringify(meta)) + "\n"; }
+ msg += thrownMsg + "\n" + eMsg + "\n" + errorName + "\n\n";
+ msg += typeMsg + "\n" + argMsg;
+ msg += "\n\n" + stackMsg + "\n" + dashMsg + "\n";
+ return msg
+ };
+ }
+
+ error.reThrow = thrower(error);
+ return error
+ }; };
+
+ /* ___filename___: dist/deps/encase/tryCatch.js */
+
+
+ /**
+ * @TODO could curry
+ *
+ * @memberOf encase
+ * @see https://github.com/fluture-js/Fluture#encase
+ * @since 4.0.0 <- moved out into a dep
+ * @since 1.0.0
+ *
+ * @param {Function} call
+ * @return {boolean | any} validation/encased function call result
+ */
+ var tryCatch = curry(3, function (call, onValid, onInvalid) { return function (a, b, c) {
+ var result;
+ try {
+ result = call(a, b, c);
+ return onValid ? onValid(result) : result
+ }
+ catch (error) {
+ // error.caught = true
+ // @NOTE: defaults to rethrow... if (isTrue(rethrow)) throw error
+ if (onInvalid) { return onInvalid(error) }
+ else { return error }
+ }
+ }; });
+
+ /* ___filename___: dist/deps/encase/tryCatch.js */
+
+ /* ___filename___: dist/deps/encase/encase.js */
+
+
+ /**
+ * @version 5.0.0 wrapped tryCatch & withSpecification in curry
+ * @version 4.0.1 added custom encaser
+ * @since 4.0.0
+ * @member encase
+ * @symb 🛡
+ *
+ * @param {Function} call function to _encase_
+ * @param {Function | undefined} [encaser=tryCatch] function to encase _with_
+ * @return {Function} -> FunctionObject{onInvalid, onValid, rethrow, call}
+ *
+ * @example
+ *
+ * const throws = x => {
+ * if (x === false) {
+ * throw new Error('invalid - cannot be false')
+ * }
+ * return true
+ * }
+ * const api = encase(throws)
+ *
+ *
+ * api.onValid(console.log)
+ * api.onInvalid(console.error)
+ *
+ * //--- invalid
+ * api.call(false)
+ * //=> 'invalid - cannot be false'
+ *
+ * //--- valid
+ * api.call(true)
+ * //=> 'true'
+ *
+ */
+ var encase = function (call, encaser) {
+ var encased = encaser ? encaser(call) : tryCatch(call);
+
+ // @TODO rethink this scoped approach
+ // left, right, rethrow
+ var onInvalid;
+ var onValid;
+
+ var config = function (a, b, c) { return encased(onValid, onInvalid)(a, b, c); };
+
+ config.then = config.onInvalid = function (fn) {
+ onInvalid = fn;
+ return config
+ };
+ config.catch = config.onValid = function (fn) {
+ onValid = fn;
+ return config
+ };
+
+ return config
+ };
+
+ /* ___filename___: dist/deps/encase/encase.js */
+
+ var index$14 = encase;
+
+ /* ___filename___: dist/deps/validators/error.js */
+
+ /* ___filename___: dist/plugins/encase.js */
+
+
+
+ var ERROR_META = {m: 1};
+
+ /**
+ * 3 steps
+ * 0. enhance error
+ * 1. encase function with a specification
+ * 2. build a function to call onInvalid or onInvalid depending
+ *
+ * @since 4.0.0
+ *
+ * @param {string} name name of the method
+ * @param {Object | Function} parent object being decorated by MethodChain
+ * @param {Object} built the current state of the decoration
+ * @return {Function} curried finisher, for specification
+ *
+ * @name methodEncasingFactory
+ * @func methodEncasingFactory
+ * @symb ⛑🏭
+ * @types encase
+ *
+ * @example
+ *
+ * methodEncasingFactory('eh', {}, {onSet: console.log})
+ * //=> Function
+ *
+ */
+ function methodEncasingFactory(name, parent, built) {
+ /**
+ * @name scopedEncase
+ * @func scopedEncase
+ * @category type
+ * @since 4.0.0-beta.1
+ *
+ * @param {Function} fnToEncase depending on the result of this, call
+ * @param {string | Function | undefined} [type=undefined] Type
+ * @param {Function | undefined} [specification=undefined] Specification
+ * @return {Function} the method...
+ *
+ * @example
+ *
+ * const fnToEncase = arg => arg === true
+ * const onInvalid = (error, key, arg, instance) => console.log(arguments)
+ * const onValid = (key, arg, instance) => console.log(arguments)
+ * const encased = scopedEncase(fnToEncase)
+ * .onValid(onValid)
+ * .onInvalid(onInvalid)
+ * //=> typedOnCall
+ *
+ */
+ return function scopedEncase(fnToEncase, type, specification) {
+ // @@debugger
+ var enhanceError = error$3(name, type, fnToEncase, parent);
+
+ // if specification is not passed in, undefined defaults to tryCatch
+ var encased = index$14(fnToEncase, specification);
+
+ // our configured functions, with fallback defaults
+ var onSet = built.onCall || built.onSet;
+ var onValid = built.onValid || onSet;
+
+ // default to re-throw
+ var onInvalid =
+ built.onInvalid ||
+ (function (arg, error) { return enhanceError(arg, error, ERROR_META).reThrow(); });
+
+ /**
+ * @desc this is the actual built function
+ * @name typedOnCall
+ * @func typedOnCall
+ * @category type
+ * @since 4.0.0-beta.1
+ *
+ * @param {any} arg arg to validate
+ * @return {Function} typedOnCall(argToValidate: any)
+ *
+ * @example
+ *
+ * const encased = encase(fnToEncase)
+ * .onValid()
+ * .onInvalid(function)
+ * .call()
+ *
+ */
+ return function typedOnCall(arg) {
+ var this$1 = this;
+
+ // nodejs way - error first, data second, instance last
+ var callInvalid = function (error) {
+ // @@debugger
+ onInvalid.call(this$1, enhanceError(arg, error), arg, name, this$1);
+ };
+
+ // @TODO: ensure it isn't a syntax error and is a type error
+ // if it is already an error, we should only enhance it
+ // @example `TypeError: Cannot read property 'call' of undefined`
+ encased
+ .onInvalid(callInvalid)
+ // @NOTE: onValid defaults to `this.set(name, arg)`
+ .onValid(function (result) {
+ // @@debugger
+ onValid.call(this$1, arg, name, this$1);
+ })
+ .call(this, arg);
+
+ return this
+ }
+ }
+ }
+
+ var encase_1 = methodEncasingFactory;
+
+ /* ___filename___: dist/deps/encase/withSpecification.js */
+
+ /* ___filename___: dist/plugins/encase.js */
+
+ /* ___filename___: dist/plugins/types.js */
+
+
+
+
+
+
+
+ // we'll be opinionated and say either `false` or `throw`
+ var spec = withSpecification(not(_false));
+
+ /**
+ * @pattern factory plugin
+ * @param {string} name
+ * @param {Object} parent
+ * @param {Object} built
+ * @return {void}
+ */
+ var types = function validatorPlugin(name, parent, built) {
+ // core domain of this fn, used by validators and configured fns
+ var type = built.type;
+
+ if (type) {
+ // if (ENV_DEVELOPMENT) {
+ // this.debugSteps('added built type')
+ // }
+
+ // create our validator in the factory,
+ var validator = validatorBuilder(type);
+
+ // then encase it, prepare a TypeError factory
+ var encase = encase_1(name, parent, built);
+ var validatorMethod = encase(validator, type, spec);
+
+ /* istanbul ignore next: dev */
+ if (dev) {
+ validatorMethod.type = type;
+ }
+
+ this.onCall(validatorMethod).onSet(validatorMethod);
+ }
+ };
+
+ /* ___filename___: dist/plugins/obj.js */
+
+
+ // @TODO optimize size here ez
+ var obj$2 = function(methods, name) {
+ var this$1 = this;
+
+ var obj = methods[name];
+
+ if (_function(obj)) {
+ return function () {
+ // @TODO: IS THIS THE BEST DEFAULT?!
+ this$1.define(false);
+ this$1.onCall(obj);
+ // .onSet(obj).onGet(obj)
+ }
+ }
+ else {
+ return function () {
+ this$1.from(obj);
+ // @NOTE: this is reserved
+ if (obj.set) { this$1.onSet(obj.set); }
+ if (obj.get) { this$1.onGet(obj.get); }
+ if (obj.call) { this$1.onCall(obj.call); }
+ if (obj.set && obj.get) {
+ this$1.define().getSet();
+ }
+ }
+ }
+ };
+
+ /* ___filename___: dist/plugins/decorate.js */
+
+
+
+ /**
+ * decorates a parent when the argument is provided
+ * BUT THE FUNCTIONS WILL STILL BE SCOPED TO CURRENT PARENT
+ * for easy factory chaining
+ *
+ * @since 4.0.0-alpha.1
+ * @memberOf MethodChain
+ * @param {Object} parentToDecorate object to put the method on instead
+ * @return {MethodChain} @chainable
+ *
+ * @see MethodChain
+ *
+ * @TODO this is more like a preset since it *adds* plugins?
+ * more of methodFactory now
+ *
+ * @example
+ *
+ * const chain = new Chain()
+ * const obj = {}
+ * chain.method('ehOh').decorate(obj).build()
+ * typeof obj.ehOh
+ * //=> 'function'
+ *
+ */
+ var decorate = function(parentToDecorate) {
+ // @TODO is objStrict?
+ // if (parentToDecorate) {
+ this.target(parentToDecorate);
+
+ // can use this to "undecorate"
+ // if (!parentToDecorate.meta) <- checks already inside of meta()
+ parentToDecorate.meta = index$8(parentToDecorate);
+
+ // default returns result of calling function,
+ // else .parentToDecorate
+ return this.plugin(function(name, parent) {
+ parentToDecorate.meta(decorated, name);
+
+ // @NOTE: so we can return...
+ /* prettier-ignore */
+ return this
+ .returns(function returnsFunction(result) {
+ return result || parentToDecorate
+ })
+ .callReturns(true)
+ })
+ };
+
+ /* ___filename___: dist/plugins/autoIncrement.js */
+ /**
+ * @plugin
+ * @param {Primitive} name method name
+ * @param {Object} parent Parent
+ * @return {MethodChain} @chainable
+ */
+ var autoIncrement = function(name, parent) {
+ return this.initial(0).onCall(function () { return parent.tap(name, function (num) { return num + 1; }); })
+ };
+
+ /* ___filename___: dist/plugins/autoGetSet.js */
+
+
+ /**
+ * @memberOf MethodChain
+ * @plugin
+ *
+ * @param {Primitive} name method name being built
+ * @param {Object} parent parent containing the method
+ * @return {MethodChain} @chainable
+ *
+ * @see MethodChain
+ *
+ * @example
+ *
+ * const chain = new Chain()
+ * chain.methods('eh').plugin(autoGetSet).build()
+ *
+ * chain.eh(1)
+ * //=> Chain
+ * chain.eh()
+ * //=> 1
+ *
+ */
+ function autoGetSet(name, parent) {
+ var auto = function (arg) { return (_undefined(arg) ? parent.get(name) : parent.set(name, arg)); };
+
+ // so we know if we defaulted them
+ auto.autoGetSet = true;
+ return this.onSet(auto).onGet(auto).onCall(auto)
+ }
+
+ var autoGetSet_1 = autoGetSet;
+
+ /* ___filename___: dist/deps/util/getDescriptor.js */
+ var getDescriptor = Object.getOwnPropertyDescriptor;
+
+ /* ___filename___: dist/deps/argumentor.js */
+ /**
+ * @desc turns arguments into an array, used as a util, for opt
+ *
+ * @since 3.0.0
+ * @return {Array}
+ *
+ * @see https://github.com/aretecode/awesome-deopt
+ * @see https://github.com/petkaantonov/bluebird/wiki/Optimization-killers
+ *
+ * @example
+ *
+ * function eh() {
+ * const args = argumentor.apply(null, arguments).slice(1)
+ *
+ * console.log(args)
+ * //=> [1, 10, 100]
+ * }
+ * eh(0, 1, 10, 100)
+ *
+ */
+ var argumentor = function() {
+ var arguments$1 = arguments;
+
+ var len = arguments.length;
+ var args = new Array(len > 1 ? len - 1 : 0);
+ for (var i = 0; i < len; ++i) { args[i] = arguments$1[i]; }
+ return args
+ };
+
+ /* ___filename___: dist/deps/util/getPrototypeOf.js */
+ var getPrototypeOf = Object.getPrototypeOf;
+
+ /* ___filename___: dist/deps/util/getPrototypeOf.js */
+
+ /* ___filename___: dist/deps/util/props.js */
+
+
+
+ var getOwnPropertyNames = Object.getOwnPropertyNames;
+ var getOwnPropertySymbols = Object.getOwnPropertySymbols;
+
+ // @TODO https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptors
+ // const getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors
+
+ /**
+ * @desc properties, property symbols, object keys
+ * ^ all again for prototype
+ *
+ * @param {Object} obj object to get properties & symbols from
+ * @return {Array} properties
+ *
+ * @example
+ * var obj = {key: true}
+ * allProperties(obj)
+ * //=> ['key']
+ *
+ * @example
+ * class One {
+ * method() {}
+ * }
+ * class Two extends One {
+ * eh() {}
+ * }
+ * allProperties(new Two())
+ * //=> ['eh', 'method']
+ *
+ */
+ function allProperties(obj) {
+ var proto = getPrototypeOf(obj);
+ return [].concat(
+ getOwnPropertyNames(obj),
+ getOwnPropertySymbols(obj),
+ keys(obj),
+ proto ? allProperties(proto) : []
+ )
+ }
+
+ var props = allProperties;
+
+ /* ___filename___: dist/deps/util/props.js */
+
+ /* ___filename___: dist/deps/gc.js */
+
+
+
+
+
+ // function gc() {
+ // if (typeof window !== 'undefined') window.global = window
+ // if (typeof global.gc === 'function') global.gc()
+ // }
+
+ /**
+ * @see https://stackoverflow.com/questions/1947995/when-should-i-use-delete-vs-setting-elements-to-null-in-javascript
+ * @see https://v8project.blogspot.ca/2015/08/getting-garbage-collection-for-free.html
+ * @see https://github.com/natewatson999/js-gc
+ * @see https://github.com/siddMahen/node-gc
+ * @see http://buildnewgames.com/garbage-collector-friendly-code/
+ * @see https://stackoverflow.com/questions/27597335/ensuring-object-can-be-garbage-collected
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management
+ *
+ * @TODO blacklist = [] param
+ * @TODO put all GC events into a cached map and debounce the operation
+ *
+ * @since 4.0.0
+ * @desc remove all methods, mark for garbage collection
+ * @param {Object} obj object to traverse and clear
+ * @return {void}
+ *
+ * @example
+ *
+ * var scoped = {}
+ * var ref = () => scoped
+ * var obj = {scoped, ref, eh: true}
+ *
+ * markForGarbageCollection(obj)
+ * //=> void
+ *
+ * obj
+ * //=> undefined|{}
+ *
+ */
+ function markForGarbageCollection(obj$$2) {
+ // @TODO: ArrayOrObj loop... like tons of libs do...
+ var props$$1 = obj(obj$$2) ? props(obj$$2) : obj$$2; //isArray(obj) ? obj
+
+ for (var p = 0; p < props$$1.length; p++) {
+ if (obj(obj$$2[p])) {
+ markForGarbageCollection(obj$$2[p]);
+ }
+ delete obj$$2[p];
+ }
+
+ // traverse(obj).forEach(function(x) {
+ // const {value} = this
+ //
+ // // @NOTE: just delete the main path first, later we can use cleaner
+ // // const shouldIgnore = path
+ // // .map(pathPart => ignore.includes(pathPart))
+ // // .includes(true)
+ // // !shouldIgnore &&
+ //
+ // /* istanbul ignore else: safety for bottom up */
+ // // ensure the longest paths in traverser are used...
+ // if (!isArray(value) && !isObj(value)) {
+ // this.remove()
+ // }
+ // })
+
+ // simple fast easy cleanup
+ // for (let p = 0; p < props.length; p++) {
+ // delete obj[p]
+ // }
+
+ props$$1 = undefined;
+ obj$$2 = undefined;
+ }
+
+ var gc = markForGarbageCollection;
+
+ /* ___filename___: dist/plugins/schema.js */
+
+ /* ___filename___: dist/plugins/types.js */
+
+ /* ___filename___: dist/plugins/obj.js */
+
+ /* ___filename___: dist/plugins/decorate.js */
+
+ /* ___filename___: dist/plugins/autoIncrement.js */
+
+ /* ___filename___: dist/plugins/autoGetSet.js */
+
+ /* ___filename___: dist/deps/util/getDescriptor.js */
+
+ /* ___filename___: dist/deps/argumentor.js */
+
+ /* ___filename___: dist/deps/gc.js */
+
+ /* ___filename___: dist/MethodChain.js */
+ /* eslint complexity: "OFF" */
+ /* eslint import/max-dependencies: "OFF" */
+
+ /**
+ * @TODO clarify .set vs .call
+ * {@link https://github.com/iluwatar/java-design-patterns/tree/master/property property-pattern}
+ * {@link https://github.com/iluwatar/java-design-patterns/tree/master/prototype prototype-pattern}
+ * {@link https://github.com/iluwatar/java-design-patterns/tree/master/step-builder step-builder-pattern}
+ * {@link https://github.com/iluwatar/java-design-patterns/tree/master/builder builder-pattern}
+ * {@link https://github.com/addyosmani/essential-js-design-patterns/blob/master/diagrams/mixins.png mixin-png}
+ * {@link https://sourcemaking.com/design_patterns/creational_patterns creational-patterns}
+ * {@link https://sourcemaking.com/design_patterns/factory_method factory-method}
+ * {@link https://medium.com/javascript-scene/javascript-factory-functions-vs-constructor-functions-vs-classes-2f22ceddf33e constructors}
+ * {@link https://www.sitepoint.com/factory-functions-javascript/ js-factory-functions}
+ */
+
+ // core
+
+
+
+
+ // plugins
+
+
+
+
+
+
+
+ // const validatorBuilder = require('./deps/validators/validatorBuilder')
+ // obj
+
+
+
+
+
+ // utils
+
+
+
+
+ // is
+
+
+
+
+
+
+
+ var DEFAULTED_KEY = 'defaulted';
+ var METHOD_KEYS = [
+ 'onInvalid',
+ 'onValid',
+ 'initial',
+ 'default',
+ 'type',
+ 'callReturns',
+ 'target',
+ 'onSet',
+ 'onCall',
+ 'onGet',
+ ];
+
+ // const SET_KEY = METHOD_KEYS[0]
+
+ function getSetFactory(_this, name, desc) {
+ _this[camelCase(("set-" + name))] = desc.set;
+ _this[camelCase(("get-" + name))] = desc.get;
+ }
+
+ function aliasFactory(name, parent, aliases) {
+ if (!_undefined(aliases)) {
+ for (var a = 0; a < aliases.length; a++) {
+ define(parent, aliases[a], getDescriptor(parent, name));
+ }
+ }
+ }
+
+ // @TODO to use as a function
+ // function _methods() {}
+ // _methods.use(obj) {
+ // this.obj = obj
+ // return _methods
+ // }
+ // _methods.extend = _methods.use
+ // _methods.methods = function(methods) {
+ // return new MethodChain(this.obj)
+ // }
+
+ var methodFactories = {};
+
+ /**
+ * ❗ using `+` will call `.build()` in a shorthand fashion
+ *
+ * @member MethodChain
+ * @inheritdoc
+ * @class
+ * @extends {ChainedMap}
+ * @type {Map}
+ *
+ * @since 4.0.0
+ *
+ * @types MethodChain
+ * @tests MethodChain
+ *
+ * @TODO maybe abstract the most re-usable core as a protected class
+ * so the shorthands could be used, and more functionality made external
+ * @TODO need to separate schema from here as external functionality & add .add
+ * @TODO .prop - for things on the instance, not in the store?
+ * !!! .sponge - absorn properties into the store
+ */
+ var MethodChain = (function (ChainedMap) {
+ function MethodChain(parent) {
+ var this$1 = this;
+
+ // timer.start('methodchain')
+
+ ChainedMap.call(this, parent);
+
+ // ----------------
+ var set = this.set.bind(this);
+
+ this.newThis = function () { return new MethodChain(parent); };
+ this.toNumber = function () { return this$1.build(0); };
+
+ /**
+ * @example
+ *
+ * chain
+ * .method('eh')
+ * .type(`?string`)
+ * .type(`string[]`)
+ * .type(`string|boolean`)
+ * .type(`boolean[]|string[]`)
+ * .type(`!date`)
+ *
+ */
+ this.extend(METHOD_KEYS);
+
+ // shorthand
+ this.method = this.methods = function (name) {
+ if (this$1.length) { return this$1.build().methods(name) }
+ else { return this$1.name(name) }
+ };
+
+ // default argument...
+ this.encase = function (x) {
+ return set('encase', parent[x] || x || true)
+ };
+
+ // alias
+ this.then = this.onValid.bind(this);
+ this.catch = this.onInvalid.bind(this);
+
+ this.returns = function (x, callReturns) { return set('returns', x || parent).callReturns(callReturns); };
+
+ // @NOTE replaces shorthands.chainWrap
+ this.chainable = this.returns;
+
+ /**
+ * @desc alias methods
+ * @since 2.0.0
+ *
+ * @param {string | Array} aliases aliases to remap to the current method being built
+ * @return {MethodChain} @chainable
+ *
+ * @NOTE these would be .transform
+ *
+ * @example
+ *
+ * const chain = new Chain()
+ * chain.methods(['canada']).alias(['eh']).build()
+ * chain.eh('actually...canada o.o')
+ * chain.get('canada')
+ * //=> 'actually...canada o.o')
+ *
+ */
+ this.alias = function (aliases) { return this$1.tap('alias', function (old, merge) { return merge(old, toArr(aliases)); }); };
+ this.plugin = function (plugin) { return this$1.tap('plugins', function (old, merge) { return merge(old, toArr(plugin)); }); };
+
+ this.camelCase = function () { return set('camel', true); };
+
+ // @NOTE: x = true is much prettier, but compiles badly
+ var defaultToTrue = function (x) { return (_undefined(x) ? true : x); };
+ this.define = function (x) { return set('define', defaultToTrue(x)); };
+ this.getSet = function (x) { return set('getSet', defaultToTrue(x)); };
+
+ // @TODO unless these use scoped vars, they should be on proto
+ // @NOTE shorthands.bindMethods
+ this.bind = function (target) { return set('bind', _undefined(target) ? parent : target); };
+ this.autoGetSet = function () { return this$1.plugin(autoGetSet_1); };
+
+ this.plugin(types);
+
+ if (objWithKeys(methodFactories)) {
+ keys(methodFactories).forEach(function (factoryName) {
+ this$1[factoryName] = function (arg) { return methodFactories[factoryName].call(this$1, arg); };
+ if (dev) {
+ this$1[factoryName].methodFactory = true;
+ }
+ });
+ }
+ }
+
+ if ( ChainedMap ) MethodChain.__proto__ = ChainedMap;
+ MethodChain.prototype = Object.create( ChainedMap && ChainedMap.prototype );
+ MethodChain.prototype.constructor = MethodChain;
+
+ /**
+ * @desc setup methods to build
+ * @category builder
+ * @memberOf MethodChain
+ *
+ * @since 4.0.0-beta.1 <- moved to plugin
+ * @since 4.0.0
+ *
+ * @param {string | Object | Array} methods method names to build
+ * @return {MethodChain} @chainable
+ *
+ * @example
+ *
+ * var obj = {}
+ * new MethodChain(obj).name('eh').build()
+ * typeof obj.eh
+ * //=> 'function'
+ *
+ */
+ MethodChain.prototype.name = function name (methods) {
+ var this$1 = this;
+
+ var names = methods;
+
+ /**
+ * @desc this is a plugin for building methods
+ * schema defaults value to `.type`
+ * this defaults values to `.onCall`
+ */
+ if (!array(methods) && obj(methods)) {
+ names = keys(methods);
+ for (var name = 0; name < names.length; name++) {
+ this$1.plugin(obj$2.call(this$1, methods, names[name]));
+ }
+ }
+ return this.set('names', names)
+ };
+
+ /**
+ * an object that contains nestable `.type`s
+ * they are recursively (using an optimized traversal cache) mapped to validators
+ * ❗ this method auto-calls .build, all other method config calls should be done before it
+ *
+ * @TODO link to `deps/is` docs
+ *
+ * @version 4.0.0-beta.1 <- moved to plugin
+ * @since 4.0.0
+ *
+ * @category types
+ * @memberOf MethodChain
+ *
+ * @param {Object} obj schema
+ * @return {MethodChain} @chainable
+ *
+ * @TODO move out into a plugin to show how easy it is to use a plugin
+ * and make it able to be split out for size when needed
+ *
+ * @TODO inherit properties (in plugin, for each key)
+ * from this for say, dotProp, getSet
+ *
+ * @TODO very @important
+ * that we setup schema validation at the highest root for validation
+ * and then have some demo for how to validate on set using say mobx
+ * observables for all the way down...
+ *
+ * @typedef `schema(schema: Obj): ChainAble`
+ *
+ * @example
+ *
+ * chain
+ * .methods()
+ * .define()
+ * .getSet()
+ * .onInvalid((error, arg, instance) => console.log(error))
+ * .schema({
+ * id: '?number',
+ * users: '?object|array',
+ * topic: '?string[]',
+ * roles: '?array',
+ * creator: {
+ * name: 'string',
+ * email: 'email',
+ * id: 'uuid',
+ * },
+ * created_at: 'date',
+ * updated_at: 'date|date[]',
+ * summary: 'string',
+ * })
+ *
+ * //--- valid
+ * chain.created_at = new Date()
+ * chain.setCreatedAt(new Date())
+ *
+ * isDate(chain.created_at) === true
+ *
+ * //--- nestable validation 👍
+ * chain.merge({creator: {name: 'string'}})
+ *
+ * //--- invalid
+ * chain.updated_at = false
+ *
+ */
+ MethodChain.prototype.schema = function schema$$1 (obj$$1) {
+ return schema.call(this, obj$$1)
+ };
+
+ /**
+ * @desc set the actual method, also need .context - use .parent
+ * @memberOf MethodChain
+ * @since 4.0.0
+ *
+ * @param {any} [returnValue=undefined] returned at the end of the function for ease of use
+ * @return {MethodChain} @chainable
+ *
+ * @TODO if passing in a name that already exists, operations are decorations... (partially done)
+ * @see https://github.com/iluwatar/java-design-patterns/tree/master/step-builder
+ *
+ * @example
+ *
+ * var obj = {}
+ * const one = new MethodChain(obj).methods('eh').getSet().build(1)
+ * //=> 1
+ *
+ * typeof obj.getEh
+ * //=> 'function'
+ *
+ */
+ MethodChain.prototype.build = function build (returnValue) {
+ var this$1 = this;
+
+ var parent = this.parent;
+ var names = toArr(this.get('names'));
+ var shouldTapName = this.get('camel');
+
+ for (var name = 0; name < names.length; name++) {
+ this$1._build(shouldTapName ? camelCase(names[name]) : names[name], parent);
+ }
+
+ // timer.stop('methodchain').log('methodchain').start('gc')
+
+ // remove refs to unused
+ this.clear();
+ delete this.parent;
+ gc(this);
+
+ // very fast - timer & ensuring props are cleaned
+ // timer.stop('gc').log('gc')
+ // require('fliplog').quick(this)
+
+ return _undefined(returnValue) ? parent : returnValue
+ };
+
+ /**
+ * @memberOf MethodChain
+ *
+ * @since 4.0.0
+ * @protected
+ * @param {Primitive} name method name
+ * @param {Object} parent being decorated
+ * @param {Object} built method being built
+ * @return {void}
+ *
+ * @TODO optimize the size of this
+ * with some bitwise operators
+ * hashing the things that have been defaulted
+ * also could be plugin
+ *
+ * @example
+ *
+ * ._defaults('', {}, {})
+ *
+ *
+ * @example
+ *
+ * let methodFactories
+ *
+ * ### `onSet`
+ *
+ * > defaults to `this.set(key, value)`
+ *
+ * ```ts
+ * public onSet(fn: Fn): MethodChain
+ * ```
+ *
+ * ### `onCall`
+ *
+ * > defaults to .onSet ^
+ *
+ * ```ts
+ * public onCall(fn: Fn): MethodChain
+ * ```
+ *
+ * ### `onGet`
+ *
+ * > defaults to `this.get(key)`
+ *
+ * ```ts
+ * public onGet(fn: Fn): MethodChain
+ * ```
+ *
+ */
+ MethodChain.prototype._defaults = function _defaults (name, parent, built) {
+ // defaults
+ var defaultOnSet = function (arg) { return parent.set(name, arg); };
+ var defaultOnGet = function () { return parent.get(name); };
+
+ // so we know if we defaulted them
+ defaultOnSet[DEFAULTED_KEY] = true;
+ defaultOnGet[DEFAULTED_KEY] = true;
+
+ // when we've[DEFAULTED_KEY] already for another method,
+ // we need a new function,
+ // else the name will be scoped incorrectly
+ var onCall = built.onCall;
+ var onSet = built.onSet;
+ var onGet = built.onGet;
+ if (!onGet || onGet[DEFAULTED_KEY]) {
+ this.onGet(defaultOnGet);
+ }
+ if (!onCall || onCall[DEFAULTED_KEY]) {
+ this.onCall(defaultOnSet);
+ }
+ if (!onSet || onSet[DEFAULTED_KEY]) {
+ this.onSet(defaultOnSet);
+ }
+ };
+
+ /**
+ * @protected
+ * @since 4.0.0-alpha.1
+ * @memberOf MethodChain
+ *
+ * @param {Primitive} name
+ * @param {Object} parent
+ * @return {void}
+ *
+ * @TODO allow config of method var in plugins since it is scoped...
+ * @TODO add to .meta(shorthands)
+ * @TODO reduce complexity if perf allows
+ * @NOTE scoping here adding default functions have to rescope arguments
+ */
+ MethodChain.prototype._build = function _build (name, parent) {
+ var this$1 = this;
+
+ var method;
+ var existing;
+ var entries = function () { return this$1.entries(); };
+
+ // could ternary `let method =` here
+ if (hasOwnProperty_1(parent, name)) {
+ existing = getDescriptor(parent, name);
+
+ // avoid `TypeError: Cannot redefine property:`
+ if (_false(existing.configurable)) {
+ return
+ }
+
+ // use existing property, when configurable
+ method = existing.value;
+
+ if (dev) {
+ method.decorated = true;
+ }
+
+ this.onCall(method).onSet(method);
+ }
+ else if (parent[name]) {
+ method = parent[name];
+
+ if (dev) {
+ method.decorated = true;
+ }
+
+ this.onCall(method).onSet(method);
+ }
+
+ // scope it once for plugins & type building, then get it again
+ var built = entries();
+
+ this._defaults(name, parent, built);
+
+ // plugins can add methods,
+ // useful as plugins/presets & decorators for multi-name building
+ var instancePlugins = built.plugins;
+ if (instancePlugins) {
+ for (var plugin = 0; plugin < instancePlugins.length; plugin++) {
+ built = entries();
+ instancePlugins[plugin].call(this$1, name, parent, built);
+ }
+ }
+
+ // after last plugin is finished, or defaults
+ built = entries();
+
+ // wrap in encasing when we have a validator or .encase
+ // @NOTE: validator plugin was here, moved into a plugin
+ if (built.encase) {
+ var encased = encase_1.call(this, name, parent, built)(method);
+
+ if (dev) {
+ encased.encased = method;
+ }
+
+ this.onCall(encased).onSet(encased);
+ method = encased;
+ built = entries();
+ }
+
+ // not destructured for better variable names
+ var shouldAddGetterSetter = built.getSet;
+ var shouldDefineGetSet = built.define;
+ var defaultValue = built.default;
+
+ // can only have `call` or `get/set`...
+ var onGet = built.onGet;
+ var onSet = built.onSet;
+ var onCall = built.onCall;
+ var initial = built.initial;
+ var bind = built.bind;
+ var returns = built.returns;
+ var callReturns = built.callReturns;
+ var alias = built.alias;
+
+ // default method, if we do not have one already
+ if (!method) {
+ method = function (arg) {
+ if ( arg === void 0 ) arg = defaultValue;
+
+ return onCall.call(parent, arg);
+ };
+
+ if (dev) {
+ method.created = true;
+ }
+ }
+
+ if (bind) {
+ // bind = bindArgument || parent
+ method = method.bind(bind);
+ }
+ if (returns) {
+ var ref = method;
+ method = function() {
+ var args = argumentor.apply(null, arguments);
+
+ // eslint-disable-next-line prefer-rest-params
+ var result = ref.apply(parent, args);
+
+ return _true(callReturns)
+ ? returns.apply(parent, [result].concat(args))
+ : returns
+ };
+ }
+
+ if (!_undefined(initial)) {
+ parent.set(name, initial);
+ }
+
+ // --------------- stripped -----------
+
+ /**
+ * !!!!! @TODO put in `plugins.post.call`
+ * !!!!! @TODO ensure unique name
+ *
+ * can add .meta on them though for re-decorating
+ * -> but this has issue with .getset so needs to be on .meta[name]
+ */
+
+ /* istanbul ignore next: dev */
+ if (dev) {
+ define(onGet, 'name', {
+ value: camelCase(((onGet.name) + "+get-" + name)),
+ });
+ define(onSet, 'name', {
+ value: camelCase(((onSet.name) + "+set-" + name)),
+ });
+ define(onCall, 'name', {
+ value: camelCase(((onCall.name) + "+call-" + name)),
+ });
+ define(method, 'name', {value: camelCase(("" + name))});
+
+ if (built.type) { method.type = built.type; }
+ if (initial) { method.initial = initial; }
+ if (bind) { method.bound = bind; }
+ if (returns) { method.returns = returns; }
+ if (alias) { method.alias = alias; }
+ if (callReturns) { method.callReturns = callReturns; }
+ if (onGet) { method._get = onGet; }
+ if (onSet) { method._set = onSet; }
+ // eslint-disable-next-line
+ if (onCall != onCall) { method._call = onCall; }
+ }
+
+ /* istanbul ignore next: dev */
+ if (debug) {
+ console.log({
+ name: name,
+ defaultValue: defaultValue,
+ initial: initial,
+ returns: returns,
+ onGet: onGet,
+ onSet: onSet,
+ method: method.toString(),
+ });
+ }
+
+ // ----------------- ;stripped ------------
+
+ // @TODO WOULD ALL BE METHOD.POST
+ // --- could be a method too ---
+ var getterSetter = {get: onGet, set: onSet};
+ var descriptor = shouldDefineGetSet ? getterSetter : {value: method};
+ if (existing) { descriptor = assign(existing, descriptor); }
+
+ // [TypeError: Invalid property descriptor.
+ // Cannot both specify accessors and a value or writable attribute, #