Skip to content

Commit

Permalink
Return mewt wrapped instances (#12)
Browse files Browse the repository at this point in the history
* code style changes

* no need to have newObj in the outer scope

* moved multiRet outside of the function, no need to redeclare

* methods that return arrays, setters and unsetters, and multi return value methods now return mewt wrapped instances

* moved constants back to method, array -> string, removed TODO
  • Loading branch information
bali182 authored and sdgluck committed Mar 28, 2017
1 parent 2141c5e commit 602dc20
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 20 deletions.
47 changes: 34 additions & 13 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,51 @@
/** @returns {Array|Object} */
module.exports = function mewt (target) {
let isA = Array.isArray(target)
, multiRet = 'push pop shift unshift'
, clone = isA ? v => [].concat(v) : v => Object.assign({}, v)
function mewt(target) {
const multiRet = 'push pop shift unshift'
const mutArrMethods = 'reverse sort splice fill copyWithin'
const nonMutArrMethods = 'filter map concat slice'

const isA = Array.isArray(target)
const clone = isA ? v => [].concat(v) : v => Object.assign({}, v)

let override = prop => (...args) => {
let cl = clone(target)
let res = cl[prop](...args)
return multiRet.includes(prop) ? [res, cl] : res
const override = prop => (...args) => {
const mutMethod = mutArrMethods.includes(prop)
const nonMutMethod = nonMutArrMethods.includes(prop)

const cl = nonMutMethod ? target : clone(target)
const res = cl[prop](...args)
const wrappedRes = (mutMethod || nonMutMethod) ? mewt(res) : res

return multiRet.includes(prop) ? [wrappedRes, mewt(cl)] : wrappedRes
}

let newObj, api = {
$set: (prop, val) => (newObj = clone(target), newObj[prop] = val, newObj),
$unset: prop => (newObj = clone(target), delete newObj[prop], newObj)
const api = {
$set: (prop, val) => {
const newObj = clone(target)
newObj[prop] = val
return mewt(newObj)
},
$unset: prop => {
const newObj = clone(target)
delete newObj[prop]
return mewt(newObj)
}
}

if (!isA && typeof target !== 'object')
if (!isA && typeof target !== 'object') {
throw new Error('mewt accepts array or object')
}

return new Proxy(target, {
set: () => {
throw new Error(`${isA ? 'array' : 'object'} is immutable`)
},
get: (_, prop) => {
if (api[prop]) return api[prop]
if (api[prop]) {
return api[prop]
}
return target[prop] && ({}.hasOwnProperty.call(target, prop) ? target[prop] : override(prop))
}
})
}

module.exports = mewt
2 changes: 1 addition & 1 deletion lib/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

59 changes: 53 additions & 6 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
const test = require('tape')
const mewt = require('./lib')

const createAssertMewt = t => input => {
t.equal(typeof input.$set, 'function')
t.equal(typeof input.$unset, 'function')
}

test('exports a function', (t) => {
t.equal(typeof mewt, 'function')
t.end()
Expand All @@ -14,6 +19,7 @@ test('throws without object or array', (t) => {
})

test('array', (t) => {
const assertMewt = createAssertMewt(t)
{
// returns new array
const a = []
Expand All @@ -28,8 +34,7 @@ test('array', (t) => {
{
// has $set & $unset
const a = mewt([])
t.equal(typeof a.$set, 'function')
t.equal(typeof a.$unset, 'function')
assertMewt(a)
}
{
// get own property
Expand All @@ -42,27 +47,31 @@ test('array', (t) => {
const n = a.$set(0, '')
t.deepEqual(n, [''])
t.notEqual(a, n)
assertMewt(n)
}
{
// $unset
const a = mewt([''])
const n = a.$unset(0)
t.deepEqual(n, [])
t.notEqual(a, n)
assertMewt(n)
}
{
// copyWithin
const a = mewt([1, 2])
const n = a.copyWithin(0, 2)
t.deepEqual(n, [1, 2])
t.notEqual(a, n)
assertMewt(n)
}
{
// fill
const a = mewt([,])
const n = a.fill('')
t.deepEqual(n, [''])
t.notEqual(a, n)
assertMewt(n)
}
{
// pop
Expand All @@ -72,6 +81,7 @@ test('array', (t) => {
t.equal(str, '')
t.deepEqual(n, [])
t.notEqual(a, n)
assertMewt(n)
}
{
// push
Expand All @@ -80,13 +90,15 @@ test('array', (t) => {
t.equal(1, len)
t.deepEqual(n, [''])
t.notEqual(a, n)
assertMewt(n)
}
{
// reverse
const a = mewt([1, 2])
const n = a.reverse()
t.deepEqual(n, [2, 1])
t.notEqual(a, n)
assertMewt(n)
}
{
// shift
Expand All @@ -95,20 +107,23 @@ test('array', (t) => {
t.equal(num, 1)
t.deepEqual(n, [2])
t.notEqual(a, n)
assertMewt(n)
}
{
// sort
const a = mewt(['c', 'b', 'a'])
const n = a.sort()
t.deepEqual(n, ['a', 'b', 'c'])
t.notEqual(a, n)
assertMewt(n)
}
{
// sort
const a = mewt(['a', 'b', 'c'])
const n = a.splice(0, 1)
t.deepEqual(n, ['a'])
t.notEqual(a, n)
assertMewt(n)
}
{
// unshift
Expand All @@ -117,11 +132,44 @@ test('array', (t) => {
t.equal(len, 2)
t.deepEqual(n, [1, 2])
t.notEqual(a, n)
assertMewt(n)
}
{
// filter
const a = mewt([1, 2, 3, 4, 5])
const filtered = a.filter(e => e % 2 === 0)
t.deepEqual(filtered, [2, 4])
assertMewt(filtered)
}
{
// map
const a = mewt([1, 2, 3, 4, 5])
const transformed = a.map(e => e * 2)
t.deepEqual(transformed, [2, 4, 6, 8, 10])
assertMewt(transformed)
}
{
// concat
const a = mewt([1, 2]).concat([3, 4, 5])
t.deepEqual(a, [1, 2, 3, 4, 5])
assertMewt(a)

const b = mewt([5, 4]).concat(mewt([3, 2, 1]))
t.deepEqual(b, [5, 4, 3, 2, 1])
assertMewt(b)
}
{
// slice
const a = mewt([1, 2, 3, 4, 5])
const sliced = a.slice(1, 4)
t.deepEqual(sliced, [2, 3, 4])
assertMewt(sliced)
}
t.end()
})

test('object', (t) => {
const assertMewt = createAssertMewt(t)
{
// returns new object
const o = {}
Expand All @@ -136,12 +184,11 @@ test('object', (t) => {
{
// has $set & $unset
const o = mewt({})
t.equal(typeof o.$set, 'function')
t.equal(typeof o.$unset, 'function')
assertMewt(o)
}
{
// get own property
const o = mewt({album: 'Aladdin Sane'})
const o = mewt({ album: 'Aladdin Sane' })
t.equal(o.album, 'Aladdin Sane')
}
{
Expand All @@ -154,7 +201,7 @@ test('object', (t) => {
}
{
// $unset
const o = mewt({album: 'Heroes'})
const o = mewt({ album: 'Heroes' })
const n = o.$unset('album')
t.equal(o.album, 'Heroes')
t.equal(n.album, undefined)
Expand Down

0 comments on commit 602dc20

Please sign in to comment.