Skip to content
This repository was archived by the owner on Jan 6, 2025. It is now read-only.

Commit f59d941

Browse files
committed
🚧 Props nav
1 parent c02f125 commit f59d941

File tree

6 files changed

+103
-9
lines changed

6 files changed

+103
-9
lines changed

packages/immutadot/src/nav2/finalNav.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
const update = updater => value => updater(value)
22

3+
const get = () => value => value
4+
5+
const unset = () => undefined
6+
37
export const finalNav = operation => {
48
switch (operation) {
59
case 'update': return update
6-
case 'get': return null
7-
case 'unset': return null
10+
case 'get': return get
11+
case 'unset': return unset
812
}
913
throw TypeError(`Unknown navigator operation ${operation}`)
1014
}

packages/immutadot/src/nav2/nav.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { finalNav } from './finalNav'
22
import { propNav } from './propNav'
3+
import { propsNav } from './propsNav'
34

45
const toNav = ([type, params]) => {
56
switch (type) {
67
case 'prop': return propNav(params)
8+
case 'props': return propsNav(params)
79
}
810
throw TypeError(`Unknown navigator type ${type}`)
911
}

packages/immutadot/src/nav2/nav.spec.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,12 @@ describe('nav.nav', () => {
1818
return output
1919
},
2020
))
21+
22+
it('should get a nested prop', () => {
23+
const input = {
24+
nested: { prop: 'foo' },
25+
other: { prop: 'baz' },
26+
}
27+
expect(nav([['prop', 'nested'], ['prop', 'prop']])('get')()(input)).toEqual('foo')
28+
})
2129
})
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
import { isNil } from 'util/lang'
22

3-
export const copy = value => isNil(value) ? {} : { ...value }
3+
export const onCopy = (cb, force = false) => value => {
4+
const nil = isNil(value)
5+
if (nil && !force) return value
6+
const newValue = nil ? {} : { ...value }
7+
cb(newValue, value)
8+
return newValue
9+
}
Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,35 @@
1-
import { copy } from './objectNav'
21
import { isNil } from 'util/lang'
2+
import { onCopy } from './objectNav'
33

44
const update = (key, next) => updater => {
55
const nextUpdater = next(updater)
6-
return value => {
7-
const newValue = copy(value)
6+
return onCopy((newValue, value) => {
87
newValue[key] = nextUpdater(isNil(value) ? undefined : value[key])
9-
return newValue
8+
})
9+
}
10+
11+
const get = (key, next) => () => {
12+
const nextGetter = next()
13+
return value => nextGetter(isNil(value) ? undefined : value[key])
14+
}
15+
16+
const unset = (key, next) => () => {
17+
const nextUnsetter = next()
18+
if (nextUnsetter) {
19+
return onCopy((newValue, value) => {
20+
newValue[key] = nextUnsetter(isNil(value) ? undefined : value[key])
21+
})
1022
}
23+
return onCopy(newValue => {
24+
delete newValue[key]
25+
})
1126
}
1227

1328
export const propNav = key => next => operation => {
1429
switch (operation) {
1530
case 'update': return update(key, next(operation))
16-
case 'get': return null
17-
case 'unset': return null
31+
case 'get': return get(key, next(operation))
32+
case 'unset': return unset(key, next(operation))
1833
}
1934
throw TypeError(`Unknown navigator operation ${operation}`)
2035
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { isNil } from 'util/lang'
2+
import { onCopy } from './objectNav'
3+
4+
const update = (keys, next) => updater => {
5+
const nextUpdater = next(updater)
6+
if (keys) {
7+
return onCopy((newValue, value) => {
8+
if (isNil(value))
9+
for (const key of keys) newValue[key] = nextUpdater(undefined)
10+
else
11+
for (const key of keys) newValue[key] = nextUpdater(value[key])
12+
})
13+
}
14+
return onCopy((newValue, value) => {
15+
if (isNil(value)) return
16+
for (const key of Object.keys(value)) newValue[key] = nextUpdater(value[key])
17+
})
18+
}
19+
20+
const get = (keys, next) => () => {
21+
const nextGetter = next()
22+
if (keys)
23+
return value => isNil(value) ? undefined : keys.map(key => nextGetter(value[key]))
24+
return value => isNil(value) ? undefined : Object.keys(value).map(key => nextGetter(value[key]))
25+
}
26+
27+
const unset = (keys, next) => () => {
28+
const nextUnsetter = next()
29+
if (nextUnsetter) {
30+
if (keys) {
31+
return onCopy((newValue, value) => {
32+
if (isNil(value))
33+
for (const key of keys) newValue[key] = nextUnsetter(undefined)
34+
else
35+
for (const key of keys) newValue[key] = nextUnsetter(value[key])
36+
}, true)
37+
}
38+
return onCopy((newValue, value) => {
39+
for (const key of Object.keys(value)) newValue[key] = nextUnsetter(value[key])
40+
})
41+
}
42+
if (keys) {
43+
return onCopy(newValue => {
44+
for (const key of keys) delete newValue[key]
45+
})
46+
}
47+
return onCopy((newValue, value) => {
48+
for (const key of Object.keys(value)) delete newValue[key]
49+
})
50+
}
51+
52+
export const propsNav = keys => next => operation => {
53+
switch (operation) {
54+
case 'update': return update(keys, next(operation))
55+
case 'get': return get(keys, next(operation))
56+
case 'unset': return unset(keys, next(operation))
57+
}
58+
throw TypeError(`Unknown navigator operation ${operation}`)
59+
}

0 commit comments

Comments
 (0)