UNPKG

4.5 kBJavaScriptView Raw
1'use strict'
2
3const {TokenTypeData} = require('./lang');
4const {chain, or, and} = require('./frontend');
5
6function getIn(obj, path) {
7 const pathGetters = [obj].concat(path.map((_part, index) => path.slice(0, index + 1).reduce((acc, part) => acc.get(part), obj)))
8 return and(...pathGetters);
9}
10
11function has(obj, key) {
12 return obj.get(key).isUndefined().not()
13}
14
15function assignIn(obj, args) {
16 return chain([
17 obj,
18 ...args
19 ]).assign();
20}
21
22function reduce(collection, predicate, initialValue) {
23 return collection.size().eq(0).ternary(
24 initialValue,
25 collection.recursiveMap((loop, value, index) =>
26 predicate(index.eq(0).ternary(
27 initialValue, index.minus(1).recur(loop)), value, index))
28 .get(collection.size().minus(1)))
29}
30
31function concat(a, b) {
32 return chain([a, b]).flatten()
33}
34
35function uniq(arr) {
36 return arr
37 .keyBy(x => x)
38 .keys()
39}
40
41function intersection(a, b) {
42 const array = a.uniq().concat(b.uniq())
43
44 return array
45 .keyBy((_, idx) => idx)
46 .groupBy(val => val)
47 .filterBy(val => val.keys().size().gt(1))
48 .keys()
49}
50
51function find(collection, predicate, givenCtx) {
52 return collection.values().filter((val, key, ctx) => predicate(val, key, ctx), givenCtx || null).get(0)
53}
54
55function join(arr, separator) {
56 return reduce(arr, (acc, value, index) => index.eq(0).ternary(acc.plus(value), acc.plus(separator).plus(value)), '')
57}
58
59function append(arr, value) {
60 return chain([arr, [value]]).flatten()
61 //return arr.size().plus(1).range().map(v => v.lt(arr.size()).ternary(arr.get(v), value))
62}
63
64function simpleSet(base, key, value) {
65 return chain([base, {[key]: value}]).assign()
66}
67
68function setIn(obj, path, value) {
69 if (!Array.isArray(path) || path.length === 0) {
70 throw new Error('only set with array paths');
71 }
72 path.forEach(val => {
73 if (typeof val !== 'string') {
74 throw new Error('all path parts in set should be strings');
75 }
76 })
77
78
79 const currentValues = path.map((part, index) =>
80 or(getIn(obj, path.slice(0, index)), chain({}))
81 )
82
83 return path.reduceRight((acc, part, index) => simpleSet(currentValues[index], part, acc), value)
84}
85
86function head(array) {
87 return array.get(0)
88}
89
90function reverse(array) {
91 return array.map((item, index) => array.get(array.size().minus(index.plus(1))))
92}
93
94function includesValue(collection, val) {
95 if (typeof val === 'boolean' || typeof val === 'number' || typeof val === 'string') {
96 return collection.anyValues((item, key, ctx) => item.eq(val))
97 }
98 return collection.anyValues((item, key, ctx) => item.eq(ctx), val)
99}
100
101function includes(collection, val) {
102 if (typeof val === 'boolean' || typeof val === 'number' || typeof val === 'string') {
103 return collection.any((item, key, ctx) => item.eq(val))
104 }
105 return collection.any((item, key, ctx) => item.eq(ctx), val)
106}
107
108function findIndex(collection, predicate) {
109 const filtered = collection.map((item, index) => predicate(item, index).ternary(index, chain(-1))).filter(item => item.gt(-1));
110 return filtered.size().ternary(
111 filtered.get(0),
112 -1
113 );
114}
115
116function pick(obj, arr) {
117 const projection = Object.assign({}, ...arr.map(key => ({[key]: obj.get(key)})));
118 return chain(projection).filterBy(item => item.isUndefined().not());
119}
120
121function every(array, predicate) {
122 return array.any((val, key, context) => predicate(val, key, context).not()).not()
123}
124
125function compact(array) {
126 return array.filter(value => value)
127}
128
129function switchCase(obj, caseTuples, defaultCase) {
130 return (caseTuples || []).reduce(
131 (result, caseTuple) => obj.eq(caseTuple[0]).ternary(
132 caseTuple[1],
133 result
134 ),
135 defaultCase || chain(null)
136 )
137}
138
139function conditionalTrace(obj, condition) {
140 return condition.ternary(
141 obj.trace(),
142 obj
143 )
144}
145
146function conditionalBreakpoint(obj, condition) {
147 return condition.ternary(
148 obj.breakpoint(),
149 obj
150 )
151}
152
153function tapTrace(obj, tapFn) {
154 return or(tapFn(obj).trace().ternary(chain(false), chain(false)), obj)
155}
156
157const sugarApi = {
158 getIn,
159 includes,
160 assignIn,
161 reduce,
162 uniq,
163 intersection,
164 concat,
165 find,
166 join,
167 append,
168 setIn,
169 pick,
170 findIndex,
171 includesValue,
172 has,
173 reverse,
174 head,
175 every,
176 simpleSet,
177 compact,
178 switch: switchCase,
179 conditionalTrace,
180 conditionalBreakpoint,
181 tapTrace
182};
183
184Object.keys(sugarApi).forEach(key => {
185 if (TokenTypeData[key]) {
186 throw new Error(`There is a builtin token with this sugar name ${key}`);
187 }
188});
189
190module.exports = sugarApi;