Skip to content

Commit b473f4a

Browse files
authored
Merge pull request #5 from mfix22/readability
Better Readability
2 parents c6184a5 + 23c5187 commit b473f4a

3 files changed

Lines changed: 74 additions & 179 deletions

File tree

index.js

Lines changed: 74 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
const { Either, either, left, fromNullable } = require('./src/either')
2-
const { List } = require('./src/list')
3-
4-
const id = _ => _
5-
const always = a => () => a
1+
function id(_) {
2+
return _
3+
}
64

75
const DEFAULTS = {
86
types: {},
@@ -12,46 +10,35 @@ const DEFAULTS = {
1210
postFilters: []
1311
}
1412

15-
/* --- Functional Utilities --- */
16-
const map = fn => x => x.map(fn)
17-
const join = m => m.join()
18-
// const chain = fn => m => m.chain(fn)
1913
const compose = (...fns) => (res, ...args) =>
2014
fns.reduceRight((accum, next) => next(accum, ...args), res)
2115

22-
const reduce = fn => zero => xs => xs.reduce(fn, zero)
23-
/* ---------------------------- */
24-
25-
const split = d => s => s.split(d)
26-
27-
const createRootObj = compose(
28-
either(Object.create, Array),
29-
n => (isNaN(n) ? left(null) : Either.of(n)),
30-
Number
31-
)
32-
33-
const handleArrays = _ => (Array.isArray(_) ? List.of(_) : Either.of(_))
34-
35-
const normalizeField = delimiter => m =>
36-
fromNullable(m)
37-
.map(m => m.indexOf(delimiter) > -1)
38-
.map(b => (b ? m : m + delimiter + m))
39-
.map(split(delimiter))
40-
41-
const getMapSpec = delimiter => mapping =>
42-
fromNullable(mapping)
43-
.map(Array.isArray)
44-
.map(b => (b ? Either.of(mapping) : left(mapping)))
45-
.map(
46-
either(
47-
compose(join, normalizeField(delimiter)),
48-
reduce((spec, field) =>
49-
normalizeField(delimiter)(field)
50-
.map(([source, target]) => [[...spec[0], source], target])
51-
.join()
52-
)([[], null])
53-
)
16+
const createRootObj = n =>
17+
isNaN(n) ? Object.create(null) : new Array(Number(n))
18+
19+
const normalizeField = delimiter => m => {
20+
if (m.indexOf(delimiter) > -1) {
21+
return m.split(delimiter)
22+
}
23+
24+
return [m, m]
25+
}
26+
27+
const getMapSpec = delimiter => {
28+
const normalizer = normalizeField(delimiter)
29+
30+
return mapping => {
31+
if (!Array.isArray(mapping)) return normalizer(mapping)
32+
33+
return mapping.reduce(
34+
(spec, field) => {
35+
const [source, target] = normalizer(field)
36+
return [[...spec[0], source], target]
37+
},
38+
[[], null]
5439
)
40+
}
41+
}
5542

5643
const normalizeMapping = mapping =>
5744
typeof mapping === 'string' ? { field: mapping } : mapping
@@ -63,67 +50,59 @@ const getMappingFilter = (type, types) => {
6350
return id
6451
}
6552

66-
const getKey = reduce((accum, k) => (accum ? accum[k] : undefined))
67-
68-
const get = (key, delimiter = DEFAULTS.objDelimiter) => obj =>
69-
compose(
70-
either(always(obj), getKey(obj)),
71-
map(split(delimiter)),
72-
fromNullable
73-
)(key)
74-
75-
const setKey = value =>
76-
reduce((accum, key, i, array) => {
77-
if (i === array.length - 1) accum[key] = value
78-
else if (!accum[key]) accum[key] = createRootObj(array[i + 1])
79-
return accum[key]
80-
})
81-
82-
const assign = (key, delimiter = DEFAULTS.objDelimiter) => (obj, value) =>
83-
compose(
84-
always(obj),
85-
either(id, setKey(value)(obj)),
86-
map(split(delimiter)),
87-
fromNullable
88-
)(key)
53+
const get = (key, delimiter = DEFAULTS.objDelimiter) => {
54+
if (key == null) return id
55+
56+
const spec = key.split(delimiter)
57+
58+
return obj => spec.reduce((a, k) => (a ? a[k] : undefined), obj)
59+
}
60+
61+
const assign = (key, delimiter = DEFAULTS.objDelimiter) => {
62+
if (key == null) return id
63+
64+
const spec = key.split(delimiter)
65+
return (obj, value) => {
66+
spec.reduce((accum, key, i, array) => {
67+
if (i === array.length - 1) accum[key] = value
68+
else if (!accum[key]) accum[key] = createRootObj(array[i + 1])
69+
return accum[key]
70+
}, obj)
71+
return obj
72+
}
73+
}
8974

9075
class Mapper {
9176
constructor(options) {
9277
this.config = Object.assign({}, DEFAULTS, options)
78+
this.getMapSpec = getMapSpec(this.config.mapDelimiter)
79+
80+
this.mapFn = compose(
81+
...this.config.postFilters,
82+
(v, m, con, c, a) =>
83+
getMappingFilter(m.type, this.config.types)(v, m, con, c, a),
84+
...this.config.preFilters
85+
)
9386
}
9487

9588
map(mappings, curr, next = Object.create(null)) {
96-
return mappings.map(normalizeMapping).reduce(
97-
(accum, mapping) =>
98-
fromNullable(mapping.field)
99-
.chain(getMapSpec(this.config.mapDelimiter))
100-
.chain(([sourceField, targetField]) =>
101-
Either.of(sourceField)
102-
.map(handleArrays)
103-
.map(map(field => get(field, this.config.objDelimiter)(curr)))
104-
.map(join)
105-
.map(_ =>
106-
compose(
107-
/* End user-land transforms */
108-
...this.config.postFilters,
109-
getMappingFilter(mapping.type, this.config.types),
110-
...this.config.preFilters
111-
/* Begin user-land transforms */
112-
)(_, mapping, this.config, curr, accum)
113-
)
114-
.map(fromNullable)
115-
.chain(
116-
either(
117-
always(accum),
118-
assign(targetField, this.config.objDelimiter).bind(
119-
this,
120-
accum
121-
)
122-
)
123-
)
124-
),
125-
next
126-
)
89+
return mappings.map(normalizeMapping).reduce((accum, mapping) => {
90+
const [sourceField, targetField] = this.getMapSpec(mapping.field)
91+
92+
const getter = field => get(field, this.config.objDelimiter)(curr)
93+
94+
let value = Array.isArray(sourceField)
95+
? sourceField.map(getter)
96+
: getter(sourceField)
97+
98+
value = this.mapFn(value, mapping, this.config, curr, accum)
99+
100+
if (value === undefined) {
101+
return accum
102+
}
103+
104+
return assign(targetField, this.config.objDelimiter)(accum, value)
105+
}, next)
127106
}
128107
}
129108

src/either.js

Lines changed: 0 additions & 58 deletions
This file was deleted.

src/list.js

Lines changed: 0 additions & 26 deletions
This file was deleted.

0 commit comments

Comments
 (0)