Format code with prettier

This commit is contained in:
Aaron Jensen 2017-04-18 17:55:46 -07:00
parent 02c6057aaf
commit dcee2038b6
No known key found for this signature in database
GPG Key ID: 395CF9A719B6724C
38 changed files with 950 additions and 834 deletions

View File

@ -1,9 +1,24 @@
{ {
"extends": "airbnb-base", "extends": [
"airbnb-base",
"prettier"
],
"plugins": [
"prettier"
],
"ecmaFeatures": { "ecmaFeatures": {
"experimentalObjectRestSpread": true "experimentalObjectRestSpread": true
}, },
"rules": { "rules": {
"prettier/prettier": [
"error",
{
"bracketSpacing": true,
"semi": false,
"singleQuote": true,
"trailingComma": "es5"
}
],
"no-confusing-arrow": "off", "no-confusing-arrow": "off",
"comma-dangle": ["error", { "comma-dangle": ["error", {
"arrays": "always-multiline", "arrays": "always-multiline",

View File

@ -1,88 +1,97 @@
'use strict'; 'use strict'
/* eslint strict:0, no-var:0, func-names:0 */ /* eslint strict:0, no-var:0, func-names:0 */
var path = require('path'); var path = require('path')
var gulp = require('gulp'); var gulp = require('gulp')
var babel = require('gulp-babel'); var babel = require('gulp-babel')
var eslint = require('gulp-eslint'); var eslint = require('gulp-eslint')
var mocha = require('gulp-mocha'); var mocha = require('gulp-mocha')
var nsp = require('gulp-nsp'); var nsp = require('gulp-nsp')
var rimraf = require('rimraf'); var rimraf = require('rimraf')
var webpack = require('webpack-stream'); var webpack = require('webpack-stream')
var KarmaServer = require('karma').Server; var KarmaServer = require('karma').Server
var createWebpackConfig = require('./createWebpackConfig.js'); var createWebpackConfig = require('./createWebpackConfig.js')
// Initialize the babel transpiler so ES2015 files gets compiled // Initialize the babel transpiler so ES2015 files gets compiled
// when they're loaded // when they're loaded
require('babel-core/register'); require('babel-core/register')
gulp.task('clean', (cb) => { gulp.task('clean', cb => {
rimraf('./dist', cb); rimraf('./dist', cb)
}); })
gulp.task('static', () => gulp.src(['*.js', 'lib/**/*.js', 'test/**/*.js']) gulp.task('static', () =>
gulp
.src(['*.js', 'lib/**/*.js', 'test/**/*.js'])
.pipe(eslint()) .pipe(eslint())
.pipe(eslint.format()) .pipe(eslint.format())
.pipe(eslint.failAfterError())); .pipe(eslint.failAfterError())
)
gulp.task('nsp', (cb) => { gulp.task('nsp', cb => {
nsp({ package: path.join(__dirname, 'package.json') }, cb); nsp({ package: path.join(__dirname, 'package.json') }, cb)
}); })
gulp.task('test', ['test:karma', 'test:node']); gulp.task('test', ['test:karma', 'test:node'])
gulp.task('test:node', () => gulp.src('test/**/*.js') gulp.task('test:node', () =>
.pipe(mocha({ reporter: 'dot' }))); gulp.src('test/**/*.js').pipe(mocha({ reporter: 'dot' }))
)
gulp.task('test:karma', (done) => { gulp.task('test:karma', done => {
new KarmaServer({ new KarmaServer(
configFile: path.join(__dirname, 'karma.conf.js'), {
singleRun: true, configFile: path.join(__dirname, 'karma.conf.js'),
}, done).start(); singleRun: true,
}); },
done
).start()
})
gulp.task('babel', () => gulp.src('lib/**/*.js') gulp.task('babel', () =>
.pipe(babel()) gulp.src('lib/**/*.js').pipe(babel()).pipe(gulp.dest('dist'))
.pipe(gulp.dest('dist'))); )
gulp.task('watch', () => { gulp.task('watch', () => {
gulp.start(['test:node']); gulp.start(['test:node'])
gulp.watch(['lib/**/*.js', 'test/**/*.js'], ['test:node']); gulp.watch(['lib/**/*.js', 'test/**/*.js'], ['test:node'])
new KarmaServer({ new KarmaServer({
configFile: path.join(__dirname, 'karma.conf.js'), configFile: path.join(__dirname, 'karma.conf.js'),
}).start(); }).start()
}); })
gulp.task('webpack', ['webpack:standalone', 'webpack:standalone:min']); gulp.task('webpack', ['webpack:standalone', 'webpack:standalone:min'])
gulp.task('webpack:standalone', () => { gulp.task('webpack:standalone', () => {
var config = createWebpackConfig({ filename: 'updeep-standalone.js' }); var config = createWebpackConfig({ filename: 'updeep-standalone.js' })
return gulp.src('lib/index.js') return gulp
.src('lib/index.js')
.pipe(webpack(config)) .pipe(webpack(config))
.pipe(gulp.dest('dist/umd/')); .pipe(gulp.dest('dist/umd/'))
}); })
gulp.task('webpack:standalone:min', () => { gulp.task('webpack:standalone:min', () => {
var config = createWebpackConfig({ var config = createWebpackConfig({
filename: 'updeep-standalone.min.js', filename: 'updeep-standalone.min.js',
minify: true, minify: true,
env: 'production', env: 'production',
}); })
return gulp.src('lib/index.js') return gulp
.src('lib/index.js')
.pipe(webpack(config)) .pipe(webpack(config))
.pipe(gulp.dest('dist/umd/')); .pipe(gulp.dest('dist/umd/'))
}); })
gulp.task('build', ['babel', 'webpack']); gulp.task('build', ['babel', 'webpack'])
gulp.task('build:clean', ['clean'], (done) => { gulp.task('build:clean', ['clean'], done => {
gulp.start('build', done); gulp.start('build', done)
}); })
gulp.task('prepublish', ['nsp', 'build:clean']); gulp.task('prepublish', ['nsp', 'build:clean'])
gulp.task('default', ['static', 'test']); gulp.task('default', ['static', 'test'])

View File

@ -1,30 +1,25 @@
'use strict'; 'use strict'
/* eslint strict:0, no-var:0, func-names:0 */ /* eslint strict:0, no-var:0, func-names:0 */
var createWebpackConfig = require('./createWebpackConfig'); var createWebpackConfig = require('./createWebpackConfig')
module.exports = function (config) { module.exports = function(config) {
config.set({ config.set({
// base path that will be used to resolve all patterns (eg. files, exclude) // base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '', basePath: '',
// frameworks to use // frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['mocha'], frameworks: ['mocha'],
// list of files / patterns to load in the browser // list of files / patterns to load in the browser
files: [ files: [
{ pattern: 'test/**/*.js', watched: false, included: true, served: true }, { pattern: 'test/**/*.js', watched: false, included: true, served: true },
], ],
// list of files to exclude // list of files to exclude
exclude: [ exclude: [],
],
// preprocess matching files before serving them to the browser // preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
@ -44,15 +39,12 @@ module.exports = function (config) {
// available reporters: https://npmjs.org/browse/keyword/karma-reporter // available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['dots'], reporters: ['dots'],
// web server port // web server port
port: 9876, port: 9876,
// enable / disable colors in the output (reporters and logs) // enable / disable colors in the output (reporters and logs)
colors: true, colors: true,
// level of logging // level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN ||
// config.LOG_INFO || config.LOG_DEBUG // config.LOG_INFO || config.LOG_DEBUG
@ -62,9 +54,8 @@ module.exports = function (config) {
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'], browsers: ['PhantomJS'],
// Continuous Integration mode // Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits // if true, Karma captures browsers, runs the tests and exits
singleRun: false, singleRun: false,
}); })
}; }

View File

@ -1,4 +1,4 @@
import freeze from './freeze'; import freeze from './freeze'
/** /**
* Returns a function that always returns the supplied value. * Returns a function that always returns the supplied value.
@ -33,8 +33,8 @@ import freeze from './freeze';
* expect(result).toEqual({ name: 'Mitch', favorites: { band: 'Coldplay' } }); * expect(result).toEqual({ name: 'Mitch', favorites: { band: 'Coldplay' } });
*/ */
function constant(value) { function constant(value) {
const frozen = freeze(value); const frozen = freeze(value)
return () => frozen; return () => frozen
} }
export default constant; export default constant

View File

@ -1,26 +1,25 @@
function isFreezable(object) { function isFreezable(object) {
if (object === null) return false; if (object === null) return false
if (object instanceof RegExp) return false; if (object instanceof RegExp) return false
return Array.isArray(object) || return Array.isArray(object) || typeof object === 'object'
typeof object === 'object';
} }
function needsFreezing(object) { function needsFreezing(object) {
return isFreezable(object) && !Object.isFrozen(object); return isFreezable(object) && !Object.isFrozen(object)
} }
function recur(object) { function recur(object) {
Object.freeze(object); Object.freeze(object)
Object.keys(object).forEach((key) => { Object.keys(object).forEach(key => {
const value = object[key]; const value = object[key]
if (needsFreezing(value)) { if (needsFreezing(value)) {
recur(value); recur(value)
} }
}); })
return object; return object
} }
/** /**
@ -39,18 +38,18 @@ function recur(object) {
*/ */
function freeze(object) { function freeze(object) {
if (process.env.NODE_ENV === 'production') { if (process.env.NODE_ENV === 'production') {
return object; return object
} }
if (process.env.UPDEEP_MODE === 'dangerously_never_freeze') { if (process.env.UPDEEP_MODE === 'dangerously_never_freeze') {
return object; return object
} }
if (needsFreezing(object)) { if (needsFreezing(object)) {
recur(object); recur(object)
} }
return object; return object
} }
export default freeze; export default freeze

View File

@ -1,6 +1,6 @@
import ifElse from './ifElse'; import ifElse from './ifElse'
import curry from './util/curry'; import curry from './util/curry'
export default curry((predicate, trueUpdates, object) => export default curry((predicate, trueUpdates, object) =>
ifElse(predicate, trueUpdates, x => x, object) ifElse(predicate, trueUpdates, x => x, object)
); )

View File

@ -1,14 +1,12 @@
import update from './update'; import update from './update'
import wrap from './wrap'; import wrap from './wrap'
function updateIfElse(predicate, trueUpdates, falseUpdates, object) { function updateIfElse(predicate, trueUpdates, falseUpdates, object) {
const test = typeof predicate === 'function' ? const test = typeof predicate === 'function' ? predicate(object) : predicate
predicate(object) :
predicate;
const updates = test ? trueUpdates : falseUpdates; const updates = test ? trueUpdates : falseUpdates
return update(updates, object); return update(updates, object)
} }
export default wrap(updateIfElse); export default wrap(updateIfElse)

View File

@ -1,31 +1,31 @@
import constant from './constant'; import constant from './constant'
import freeze from './freeze'; import freeze from './freeze'
import is from './is'; import is from './is'
import _if from './if'; import _if from './if'
import ifElse from './ifElse'; import ifElse from './ifElse'
import map from './map'; import map from './map'
import omit from './omit'; import omit from './omit'
import omitBy from './omitBy'; import omitBy from './omitBy'
import reject from './reject'; import reject from './reject'
import update from './update'; import update from './update'
import updateIn from './updateIn'; import updateIn from './updateIn'
import withDefault from './withDefault'; import withDefault from './withDefault'
import { _ } from './util/curry'; import { _ } from './util/curry'
const u = update; const u = update
u._ = _; u._ = _
u.constant = constant; u.constant = constant
u.if = _if; u.if = _if
u.ifElse = ifElse; u.ifElse = ifElse
u.is = is; u.is = is
u.freeze = freeze; u.freeze = freeze
u.map = map; u.map = map
u.omit = omit; u.omit = omit
u.omitBy = omitBy; u.omitBy = omitBy
u.reject = reject; u.reject = reject
u.update = update; u.update = update
u.updateIn = updateIn; u.updateIn = updateIn
u.withDefault = withDefault; u.withDefault = withDefault
module.exports = u; module.exports = u

View File

@ -1,21 +1,21 @@
import splitPath from './util/splitPath'; import splitPath from './util/splitPath'
import curry from './util/curry'; import curry from './util/curry'
function is(path, predicate, object) { function is(path, predicate, object) {
const parts = splitPath(path); const parts = splitPath(path)
let rest = object; let rest = object
for (let i = 0; i < parts.length; i += 1) { for (let i = 0; i < parts.length; i += 1) {
if (typeof rest === 'undefined') return false; if (typeof rest === 'undefined') return false
const part = parts[i]; const part = parts[i]
rest = rest[part]; rest = rest[part]
} }
if (typeof predicate === 'function') { if (typeof predicate === 'function') {
return predicate(rest); return predicate(rest)
} }
return predicate === rest; return predicate === rest
} }
export default curry(is); export default curry(is)

View File

@ -1,39 +1,33 @@
import forEach from 'lodash/forEach'; import forEach from 'lodash/forEach'
import mapArray from 'lodash/map'; import mapArray from 'lodash/map'
import mapObject from 'lodash/mapValues'; import mapObject from 'lodash/mapValues'
import update from './update'; import update from './update'
import wrap from './wrap'; import wrap from './wrap'
function shallowEqual(object, otherObject) { function shallowEqual(object, otherObject) {
let equal = true; let equal = true
// eslint-disable-next-line consistent-return // eslint-disable-next-line consistent-return
forEach(otherObject, (value, key) => { forEach(otherObject, (value, key) => {
if (value !== object[key]) { if (value !== object[key]) {
equal = false; equal = false
// exit early // exit early
return false; return false
} }
}); })
return equal; return equal
} }
function map(iteratee, object) { function map(iteratee, object) {
const updater = typeof iteratee === 'function' ? const updater = typeof iteratee === 'function' ? iteratee : update(iteratee)
iteratee :
update(iteratee);
const mapper = Array.isArray(object) ? const mapper = Array.isArray(object) ? mapArray : mapObject
mapArray :
mapObject;
const newObject = mapper(object, updater); const newObject = mapper(object, updater)
const equal = shallowEqual(object, newObject); const equal = shallowEqual(object, newObject)
return equal ? return equal ? object : newObject
object :
newObject;
} }
export default wrap(map); export default wrap(map)

View File

@ -1,8 +1,8 @@
import _omit from 'lodash/omit'; import _omit from 'lodash/omit'
import wrap from './wrap'; import wrap from './wrap'
function omit(predicate, collection) { function omit(predicate, collection) {
return _omit(collection, predicate); return _omit(collection, predicate)
} }
export default wrap(omit); export default wrap(omit)

View File

@ -1,8 +1,8 @@
import _omitBy from 'lodash/omitBy'; import _omitBy from 'lodash/omitBy'
import wrap from './wrap'; import wrap from './wrap'
function omitBy(predicate, collection) { function omitBy(predicate, collection) {
return _omitBy(collection, predicate); return _omitBy(collection, predicate)
} }
export default wrap(omitBy); export default wrap(omitBy)

View File

@ -1,13 +1,11 @@
import _reject from 'lodash/reject'; import _reject from 'lodash/reject'
import wrap from './wrap'; import wrap from './wrap'
function reject(predicate, collection) { function reject(predicate, collection) {
const result = _reject(collection, predicate); const result = _reject(collection, predicate)
const equal = collection.length === result.length; const equal = collection.length === result.length
return equal ? return equal ? collection : result
collection :
result;
} }
export default wrap(reject); export default wrap(reject)

View File

@ -1,40 +1,49 @@
import isPlainObject from 'lodash/isPlainObject'; import isPlainObject from 'lodash/isPlainObject'
import wrap from './wrap'; import wrap from './wrap'
function isEmpty(object) { function isEmpty(object) {
return !Object.keys(object).length; return !Object.keys(object).length
} }
function reduce(object, callback, initialValue) { function reduce(object, callback, initialValue) {
return Object.keys(object).reduce((acc, key) => callback(acc, object[key], key), initialValue); return Object.keys(object).reduce(
(acc, key) => callback(acc, object[key], key),
initialValue
)
} }
function resolveUpdates(updates, object) { function resolveUpdates(updates, object) {
return reduce(updates, (acc, value, key) => { return reduce(
let updatedValue = value; updates,
(acc, value, key) => {
let updatedValue = value
if (!Array.isArray(value) && value !== null && typeof value === 'object') { if (
updatedValue = update(value, object[key]); // eslint-disable-line no-use-before-define !Array.isArray(value) && value !== null && typeof value === 'object'
} else if (typeof value === 'function') { ) {
updatedValue = value(object[key]); updatedValue = update(value, object[key]) // eslint-disable-line no-use-before-define
} } else if (typeof value === 'function') {
updatedValue = value(object[key])
}
if (object[key] !== updatedValue) { if (object[key] !== updatedValue) {
acc[key] = updatedValue; // eslint-disable-line no-param-reassign acc[key] = updatedValue // eslint-disable-line no-param-reassign
} }
return acc; return acc
}, {}); },
{}
)
} }
function updateArray(updates, object) { function updateArray(updates, object) {
const newArray = [...object]; const newArray = [...object]
Object.keys(updates).forEach((key) => { Object.keys(updates).forEach(key => {
newArray[key] = updates[key]; newArray[key] = updates[key]
}); })
return newArray; return newArray
} }
/** /**
@ -56,28 +65,28 @@ function updateArray(updates, object) {
*/ */
function update(updates, object, ...args) { function update(updates, object, ...args) {
if (typeof updates === 'function') { if (typeof updates === 'function') {
return updates(object, ...args); return updates(object, ...args)
} }
if (!isPlainObject(updates)) { if (!isPlainObject(updates)) {
return updates; return updates
} }
const defaultedObject = (typeof object === 'undefined' || object === null) ? const defaultedObject = typeof object === 'undefined' || object === null
{} : ? {}
object; : object
const resolvedUpdates = resolveUpdates(updates, defaultedObject); const resolvedUpdates = resolveUpdates(updates, defaultedObject)
if (isEmpty(resolvedUpdates)) { if (isEmpty(resolvedUpdates)) {
return defaultedObject; return defaultedObject
} }
if (Array.isArray(defaultedObject)) { if (Array.isArray(defaultedObject)) {
return updateArray(resolvedUpdates, defaultedObject); return updateArray(resolvedUpdates, defaultedObject)
} }
return { ...defaultedObject, ...resolvedUpdates }; return { ...defaultedObject, ...resolvedUpdates }
} }
export default wrap(update, 2); export default wrap(update, 2)

View File

@ -1,28 +1,28 @@
import curry from './util/curry'; import curry from './util/curry'
import update from './update'; import update from './update'
import map from './map'; import map from './map'
import splitPath from './util/splitPath'; import splitPath from './util/splitPath'
const wildcard = '*'; const wildcard = '*'
function reducePath(acc, key) { function reducePath(acc, key) {
if (key === wildcard) { if (key === wildcard) {
return value => return value =>
Object.prototype.hasOwnProperty.call(value, wildcard) ? (Object.prototype.hasOwnProperty.call(value, wildcard)
// If we actually have wildcard as a property, update that ? // If we actually have wildcard as a property, update that
update({ [wildcard]: acc }, value) : update({ [wildcard]: acc }, value)
// Otherwise map over all properties : // Otherwise map over all properties
map(acc, value); map(acc, value))
} }
return { [key]: acc }; return { [key]: acc }
} }
function updateIn(path, value, object) { function updateIn(path, value, object) {
const parts = splitPath(path); const parts = splitPath(path)
const updates = parts.reduceRight(reducePath, value); const updates = parts.reduceRight(reducePath, value)
return update(updates, object); return update(updates, object)
} }
export default curry(updateIn); export default curry(updateIn)

View File

@ -1,128 +1,126 @@
/* eslint no-shadow:0, no-param-reassign:0 prefer-rest-params:0 */ /* eslint no-shadow:0, no-param-reassign:0 prefer-rest-params:0 */
export const _ = '@@updeep/placeholder'; export const _ = '@@updeep/placeholder'
function countArguments(args, max) { function countArguments(args, max) {
let n = args.length; let n = args.length
if (n > max) n = max; if (n > max) n = max
while (args[n - 1] === _) { while (args[n - 1] === _) {
n -= 1; n -= 1
} }
return n; return n
} }
export function curry1(fn) { export function curry1(fn) {
return function curried(a, ...args) { return function curried(a, ...args) {
const [b, c] = args; const [b, c] = args
const n = countArguments(arguments); const n = countArguments(arguments)
if (n >= 1) return fn(a, b, c); if (n >= 1) return fn(a, b, c)
return curried; return curried
}; }
} }
export function curry2(fn) { export function curry2(fn) {
return function curried(a, b, ...args) { return function curried(a, b, ...args) {
const [c, d] = args; const [c, d] = args
const n = countArguments(arguments, 2); const n = countArguments(arguments, 2)
if (b === _ || c === _ || d === _) { if (b === _ || c === _ || d === _) {
throw new Error('Can only use placeholder on first argument of this function.'); throw new Error(
'Can only use placeholder on first argument of this function.'
)
} }
if (n >= 2) { if (n >= 2) {
if (a === _) return curry1((a, c, d) => fn(a, b, c, d)); if (a === _) return curry1((a, c, d) => fn(a, b, c, d))
return fn(a, b, c, d); return fn(a, b, c, d)
} }
if (n === 1) return curry1((b, c, d) => fn(a, b, c, d)); if (n === 1) return curry1((b, c, d) => fn(a, b, c, d))
return curried; return curried
}; }
} }
export function curry3(fn) { export function curry3(fn) {
return function curried(a, b, c, ...args) { return function curried(a, b, c, ...args) {
const [d, e] = args; const [d, e] = args
const n = countArguments(arguments, 3); const n = countArguments(arguments, 3)
if (c === _ || d === _ || e === _) { if (c === _ || d === _ || e === _) {
throw new Error('Can only use placeholder on first or second argument of this function.'); throw new Error(
'Can only use placeholder on first or second argument of this function.'
)
} }
if (n >= 3) { if (n >= 3) {
if (a === _) { if (a === _) {
if (b === _) return curry2((a, b, d, e) => fn(a, b, c, d, e)); if (b === _) return curry2((a, b, d, e) => fn(a, b, c, d, e))
return curry1((a, d, e) => fn(a, b, c, d, e)); return curry1((a, d, e) => fn(a, b, c, d, e))
} }
if (b === _) return curry1((b, d, e) => fn(a, b, c, d, e)); if (b === _) return curry1((b, d, e) => fn(a, b, c, d, e))
return fn(a, b, c, d, e); return fn(a, b, c, d, e)
} }
if (n === 2) { if (n === 2) {
if (a === _) return curry2((a, c, d, e) => fn(a, b, c, d, e)); if (a === _) return curry2((a, c, d, e) => fn(a, b, c, d, e))
return curry1((c, d, e) => fn(a, b, c, d, e)); return curry1((c, d, e) => fn(a, b, c, d, e))
} }
if (n === 1) return curry2((b, c, d, e) => fn(a, b, c, d, e)); if (n === 1) return curry2((b, c, d, e) => fn(a, b, c, d, e))
return curried; return curried
}; }
} }
export function curry4(fn) { export function curry4(fn) {
return function curried(a, b, c, d, ...args) { return function curried(a, b, c, d, ...args) {
const [e, f] = args; const [e, f] = args
const n = countArguments(arguments, 4); const n = countArguments(arguments, 4)
if (d === _ || e === _ || f === _) { if (d === _ || e === _ || f === _) {
throw new Error( throw new Error(
'Can only use placeholder on first, second or third argument of this function.' 'Can only use placeholder on first, second or third argument of this function.'
); )
} }
if (n >= 4) { if (n >= 4) {
if (a === _) { if (a === _) {
if (b === _) { if (b === _) {
if (c === _) return curry3((a, b, c, e, f) => fn(a, b, c, d, e, f)); if (c === _) return curry3((a, b, c, e, f) => fn(a, b, c, d, e, f))
return curry2((a, b, e, f) => fn(a, b, c, d, e, f)); return curry2((a, b, e, f) => fn(a, b, c, d, e, f))
} }
if (c === _) return curry2((a, c, e, f) => fn(a, b, c, d, e, f)); if (c === _) return curry2((a, c, e, f) => fn(a, b, c, d, e, f))
return curry1((a, e, f) => fn(a, b, c, d, e, f)); return curry1((a, e, f) => fn(a, b, c, d, e, f))
} }
if (b === _) { if (b === _) {
if (c === _) return curry2((b, c, e, f) => fn(a, b, c, d, e, f)); if (c === _) return curry2((b, c, e, f) => fn(a, b, c, d, e, f))
return curry1((b, e, f) => fn(a, b, c, d, e, f)); return curry1((b, e, f) => fn(a, b, c, d, e, f))
} }
if (c === _) return curry1((c, e, f) => fn(a, b, c, d, e, f)); if (c === _) return curry1((c, e, f) => fn(a, b, c, d, e, f))
return fn(a, b, c, d, e, f); return fn(a, b, c, d, e, f)
} }
if (n === 3) { if (n === 3) {
if (a === _) { if (a === _) {
if (b === _) return curry3((a, b, d, e, f) => fn(a, b, c, d, e, f)); if (b === _) return curry3((a, b, d, e, f) => fn(a, b, c, d, e, f))
return curry2((a, d, e, f) => fn(a, b, c, d, e, f)); return curry2((a, d, e, f) => fn(a, b, c, d, e, f))
} }
if (b === _) return curry2((b, d, e, f) => fn(a, b, c, d, e, f)); if (b === _) return curry2((b, d, e, f) => fn(a, b, c, d, e, f))
return curry1((d, e, f) => fn(a, b, c, d, e, f)); return curry1((d, e, f) => fn(a, b, c, d, e, f))
} }
if (n === 2) { if (n === 2) {
if (a === _) return curry3((a, c, d, e, f) => fn(a, b, c, d, e, f)); if (a === _) return curry3((a, c, d, e, f) => fn(a, b, c, d, e, f))
return curry2((c, d, e, f) => fn(a, b, c, d, e, f)); return curry2((c, d, e, f) => fn(a, b, c, d, e, f))
} }
if (n === 1) return curry3((b, c, d, e, f) => fn(a, b, c, d, e, f)); if (n === 1) return curry3((b, c, d, e, f) => fn(a, b, c, d, e, f))
return curried; return curried
}; }
} }
export default function curry(fn, length = fn.length) { export default function curry(fn, length = fn.length) {
return [ return [fn, curry1, curry2, curry3, curry4][length](fn)
fn,
curry1,
curry2,
curry3,
curry4,
][length](fn);
} }

View File

@ -1,7 +1,5 @@
import reject from 'lodash/reject'; import reject from 'lodash/reject'
export default function splitPath(path) { export default function splitPath(path) {
return Array.isArray(path) ? return Array.isArray(path) ? path : reject(`${path}`.split('.'), x => !x)
path :
reject((`${path}`).split('.'), x => !x);
} }

View File

@ -1,12 +1,12 @@
import update from './update'; import update from './update'
import curry from './util/curry'; import curry from './util/curry'
function withDefault(defaultValue, updates, object) { function withDefault(defaultValue, updates, object) {
if (typeof object === 'undefined') { if (typeof object === 'undefined') {
return update(updates, defaultValue); return update(updates, defaultValue)
} }
return update(updates, object); return update(updates, object)
} }
export default curry(withDefault); export default curry(withDefault)

View File

@ -1,9 +1,6 @@
import curry from './util/curry'; import curry from './util/curry'
import freeze from './freeze'; import freeze from './freeze'
export default function wrap(func, length = func.length) { export default function wrap(func, length = func.length) {
return curry( return curry((...args) => freeze(func(...args)), length)
(...args) => freeze(func(...args)),
length
);
} }

View File

@ -40,7 +40,9 @@
"chai": "^3.2.0", "chai": "^3.2.0",
"eslint": "^3.19.0", "eslint": "^3.19.0",
"eslint-config-airbnb-base": "^11.1.3", "eslint-config-airbnb-base": "^11.1.3",
"eslint-config-prettier": "^1.6.0",
"eslint-plugin-import": "^2.2.0", "eslint-plugin-import": "^2.2.0",
"eslint-plugin-prettier": "^2.0.1",
"exports-loader": "^0.6.2", "exports-loader": "^0.6.2",
"gulp": "^3.6.0", "gulp": "^3.6.0",
"gulp-babel": "^6.1.1", "gulp-babel": "^6.1.1",
@ -56,6 +58,7 @@
"karma-webpack": "^1.7.0", "karma-webpack": "^1.7.0",
"mocha": "^2.2.5", "mocha": "^2.2.5",
"phantomjs-prebuilt": "^2.1.14", "phantomjs-prebuilt": "^2.1.14",
"prettier": "^1.1.0",
"rimraf": "^2.4.2", "rimraf": "^2.4.2",
"webpack": "^1.10.5", "webpack": "^1.10.5",
"webpack-dev-server": "^1.10.1", "webpack-dev-server": "^1.10.1",

View File

@ -1,87 +1,87 @@
/* eslint no-console:0, no-unused-vars:0, import/no-extraneous-dependencies:0 */ /* eslint no-console:0, no-unused-vars:0, import/no-extraneous-dependencies:0 */
/* global document */ /* global document */
const Benchmark = require('benchmark'); const Benchmark = require('benchmark')
const u = require('../lib'); const u = require('../lib')
const _ = require('lodash'); const _ = require('lodash')
const { curry2, curry4 } = require('../lib/util/curry'); const { curry2, curry4 } = require('../lib/util/curry')
const add4 = (a, b, c, d) => a + b + c + d; const add4 = (a, b, c, d) => a + b + c + d
const add2 = (a, b) => a + b; const add2 = (a, b) => a + b
const fakeCurryAdd = x => y => x + y; const fakeCurryAdd = x => y => x + y
const lodashCurryAdd2 = _.curry(add2); const lodashCurryAdd2 = _.curry(add2)
const updeepCurryAdd2 = curry2(add2); const updeepCurryAdd2 = curry2(add2)
const lodashCurryAdd4 = _.curry(add4); const lodashCurryAdd4 = _.curry(add4)
const updeepCurryAdd4 = curry4(add4); const updeepCurryAdd4 = curry4(add4)
// const updeepCurryBig = curry.curryBig(add); // const updeepCurryBig = curry.curryBig(add);
const array = [0, 1, 2, 3, 4, 5]; const array = [0, 1, 2, 3, 4, 5]
// const doUpdate = u(x => x + 1); // const doUpdate = u(x => x + 1);
function log(str) { function log(str) {
if (typeof document !== 'undefined') { if (typeof document !== 'undefined') {
console.log(str); console.log(str)
const el = document.getElementById('perf'); const el = document.getElementById('perf')
el.innerHTML += str; el.innerHTML += str
} }
} }
function createSuite(suiteName, tests) { function createSuite(suiteName, tests) {
const suite = Benchmark.Suite(); // eslint-disable const suite = Benchmark.Suite() // eslint-disable
return () => { return () => {
log(`<h2>${suiteName}</h2><ul>`); log(`<h2>${suiteName}</h2><ul>`)
_.each(tests, (fn, testName) => { _.each(tests, (fn, testName) => {
suite.add(testName, fn); suite.add(testName, fn)
}); })
suite.on('cycle', (event) => { suite
log(`<li>${String(event.target)}</li>`); .on('cycle', event => {
}) log(`<li>${String(event.target)}</li>`)
.on('complete', () => { })
log('</ul>'); .on('complete', () => {
}) log('</ul>')
.run({ async: true }); })
}; .run({ async: true })
}
} }
const curryVsLodash = createSuite('Curry', { const curryVsLodash = createSuite('Curry', {
'updeep curry': () => { 'updeep curry': () => {
updeepCurryAdd4(3)(4)(5)(6); updeepCurryAdd4(3)(4)(5)(6)
updeepCurryAdd4(3, 4, 5, 6); updeepCurryAdd4(3, 4, 5, 6)
updeepCurryAdd4(u._, 4, u._, 6)(3, 4); updeepCurryAdd4(u._, 4, u._, 6)(3, 4)
updeepCurryAdd2(3)(4); updeepCurryAdd2(3)(4)
updeepCurryAdd2(3, 4); updeepCurryAdd2(3, 4)
}, },
'lodash curry': () => { 'lodash curry': () => {
lodashCurryAdd4(3)(4)(5)(6); lodashCurryAdd4(3)(4)(5)(6)
lodashCurryAdd4(3, 4, 5, 6); lodashCurryAdd4(3, 4, 5, 6)
lodashCurryAdd4(_, 4, _, 6)(3, 4); lodashCurryAdd4(_, 4, _, 6)(3, 4)
lodashCurryAdd2(3)(4); lodashCurryAdd2(3)(4)
lodashCurryAdd2(3, 4); lodashCurryAdd2(3, 4)
}, },
}); })
const mapVsLodash = createSuite('Map', { const mapVsLodash = createSuite('Map', {
'_.map': () => _.map(array, fakeCurryAdd(8)), '_.map': () => _.map(array, fakeCurryAdd(8)),
'u.map': () => u.map(fakeCurryAdd(8), array), 'u.map': () => u.map(fakeCurryAdd(8), array),
}); })
const fn = (a, b, c, d, e) => a + b + c + d + e; const fn = (a, b, c, d, e) => a + b + c + d + e
const fnControl = (a, b, c, d, e) => fn(a, b, c, d, e); const fnControl = (a, b, c, d, e) => fn(a, b, c, d, e)
const fnApply = (...args) => fn(...args); const fnApply = (...args) => fn(...args)
const fnDestructure = (...args) => { const fnDestructure = (...args) => {
const [a, b, c, d, e] = args; const [a, b, c, d, e] = args
return fn(a, b, c, d, e); return fn(a, b, c, d, e)
}; }
const applyVsDestructure = createSuite('apply vs destructure', { const applyVsDestructure = createSuite('apply vs destructure', {
control: () => fnControl(1, 2, 3, 4, 5), control: () => fnControl(1, 2, 3, 4, 5),
apply: () => fnApply(1, 2, 3, 4, 5), apply: () => fnApply(1, 2, 3, 4, 5),
destructure: () => fnDestructure(1, 2, 3, 4, 5), destructure: () => fnDestructure(1, 2, 3, 4, 5),
}); })
curryVsLodash(); curryVsLodash()
mapVsLodash(); mapVsLodash()
// applyVsDestructure(); // applyVsDestructure();

View File

@ -1,34 +1,29 @@
'use strict'; 'use strict'
/* eslint strict:0, no-var:0, func-names:0 */ /* eslint strict:0, no-var:0, func-names:0 */
var path = require('path'); var path = require('path')
var config = require('../createWebpackConfig')({ var config = require('../createWebpackConfig')({
context: __dirname, context: __dirname,
entry: [ entry: ['webpack/hot/dev-server', './index.js'],
'webpack/hot/dev-server',
'./index.js',
],
minify: false, minify: false,
env: 'production', env: 'production',
}); })
config.output = { config.output = {
path: path.join(__dirname, './build'), path: path.join(__dirname, './build'),
publicPath: '/assets/', publicPath: '/assets/',
filename: 'perf.js', filename: 'perf.js',
}; }
config.devServer = { config.devServer = {
contentBase: __dirname, contentBase: __dirname,
noInfo: true, noInfo: true,
hot: true, hot: true,
inline: true, inline: true,
}; }
config.module.noParse = [ config.module.noParse = [/benchmark\.js$/]
/benchmark\.js$/,
];
module.exports = config; module.exports = config

View File

@ -1,17 +1,17 @@
import { expect } from 'chai'; import { expect } from 'chai'
import u from '../lib'; import u from '../lib'
describe('u.constant', () => { describe('u.constant', () => {
it('returns what it is given... constantly', () => { it('returns what it is given... constantly', () => {
const func = u.constant(4); const func = u.constant(4)
expect(func()).to.equal(4); expect(func()).to.equal(4)
expect(func('hi')).to.equal(4); expect(func('hi')).to.equal(4)
expect(func('hi', 8)).to.equal(4); expect(func('hi', 8)).to.equal(4)
expect(func(4)).to.equal(4); expect(func(4)).to.equal(4)
}); })
it('freezes the result', () => { it('freezes the result', () => {
expect(Object.isFrozen(u.constant({})())).to.be.true; expect(Object.isFrozen(u.constant({})())).to.be.true
}); })
}); })

View File

@ -1,74 +1,74 @@
import { expect } from 'chai'; import { expect } from 'chai'
import u from '../lib'; import u from '../lib'
describe('u.freeze', () => { describe('u.freeze', () => {
afterEach(() => { afterEach(() => {
delete process.env.NODE_ENV; delete process.env.NODE_ENV
}); })
it('freezes objects', () => { it('freezes objects', () => {
const object = {}; const object = {}
u.freeze(object); u.freeze(object)
expect(Object.isFrozen(object)).to.be.true; expect(Object.isFrozen(object)).to.be.true
}); })
it('freezes nested objects', () => { it('freezes nested objects', () => {
const object = { foo: { bar: 3 } }; const object = { foo: { bar: 3 } }
u.freeze(object); u.freeze(object)
expect(Object.isFrozen(object.foo)).to.be.true; expect(Object.isFrozen(object.foo)).to.be.true
}); })
it('freezes nested arrays', () => { it('freezes nested arrays', () => {
const object = [[0]]; const object = [[0]]
u.freeze(object); u.freeze(object)
expect(Object.isFrozen(object)).to.be.true; expect(Object.isFrozen(object)).to.be.true
expect(Object.isFrozen(object[0])).to.be.true; expect(Object.isFrozen(object[0])).to.be.true
}); })
it('ignores functions', () => { it('ignores functions', () => {
const object = { foo: () => 1 }; const object = { foo: () => 1 }
u.freeze(object); u.freeze(object)
expect(Object.isFrozen(object.foo)).to.be.false; expect(Object.isFrozen(object.foo)).to.be.false
}); })
it('ignores regexps', () => { it('ignores regexps', () => {
const object = { foo: /\d/ }; const object = { foo: /\d/ }
u.freeze(object); u.freeze(object)
expect(Object.isFrozen(object.foo)).to.be.false; expect(Object.isFrozen(object.foo)).to.be.false
}); })
it('does not freeze children if the parent is already frozen', () => { it('does not freeze children if the parent is already frozen', () => {
const object = { foo: {} }; const object = { foo: {} }
Object.freeze(object); Object.freeze(object)
u.freeze(object); u.freeze(object)
expect(Object.isFrozen(object.foo)).to.be.false; expect(Object.isFrozen(object.foo)).to.be.false
}); })
if (typeof process !== 'undefined') { if (typeof process !== 'undefined') {
it('does not freeze in production', () => { it('does not freeze in production', () => {
process.env.NODE_ENV = 'production'; process.env.NODE_ENV = 'production'
const object = {}; const object = {}
u.freeze(object); u.freeze(object)
expect(Object.isFrozen(object)).to.be.false; expect(Object.isFrozen(object)).to.be.false
}); })
} }
it('handles null objects', () => { it('handles null objects', () => {
const object = { foo: null }; const object = { foo: null }
u.freeze(object); u.freeze(object)
expect(Object.isFrozen(object)).to.be.true; expect(Object.isFrozen(object)).to.be.true
}); })
it('returns the same object', () => { it('returns the same object', () => {
const object = {}; const object = {}
const result = u.freeze(object); const result = u.freeze(object)
expect(result).to.equal(object); expect(result).to.equal(object)
}); })
}); })

View File

@ -1,44 +1,47 @@
import { expect } from 'chai'; import { expect } from 'chai'
import u from '../lib'; import u from '../lib'
describe('u.if', () => { describe('u.if', () => {
it('does not update if the predicate is false', () => { it('does not update if the predicate is false', () => {
const object = { a: 0 }; const object = { a: 0 }
let result = u.if(false, { b: 1 }, object); let result = u.if(false, { b: 1 }, object)
expect(result).to.eql(object); expect(result).to.eql(object)
result = u({ x: u.if(false, 1) }, {}); result = u({ x: u.if(false, 1) }, {})
expect(result).to.eql({}); expect(result).to.eql({})
}); })
it('does update if the predicate is true', () => { it('does update if the predicate is true', () => {
const object = { a: 0 }; const object = { a: 0 }
const result = u.if(true, { b: 1 }, object); const result = u.if(true, { b: 1 }, object)
expect(result).to.eql({ a: 0, b: 1 }); expect(result).to.eql({ a: 0, b: 1 })
}); })
it('will use the result of a function passed as a predicate', () => { it('will use the result of a function passed as a predicate', () => {
const object = { a: 0 }; const object = { a: 0 }
const aIsThree = x => x.a === 3; const aIsThree = x => x.a === 3
const result = u.if(aIsThree, { b: 1 }, object); const result = u.if(aIsThree, { b: 1 }, object)
expect(result).to.eql({ a: 0 }); expect(result).to.eql({ a: 0 })
}); })
it('can be partially applied', () => { it('can be partially applied', () => {
const object = { a: 2 }; const object = { a: 2 }
const isEven = x => x % 2 === 0; const isEven = x => x % 2 === 0
const inc = x => x + 1; const inc = x => x + 1
const result = u({ const result = u(
a: u.if(isEven, inc), {
}, object); a: u.if(isEven, inc),
},
object
)
expect(result).to.eql({ a: 3 }); expect(result).to.eql({ a: 3 })
}); })
it('freezes the result', () => { it('freezes the result', () => {
expect(Object.isFrozen(u.if(true, {}, {}))).to.be.true; expect(Object.isFrozen(u.if(true, {}, {}))).to.be.true
expect(Object.isFrozen(u.if(false, {}, {}))).to.be.true; expect(Object.isFrozen(u.if(false, {}, {}))).to.be.true
}); })
}); })

View File

@ -1,42 +1,45 @@
import { expect } from 'chai'; import { expect } from 'chai'
import u from '../lib'; import u from '../lib'
describe('u.ifElse', () => { describe('u.ifElse', () => {
it('does updates with the else if the predicate is false', () => { it('does updates with the else if the predicate is false', () => {
const object = { a: 0 }; const object = { a: 0 }
const result = u.ifElse(false, { b: 1 }, { b: 2 }, object); const result = u.ifElse(false, { b: 1 }, { b: 2 }, object)
expect(result).to.eql({ a: 0, b: 2 }); expect(result).to.eql({ a: 0, b: 2 })
}); })
it('updates with the true update if the predicate is true', () => { it('updates with the true update if the predicate is true', () => {
const object = { a: 0 }; const object = { a: 0 }
const result = u.ifElse(true, { b: 1 }, { b: 4 }, object); const result = u.ifElse(true, { b: 1 }, { b: 4 }, object)
expect(result).to.eql({ a: 0, b: 1 }); expect(result).to.eql({ a: 0, b: 1 })
}); })
it('will use the result of a function passed as a predicate', () => { it('will use the result of a function passed as a predicate', () => {
const object = { a: 0 }; const object = { a: 0 }
const aIsThree = x => x.a === 3; const aIsThree = x => x.a === 3
const result = u.ifElse(aIsThree, { b: 1 }, { b: 4 }, object); const result = u.ifElse(aIsThree, { b: 1 }, { b: 4 }, object)
expect(result).to.eql({ a: 0, b: 4 }); expect(result).to.eql({ a: 0, b: 4 })
}); })
it('can be partially applied', () => { it('can be partially applied', () => {
const object = { a: 2 }; const object = { a: 2 }
const isEven = x => x % 2 === 0; const isEven = x => x % 2 === 0
const inc = x => x + 1; const inc = x => x + 1
const dec = x => x - 1; const dec = x => x - 1
const result = u({ const result = u(
a: u.ifElse(isEven, inc, dec), {
}, object); a: u.ifElse(isEven, inc, dec),
},
object
)
expect(result).to.eql({ a: 3 }); expect(result).to.eql({ a: 3 })
}); })
it('freezes the result', () => { it('freezes the result', () => {
expect(Object.isFrozen(u.ifElse(true, {}, {}, {}))).to.be.true; expect(Object.isFrozen(u.ifElse(true, {}, {}, {}))).to.be.true
expect(Object.isFrozen(u.ifElse(false, {}, {}, {}))).to.be.true; expect(Object.isFrozen(u.ifElse(false, {}, {}, {}))).to.be.true
}); })
}); })

View File

@ -1,59 +1,59 @@
import { expect } from 'chai'; import { expect } from 'chai'
import u from '../lib'; import u from '../lib'
describe('u.is', () => { describe('u.is', () => {
it('returns true if path matches a value predicate', () => { it('returns true if path matches a value predicate', () => {
const result = u.is('a.b', 4, { a: { b: 4 } }); const result = u.is('a.b', 4, { a: { b: 4 } })
expect(result).to.be.true; expect(result).to.be.true
}); })
it('returns true if path matches a function predicate', () => { it('returns true if path matches a function predicate', () => {
const isEven = x => x % 2 === 0; const isEven = x => x % 2 === 0
const result = u.is('a.b', isEven, { a: { b: 6 } }); const result = u.is('a.b', isEven, { a: { b: 6 } })
expect(result).to.be.true; expect(result).to.be.true
}); })
it('returns false if path matches a value predicate', () => { it('returns false if path matches a value predicate', () => {
const result = u.is('a.b', 4, { a: { b: 5 } }); const result = u.is('a.b', 4, { a: { b: 5 } })
expect(result).to.be.false; expect(result).to.be.false
}); })
it('returns false if path matches a function predicate', () => { it('returns false if path matches a function predicate', () => {
const isEven = x => x % 2 === 0; const isEven = x => x % 2 === 0
const result = u.is('a.b', isEven, { a: { b: 7 } }); const result = u.is('a.b', isEven, { a: { b: 7 } })
expect(result).to.be.false; expect(result).to.be.false
}); })
it('returns false if the path does not exist', () => { it('returns false if the path does not exist', () => {
const result = u.is('a.b.c.d', 4, { a: { b: {} } }); const result = u.is('a.b.c.d', 4, { a: { b: {} } })
expect(result).to.be.false; expect(result).to.be.false
}); })
it('can test for undefined', () => { it('can test for undefined', () => {
const result = u.is('a.b.c', undefined, { a: { b: {} } }); const result = u.is('a.b.c', undefined, { a: { b: {} } })
expect(result).to.be.true; expect(result).to.be.true
}); })
it('tests the actual object if a blank path is given', () => { it('tests the actual object if a blank path is given', () => {
const result = u.is('', 4, 4); const result = u.is('', 4, 4)
expect(result).to.be.true; expect(result).to.be.true
}); })
it('can use arrays as paths', () => { it('can use arrays as paths', () => {
const result = u.is(['a', 'b'], 4, { a: { b: 4 } }); const result = u.is(['a', 'b'], 4, { a: { b: 4 } })
expect(result).to.be.true; expect(result).to.be.true
}); })
it('can include array indexes in paths', () => { it('can include array indexes in paths', () => {
let result = u.is('a.1.b', 4, { a: [{}, { b: 4 }] }); let result = u.is('a.1.b', 4, { a: [{}, { b: 4 }] })
expect(result).to.be.true; expect(result).to.be.true
result = u.is(['a', 1, 'b'], 4, { a: [{}, { b: 4 }] }); result = u.is(['a', 1, 'b'], 4, { a: [{}, { b: 4 }] })
expect(result).to.be.true; expect(result).to.be.true
}); })
it('can be partially applied', () => { it('can be partially applied', () => {
const result = u.is('a.b')(4)({ a: { b: 4 } }); const result = u.is('a.b')(4)({ a: { b: 4 } })
expect(result).to.be.true; expect(result).to.be.true
}); })
}); })

View File

@ -1,72 +1,75 @@
import { expect } from 'chai'; import { expect } from 'chai'
import u from '../lib'; import u from '../lib'
describe('u.map', () => { describe('u.map', () => {
it('applies updates to each item in an array', () => { it('applies updates to each item in an array', () => {
const object = [0, 1, 2]; const object = [0, 1, 2]
const inc = x => x + 1; const inc = x => x + 1
const result = u.map(inc, object); const result = u.map(inc, object)
expect(result).to.eql([1, 2, 3]); expect(result).to.eql([1, 2, 3])
}); })
it('applies updates to each value in an object', () => { it('applies updates to each value in an object', () => {
const object = { a: 0, b: 1, c: 2 }; const object = { a: 0, b: 1, c: 2 }
const inc = x => x + 1; const inc = x => x + 1
const result = u.map(inc, object); const result = u.map(inc, object)
expect(result).to.eql({ a: 1, b: 2, c: 3 }); expect(result).to.eql({ a: 1, b: 2, c: 3 })
}); })
it('can update with a regular updates object', () => { it('can update with a regular updates object', () => {
const object = [{ a: 0 }, { a: 0 }]; const object = [{ a: 0 }, { a: 0 }]
const result = u.map({ a: 1 }, object); const result = u.map({ a: 1 }, object)
expect(result).to.eql([{ a: 1 }, { a: 1 }]); expect(result).to.eql([{ a: 1 }, { a: 1 }])
}); })
it('returns the same object if no updates are made', () => { it('returns the same object if no updates are made', () => {
const array = [0, 1]; const array = [0, 1]
const ident = x => x; const ident = x => x
let result = u.map(ident, array); let result = u.map(ident, array)
expect(result).to.equal(array); expect(result).to.equal(array)
const object = { a: 0 }; const object = { a: 0 }
result = u.map(ident, object); result = u.map(ident, object)
expect(result).to.equal(object); expect(result).to.equal(object)
}); })
it('passes the key or index as the second parameter to the iteratee', () => { it('passes the key or index as the second parameter to the iteratee', () => {
const object = { const object = {
a: { x: 0 }, a: { x: 0 },
b: [3, 3], b: [3, 3],
}; }
const setToKey = (_, key) => key; const setToKey = (_, key) => key
const result = u.map(u.map(setToKey), object); const result = u.map(u.map(setToKey), object)
expect(result).to.eql({ expect(result).to.eql({
a: { x: 'x' }, a: { x: 'x' },
b: [0, 1], b: [0, 1],
}); })
}); })
it('can be partially applied', () => { it('can be partially applied', () => {
const object = { const object = {
b: [3, 3], b: [3, 3],
}; }
const setToKey = (_, key) => key; const setToKey = (_, key) => key
const result = u({ const result = u(
b: u.map(setToKey), {
}, object); b: u.map(setToKey),
},
object
)
expect(result).to.eql({ expect(result).to.eql({
b: [0, 1], b: [0, 1],
}); })
}); })
it('freezes the result', () => { it('freezes the result', () => {
expect(Object.isFrozen(u.map({}, {}))).to.be.true; expect(Object.isFrozen(u.map({}, {}))).to.be.true
}); })
}); })

View File

@ -1,14 +1,14 @@
import { expect } from 'chai'; import { expect } from 'chai'
import u from '../lib'; import u from '../lib'
describe('u.omit', () => { describe('u.omit', () => {
it('can omit a key', () => { it('can omit a key', () => {
const result = u({ foo: u.omit('bar') }, { foo: { bar: 7 } }); const result = u({ foo: u.omit('bar') }, { foo: { bar: 7 } })
expect(result).to.eql({ foo: {} }); expect(result).to.eql({ foo: {} })
}); })
it('freezes the result', () => { it('freezes the result', () => {
expect(Object.isFrozen(u.omit('a', {}))).to.be.true; expect(Object.isFrozen(u.omit('a', {}))).to.be.true
}); })
}); })

View File

@ -1,15 +1,18 @@
import { expect } from 'chai'; import { expect } from 'chai'
import u from '../lib'; import u from '../lib'
describe('u.omitBy', () => { describe('u.omitBy', () => {
it('can omitBy with a function', () => { it('can omitBy with a function', () => {
const predicate = (value, key) => (value === 7 && key === 'bar'); const predicate = (value, key) => value === 7 && key === 'bar'
const result = u({ foo: u.omitBy(predicate) }, { foo: { bar: 7, baz: 'a' } }); const result = u(
{ foo: u.omitBy(predicate) },
{ foo: { bar: 7, baz: 'a' } }
)
expect(result).to.eql({ foo: { baz: 'a' } }); expect(result).to.eql({ foo: { baz: 'a' } })
}); })
it('freezes the result', () => { it('freezes the result', () => {
expect(Object.isFrozen(u.omit('a', {}))).to.be.true; expect(Object.isFrozen(u.omit('a', {}))).to.be.true
}); })
}); })

View File

@ -1,38 +1,44 @@
import { expect } from 'chai'; import { expect } from 'chai'
import u from '../lib'; import u from '../lib'
describe('u.reject', () => { describe('u.reject', () => {
it('can reject by index', () => { it('can reject by index', () => {
const result = u.reject((_, index) => index === 1, [3, 4, 5]); const result = u.reject((_, index) => index === 1, [3, 4, 5])
expect(result).to.eql([3, 5]); expect(result).to.eql([3, 5])
}); })
it('can reject with callback shorthand', () => { it('can reject with callback shorthand', () => {
const result = u.reject('bad', [{ bad: true }, { bad: false }]); const result = u.reject('bad', [{ bad: true }, { bad: false }])
expect(result).to.eql([{ bad: false }]); expect(result).to.eql([{ bad: false }])
}); })
it('returns the same instance if reject doesn\'t make changes', () => { it("returns the same instance if reject doesn't make changes", () => {
const object = { foo: [1, 2, 3] }; const object = { foo: [1, 2, 3] }
const result = u({ const result = u(
foo: u.reject(x => x === 'Justin Bieber'), {
}, object); foo: u.reject(x => x === 'Justin Bieber'),
},
object
)
expect(result).to.equal(object); expect(result).to.equal(object)
}); })
it('returns a different instance if reject makes changes', () => { it('returns a different instance if reject makes changes', () => {
const object = { foo: [1, 2, 3, 4] }; const object = { foo: [1, 2, 3, 4] }
const result = u({ const result = u(
foo: u.reject(x => x === 4), {
}, object); foo: u.reject(x => x === 4),
},
object
)
expect(result).to.not.equal(object); expect(result).to.not.equal(object)
}); })
it('freezes the result', () => { it('freezes the result', () => {
expect(Object.isFrozen(u.reject('a', []))).to.be.true; expect(Object.isFrozen(u.reject('a', []))).to.be.true
}); })
}); })

View File

@ -1,61 +1,61 @@
import { expect } from 'chai'; import { expect } from 'chai'
import u from '../lib'; import u from '../lib'
describe('u.updateIn', () => { describe('u.updateIn', () => {
it('can update a single path described with a string', () => { it('can update a single path described with a string', () => {
const object = { a: { b: 0 } }; const object = { a: { b: 0 } }
const result = u.updateIn('a.b', 3, object); const result = u.updateIn('a.b', 3, object)
expect(result).to.eql({ a: { b: 3 } }); expect(result).to.eql({ a: { b: 3 } })
}); })
it('can update a single path described with a string with a function', () => { it('can update a single path described with a string with a function', () => {
const inc = x => x + 1; const inc = x => x + 1
const object = { a: { b: 0 } }; const object = { a: { b: 0 } }
const result = u.updateIn('a.b', inc, object); const result = u.updateIn('a.b', inc, object)
expect(result).to.eql({ a: { b: 1 } }); expect(result).to.eql({ a: { b: 1 } })
}); })
it('can update a single path described with an array', () => { it('can update a single path described with an array', () => {
const object = { a: { b: 0 } }; const object = { a: { b: 0 } }
const result = u.updateIn(['a', 'b'], 3, object); const result = u.updateIn(['a', 'b'], 3, object)
expect(result).to.eql({ a: { b: 3 } }); expect(result).to.eql({ a: { b: 3 } })
}); })
it('can update arrays', () => { it('can update arrays', () => {
const object = { a: [0, 0, 0] }; const object = { a: [0, 0, 0] }
const result = u.updateIn('a.1', 3, object); const result = u.updateIn('a.1', 3, object)
expect(result).to.eql({ a: [0, 3, 0] }); expect(result).to.eql({ a: [0, 3, 0] })
}); })
it('can be partially applied', () => { it('can be partially applied', () => {
const object = { a: { b: 0 } }; const object = { a: { b: 0 } }
const result = u.updateIn('a.b')(3)(object); const result = u.updateIn('a.b')(3)(object)
expect(result).to.eql({ a: { b: 3 } }); expect(result).to.eql({ a: { b: 3 } })
}); })
it('replaces the object outright if the path is empty', () => { it('replaces the object outright if the path is empty', () => {
const object = {}; const object = {}
const result = u.updateIn('', 3, object); const result = u.updateIn('', 3, object)
expect(result).to.equal(3); expect(result).to.equal(3)
}); })
it('freezes the result', () => { it('freezes the result', () => {
expect(Object.isFrozen(u.updateIn('a', 0, {}))).to.be.true; expect(Object.isFrozen(u.updateIn('a', 0, {}))).to.be.true
}); })
it('can multiple elements of an array with *', () => { it('can multiple elements of an array with *', () => {
let object = { a: [{ b: 0 }, { b: 1 }, { b: 2 }] }; let object = { a: [{ b: 0 }, { b: 1 }, { b: 2 }] }
let result = u.updateIn('a.*.b', x => x + 1, object); let result = u.updateIn('a.*.b', x => x + 1, object)
expect(result).to.eql({ a: [{ b: 1 }, { b: 2 }, { b: 3 }] }); expect(result).to.eql({ a: [{ b: 1 }, { b: 2 }, { b: 3 }] })
object = { a: [0, 1, 2] }; object = { a: [0, 1, 2] }
result = u.updateIn(['a', '*'], x => x + 1, object); result = u.updateIn(['a', '*'], x => x + 1, object)
expect(result).to.eql({ a: [1, 2, 3] }); expect(result).to.eql({ a: [1, 2, 3] })
}); })
it('can update properties named *', () => { it('can update properties named *', () => {
const object = { '*': 1, x: 1 }; const object = { '*': 1, x: 1 }
const result = u.updateIn('*', x => x + 1, object); const result = u.updateIn('*', x => x + 1, object)
expect(result).to.eql({ '*': 2, x: 1 }); expect(result).to.eql({ '*': 2, x: 1 })
}); })
}); })

View File

@ -1,143 +1,145 @@
import { expect } from 'chai'; import { expect } from 'chai'
import u from '../lib'; import u from '../lib'
describe('updeep', () => { describe('updeep', () => {
it('does not change anything if no updates are specified', () => { it('does not change anything if no updates are specified', () => {
const object = { foo: 3, bar: [7, 5] }; const object = { foo: 3, bar: [7, 5] }
const result = u({}, object); const result = u({}, object)
expect(result).to.equal(object); expect(result).to.equal(object)
}); })
it('can update with fixed values', () => { it('can update with fixed values', () => {
const object = { foo: 3, bar: [7, 5] }; const object = { foo: 3, bar: [7, 5] }
const result = u({ foo: 4 }, object); const result = u({ foo: 4 }, object)
expect(result).to.deep.equal({ foo: 4, bar: [7, 5] }); expect(result).to.deep.equal({ foo: 4, bar: [7, 5] })
}); })
it('returns the same instance if an update doesn\'t make changes', () => { it("returns the same instance if an update doesn't make changes", () => {
const object = { foo: 3 }; const object = { foo: 3 }
const result = u({ foo: 3 }, object); const result = u({ foo: 3 }, object)
expect(result).to.equal(object); expect(result).to.equal(object)
}); })
it('can update a nested structure', () => { it('can update a nested structure', () => {
const object = { foo: { bar: 7, bam: 3 }, baz: 32 }; const object = { foo: { bar: 7, bam: 3 }, baz: 32 }
const result = u({ foo: { bar: 8 } }, object); const result = u({ foo: { bar: 8 } }, object)
expect(result).to.deep.equal({ foo: { bar: 8, bam: 3 }, baz: 32 }); expect(result).to.deep.equal({ foo: { bar: 8, bam: 3 }, baz: 32 })
}); })
it('can update arrays', () => { it('can update arrays', () => {
const object = [1, 2, 3]; const object = [1, 2, 3]
const result = u({ 1: 7 }, object); const result = u({ 1: 7 }, object)
expect(result).to.deep.equal([1, 7, 3]); expect(result).to.deep.equal([1, 7, 3])
}); })
it('replaces the object outright if updates are a constant', () => { it('replaces the object outright if updates are a constant', () => {
expect(u(3, {})).to.equal(3); expect(u(3, {})).to.equal(3)
expect(u(null, {})).to.be.null; expect(u(null, {})).to.be.null
}); })
it('can add an element to an array', () => { it('can add an element to an array', () => {
const object = []; const object = []
const result = u({ 0: 3 }, object); const result = u({ 0: 3 }, object)
expect(result).to.eql([3]); expect(result).to.eql([3])
}); })
it('can update nested arrays', () => { it('can update nested arrays', () => {
const object = { foo: [1, 2, 3], bar: 9 }; const object = { foo: [1, 2, 3], bar: 9 }
const result = u({ foo: { 1: 7 } }, object); const result = u({ foo: { 1: 7 } }, object)
expect(result).to.deep.equal({ foo: [1, 7, 3], bar: 9 }); expect(result).to.deep.equal({ foo: [1, 7, 3], bar: 9 })
}); })
it('can use functions to update values', () => { it('can use functions to update values', () => {
const inc = i => i + 1; const inc = i => i + 1
const object = { foo: 3, bar: 4, baz: 7 }; const object = { foo: 3, bar: 4, baz: 7 }
const result = u({ foo: inc, bar: inc }, object); const result = u({ foo: inc, bar: inc }, object)
expect(result).to.deep.equal({ foo: 4, bar: 5, baz: 7 }); expect(result).to.deep.equal({ foo: 4, bar: 5, baz: 7 })
}); })
it('can be partially applied', () => { it('can be partially applied', () => {
const inc = i => i + 1; const inc = i => i + 1
const object = { foo: 3 }; const object = { foo: 3 }
const incFoo = u({ foo: inc }); const incFoo = u({ foo: inc })
const result = incFoo(object); const result = incFoo(object)
expect(result).to.deep.equal({ foo: 4 }); expect(result).to.deep.equal({ foo: 4 })
}); })
it('passes additional arguments on to updates if it is a function', () => { it('passes additional arguments on to updates if it is a function', () => {
const func = (_, x) => x; const func = (_, x) => x
const result = u(func, 0, 4); const result = u(func, 0, 4)
expect(result).to.equal(4); expect(result).to.equal(4)
}); })
it('can update if the value is an array', () => { it('can update if the value is an array', () => {
const object = {}; const object = {}
const result = u({ foo: [0, 1] }, object); const result = u({ foo: [0, 1] }, object)
expect(result).to.deep.equal({ foo: [0, 1] }); expect(result).to.deep.equal({ foo: [0, 1] })
}); })
it('can update when original object is undefined', () => { it('can update when original object is undefined', () => {
const result = u({ foo: [0, 1] }, undefined); const result = u({ foo: [0, 1] }, undefined)
expect(result).to.deep.equal({ foo: [0, 1] }); expect(result).to.deep.equal({ foo: [0, 1] })
}); })
it('can take a function as the updater', () => { it('can take a function as the updater', () => {
const result = u(i => i + 1, 7); const result = u(i => i + 1, 7)
expect(result).to.eql(8); expect(result).to.eql(8)
}); })
it('deeply freezes the result', () => { it('deeply freezes the result', () => {
const result = u({ foo: { bar: 3 } }, { foo: { bar: 0 } }); const result = u({ foo: { bar: 3 } }, { foo: { bar: 0 } })
expect(Object.isFrozen(result)).to.be.true; expect(Object.isFrozen(result)).to.be.true
expect(Object.isFrozen(result.foo)).to.be.true; expect(Object.isFrozen(result.foo)).to.be.true
}); })
it('assigns null values', () => { it('assigns null values', () => {
expect(u({ isNull: null }, {})).to.eql({ isNull: null }); expect(u({ isNull: null }, {})).to.eql({ isNull: null })
}); })
it('can use a placeholder to partially apply', () => { it('can use a placeholder to partially apply', () => {
function increment(i) { return i + 1; } function increment(i) {
const updateJoe = u(u._, { name: 'Joe Merrill', age: 21 }); return i + 1
const result = updateJoe({ age: increment }); }
const updateJoe = u(u._, { name: 'Joe Merrill', age: 21 })
const result = updateJoe({ age: increment })
expect(result).to.eql({ name: 'Joe Merrill', age: 22 }); expect(result).to.eql({ name: 'Joe Merrill', age: 22 })
}); })
it('defaults to an empty object when null or undefined', () => { it('defaults to an empty object when null or undefined', () => {
let result = u({ a: { b: 0 } }, { a: null }); let result = u({ a: { b: 0 } }, { a: null })
expect(result).to.eql({ a: { b: 0 } }); expect(result).to.eql({ a: { b: 0 } })
result = u({ a: { b: 0 } }, { a: undefined }); result = u({ a: { b: 0 } }, { a: undefined })
expect(result).to.eql({ a: { b: 0 } }); expect(result).to.eql({ a: { b: 0 } })
result = u({ a: { b: 0 } }, { }); result = u({ a: { b: 0 } }, {})
expect(result).to.eql({ a: { b: 0 } }); expect(result).to.eql({ a: { b: 0 } })
}); })
it('preserves empty objects when empty updates are specified', () => { it('preserves empty objects when empty updates are specified', () => {
const result = u({ a: {} }, {}); const result = u({ a: {} }, {})
expect(result).to.eql({ a: {} }); expect(result).to.eql({ a: {} })
}); })
it('works with date objects', () => { it('works with date objects', () => {
const date = new Date(); const date = new Date()
const result = u({ created: date }, {}); const result = u({ created: date }, {})
expect(result).to.eql({ created: date }); expect(result).to.eql({ created: date })
}); })
}); })

View File

@ -1,110 +1,110 @@
import { expect } from 'chai'; import { expect } from 'chai'
import { curry1, curry2, curry3, curry4, _ } from '../../lib/util/curry'; import { curry1, curry2, curry3, curry4, _ } from '../../lib/util/curry'
describe('curry1', () => { describe('curry1', () => {
it('can curry one arguments', () => { it('can curry one arguments', () => {
const addOne = curry1(x => x + 1); const addOne = curry1(x => x + 1)
expect(addOne(3)).to.equal(4); expect(addOne(3)).to.equal(4)
expect(addOne()(3)).to.equal(4); expect(addOne()(3)).to.equal(4)
}); })
it('will take up to two extra arguments', () => { it('will take up to two extra arguments', () => {
const curried = curry1((a, b, c) => [a, b, c]); const curried = curry1((a, b, c) => [a, b, c])
expect(curried(1, 2, 3, 4)).to.eql([1, 2, 3]); expect(curried(1, 2, 3, 4)).to.eql([1, 2, 3])
}); })
it('returns a fn with arity of 1', () => { it('returns a fn with arity of 1', () => {
const curried = curry1((a, b, c) => [a, b, c]); const curried = curry1((a, b, c) => [a, b, c])
expect(curried).to.have.length(1); expect(curried).to.have.length(1)
}); })
}); })
describe('curry2', () => { describe('curry2', () => {
it('can curry two arguments', () => { it('can curry two arguments', () => {
const add = curry2((x, y) => x + y); const add = curry2((x, y) => x + y)
expect(add(3)(4)).to.equal(7); expect(add(3)(4)).to.equal(7)
expect(add()(3)()(4)).to.equal(7); expect(add()(3)()(4)).to.equal(7)
expect(add(3, 4)).to.equal(7); expect(add(3, 4)).to.equal(7)
}); })
it('will take up to two extra arguments', () => { it('will take up to two extra arguments', () => {
const curried = curry2((a, b, c, d) => [a, b, c, d]); const curried = curry2((a, b, c, d) => [a, b, c, d])
expect(curried(1, 2, 3, 4, 5)).to.eql([1, 2, 3, 4]); expect(curried(1, 2, 3, 4, 5)).to.eql([1, 2, 3, 4])
}); })
it('can use the placeholder', () => { it('can use the placeholder', () => {
const curried = curry2((a, b, c, d) => [a, b, c, d]); const curried = curry2((a, b, c, d) => [a, b, c, d])
expect(curried(_, 2)(1, 3, 4)).to.eql([1, 2, 3, 4]); expect(curried(_, 2)(1, 3, 4)).to.eql([1, 2, 3, 4])
}); })
it('returns a fn with arity of 2', () => { it('returns a fn with arity of 2', () => {
const curried = curry2((a, b, c, d) => [a, b, c, d]); const curried = curry2((a, b, c, d) => [a, b, c, d])
expect(curried).to.have.length(2); expect(curried).to.have.length(2)
}); })
}); })
describe('curry3', () => { describe('curry3', () => {
it('can curry three arguments', () => { it('can curry three arguments', () => {
const add = curry3((x, y, z) => x + y + z); const add = curry3((x, y, z) => x + y + z)
expect(add(3, _)(4)(5)).to.equal(12); expect(add(3, _)(4)(5)).to.equal(12)
expect(add()(3)()(4, 5)).to.equal(12); expect(add()(3)()(4, 5)).to.equal(12)
expect(add(3, 4, 5)).to.equal(12); expect(add(3, 4, 5)).to.equal(12)
}); })
it('will take up to two extra arguments', () => { it('will take up to two extra arguments', () => {
const curried = curry3((a, b, c, d, e) => [a, b, c, d, e]); const curried = curry3((a, b, c, d, e) => [a, b, c, d, e])
expect(curried(1, 2, 3, 4, 5, 6)).to.eql([1, 2, 3, 4, 5]); expect(curried(1, 2, 3, 4, 5, 6)).to.eql([1, 2, 3, 4, 5])
}); })
it('can use the placeholder', () => { it('can use the placeholder', () => {
const curried = curry3((a, b, c, d, e) => [a, b, c, d, e]); const curried = curry3((a, b, c, d, e) => [a, b, c, d, e])
expect(curried(_, 2)('a', 3, 4, 5)).to.eql(['a', 2, 3, 4, 5]); expect(curried(_, 2)('a', 3, 4, 5)).to.eql(['a', 2, 3, 4, 5])
expect(curried('b', _, 3)(2, 4, 5)).to.eql(['b', 2, 3, 4, 5]); expect(curried('b', _, 3)(2, 4, 5)).to.eql(['b', 2, 3, 4, 5])
expect(curried(_, 2, 3)('c', 4, 5)).to.eql(['c', 2, 3, 4, 5]); expect(curried(_, 2, 3)('c', 4, 5)).to.eql(['c', 2, 3, 4, 5])
expect(curried(_, _, 3)('d', 2, 4, 5)).to.eql(['d', 2, 3, 4, 5]); expect(curried(_, _, 3)('d', 2, 4, 5)).to.eql(['d', 2, 3, 4, 5])
}); })
it('returns a fn with arity of 3', () => { it('returns a fn with arity of 3', () => {
const curried = curry3((a, b, c, d, e) => [a, b, c, d, e]); const curried = curry3((a, b, c, d, e) => [a, b, c, d, e])
expect(curried).to.have.length(3); expect(curried).to.have.length(3)
}); })
}); })
describe('curry4', () => { describe('curry4', () => {
it('can curry four arguments', () => { it('can curry four arguments', () => {
const add = curry4((x, y, z, u) => x + y + z + u); const add = curry4((x, y, z, u) => x + y + z + u)
expect(add(3, _)(4)(5)(6)).to.equal(18); expect(add(3, _)(4)(5)(6)).to.equal(18)
expect(add()(3)()(4, 5, 6)).to.equal(18); expect(add()(3)()(4, 5, 6)).to.equal(18)
expect(add(3, 4, 5, 6)).to.equal(18); expect(add(3, 4, 5, 6)).to.equal(18)
}); })
it('will take up to two extra arguments', () => { it('will take up to two extra arguments', () => {
const curried = curry4((a, b, c, d, e, f) => [a, b, c, d, e, f]); const curried = curry4((a, b, c, d, e, f) => [a, b, c, d, e, f])
expect(curried(1, 2, 3, 4, 5, 6, 7)).to.eql([1, 2, 3, 4, 5, 6]); expect(curried(1, 2, 3, 4, 5, 6, 7)).to.eql([1, 2, 3, 4, 5, 6])
}); })
it('can use the placeholder', () => { it('can use the placeholder', () => {
const curried = curry4((a, b, c, d, e, f) => [a, b, c, d, e, f]); const curried = curry4((a, b, c, d, e, f) => [a, b, c, d, e, f])
expect(curried(_, 2)('a', 3, 4, 5, 6)).to.eql(['a', 2, 3, 4, 5, 6]); expect(curried(_, 2)('a', 3, 4, 5, 6)).to.eql(['a', 2, 3, 4, 5, 6])
expect(curried(_, 2, 3)('b', 4, 5, 6)).to.eql(['b', 2, 3, 4, 5, 6]); expect(curried(_, 2, 3)('b', 4, 5, 6)).to.eql(['b', 2, 3, 4, 5, 6])
expect(curried(_, 2, 3, 4)('c', 5, 6)).to.eql(['c', 2, 3, 4, 5, 6]); expect(curried(_, 2, 3, 4)('c', 5, 6)).to.eql(['c', 2, 3, 4, 5, 6])
expect(curried('d', _, 3)(2, 4, 5, 6)).to.eql(['d', 2, 3, 4, 5, 6]); expect(curried('d', _, 3)(2, 4, 5, 6)).to.eql(['d', 2, 3, 4, 5, 6])
expect(curried('e', _, 3, 4)(2, 5, 6)).to.eql(['e', 2, 3, 4, 5, 6]); expect(curried('e', _, 3, 4)(2, 5, 6)).to.eql(['e', 2, 3, 4, 5, 6])
expect(curried('f', 2, _, 4)(3, 5, 6)).to.eql(['f', 2, 3, 4, 5, 6]); expect(curried('f', 2, _, 4)(3, 5, 6)).to.eql(['f', 2, 3, 4, 5, 6])
expect(curried(_, _, 3)('g', 2, 4, 5, 6)).to.eql(['g', 2, 3, 4, 5, 6]); expect(curried(_, _, 3)('g', 2, 4, 5, 6)).to.eql(['g', 2, 3, 4, 5, 6])
expect(curried(_, _, 3, 4)('h', 2, 5, 6)).to.eql(['h', 2, 3, 4, 5, 6]); expect(curried(_, _, 3, 4)('h', 2, 5, 6)).to.eql(['h', 2, 3, 4, 5, 6])
expect(curried(_, 2, _, 4)('i', 3, 5, 6)).to.eql(['i', 2, 3, 4, 5, 6]); expect(curried(_, 2, _, 4)('i', 3, 5, 6)).to.eql(['i', 2, 3, 4, 5, 6])
expect(curried('j', _, _, 4)(2, 3, 5, 6)).to.eql(['j', 2, 3, 4, 5, 6]); expect(curried('j', _, _, 4)(2, 3, 5, 6)).to.eql(['j', 2, 3, 4, 5, 6])
expect(curried(_, _, _, 4)('k', 2, 3, 5, 6)).to.eql(['k', 2, 3, 4, 5, 6]); expect(curried(_, _, _, 4)('k', 2, 3, 5, 6)).to.eql(['k', 2, 3, 4, 5, 6])
}); })
it('returns a fn with arity of 4', () => { it('returns a fn with arity of 4', () => {
const curried = curry4((a, b, c, d, e, f) => [a, b, c, d, e, f]); const curried = curry4((a, b, c, d, e, f) => [a, b, c, d, e, f])
expect(curried).to.have.length(4); expect(curried).to.have.length(4)
}); })
}); })

View File

@ -1,22 +1,22 @@
import { expect } from 'chai'; import { expect } from 'chai'
import splitPath from '../../lib/util/splitPath'; import splitPath from '../../lib/util/splitPath'
describe('splitPath', () => { describe('splitPath', () => {
it('treats a number as a single step path', () => { it('treats a number as a single step path', () => {
const path = 1; const path = 1
const result = splitPath(path); const result = splitPath(path)
expect(result).to.deep.equal(['1']); expect(result).to.deep.equal(['1'])
}); })
it('handles arrays', () => { it('handles arrays', () => {
const path = ['foo', 'bar', 'x']; const path = ['foo', 'bar', 'x']
const result = splitPath(path); const result = splitPath(path)
expect(result).to.equal(path); expect(result).to.equal(path)
}); })
it('handles strings separated by dots', () => { it('handles strings separated by dots', () => {
const path = 'bar.0.y'; const path = 'bar.0.y'
const result = splitPath(path); const result = splitPath(path)
expect(result).to.deep.equal(['bar', '0', 'y']); expect(result).to.deep.equal(['bar', '0', 'y'])
}); })
}); })

View File

@ -1,31 +1,34 @@
import { expect } from 'chai'; import { expect } from 'chai'
import u from '../lib'; import u from '../lib'
describe('u.withDefault', () => { describe('u.withDefault', () => {
it('uses the default as the basis for the update if the object is undefined', () => { it('uses the default as the basis for the update if the object is undefined', () => {
const inc = x => x + 1; const inc = x => x + 1
const result = u.withDefault({ a: 0 }, { a: inc }, undefined); const result = u.withDefault({ a: 0 }, { a: inc }, undefined)
expect(result).to.eql({ a: 1 }); expect(result).to.eql({ a: 1 })
}); })
it('uses ignores the default if the object is defined', () => { it('uses ignores the default if the object is defined', () => {
const inc = x => x + 1; const inc = x => x + 1
const result = u.withDefault({ a: 0 }, { a: inc }, { a: 3 }); const result = u.withDefault({ a: 0 }, { a: inc }, { a: 3 })
expect(result).to.eql({ a: 4 }); expect(result).to.eql({ a: 4 })
}); })
it('can be partially applied', () => { it('can be partially applied', () => {
const object = {}; const object = {}
const result = u({ const result = u(
foo: u.withDefault([], { 0: 'bar' }), {
}, object); foo: u.withDefault([], { 0: 'bar' }),
},
object
)
expect(result).to.eql({ foo: ['bar'] }); expect(result).to.eql({ foo: ['bar'] })
}); })
it('freezes the result', () => { it('freezes the result', () => {
expect(Object.isFrozen(u.withDefault({}, { a: 1 })(undefined))).to.be.true; expect(Object.isFrozen(u.withDefault({}, { a: 1 })(undefined))).to.be.true
}); })
}); })

View File

@ -1,5 +1,5 @@
'use strict'; 'use strict'
/* eslint strict:0, no-var:0, func-names:0 */ /* eslint strict:0, no-var:0, func-names:0 */
module.exports = require('./createWebpackConfig')(); module.exports = require('./createWebpackConfig')()

117
yarn.lock
View File

@ -73,6 +73,12 @@ ansi-styles@^2.1.0, ansi-styles@^2.2.1:
version "2.2.1" version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
ansi-styles@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.0.0.tgz#5404e93a544c4fec7f048262977bebfe3155e0c1"
dependencies:
color-convert "^1.0.0"
anymatch@^1.3.0: anymatch@^1.3.0:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507"
@ -167,6 +173,10 @@ assertion-error@^1.0.1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c"
ast-types@0.9.8:
version "0.9.8"
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.8.tgz#6cb6a40beba31f49f20928e28439fc14a3dab078"
async-each@^1.0.0: async-each@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
@ -195,7 +205,7 @@ aws4@^1.2.1:
version "1.6.0" version "1.6.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
babel-code-frame@^6.16.0, babel-code-frame@^6.22.0: babel-code-frame@6.22.0, babel-code-frame@^6.16.0, babel-code-frame@^6.22.0:
version "6.22.0" version "6.22.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4"
dependencies: dependencies:
@ -742,6 +752,10 @@ babel-types@^6.19.0, babel-types@^6.24.1:
lodash "^4.2.0" lodash "^4.2.0"
to-fast-properties "^1.0.1" to-fast-properties "^1.0.1"
babylon@7.0.0-beta.8:
version "7.0.0-beta.8"
resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.8.tgz#2bdc5ae366041442c27e068cce6f0d7c06ea9949"
babylon@^6.11.0, babylon@^6.15.0: babylon@^6.11.0, babylon@^6.15.0:
version "6.16.1" version "6.16.1"
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.16.1.tgz#30c5a22f481978a9e7f8cdfdf496b11d94b404d3" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.16.1.tgz#30c5a22f481978a9e7f8cdfdf496b11d94b404d3"
@ -951,7 +965,7 @@ chalk@1.1.1:
strip-ansi "^3.0.0" strip-ansi "^3.0.0"
supports-color "^2.0.0" supports-color "^2.0.0"
chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
version "1.1.3" version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
dependencies: dependencies:
@ -1028,6 +1042,16 @@ code-point-at@^1.0.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" 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.2"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.2.tgz#5c8ab72b64bd2215d617ae9559ebb148475cf98d"
colors@1.0.3: colors@1.0.3:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
@ -1514,6 +1538,12 @@ eslint-config-airbnb-base@^11.1.3:
version "11.1.3" version "11.1.3"
resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.1.3.tgz#0e8db71514fa36b977fbcf977c01edcf863e0cf0" resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.1.3.tgz#0e8db71514fa36b977fbcf977c01edcf863e0cf0"
eslint-config-prettier@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-1.6.0.tgz#56e53a8eb461c06eced20cec40d765c185100fd5"
dependencies:
get-stdin "^5.0.1"
eslint-import-resolver-node@^0.2.0: eslint-import-resolver-node@^0.2.0:
version "0.2.3" version "0.2.3"
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz#5add8106e8c928db2cba232bcd9efa846e3da16c" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz#5add8106e8c928db2cba232bcd9efa846e3da16c"
@ -1544,6 +1574,12 @@ eslint-plugin-import@^2.2.0:
minimatch "^3.0.3" minimatch "^3.0.3"
pkg-up "^1.0.0" pkg-up "^1.0.0"
eslint-plugin-prettier@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.0.1.tgz#2ae1216cf053dd728360ca8560bf1aabc8af3fa9"
dependencies:
requireindex "~1.1.0"
eslint@^3.0.0, eslint@^3.19.0: eslint@^3.0.0, eslint@^3.19.0:
version "3.19.0" version "3.19.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc" resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc"
@ -1616,7 +1652,7 @@ estraverse@~4.1.0:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.1.1.tgz#f6caca728933a850ef90661d0e17982ba47111a2" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.1.1.tgz#f6caca728933a850ef90661d0e17982ba47111a2"
esutils@^2.0.2: esutils@2.0.2, esutils@^2.0.2:
version "2.0.2" version "2.0.2"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
@ -1871,6 +1907,10 @@ flat-cache@^1.2.1:
graceful-fs "^4.1.2" graceful-fs "^4.1.2"
write "^0.2.1" write "^0.2.1"
flow-parser@0.43.0:
version "0.43.0"
resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.43.0.tgz#e2b8eb1ac83dd53f7b6b04a7c35b6a52c33479b7"
for-in@^1.0.1: for-in@^1.0.1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
@ -1980,6 +2020,10 @@ generate-object-property@^1.1.0:
dependencies: dependencies:
is-property "^1.0.0" is-property "^1.0.0"
get-stdin@5.0.1, get-stdin@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398"
getpass@^0.1.1: getpass@^0.1.1:
version "0.1.6" version "0.1.6"
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6"
@ -2029,16 +2073,7 @@ glob@3.2.11:
inherits "2" inherits "2"
minimatch "0.3" minimatch "0.3"
glob@^4.3.1: glob@7.1.1, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5:
version "4.5.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f"
dependencies:
inflight "^1.0.4"
inherits "2"
minimatch "^2.0.1"
once "^1.3.0"
glob@^7.0.0, glob@^7.0.3, glob@^7.0.5:
version "7.1.1" version "7.1.1"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
dependencies: dependencies:
@ -2049,6 +2084,15 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5:
once "^1.3.0" once "^1.3.0"
path-is-absolute "^1.0.0" path-is-absolute "^1.0.0"
glob@^4.3.1:
version "4.5.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f"
dependencies:
inflight "^1.0.4"
inherits "2"
minimatch "^2.0.1"
once "^1.3.0"
glob@~3.1.21: glob@~3.1.21:
version "3.1.21" version "3.1.21"
resolved "https://registry.yarnpkg.com/glob/-/glob-3.1.21.tgz#d29e0a055dea5138f4d07ed40e8982e83c2066cd" resolved "https://registry.yarnpkg.com/glob/-/glob-3.1.21.tgz#d29e0a055dea5138f4d07ed40e8982e83c2066cd"
@ -2618,6 +2662,22 @@ jade@0.26.3:
commander "0.6.1" commander "0.6.1"
mkdirp "0.3.0" mkdirp "0.3.0"
jest-matcher-utils@^19.0.0:
version "19.0.0"
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-19.0.0.tgz#5ecd9b63565d2b001f61fbf7ec4c7f537964564d"
dependencies:
chalk "^1.1.3"
pretty-format "^19.0.0"
jest-validate@19.0.0:
version "19.0.0"
resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-19.0.0.tgz#8c6318a20ecfeaba0ba5378bfbb8277abded4173"
dependencies:
chalk "^1.1.1"
jest-matcher-utils "^19.0.0"
leven "^2.0.0"
pretty-format "^19.0.0"
jodid25519@^1.0.0: jodid25519@^1.0.0:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967" resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967"
@ -2790,6 +2850,10 @@ lazy-cache@^1.0.3:
version "1.0.4" version "1.0.4"
resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
leven@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
levn@^0.3.0, levn@~0.3.0: levn@^0.3.0, levn@~0.3.0:
version "0.3.0" version "0.3.0"
resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
@ -3110,7 +3174,7 @@ minimist@0.0.8, minimist@~0.0.1:
version "0.0.8" version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
minimist@^1.1.0, minimist@^1.2.0: minimist@1.2.0, minimist@^1.1.0, minimist@^1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
@ -3544,6 +3608,27 @@ preserve@^0.2.0:
version "0.2.0" version "0.2.0"
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
prettier@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.1.0.tgz#9d6ad005703efefa66b6999b8916bfc6afeaf9f8"
dependencies:
ast-types "0.9.8"
babel-code-frame "6.22.0"
babylon "7.0.0-beta.8"
chalk "1.1.3"
esutils "2.0.2"
flow-parser "0.43.0"
get-stdin "5.0.1"
glob "7.1.1"
jest-validate "19.0.0"
minimist "1.2.0"
pretty-format@^19.0.0:
version "19.0.0"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-19.0.0.tgz#56530d32acb98a3fa4851c4e2b9d37b420684c84"
dependencies:
ansi-styles "^3.0.0"
pretty-hrtime@^1.0.0: pretty-hrtime@^1.0.0:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
@ -3827,6 +3912,10 @@ require-uncached@^1.0.2:
caller-path "^0.1.0" caller-path "^0.1.0"
resolve-from "^1.0.0" resolve-from "^1.0.0"
requireindex@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.1.0.tgz#e5404b81557ef75db6e49c5a72004893fe03e162"
requires-port@1.0.x, requires-port@1.x.x: requires-port@1.0.x, requires-port@1.x.x:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"