pepka 0.12.2 → 0.13.0-b1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.circleci/config.yml +19 -19
- package/.github/ISSUE_TEMPLATE/bug_report.md +38 -38
- package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
- package/CODE_OF_CONDUCT.md +76 -76
- package/CONTRIBUTING.md +3 -3
- package/LICENSE +21 -21
- package/README.md +36 -10
- package/dist/bundle.d.ts +18 -11
- package/dist/bundle.dev.js +119 -77
- package/dist/bundle.js +1 -1
- package/dist/es/quick.js +1 -0
- package/dist/es/types.js +1 -0
- package/package.json +14 -16
- package/rollup.config.js +34 -33
- package/src/common.ts +14 -14
- package/src/curry.ts +99 -53
- package/src/index.ts +6 -5
- package/src/quick.ts +98 -97
- package/src/safe.ts +392 -404
- package/src/types.ts +14 -7
- package/src/uncurry.ts +11 -0
- package/src/utils.ts +11 -11
- package/test/in-browser.ts +3 -3
- package/test/workbench.html +9 -9
- package/tsconfig.json +18 -20
- package/tslint.json +24 -24
package/src/safe.ts
CHANGED
|
@@ -1,404 +1,392 @@
|
|
|
1
|
-
import { __, curry } from './curry'
|
|
2
|
-
import { isNum, nul, isUndef, undef, isNull, isArray, isFunc, isStr, isObj } from './utils'
|
|
3
|
-
import { qmergeDeep, qreduce, qappend, qmapKeys, qmergeDeepX, qmergeDeepAdd } from './quick'
|
|
4
|
-
import { AnyFunc, Cond, AnyObject, Reducer } from './types'
|
|
5
|
-
import { type } from './common'
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
!((v===
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
s: any
|
|
37
|
-
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
s: any
|
|
44
|
-
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
)
|
|
62
|
-
export const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
export const
|
|
83
|
-
export const
|
|
84
|
-
export const
|
|
85
|
-
export const
|
|
86
|
-
export const
|
|
87
|
-
export const
|
|
88
|
-
export const
|
|
89
|
-
export const
|
|
90
|
-
export const
|
|
91
|
-
export const
|
|
92
|
-
export const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
export const
|
|
99
|
-
export const
|
|
100
|
-
export const
|
|
101
|
-
export const
|
|
102
|
-
export const
|
|
103
|
-
export const
|
|
104
|
-
export const
|
|
105
|
-
export const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
[],
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
)
|
|
150
|
-
export const lt =
|
|
151
|
-
|
|
152
|
-
)
|
|
153
|
-
export const
|
|
154
|
-
|
|
155
|
-
)
|
|
156
|
-
export const
|
|
157
|
-
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
export const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
)
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
)
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
)
|
|
188
|
-
export const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
export const
|
|
203
|
-
(
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
)
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
)
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
)
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
)
|
|
278
|
-
export const
|
|
279
|
-
(
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
)
|
|
283
|
-
)
|
|
284
|
-
export const
|
|
285
|
-
(
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
export const
|
|
291
|
-
(
|
|
292
|
-
)
|
|
293
|
-
export const
|
|
294
|
-
(
|
|
295
|
-
)
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
export const
|
|
303
|
-
(
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
)
|
|
329
|
-
export const
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
)
|
|
341
|
-
export const
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
)
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
)
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
/**
|
|
374
|
-
export const
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
)
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
export const composeAsync = (() => {
|
|
394
|
-
const pipe = async (fns: AnyFunc[], data: any, i: number): Promise<any> =>
|
|
395
|
-
~i ? await pipe(fns, await fns[i](data), --i) : data
|
|
396
|
-
return <T = any>(...fns: AnyFunc[]) =>
|
|
397
|
-
(data?: any) => pipe(fns, data, fns.length-1) as Promise<T>
|
|
398
|
-
})()
|
|
399
|
-
|
|
400
|
-
// ALIASES
|
|
401
|
-
|
|
402
|
-
export const mirror = identity
|
|
403
|
-
export const reflect = identity
|
|
404
|
-
export const echo = identity
|
|
1
|
+
import { __, curry, curry2, curry3 } from './curry'
|
|
2
|
+
import { isNum, nul, isUndef, undef, isNull, isArray, isFunc, isStr, isObj } from './utils'
|
|
3
|
+
import { qmergeDeep, qreduce, qappend, qmapKeys, qmergeDeepX, qmergeDeepAdd } from './quick'
|
|
4
|
+
import { AnyFunc, Cond, AnyObject, Reducer } from './types'
|
|
5
|
+
import { type } from './common'
|
|
6
|
+
import { F as FT } from 'ts-toolbelt'
|
|
7
|
+
// over, lensProp
|
|
8
|
+
|
|
9
|
+
export const equals = curry2((a: any, b: any) => {
|
|
10
|
+
const typea = type(a)
|
|
11
|
+
if(typea===type(b) && (typea==='Object' || typea=='Array')) {
|
|
12
|
+
if(isNull(a) || isNull(b)) {
|
|
13
|
+
return a===b
|
|
14
|
+
}
|
|
15
|
+
if(a===b) {
|
|
16
|
+
return true
|
|
17
|
+
}
|
|
18
|
+
for(const v of [a, b]) {
|
|
19
|
+
for(const k in v) {
|
|
20
|
+
if(
|
|
21
|
+
!((v===b) && (k in a)) &&
|
|
22
|
+
!((v===a) && (k in b) && equals(a[k], b[k]))
|
|
23
|
+
) {
|
|
24
|
+
return false
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return true
|
|
29
|
+
}
|
|
30
|
+
return a===b
|
|
31
|
+
})
|
|
32
|
+
export const ifElse = curry(
|
|
33
|
+
(
|
|
34
|
+
cond: (s: any) => boolean,
|
|
35
|
+
pipeYes: (s: any) => any,
|
|
36
|
+
pipeNo: (s: any) => any,
|
|
37
|
+
s: any
|
|
38
|
+
) => cond(s) ? pipeYes(s) : pipeNo(s)
|
|
39
|
+
)
|
|
40
|
+
export const when = curry3(
|
|
41
|
+
(
|
|
42
|
+
cond: (s: any) => boolean,
|
|
43
|
+
pipe: (s: any) => any,
|
|
44
|
+
s: any
|
|
45
|
+
) => ifElse(cond, pipe, identity, s)
|
|
46
|
+
)
|
|
47
|
+
export const compose: FT.Compose = (
|
|
48
|
+
(...fns: AnyFunc[]) =>
|
|
49
|
+
(s: any = __) => {
|
|
50
|
+
for(let i = length(fns)-1; i>-1; i--) {
|
|
51
|
+
s = s===__ ? fns[i]() : fns[i](s)
|
|
52
|
+
}
|
|
53
|
+
return s
|
|
54
|
+
}
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
export const bind = curry2<AnyFunc>(
|
|
58
|
+
(fn: AnyFunc, context: any) => fn.bind(context)
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
const _nth = <T=any>(i: number, data: T[]) => data[i]
|
|
62
|
+
export const nth = curry2(_nth)
|
|
63
|
+
|
|
64
|
+
export const includes = curry2(
|
|
65
|
+
(s: any, ss: any[]) => {
|
|
66
|
+
if(isStr(ss)) {
|
|
67
|
+
return ss.includes(s)
|
|
68
|
+
} else {
|
|
69
|
+
for(const a of ss) {
|
|
70
|
+
if(equals(a, s)) {
|
|
71
|
+
return true
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return false
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
export const slice = curry3(
|
|
79
|
+
(from: number, to: number|null, o: any[] | string) =>
|
|
80
|
+
o.slice(from, (isNum(to)?to:Infinity) as number)
|
|
81
|
+
)
|
|
82
|
+
export const head = nth(0)
|
|
83
|
+
export const tail = slice(1, nul)
|
|
84
|
+
export const add = curry2((n: number, m: number) => n+m)
|
|
85
|
+
export const subtract = curry2((n: number, m: number) => m-n)
|
|
86
|
+
export const flip = (fn: Function) => curry((b: any, a: any) => fn(a, b))
|
|
87
|
+
export const isNil = (s: any) => isNull(s) || isUndef(s)
|
|
88
|
+
export const length = (s: any[] | string) => s.length
|
|
89
|
+
export const always = <T=any>(s: T) => () => s
|
|
90
|
+
export const identity = (s: any) => s
|
|
91
|
+
export const trim = (s: string) => s.trim()
|
|
92
|
+
export const last = (s: any[] | string) => s[length(s)-1]
|
|
93
|
+
export const not = (o: boolean) => !o
|
|
94
|
+
export const complement = (fn: AnyFunc) => (...args: any) => {
|
|
95
|
+
const out = fn(...args)
|
|
96
|
+
return (isFunc(out) && (out as any).$args_left) ? complement(out) : not(out)
|
|
97
|
+
}
|
|
98
|
+
export const keys = (o: AnyObject | any[]) => Object.keys(o)
|
|
99
|
+
export const values = (o: AnyObject | any[]) => Object.values(o)
|
|
100
|
+
export const toPairs = (o: AnyObject | any[]) => Object.entries(o)
|
|
101
|
+
export const test = curry2((re: RegExp, s: string) => re.test(s))
|
|
102
|
+
export const tap = curry2((fn: Function, s: any) => { fn(s); return s })
|
|
103
|
+
export const append = curry2((s: any, xs: any[]) => [...xs, s])
|
|
104
|
+
export const split = curry2((s: string, xs: string) => xs.split(s))
|
|
105
|
+
export const T = always<true>(true) as (...args: any[]) => true
|
|
106
|
+
export const F = always<false>(false) as (...args: any[]) => false
|
|
107
|
+
export const sizeof = (s: any[] | string | AnyObject) => {
|
|
108
|
+
if(type(s) === 'Object') {
|
|
109
|
+
let len = 0
|
|
110
|
+
for(let _k in s as AnyObject) len++
|
|
111
|
+
return len
|
|
112
|
+
} else return length(s as any[])
|
|
113
|
+
}
|
|
114
|
+
export const range = curry2((from: number, to: number) =>
|
|
115
|
+
genBy(add(from), to-from)
|
|
116
|
+
)
|
|
117
|
+
export const uniq = (xs: any[]) => qreduce(
|
|
118
|
+
(accum: any[], x: any) =>
|
|
119
|
+
includes(x, accum) ? accum : qappend(x, accum),
|
|
120
|
+
[], xs)
|
|
121
|
+
export const intersection = curry2(
|
|
122
|
+
(xs1: any[], xs2: any[]) => xs1.filter(flip(includes)(xs2))
|
|
123
|
+
)
|
|
124
|
+
export const genBy = curry2(
|
|
125
|
+
(
|
|
126
|
+
generator: (i: number) => any,
|
|
127
|
+
length: number
|
|
128
|
+
) => [...Array(length)].map((_, i) => generator(i))
|
|
129
|
+
)
|
|
130
|
+
export const once = <Func extends AnyFunc>(fn: Func) => {
|
|
131
|
+
let done = false, cache: any
|
|
132
|
+
return (...args: Parameters<Func>) => {
|
|
133
|
+
if(done) {
|
|
134
|
+
return cache
|
|
135
|
+
} else {
|
|
136
|
+
done = true
|
|
137
|
+
return cache = fn(...args)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
export const reverse = (xs: any[]) => compose(
|
|
142
|
+
(ln: number) => reduce(
|
|
143
|
+
(nxs: any[], _: any, i: number) => qappend(xs[ln-i], nxs),
|
|
144
|
+
[], xs
|
|
145
|
+
),
|
|
146
|
+
add(-1),
|
|
147
|
+
length
|
|
148
|
+
)(xs)
|
|
149
|
+
export const gt = curry2( (a: number, b: number) => a>b )
|
|
150
|
+
export const lt = curry2( (a: number, b: number) => a<b )
|
|
151
|
+
export const gte = curry2( (a: number, b: number) => b>=a )
|
|
152
|
+
export const lte = curry2( (a: number, b: number) => b<=a )
|
|
153
|
+
export const sort = curry2((sortFn: any, xs: any[]) => xs.sort(sortFn))
|
|
154
|
+
export const find = curry2((fn: Cond, s: any[]) => s.find(fn))
|
|
155
|
+
export const findIndex = curry2((fn: Cond, s: any[]) => s.findIndex(fn))
|
|
156
|
+
export const indexOf = curry2((x: any, xs: any[]) => findIndex(equals(x), xs))
|
|
157
|
+
export const explore = (caption: string, level = 'log') => tap(
|
|
158
|
+
(v: any) => console[level](caption, v)
|
|
159
|
+
)
|
|
160
|
+
export const cond = curry2(
|
|
161
|
+
(pairs: [Cond, Function][], s: any) => {
|
|
162
|
+
for(const [cond, fn] of pairs) {
|
|
163
|
+
if(cond(s)) {
|
|
164
|
+
return fn(s)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
)
|
|
169
|
+
export const assoc = curry3(
|
|
170
|
+
(prop: string, v: any, obj: AnyObject) => ({
|
|
171
|
+
...obj,
|
|
172
|
+
[prop]: v
|
|
173
|
+
})
|
|
174
|
+
)
|
|
175
|
+
export const assocPath = curry3(
|
|
176
|
+
(_path: string[], v: any, o: AnyObject) => compose(
|
|
177
|
+
(first: string) => assoc(
|
|
178
|
+
first,
|
|
179
|
+
length(_path)<2
|
|
180
|
+
? v
|
|
181
|
+
: assocPath(slice(1, null, _path), v, isObj(o[first]) ? o[first] : {}),
|
|
182
|
+
o
|
|
183
|
+
),
|
|
184
|
+
head
|
|
185
|
+
)(_path)
|
|
186
|
+
)
|
|
187
|
+
export const all = curry2((pred: Cond, xs: any[]) => xs.every(pred))
|
|
188
|
+
export const any = curry2((pred: Cond, xs: any[]) => xs.some(pred))
|
|
189
|
+
export const allPass = curry2(
|
|
190
|
+
(preds: Cond[], x: any) => preds.every((pred) => pred(x))
|
|
191
|
+
)
|
|
192
|
+
export const anyPass = curry2(
|
|
193
|
+
(preds: Cond[], x: any) => preds.some((pred) => pred(x))
|
|
194
|
+
)
|
|
195
|
+
export const prop = curry2( (key: string, o: AnyObject) => o[key] )
|
|
196
|
+
export const propEq = curry3(
|
|
197
|
+
(key: string, value: any, o: AnyObject) => equals(o[key], value)
|
|
198
|
+
)
|
|
199
|
+
export const propsEq = curry3(
|
|
200
|
+
(key: string, o1: any, o2: AnyObject) => equals(o1[key], o2[key])
|
|
201
|
+
)
|
|
202
|
+
export const pathOr = curry3(
|
|
203
|
+
(_default: any, path: string[], o: any) =>
|
|
204
|
+
ifElse(length,
|
|
205
|
+
() => isNil(o)
|
|
206
|
+
? _default
|
|
207
|
+
: compose(
|
|
208
|
+
ifElse(isNil,
|
|
209
|
+
always(_default),
|
|
210
|
+
(o: any) => pathOr(_default, slice(1, nul, path), o)
|
|
211
|
+
),
|
|
212
|
+
flip(prop)(o),
|
|
213
|
+
head
|
|
214
|
+
)(path),
|
|
215
|
+
always(o),
|
|
216
|
+
path)
|
|
217
|
+
)
|
|
218
|
+
export const path = pathOr(undef)
|
|
219
|
+
export const pathEq = curry3(
|
|
220
|
+
(_path: string[], value: any, o: AnyObject) => equals(path(_path, o), value)
|
|
221
|
+
)
|
|
222
|
+
export const pathsEq = curry3(
|
|
223
|
+
(_path: string[], o1: AnyObject, o2: AnyObject) =>
|
|
224
|
+
equals(path(_path, o1), path(_path, o2))
|
|
225
|
+
)
|
|
226
|
+
const typed_arr_re = /^(.*?)(8|16|32|64)(Clamped)?Array$/
|
|
227
|
+
export const clone = (s: any, shallow = false) => {
|
|
228
|
+
const t = type(s)
|
|
229
|
+
switch(t) {
|
|
230
|
+
case 'Null': return s
|
|
231
|
+
case 'Array': return shallow ? [...s] : map(clone, s)
|
|
232
|
+
case 'Object':
|
|
233
|
+
if(shallow) return {...s}
|
|
234
|
+
const out = {}
|
|
235
|
+
for(let k in s) {
|
|
236
|
+
out[k] = clone(s[k])
|
|
237
|
+
}
|
|
238
|
+
return out
|
|
239
|
+
case 'String': case 'Number':
|
|
240
|
+
case 'Boolean': case 'Symbol':
|
|
241
|
+
return s
|
|
242
|
+
default:
|
|
243
|
+
return typed_arr_re.test(t) ? s.constructor.from(s) : s
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
export const cloneShallow = (s: any) => clone(s, true)
|
|
247
|
+
|
|
248
|
+
export const reduce = curry3(
|
|
249
|
+
(fn: Reducer, accum: any, arr: any[]) =>
|
|
250
|
+
qreduce(fn, clone(accum), arr)
|
|
251
|
+
)
|
|
252
|
+
export const pickBy = curry2(
|
|
253
|
+
(cond: Cond, o: AnyObject) => filter(cond, o)
|
|
254
|
+
)
|
|
255
|
+
export const pick = curry2(
|
|
256
|
+
(props: string[], o: AnyObject) => {
|
|
257
|
+
const out = {}
|
|
258
|
+
for(const p of props) {
|
|
259
|
+
if(p in o) {
|
|
260
|
+
out[p] = o[p]
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return out
|
|
264
|
+
}
|
|
265
|
+
)
|
|
266
|
+
export const omit = curry2(
|
|
267
|
+
(props: string[], o: AnyObject) => filter(
|
|
268
|
+
(_: any, k: string) => !includes(k, props),
|
|
269
|
+
o
|
|
270
|
+
)
|
|
271
|
+
)
|
|
272
|
+
export const fromPairs = (pairs: [string, any][]) => reduce(
|
|
273
|
+
(o: AnyObject, pair: [string, any]) => assoc(...pair, o),
|
|
274
|
+
{}, pairs
|
|
275
|
+
)
|
|
276
|
+
type Concat = ((a: string, b: string) => string)
|
|
277
|
+
| ((a: any[], b: any[]) => any[])
|
|
278
|
+
export const concat = curry2(
|
|
279
|
+
((a, b) => a.concat(b)) as Concat
|
|
280
|
+
)
|
|
281
|
+
export const join = curry2(
|
|
282
|
+
(delimeter: string, arr: string[]) => arr.join(delimeter)
|
|
283
|
+
)
|
|
284
|
+
export const map = curry2(
|
|
285
|
+
(pipe: (s: any) => any, arr: any[]) => arr.map(pipe)
|
|
286
|
+
)
|
|
287
|
+
export const forEach = curry2(
|
|
288
|
+
(pipe: (s: any) => any, arr: any[]) => arr.forEach(pipe)
|
|
289
|
+
)
|
|
290
|
+
export const both = curry3(
|
|
291
|
+
(cond1: Cond, cond2: Cond, s: any) => cond2(s) && cond1(s)
|
|
292
|
+
)
|
|
293
|
+
export const isEmpty = (s: any) => {
|
|
294
|
+
switch(type(s)) {
|
|
295
|
+
case 'String': case 'Array': return length(s)==0
|
|
296
|
+
case 'Object':
|
|
297
|
+
for(const _k in s) return false
|
|
298
|
+
return true
|
|
299
|
+
default: return null
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
export const empty = (s: any) => {
|
|
303
|
+
switch(type(s)) {
|
|
304
|
+
case 'String': return ''
|
|
305
|
+
case 'Object': return {}
|
|
306
|
+
case 'Array': return []
|
|
307
|
+
default: return undef
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
export const replace = curry3(
|
|
311
|
+
(
|
|
312
|
+
a: string | RegExp,
|
|
313
|
+
b: string,
|
|
314
|
+
where: string
|
|
315
|
+
) => where.replace(a, b)
|
|
316
|
+
)
|
|
317
|
+
export const filter = curry2(
|
|
318
|
+
(
|
|
319
|
+
cond: (v: any, k: string | number) => boolean,
|
|
320
|
+
data: any[] | AnyObject
|
|
321
|
+
) => isArray(data)
|
|
322
|
+
? data.filter(cond)
|
|
323
|
+
: compose(
|
|
324
|
+
fromPairs,
|
|
325
|
+
filter(([k, v]) => cond(v, k)),
|
|
326
|
+
toPairs
|
|
327
|
+
)(data)
|
|
328
|
+
)
|
|
329
|
+
export const memoize = (fn: Function) => {
|
|
330
|
+
let cache: any
|
|
331
|
+
let cached = false
|
|
332
|
+
return () => cached ? cache : (cached = true, cache = fn())
|
|
333
|
+
}
|
|
334
|
+
export const mergeShallow = curry2(
|
|
335
|
+
(o1: AnyObject, o2: AnyObject): AnyObject =>
|
|
336
|
+
Object.assign({}, o1, o2)
|
|
337
|
+
)
|
|
338
|
+
export const mergeDeep = curry2(
|
|
339
|
+
(a: AnyObject, b: AnyObject) => qmergeDeep(clone(a), clone(b))
|
|
340
|
+
)
|
|
341
|
+
export const mergeDeepX = curry2(
|
|
342
|
+
(a: AnyObject, b: AnyObject) => qmergeDeepX(clone(a), clone(b))
|
|
343
|
+
)
|
|
344
|
+
export const mergeDeepAdd = curry2(
|
|
345
|
+
(a: AnyObject, b: AnyObject) => qmergeDeepAdd(clone(a), clone(b))
|
|
346
|
+
)
|
|
347
|
+
export const overProp = curry3(
|
|
348
|
+
(prop: string, pipe: AnyFunc, data: any) =>
|
|
349
|
+
assoc(prop, pipe(data[prop]), data)
|
|
350
|
+
)
|
|
351
|
+
/** mapKeys({ a: 'b' }, { a: 44 }) -> { b: 44 } */
|
|
352
|
+
export const mapKeys = curry2(
|
|
353
|
+
(
|
|
354
|
+
keyMap: {[oldKey: string]: string},
|
|
355
|
+
o: AnyObject
|
|
356
|
+
) => qmapKeys(keyMap, Object.assign({}, o))
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
// ASYNCS
|
|
360
|
+
|
|
361
|
+
/** One promise waits for another. */
|
|
362
|
+
export const forEachSerial = (() => {
|
|
363
|
+
const pipe = async (fn: AnyFunc, items: any[], i: number) => {
|
|
364
|
+
if(i<items.length) {
|
|
365
|
+
await fn(items[i])
|
|
366
|
+
await pipe(fn, items, ++i)
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return curry2(
|
|
370
|
+
(fn: AnyFunc, items: any[]) => pipe(fn, items, 0)
|
|
371
|
+
)
|
|
372
|
+
})()
|
|
373
|
+
/** Promise.all wrapper for functional pipelining. */
|
|
374
|
+
export const waitAll = (promises: Promise<any>[]) => Promise.all(promises)
|
|
375
|
+
export const waitTap = curry2(async (fn: Function, s: any) => { await fn(s); return s })
|
|
376
|
+
/** Waits for all promises mapped by the fn. */
|
|
377
|
+
export const forEachAsync = curry2(
|
|
378
|
+
(fn: (item: any) => Promise<any>, items: any[]) =>
|
|
379
|
+
Promise.all(items.map(fn))
|
|
380
|
+
)
|
|
381
|
+
/** The same as compose, but waits for promises in chains and returns a Promise. */
|
|
382
|
+
export const composeAsync = (() => {
|
|
383
|
+
const pipe = async (fns: AnyFunc[], data: any, i: number): Promise<any> =>
|
|
384
|
+
~i ? await pipe(fns, await fns[i](data), --i) : data
|
|
385
|
+
return <T = any>(...fns: AnyFunc[]) =>
|
|
386
|
+
(data?: any) => pipe(fns, data, fns.length-1) as Promise<T>
|
|
387
|
+
})() as FT.Compose<'async'>
|
|
388
|
+
|
|
389
|
+
// ALIASES
|
|
390
|
+
export const mirror = identity
|
|
391
|
+
export const reflect = identity
|
|
392
|
+
export const echo = identity
|