pepka 1.4.3 → 1.6.0
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/dist/bundle.cjs +45 -27
- package/dist/bundle.d.ts +100 -37
- package/dist/bundle.mjs +45 -28
- package/package.json +2 -2
- package/src/common.ts +2 -1
- package/src/curry.ts +2 -1
- package/src/internal_types.ts +7 -0
- package/src/quick.ts +12 -9
- package/src/safe.ts +80 -44
- package/src/strings.ts +2 -2
- package/src/types.ts +3 -7
package/dist/bundle.cjs
CHANGED
|
@@ -136,7 +136,6 @@ const qstartsWithWith = (comparator) => curry2((start, s) => {
|
|
|
136
136
|
return true;
|
|
137
137
|
});
|
|
138
138
|
|
|
139
|
-
// TODO: qoverProp, qover array ?
|
|
140
139
|
/** Then next fns seem to be excess due to their safe ver performance should be the same or better:
|
|
141
140
|
* qflat, qpick
|
|
142
141
|
*/
|
|
@@ -144,7 +143,7 @@ const qappend = curry2((s, xs) => { xs.push(s); return xs; });
|
|
|
144
143
|
const qassoc = curry3((prop, v, obj) => { obj[prop] = v; return obj; });
|
|
145
144
|
const qreduce = curry3((fn, accum, arr) => arr.reduce(fn, accum));
|
|
146
145
|
// strategy is for arrays: 1->clean, 2->merge, 3->push.
|
|
147
|
-
const mergeDeep$1 =
|
|
146
|
+
const mergeDeep$1 = (strategy) => curry2((o1, o2) => {
|
|
148
147
|
for (let k in o2) {
|
|
149
148
|
switch (type(o2[k])) {
|
|
150
149
|
case 'Array':
|
|
@@ -154,7 +153,7 @@ const mergeDeep$1 = curry3((strategy, o1, o2) => {
|
|
|
154
153
|
const o1k = o1[k], o2k = o2[k];
|
|
155
154
|
for (const i in o2k)
|
|
156
155
|
if (o1k[i])
|
|
157
|
-
mergeDeep$1(strategy
|
|
156
|
+
mergeDeep$1(strategy)(o1k[i], o2k[i]);
|
|
158
157
|
else
|
|
159
158
|
o1k[i] = o2k[i];
|
|
160
159
|
break;
|
|
@@ -165,7 +164,7 @@ const mergeDeep$1 = curry3((strategy, o1, o2) => {
|
|
|
165
164
|
break;
|
|
166
165
|
case 'Object':
|
|
167
166
|
if (type(o1[k]) === 'Object') {
|
|
168
|
-
mergeDeep$1(strategy
|
|
167
|
+
mergeDeep$1(strategy)(o1[k], o2[k]);
|
|
169
168
|
break;
|
|
170
169
|
}
|
|
171
170
|
default:
|
|
@@ -195,7 +194,7 @@ const qmapKeys = curry2((keyMap, o) => {
|
|
|
195
194
|
return o;
|
|
196
195
|
});
|
|
197
196
|
const qmap = curry2((pipe, arr) => {
|
|
198
|
-
for (
|
|
197
|
+
for (const i in arr)
|
|
199
198
|
arr[i] = pipe(arr[i], +i, arr);
|
|
200
199
|
return arr;
|
|
201
200
|
});
|
|
@@ -247,6 +246,8 @@ const qreverse = (arr) => arr.reverse();
|
|
|
247
246
|
const qomit = curry2((props, o) => qfilter((_, k) => !includes(k, props), o));
|
|
248
247
|
/** @param start string | any[] @param s string | any[] */
|
|
249
248
|
const qstartsWith = qstartsWithWith(eq);
|
|
249
|
+
/** @param prop string @param pipe(data[prop]) @param data any @returns data with prop over pipe. */
|
|
250
|
+
const qoverProp = curry3((prop, pipe, data) => qassoc(prop, pipe(data[prop]), data));
|
|
250
251
|
|
|
251
252
|
// TODO: possibly introduce a second argument limiting unfolding.
|
|
252
253
|
const uncurry = (fn) => (...args) => qreduce(((fn, arg) => fn ? fn(arg) : fn), fn, args);
|
|
@@ -273,10 +274,14 @@ const bind = curry2((fn, context) => fn.bind(context));
|
|
|
273
274
|
const nth = curry2((i, data) => data[i]);
|
|
274
275
|
const slice = curry3((from, to, o) => o.slice(from, (isNum(to) ? to : inf)));
|
|
275
276
|
const flip = (fn) => curry2((b, a) => fn(a, b));
|
|
276
|
-
/** @returns first element of an array. */
|
|
277
|
+
/** @returns first element of an array or a string. */
|
|
277
278
|
const head = nth(0);
|
|
278
|
-
/** @returns last element of an array. */
|
|
279
|
+
/** @returns last element of an array or a string. */
|
|
279
280
|
const tail = slice(1, inf);
|
|
281
|
+
/** Returns last element of an array, readonly array or a string.
|
|
282
|
+
* @param s Array to extract that element.
|
|
283
|
+
* @returns undefined if s is empty or last element. */
|
|
284
|
+
const last = (s) => s[length(s) - 1];
|
|
280
285
|
/** @param a @param b @returns a+b */
|
|
281
286
|
const add = curry2((a, b) => a + b);
|
|
282
287
|
/** @param a @param b @returns b-a */
|
|
@@ -295,11 +300,10 @@ const sort = curry2((sortFn, xs) => xs.sort(sortFn));
|
|
|
295
300
|
const find = curry2((fn, s) => s.find(fn));
|
|
296
301
|
const findIndex = curry2((fn, s) => s.findIndex(fn));
|
|
297
302
|
const indexOf = curry2((x, xs) => findIndex(equals(x), xs));
|
|
298
|
-
const divide = curry2((
|
|
303
|
+
const divide = curry2((a, b) => b / a);
|
|
299
304
|
const always = (s) => () => s;
|
|
300
305
|
const identity = (s) => s;
|
|
301
306
|
const trim = (s) => s.trim();
|
|
302
|
-
const last = (s) => s[length(s) - 1];
|
|
303
307
|
/** @param start string | any[] @param s string | any[] */
|
|
304
308
|
const startsWith = qstartsWithWith((x, y) => equals(x, y));
|
|
305
309
|
const not = (x) => !x;
|
|
@@ -343,14 +347,13 @@ const range = curry2((from, to) => genBy(add(from), to - from));
|
|
|
343
347
|
const uniq = (xs) => qreduce((accum, x) => find(equals(x), accum) ? accum : qappend(x, accum), [], xs);
|
|
344
348
|
const intersection = curry2((xs1, xs2) => xs1.filter(flip(includes)(xs2)));
|
|
345
349
|
const diff = curry2((_xs1, _xs2) => {
|
|
346
|
-
// BUG: if _xs1 is empty, results in [undefined, ...]
|
|
347
350
|
let len1 = length(_xs1);
|
|
348
|
-
let len2 = length(_xs2);
|
|
349
|
-
const xs1 = len1 > len2 ? _xs1 : _xs2;
|
|
350
|
-
const xs2 = len1 > len2 ? _xs2 : _xs1;
|
|
351
|
-
if (len1
|
|
351
|
+
let len2 = length(_xs2);
|
|
352
|
+
const xs1 = len1 > len2 ? _xs1 : _xs2;
|
|
353
|
+
const xs2 = len1 > len2 ? _xs2 : _xs1;
|
|
354
|
+
if (len1 < len2)
|
|
352
355
|
[len1, len2] = [len2, len1];
|
|
353
|
-
const xset2 = new Set(xs2);
|
|
356
|
+
const xset2 = new Set(xs2);
|
|
354
357
|
const common = new Set();
|
|
355
358
|
const out = [];
|
|
356
359
|
let i;
|
|
@@ -378,7 +381,10 @@ const once = (fn) => {
|
|
|
378
381
|
return cache = fn(...args);
|
|
379
382
|
};
|
|
380
383
|
};
|
|
381
|
-
const reverse = (xs) =>
|
|
384
|
+
const reverse = (xs) => {
|
|
385
|
+
const ln = length(xs) - 1;
|
|
386
|
+
return map((_, i) => xs[ln - i], xs);
|
|
387
|
+
};
|
|
382
388
|
const explore = (caption, level = 'log') => tap((v) => console[level](caption, v));
|
|
383
389
|
const cond = curry2((pairs, s) => {
|
|
384
390
|
for (const [cond, fn] of pairs)
|
|
@@ -444,7 +450,6 @@ const freezeShallow = (o) => qfreezeShallow(clone(o));
|
|
|
444
450
|
* @param array T2[]
|
|
445
451
|
*/
|
|
446
452
|
const reduce = curry3((reducer, accum, arr) => qreduce(reducer, clone(accum), arr));
|
|
447
|
-
const pickBy = curry2((cond, o) => filter(cond, o));
|
|
448
453
|
const pick = curry2((props, o) => {
|
|
449
454
|
const out = {};
|
|
450
455
|
for (const p of props)
|
|
@@ -452,6 +457,7 @@ const pick = curry2((props, o) => {
|
|
|
452
457
|
out[p] = o[p];
|
|
453
458
|
return out;
|
|
454
459
|
});
|
|
460
|
+
const pickBy = curry2((cond, o) => compose(flip(pick)(o), qfilter(cond), keys)(o));
|
|
455
461
|
const omit = curry2((props, o) => filter((_, k) => !includes(k, props), o));
|
|
456
462
|
const fromPairs = (pairs) => Object.fromEntries(pairs);
|
|
457
463
|
const concat = curry2(((a, b) => b.concat(a)));
|
|
@@ -486,15 +492,26 @@ const replace = curry3((a, b, where
|
|
|
486
492
|
const filter = curry2((cond, data) => isArray(data)
|
|
487
493
|
? data.filter(cond)
|
|
488
494
|
: qfilter(cond, { ...data }));
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
495
|
+
/** Saves result of a function with given key and avoids calling it again.
|
|
496
|
+
* @param {(...args: Args) string} keyGen that takes the same args and returns a key for the cache.
|
|
497
|
+
* @param {(...args: Args) any} fn to be cached.
|
|
498
|
+
*/
|
|
499
|
+
const memoize = curry2((keyGen, fn) => {
|
|
500
|
+
const cache = {};
|
|
501
|
+
return (...args) => {
|
|
502
|
+
const key = keyGen(...args);
|
|
503
|
+
if (key in cache)
|
|
504
|
+
return cache[key];
|
|
505
|
+
const res = fn(...args);
|
|
506
|
+
cache[key] = res;
|
|
507
|
+
return res;
|
|
508
|
+
};
|
|
509
|
+
});
|
|
494
510
|
const mergeShallow = curry2((o1, o2) => Object.assign({}, o1, o2));
|
|
495
|
-
const mergeDeep = curry2((a, b) => qmergeDeep(clone(a),
|
|
496
|
-
const mergeDeepX = curry2((a, b) => qmergeDeepX(clone(a),
|
|
497
|
-
const mergeDeepAdd = curry2((a, b) => qmergeDeepAdd(clone(a),
|
|
511
|
+
const mergeDeep = curry2((a, b) => qmergeDeep(clone(a), b));
|
|
512
|
+
const mergeDeepX = curry2((a, b) => qmergeDeepX(clone(a), b));
|
|
513
|
+
const mergeDeepAdd = curry2((a, b) => qmergeDeepAdd(clone(a), b));
|
|
514
|
+
/** @param prop string @param pipe(data[prop]) @param data any @returns data with prop over pipe. */
|
|
498
515
|
const overProp = curry3((prop, pipe, data) => assoc(prop, pipe(data[prop]), data));
|
|
499
516
|
/** mapKeys({ a: 'b' }, { a: 44 }) -> { b: 44 } */
|
|
500
517
|
const mapKeys = curry2((keyMap, o) => qmapKeys(keyMap, Object.assign({}, o)));
|
|
@@ -519,12 +536,12 @@ const some = any;
|
|
|
519
536
|
const ecran = '\\';
|
|
520
537
|
// TODO: make it splicy, not accumulatie by symbols.
|
|
521
538
|
/** Supports ecrans: '\\{"json": {yes} \\}'
|
|
522
|
-
@returns
|
|
539
|
+
@returns getTmpl('one{meme}two')({meme: 42}) -> one42two */
|
|
523
540
|
const getTmpl = (tmpl) => {
|
|
524
541
|
const parts = [];
|
|
525
542
|
const keymap = [];
|
|
526
543
|
const len = tmpl.length;
|
|
527
|
-
let i = 0, s, ln, start = 0, open = false, hasEcran =
|
|
544
|
+
let i = 0, s, ln, start = 0, open = false, hasEcran = false, hasEcranNext = false, nextChar;
|
|
528
545
|
for (i = 0; i < len; i++) {
|
|
529
546
|
s = tmpl[i];
|
|
530
547
|
switch (s) {
|
|
@@ -703,6 +720,7 @@ exports.qmergeDeepAdd = qmergeDeepAdd;
|
|
|
703
720
|
exports.qmergeDeepX = qmergeDeepX;
|
|
704
721
|
exports.qmergeShallow = qmergeShallow;
|
|
705
722
|
exports.qomit = qomit;
|
|
723
|
+
exports.qoverProp = qoverProp;
|
|
706
724
|
exports.qprepend = qprepend;
|
|
707
725
|
exports.qreduce = qreduce;
|
|
708
726
|
exports.qreverse = qreverse;
|
package/dist/bundle.d.ts
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
// Generated by dts-bundle-generator v9.5.1
|
|
2
2
|
|
|
3
|
+
type AnyArgs = any[];
|
|
4
|
+
type AnyArray<T = any> = T[] | readonly T[];
|
|
5
|
+
type Split<S extends string> = S extends `${infer U}${infer V}` ? [
|
|
6
|
+
U,
|
|
7
|
+
...Split<V>
|
|
8
|
+
] : [
|
|
9
|
+
];
|
|
10
|
+
type IndexesOfArray<A> = Exclude<keyof A, keyof [
|
|
11
|
+
]>;
|
|
3
12
|
export type Cond = (x1?: any, x2?: any, x3?: any) => boolean;
|
|
4
13
|
export interface AnyObject {
|
|
5
14
|
[k: string]: any;
|
|
6
15
|
}
|
|
7
|
-
export type AnyArgs = any[];
|
|
8
16
|
export type Reducer<T = any> = (accum: T, cur: any, index: number) => T;
|
|
9
17
|
export type AnyFunc<ReturnT = any, Args extends AnyArgs = AnyArgs> = (...args: Args) => ReturnT;
|
|
10
|
-
export type TupleFn<ARG1 = any, ARG2 = any, Out = any> = (a: ARG1, b: ARG2) => Out;
|
|
11
18
|
export type Curried<Args extends AnyArgs = AnyArgs, ReturnT = any> = (arg: Args[number]) => Curried<Args> | ReturnT;
|
|
12
|
-
export type BasicType = "String" | "Object" | "Number" | "Symbol" | "Array" | "Null" | "Undefined";
|
|
13
19
|
type Placeholder = symbol;
|
|
14
20
|
export declare const __: Placeholder;
|
|
15
21
|
export declare const curry: (fn: AnyFunc) => (...args: AnyArgs) => any;
|
|
@@ -33,7 +39,7 @@ export declare const typeIs: {
|
|
|
33
39
|
(a: string): (b: any) => boolean;
|
|
34
40
|
(a: string, b: any): boolean;
|
|
35
41
|
};
|
|
36
|
-
declare const length$1: (s:
|
|
42
|
+
declare const length$1: (s: AnyArray | string) => number;
|
|
37
43
|
export declare const isNil: (s: any) => boolean;
|
|
38
44
|
export declare const eq: {
|
|
39
45
|
(a: symbol, b: any): (a: any) => boolean;
|
|
@@ -78,10 +84,10 @@ export declare const bind: {
|
|
|
78
84
|
(a: any, b: any): any;
|
|
79
85
|
};
|
|
80
86
|
export declare const nth: {
|
|
81
|
-
(a: symbol, b: string |
|
|
82
|
-
(a: number, b: symbol): (b: string |
|
|
83
|
-
(a: number): (b: string |
|
|
84
|
-
(a: number, b: string |
|
|
87
|
+
(a: symbol, b: string | any[]): (a: number) => any;
|
|
88
|
+
(a: number, b: symbol): (b: string | any[]) => any;
|
|
89
|
+
(a: number): (b: string | any[]) => any;
|
|
90
|
+
(a: number, b: string | any[]): any;
|
|
85
91
|
};
|
|
86
92
|
export declare const slice: (...args: AnyArgs) => any;
|
|
87
93
|
export declare const flip: <T extends AnyFunc>(fn: T) => {
|
|
@@ -90,10 +96,42 @@ export declare const flip: <T extends AnyFunc>(fn: T) => {
|
|
|
90
96
|
(a: Parameters<T>[1]): (b: Parameters<T>[0]) => any;
|
|
91
97
|
(a: Parameters<T>[1], b: Parameters<T>[0]): any;
|
|
92
98
|
};
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
99
|
+
type FirstChar<T extends string> = T extends `${infer First}${string}` ? Split<T>["length"] extends 1 ? T : FirstChar<First> : T;
|
|
100
|
+
type HeadOverload = {
|
|
101
|
+
<T extends string>(s: T): FirstChar<T>;
|
|
102
|
+
<T extends readonly any[]>(s: T): T extends Array<0> ? undefined : T extends readonly [
|
|
103
|
+
infer U,
|
|
104
|
+
...any[]
|
|
105
|
+
] ? U : T extends (infer Y)[] ? Y : any;
|
|
106
|
+
<T extends any>(s: T[]): null;
|
|
107
|
+
};
|
|
108
|
+
/** @returns first element of an array or a string. */
|
|
109
|
+
export declare const head: HeadOverload;
|
|
110
|
+
type Tail<T extends string> = T extends `${string}${infer Tail}` ? Tail : T extends "" ? "" : string;
|
|
111
|
+
type TailOverload = {
|
|
112
|
+
<T extends string>(s: T): Tail<T>;
|
|
113
|
+
<T extends readonly any[]>(s: T): T extends Array<0> ? [
|
|
114
|
+
] : T extends readonly [
|
|
115
|
+
any,
|
|
116
|
+
...infer U
|
|
117
|
+
] ? U : T;
|
|
118
|
+
<T extends any>(s: T[]): null;
|
|
119
|
+
};
|
|
120
|
+
/** @returns last element of an array or a string. */
|
|
121
|
+
export declare const tail: TailOverload;
|
|
122
|
+
type LastChar<T extends string> = T extends `${string}${infer Rest}` ? (Split<T>["length"] extends 1 ? T : LastChar<Rest>) : T;
|
|
123
|
+
type LastOverload = {
|
|
124
|
+
<T extends string>(s: T): LastChar<T>;
|
|
125
|
+
<T extends readonly any[]>(s: T): T extends Array<0> ? undefined : T extends readonly [
|
|
126
|
+
...any[],
|
|
127
|
+
infer U
|
|
128
|
+
] ? U : T extends (infer Y)[] ? Y : any;
|
|
129
|
+
<T extends any>(s: T[]): null;
|
|
130
|
+
};
|
|
131
|
+
/** Returns last element of an array, readonly array or a string.
|
|
132
|
+
* @param s Array to extract that element.
|
|
133
|
+
* @returns undefined if s is empty or last element. */
|
|
134
|
+
export declare const last: LastOverload;
|
|
97
135
|
/** @param a @param b @returns a+b */
|
|
98
136
|
export declare const add: {
|
|
99
137
|
(a: symbol, b: number): (a: number) => number;
|
|
@@ -144,10 +182,10 @@ export declare const lte: {
|
|
|
144
182
|
(a: number, b: number): boolean;
|
|
145
183
|
};
|
|
146
184
|
export declare const sort: {
|
|
147
|
-
(a: symbol, b: any[]): (a: any) => any[];
|
|
148
|
-
(a: any, b: symbol): (b: any[]) => any[];
|
|
149
|
-
(a: any): (b: any[]) => any[];
|
|
150
|
-
(a: any, b: any[]): any[];
|
|
185
|
+
(a: symbol, b: any[]): (a: (a: any, b: any) => number) => any[];
|
|
186
|
+
(a: (a: any, b: any) => number, b: symbol): (b: any[]) => any[];
|
|
187
|
+
(a: (a: any, b: any) => number): (b: any[]) => any[];
|
|
188
|
+
(a: (a: any, b: any) => number, b: any[]): any[];
|
|
151
189
|
};
|
|
152
190
|
export declare const find: {
|
|
153
191
|
(a: symbol, b: any[]): (a: Cond) => any;
|
|
@@ -174,9 +212,8 @@ export declare const divide: {
|
|
|
174
212
|
(a: number, b: number): number;
|
|
175
213
|
};
|
|
176
214
|
export declare const always: <T = any>(s: T) => () => T;
|
|
177
|
-
export declare const identity: (s:
|
|
215
|
+
export declare const identity: <T = any>(s: T) => T;
|
|
178
216
|
export declare const trim: (s: string) => string;
|
|
179
|
-
export declare const last: (s: any[] | string) => any;
|
|
180
217
|
/** @param start string | any[] @param s string | any[] */
|
|
181
218
|
export declare const startsWith: {
|
|
182
219
|
(a: symbol, b: string | any[]): (a: string | any[]) => boolean;
|
|
@@ -190,11 +227,9 @@ type NotOverload = {
|
|
|
190
227
|
(x: any): boolean;
|
|
191
228
|
};
|
|
192
229
|
export declare const not: NotOverload;
|
|
193
|
-
type IndexesOfArray<A> = Exclude<keyof A, keyof [
|
|
194
|
-
]>;
|
|
195
230
|
type KeysOverload = {
|
|
196
|
-
<T extends any[]>(o: T): string[];
|
|
197
231
|
<T extends readonly any[]>(o: T): IndexesOfArray<T>[];
|
|
232
|
+
<T extends any[]>(o: T): string[];
|
|
198
233
|
<T extends AnyObject>(o: T): (keyof T)[];
|
|
199
234
|
};
|
|
200
235
|
export declare const keys: KeysOverload;
|
|
@@ -284,7 +319,7 @@ export declare const genBy: {
|
|
|
284
319
|
(a: (i: number) => any, b: number): any[];
|
|
285
320
|
};
|
|
286
321
|
export declare const once: <Func extends AnyFunc>(fn: Func) => (...args: Parameters<Func>) => any;
|
|
287
|
-
export declare const reverse: (xs:
|
|
322
|
+
export declare const reverse: <T extends unknown>(xs: T[]) => T[];
|
|
288
323
|
export declare const explore: (caption: string, level?: string) => (b: any) => any;
|
|
289
324
|
export declare const cond: {
|
|
290
325
|
(a: symbol, b: any): (a: [
|
|
@@ -361,18 +396,18 @@ export declare const freezeShallow: <T extends AnyObject>(o: T) => Readonly<T>;
|
|
|
361
396
|
* @param array T2[]
|
|
362
397
|
*/
|
|
363
398
|
export declare const reduce: (...args: AnyArgs) => any;
|
|
364
|
-
export declare const pickBy: {
|
|
365
|
-
(a: symbol, b: AnyObject): (a: Cond) => any;
|
|
366
|
-
(a: Cond, b: symbol): (b: AnyObject) => any;
|
|
367
|
-
(a: Cond): (b: AnyObject) => any;
|
|
368
|
-
(a: Cond, b: AnyObject): any;
|
|
369
|
-
};
|
|
370
399
|
export declare const pick: {
|
|
371
400
|
(a: symbol, b: AnyObject): (a: string[]) => {};
|
|
372
401
|
(a: string[], b: symbol): (b: AnyObject) => {};
|
|
373
402
|
(a: string[]): (b: AnyObject) => {};
|
|
374
403
|
(a: string[], b: AnyObject): {};
|
|
375
404
|
};
|
|
405
|
+
export declare const pickBy: {
|
|
406
|
+
(a: symbol, b: AnyObject): (a: Cond) => any;
|
|
407
|
+
(a: Cond, b: symbol): (b: AnyObject) => any;
|
|
408
|
+
(a: Cond): (b: AnyObject) => any;
|
|
409
|
+
(a: Cond, b: AnyObject): any;
|
|
410
|
+
};
|
|
376
411
|
export declare const omit: {
|
|
377
412
|
(a: symbol, b: AnyObject): (a: string[]) => any;
|
|
378
413
|
(a: string[], b: symbol): (b: AnyObject) => any;
|
|
@@ -425,7 +460,16 @@ export declare const filter: {
|
|
|
425
460
|
(a: (v: any, k: string | number) => boolean): (b: any[] | AnyObject) => any;
|
|
426
461
|
(a: (v: any, k: string | number) => boolean, b: any[] | AnyObject): any;
|
|
427
462
|
};
|
|
428
|
-
|
|
463
|
+
/** Saves result of a function with given key and avoids calling it again.
|
|
464
|
+
* @param {(...args: Args) string} keyGen that takes the same args and returns a key for the cache.
|
|
465
|
+
* @param {(...args: Args) any} fn to be cached.
|
|
466
|
+
*/
|
|
467
|
+
export declare const memoize: {
|
|
468
|
+
(a: symbol, b: AnyFunc<any, any[]>): (a: (...args: any[]) => string) => (...args: any[]) => any;
|
|
469
|
+
(a: (...args: any[]) => string, b: symbol): (b: AnyFunc<any, any[]>) => (...args: any[]) => any;
|
|
470
|
+
(a: (...args: any[]) => string): (b: AnyFunc<any, any[]>) => (...args: any[]) => any;
|
|
471
|
+
(a: (...args: any[]) => string, b: AnyFunc<any, any[]>): (...args: any[]) => any;
|
|
472
|
+
};
|
|
429
473
|
export declare const mergeShallow: {
|
|
430
474
|
(a: symbol, b: AnyObject): (a: AnyObject) => AnyObject;
|
|
431
475
|
(a: AnyObject, b: symbol): (b: AnyObject) => AnyObject;
|
|
@@ -450,6 +494,7 @@ export declare const mergeDeepAdd: {
|
|
|
450
494
|
(a: AnyObject): (b: AnyObject) => AnyObject;
|
|
451
495
|
(a: AnyObject, b: AnyObject): AnyObject;
|
|
452
496
|
};
|
|
497
|
+
/** @param prop string @param pipe(data[prop]) @param data any @returns data with prop over pipe. */
|
|
453
498
|
export declare const overProp: (...args: AnyArgs) => any;
|
|
454
499
|
/** mapKeys({ a: 'b' }, { a: 44 }) -> { b: 44 } */
|
|
455
500
|
export declare const mapKeys: {
|
|
@@ -485,9 +530,9 @@ export declare const zipObj: {
|
|
|
485
530
|
* @param b T2[]
|
|
486
531
|
*/
|
|
487
532
|
export declare const zipWith: (...args: AnyArgs) => any;
|
|
488
|
-
export declare const mirror: (s:
|
|
489
|
-
export declare const reflect: (s:
|
|
490
|
-
export declare const echo: (s:
|
|
533
|
+
export declare const mirror: <T = any>(s: T) => T;
|
|
534
|
+
export declare const reflect: <T = any>(s: T) => T;
|
|
535
|
+
export declare const echo: <T = any>(s: T) => T;
|
|
491
536
|
export declare const notf: (fn: AnyFunc) => (...args: any) => boolean | any;
|
|
492
537
|
export declare const push: {
|
|
493
538
|
(a: symbol, b: any[]): (a: any) => any[];
|
|
@@ -512,9 +557,24 @@ export declare const qappend: {
|
|
|
512
557
|
};
|
|
513
558
|
export declare const qassoc: (...args: AnyArgs) => any;
|
|
514
559
|
export declare const qreduce: (...args: AnyArgs) => any;
|
|
515
|
-
export declare const qmergeDeep:
|
|
516
|
-
|
|
517
|
-
|
|
560
|
+
export declare const qmergeDeep: {
|
|
561
|
+
(a: symbol, b: AnyObject): (a: AnyObject) => AnyObject;
|
|
562
|
+
(a: AnyObject, b: symbol): (b: AnyObject) => AnyObject;
|
|
563
|
+
(a: AnyObject): (b: AnyObject) => AnyObject;
|
|
564
|
+
(a: AnyObject, b: AnyObject): AnyObject;
|
|
565
|
+
};
|
|
566
|
+
export declare const qmergeDeepX: {
|
|
567
|
+
(a: symbol, b: AnyObject): (a: AnyObject) => AnyObject;
|
|
568
|
+
(a: AnyObject, b: symbol): (b: AnyObject) => AnyObject;
|
|
569
|
+
(a: AnyObject): (b: AnyObject) => AnyObject;
|
|
570
|
+
(a: AnyObject, b: AnyObject): AnyObject;
|
|
571
|
+
};
|
|
572
|
+
export declare const qmergeDeepAdd: {
|
|
573
|
+
(a: symbol, b: AnyObject): (a: AnyObject) => AnyObject;
|
|
574
|
+
(a: AnyObject, b: symbol): (b: AnyObject) => AnyObject;
|
|
575
|
+
(a: AnyObject): (b: AnyObject) => AnyObject;
|
|
576
|
+
(a: AnyObject, b: AnyObject): AnyObject;
|
|
577
|
+
};
|
|
518
578
|
export declare const qmergeShallow: {
|
|
519
579
|
(a: symbol, b: AnyObject): (a: AnyObject) => AnyObject;
|
|
520
580
|
(a: AnyObject, b: symbol): (b: AnyObject) => AnyObject;
|
|
@@ -554,7 +614,8 @@ export declare const qfilter: {
|
|
|
554
614
|
(a: (v: any, k: string | number) => boolean): (b: any[] | AnyObject) => any[] | AnyObject;
|
|
555
615
|
(a: (v: any, k: string | number) => boolean, b: any[] | AnyObject): any[] | AnyObject;
|
|
556
616
|
};
|
|
557
|
-
export declare const qempty:
|
|
617
|
+
export declare const qempty: <T extends any[] | AnyObject>(o: T) => T extends any[] ? [
|
|
618
|
+
] : {};
|
|
558
619
|
export declare const qfreeze: <T extends AnyObject>(o: T) => Readonly<T>;
|
|
559
620
|
export declare const qfreezeShallow: <T extends AnyObject>(o: T) => Readonly<T>;
|
|
560
621
|
export declare const qprepend: {
|
|
@@ -578,9 +639,11 @@ export declare const qstartsWith: {
|
|
|
578
639
|
(a: string | any[]): (b: string | any[]) => boolean;
|
|
579
640
|
(a: string | any[], b: string | any[]): boolean;
|
|
580
641
|
};
|
|
642
|
+
/** @param prop string @param pipe(data[prop]) @param data any @returns data with prop over pipe. */
|
|
643
|
+
export declare const qoverProp: (...args: AnyArgs) => any;
|
|
581
644
|
type StrTmpl = ((data: AnyObject) => string);
|
|
582
645
|
/** Supports ecrans: '\\{"json": {yes} \\}'
|
|
583
|
-
@returns
|
|
646
|
+
@returns getTmpl('one{meme}two')({meme: 42}) -> one42two */
|
|
584
647
|
export declare const getTmpl: (tmpl: string) => StrTmpl;
|
|
585
648
|
/** One promise waits for another. */
|
|
586
649
|
export declare const forEachSerial: {
|
package/dist/bundle.mjs
CHANGED
|
@@ -134,7 +134,6 @@ const qstartsWithWith = (comparator) => curry2((start, s) => {
|
|
|
134
134
|
return true;
|
|
135
135
|
});
|
|
136
136
|
|
|
137
|
-
// TODO: qoverProp, qover array ?
|
|
138
137
|
/** Then next fns seem to be excess due to their safe ver performance should be the same or better:
|
|
139
138
|
* qflat, qpick
|
|
140
139
|
*/
|
|
@@ -142,7 +141,7 @@ const qappend = curry2((s, xs) => { xs.push(s); return xs; });
|
|
|
142
141
|
const qassoc = curry3((prop, v, obj) => { obj[prop] = v; return obj; });
|
|
143
142
|
const qreduce = curry3((fn, accum, arr) => arr.reduce(fn, accum));
|
|
144
143
|
// strategy is for arrays: 1->clean, 2->merge, 3->push.
|
|
145
|
-
const mergeDeep$1 =
|
|
144
|
+
const mergeDeep$1 = (strategy) => curry2((o1, o2) => {
|
|
146
145
|
for (let k in o2) {
|
|
147
146
|
switch (type(o2[k])) {
|
|
148
147
|
case 'Array':
|
|
@@ -152,7 +151,7 @@ const mergeDeep$1 = curry3((strategy, o1, o2) => {
|
|
|
152
151
|
const o1k = o1[k], o2k = o2[k];
|
|
153
152
|
for (const i in o2k)
|
|
154
153
|
if (o1k[i])
|
|
155
|
-
mergeDeep$1(strategy
|
|
154
|
+
mergeDeep$1(strategy)(o1k[i], o2k[i]);
|
|
156
155
|
else
|
|
157
156
|
o1k[i] = o2k[i];
|
|
158
157
|
break;
|
|
@@ -163,7 +162,7 @@ const mergeDeep$1 = curry3((strategy, o1, o2) => {
|
|
|
163
162
|
break;
|
|
164
163
|
case 'Object':
|
|
165
164
|
if (type(o1[k]) === 'Object') {
|
|
166
|
-
mergeDeep$1(strategy
|
|
165
|
+
mergeDeep$1(strategy)(o1[k], o2[k]);
|
|
167
166
|
break;
|
|
168
167
|
}
|
|
169
168
|
default:
|
|
@@ -193,7 +192,7 @@ const qmapKeys = curry2((keyMap, o) => {
|
|
|
193
192
|
return o;
|
|
194
193
|
});
|
|
195
194
|
const qmap = curry2((pipe, arr) => {
|
|
196
|
-
for (
|
|
195
|
+
for (const i in arr)
|
|
197
196
|
arr[i] = pipe(arr[i], +i, arr);
|
|
198
197
|
return arr;
|
|
199
198
|
});
|
|
@@ -245,6 +244,8 @@ const qreverse = (arr) => arr.reverse();
|
|
|
245
244
|
const qomit = curry2((props, o) => qfilter((_, k) => !includes(k, props), o));
|
|
246
245
|
/** @param start string | any[] @param s string | any[] */
|
|
247
246
|
const qstartsWith = qstartsWithWith(eq);
|
|
247
|
+
/** @param prop string @param pipe(data[prop]) @param data any @returns data with prop over pipe. */
|
|
248
|
+
const qoverProp = curry3((prop, pipe, data) => qassoc(prop, pipe(data[prop]), data));
|
|
248
249
|
|
|
249
250
|
// TODO: possibly introduce a second argument limiting unfolding.
|
|
250
251
|
const uncurry = (fn) => (...args) => qreduce(((fn, arg) => fn ? fn(arg) : fn), fn, args);
|
|
@@ -271,10 +272,14 @@ const bind = curry2((fn, context) => fn.bind(context));
|
|
|
271
272
|
const nth = curry2((i, data) => data[i]);
|
|
272
273
|
const slice = curry3((from, to, o) => o.slice(from, (isNum(to) ? to : inf)));
|
|
273
274
|
const flip = (fn) => curry2((b, a) => fn(a, b));
|
|
274
|
-
/** @returns first element of an array. */
|
|
275
|
+
/** @returns first element of an array or a string. */
|
|
275
276
|
const head = nth(0);
|
|
276
|
-
/** @returns last element of an array. */
|
|
277
|
+
/** @returns last element of an array or a string. */
|
|
277
278
|
const tail = slice(1, inf);
|
|
279
|
+
/** Returns last element of an array, readonly array or a string.
|
|
280
|
+
* @param s Array to extract that element.
|
|
281
|
+
* @returns undefined if s is empty or last element. */
|
|
282
|
+
const last = (s) => s[length(s) - 1];
|
|
278
283
|
/** @param a @param b @returns a+b */
|
|
279
284
|
const add = curry2((a, b) => a + b);
|
|
280
285
|
/** @param a @param b @returns b-a */
|
|
@@ -293,11 +298,10 @@ const sort = curry2((sortFn, xs) => xs.sort(sortFn));
|
|
|
293
298
|
const find = curry2((fn, s) => s.find(fn));
|
|
294
299
|
const findIndex = curry2((fn, s) => s.findIndex(fn));
|
|
295
300
|
const indexOf = curry2((x, xs) => findIndex(equals(x), xs));
|
|
296
|
-
const divide = curry2((
|
|
301
|
+
const divide = curry2((a, b) => b / a);
|
|
297
302
|
const always = (s) => () => s;
|
|
298
303
|
const identity = (s) => s;
|
|
299
304
|
const trim = (s) => s.trim();
|
|
300
|
-
const last = (s) => s[length(s) - 1];
|
|
301
305
|
/** @param start string | any[] @param s string | any[] */
|
|
302
306
|
const startsWith = qstartsWithWith((x, y) => equals(x, y));
|
|
303
307
|
const not = (x) => !x;
|
|
@@ -341,14 +345,13 @@ const range = curry2((from, to) => genBy(add(from), to - from));
|
|
|
341
345
|
const uniq = (xs) => qreduce((accum, x) => find(equals(x), accum) ? accum : qappend(x, accum), [], xs);
|
|
342
346
|
const intersection = curry2((xs1, xs2) => xs1.filter(flip(includes)(xs2)));
|
|
343
347
|
const diff = curry2((_xs1, _xs2) => {
|
|
344
|
-
// BUG: if _xs1 is empty, results in [undefined, ...]
|
|
345
348
|
let len1 = length(_xs1);
|
|
346
|
-
let len2 = length(_xs2);
|
|
347
|
-
const xs1 = len1 > len2 ? _xs1 : _xs2;
|
|
348
|
-
const xs2 = len1 > len2 ? _xs2 : _xs1;
|
|
349
|
-
if (len1
|
|
349
|
+
let len2 = length(_xs2);
|
|
350
|
+
const xs1 = len1 > len2 ? _xs1 : _xs2;
|
|
351
|
+
const xs2 = len1 > len2 ? _xs2 : _xs1;
|
|
352
|
+
if (len1 < len2)
|
|
350
353
|
[len1, len2] = [len2, len1];
|
|
351
|
-
const xset2 = new Set(xs2);
|
|
354
|
+
const xset2 = new Set(xs2);
|
|
352
355
|
const common = new Set();
|
|
353
356
|
const out = [];
|
|
354
357
|
let i;
|
|
@@ -376,7 +379,10 @@ const once = (fn) => {
|
|
|
376
379
|
return cache = fn(...args);
|
|
377
380
|
};
|
|
378
381
|
};
|
|
379
|
-
const reverse = (xs) =>
|
|
382
|
+
const reverse = (xs) => {
|
|
383
|
+
const ln = length(xs) - 1;
|
|
384
|
+
return map((_, i) => xs[ln - i], xs);
|
|
385
|
+
};
|
|
380
386
|
const explore = (caption, level = 'log') => tap((v) => console[level](caption, v));
|
|
381
387
|
const cond = curry2((pairs, s) => {
|
|
382
388
|
for (const [cond, fn] of pairs)
|
|
@@ -442,7 +448,6 @@ const freezeShallow = (o) => qfreezeShallow(clone(o));
|
|
|
442
448
|
* @param array T2[]
|
|
443
449
|
*/
|
|
444
450
|
const reduce = curry3((reducer, accum, arr) => qreduce(reducer, clone(accum), arr));
|
|
445
|
-
const pickBy = curry2((cond, o) => filter(cond, o));
|
|
446
451
|
const pick = curry2((props, o) => {
|
|
447
452
|
const out = {};
|
|
448
453
|
for (const p of props)
|
|
@@ -450,6 +455,7 @@ const pick = curry2((props, o) => {
|
|
|
450
455
|
out[p] = o[p];
|
|
451
456
|
return out;
|
|
452
457
|
});
|
|
458
|
+
const pickBy = curry2((cond, o) => compose(flip(pick)(o), qfilter(cond), keys)(o));
|
|
453
459
|
const omit = curry2((props, o) => filter((_, k) => !includes(k, props), o));
|
|
454
460
|
const fromPairs = (pairs) => Object.fromEntries(pairs);
|
|
455
461
|
const concat = curry2(((a, b) => b.concat(a)));
|
|
@@ -484,15 +490,26 @@ const replace = curry3((a, b, where
|
|
|
484
490
|
const filter = curry2((cond, data) => isArray(data)
|
|
485
491
|
? data.filter(cond)
|
|
486
492
|
: qfilter(cond, { ...data }));
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
493
|
+
/** Saves result of a function with given key and avoids calling it again.
|
|
494
|
+
* @param {(...args: Args) string} keyGen that takes the same args and returns a key for the cache.
|
|
495
|
+
* @param {(...args: Args) any} fn to be cached.
|
|
496
|
+
*/
|
|
497
|
+
const memoize = curry2((keyGen, fn) => {
|
|
498
|
+
const cache = {};
|
|
499
|
+
return (...args) => {
|
|
500
|
+
const key = keyGen(...args);
|
|
501
|
+
if (key in cache)
|
|
502
|
+
return cache[key];
|
|
503
|
+
const res = fn(...args);
|
|
504
|
+
cache[key] = res;
|
|
505
|
+
return res;
|
|
506
|
+
};
|
|
507
|
+
});
|
|
492
508
|
const mergeShallow = curry2((o1, o2) => Object.assign({}, o1, o2));
|
|
493
|
-
const mergeDeep = curry2((a, b) => qmergeDeep(clone(a),
|
|
494
|
-
const mergeDeepX = curry2((a, b) => qmergeDeepX(clone(a),
|
|
495
|
-
const mergeDeepAdd = curry2((a, b) => qmergeDeepAdd(clone(a),
|
|
509
|
+
const mergeDeep = curry2((a, b) => qmergeDeep(clone(a), b));
|
|
510
|
+
const mergeDeepX = curry2((a, b) => qmergeDeepX(clone(a), b));
|
|
511
|
+
const mergeDeepAdd = curry2((a, b) => qmergeDeepAdd(clone(a), b));
|
|
512
|
+
/** @param prop string @param pipe(data[prop]) @param data any @returns data with prop over pipe. */
|
|
496
513
|
const overProp = curry3((prop, pipe, data) => assoc(prop, pipe(data[prop]), data));
|
|
497
514
|
/** mapKeys({ a: 'b' }, { a: 44 }) -> { b: 44 } */
|
|
498
515
|
const mapKeys = curry2((keyMap, o) => qmapKeys(keyMap, Object.assign({}, o)));
|
|
@@ -517,12 +534,12 @@ const some = any;
|
|
|
517
534
|
const ecran = '\\';
|
|
518
535
|
// TODO: make it splicy, not accumulatie by symbols.
|
|
519
536
|
/** Supports ecrans: '\\{"json": {yes} \\}'
|
|
520
|
-
@returns
|
|
537
|
+
@returns getTmpl('one{meme}two')({meme: 42}) -> one42two */
|
|
521
538
|
const getTmpl = (tmpl) => {
|
|
522
539
|
const parts = [];
|
|
523
540
|
const keymap = [];
|
|
524
541
|
const len = tmpl.length;
|
|
525
|
-
let i = 0, s, ln, start = 0, open = false, hasEcran =
|
|
542
|
+
let i = 0, s, ln, start = 0, open = false, hasEcran = false, hasEcranNext = false, nextChar;
|
|
526
543
|
for (i = 0; i < len; i++) {
|
|
527
544
|
s = tmpl[i];
|
|
528
545
|
switch (s) {
|
|
@@ -593,4 +610,4 @@ const composeAsync = (() => {
|
|
|
593
610
|
return (...fns) => (...input) => pipe(fns, input, fns.length - 1);
|
|
594
611
|
})();
|
|
595
612
|
|
|
596
|
-
export { F, T, __, add, all, allPass, always, any, anyPass, append, assoc, assocPath, bind, both, callFrom, callWith, clone, cloneShallow, complement, compose, composeAsync, concat, cond, curry, curry2, curry3, diff, divide, echo, empty, eq, equals, explore, filter, find, findIndex, flat, flatShallow, flatTo, flip, forEach, forEachAsync, forEachSerial, freeze, freezeShallow, fromPairs, genBy, getTmpl, gt, gte, head, identity, ifElse, includes, indexOf, intersection, isEmpty, isNil, join, keys, last, length, lt, lte, map, mapKeys, mapObj, memoize, mergeDeep, mergeDeepAdd, mergeDeepX, mergeShallow, mirror, multiply, noop, not, notf, nth, omit, once, overProp, path, pathEq, pathExists, pathOr, pathsEq, pick, pickBy, prepend, prop, propEq, propsEq, push, qappend, qassoc, qassocPath, qempty, qfilter, qfreeze, qfreezeShallow, qmap, qmapKeys, qmapObj, qmergeDeep, qmergeDeepAdd, qmergeDeepX, qmergeShallow, qomit, qprepend, qreduce, qreverse, qstartsWith, qstartsWithWith, range, reduce, reflect, replace, reverse, sizeof, slice, some, sort, split, startsWith, subtract, symbol, tail, take, tap, test, toLower, toPairs, toUpper, trim, type, typeIs, uncurry, uniq, values, waitAll, waitTap, weakEq, when, zip, zipObj, zipWith };
|
|
613
|
+
export { F, T, __, add, all, allPass, always, any, anyPass, append, assoc, assocPath, bind, both, callFrom, callWith, clone, cloneShallow, complement, compose, composeAsync, concat, cond, curry, curry2, curry3, diff, divide, echo, empty, eq, equals, explore, filter, find, findIndex, flat, flatShallow, flatTo, flip, forEach, forEachAsync, forEachSerial, freeze, freezeShallow, fromPairs, genBy, getTmpl, gt, gte, head, identity, ifElse, includes, indexOf, intersection, isEmpty, isNil, join, keys, last, length, lt, lte, map, mapKeys, mapObj, memoize, mergeDeep, mergeDeepAdd, mergeDeepX, mergeShallow, mirror, multiply, noop, not, notf, nth, omit, once, overProp, path, pathEq, pathExists, pathOr, pathsEq, pick, pickBy, prepend, prop, propEq, propsEq, push, qappend, qassoc, qassocPath, qempty, qfilter, qfreeze, qfreezeShallow, qmap, qmapKeys, qmapObj, qmergeDeep, qmergeDeepAdd, qmergeDeepX, qmergeShallow, qomit, qoverProp, qprepend, qreduce, qreverse, qstartsWith, qstartsWithWith, range, reduce, reflect, replace, reverse, sizeof, slice, some, sort, split, startsWith, subtract, symbol, tail, take, tap, test, toLower, toPairs, toUpper, trim, type, typeIs, uncurry, uniq, values, waitAll, waitTap, weakEq, when, zip, zipObj, zipWith };
|
package/package.json
CHANGED
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"prod": "npm run gentypes && npm run prod:es && npm run prod:cjs",
|
|
43
43
|
"all": "npm run dev && npm run prod"
|
|
44
44
|
},
|
|
45
|
-
"version": "1.
|
|
45
|
+
"version": "1.6.0",
|
|
46
46
|
"ava": {
|
|
47
47
|
"files": [
|
|
48
48
|
"./test/specs/*.ts"
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"dts-bundle-generator": "^9.5.1",
|
|
68
68
|
"nyc": "^15.1.0",
|
|
69
69
|
"prepend": "^1.0.2",
|
|
70
|
-
"rollup": "^4.
|
|
70
|
+
"rollup": "^4.17.0",
|
|
71
71
|
"rollup-plugin-typescript2": "^0.36.0",
|
|
72
72
|
"ts-node": "^10.9.2",
|
|
73
73
|
"tslint": "^6.1.3",
|
package/src/common.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { curry2 } from "./curry"
|
|
2
|
+
import { AnyArray } from "./internal_types"
|
|
2
3
|
import { to, isNull, isStr, isUndef } from "./utils"
|
|
3
4
|
|
|
4
5
|
// It's faster that toUpperCase() !
|
|
@@ -14,7 +15,7 @@ export const type = (s: any): string => {
|
|
|
14
15
|
: caseMap[t[0]] + t.slice(1)
|
|
15
16
|
}
|
|
16
17
|
export const typeIs = curry2((t: string, s: any) => type(s)===t)
|
|
17
|
-
export const length = (s:
|
|
18
|
+
export const length = (s: AnyArray | string) => s.length
|
|
18
19
|
export const isNil = (s: any) => isNull(s) || isUndef(s)
|
|
19
20
|
export const eq = curry2((a: any, b: any) => a===b)
|
|
20
21
|
export const equals = curry2((a: any, b: any) => {
|
package/src/curry.ts
CHANGED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type AnyArgs = any[]
|
|
2
|
+
export type BasicType = 'String'|'Object'|'Number'|'Symbol'|'Array'|'Null'|'Undefined'
|
|
3
|
+
export type TupleFn<ARG1=any, ARG2=any, Out=any> = (a: ARG1, b: ARG2) => Out
|
|
4
|
+
export type IDArray = Uint8Array|Uint16Array|Uint32Array
|
|
5
|
+
export type AnyArray<T=any> = T[] | readonly T[]
|
|
6
|
+
export type Split<S extends string> = S extends `${infer U}${infer V}` ? [U, ...Split<V>] : []
|
|
7
|
+
export type IndexesOfArray<A> = Exclude<keyof A, keyof []>
|
package/src/quick.ts
CHANGED
|
@@ -2,8 +2,6 @@ import { curry2, curry3 } from "./curry"
|
|
|
2
2
|
import { includes, isNil, type, eq, qstartsWithWith } from "./common"
|
|
3
3
|
import { AnyObject, Reducer, AnyFunc } from "./types"
|
|
4
4
|
import { isFunc, isArray, isObj } from "./utils"
|
|
5
|
-
// TODO: qoverProp, qover array ?
|
|
6
|
-
|
|
7
5
|
/** Then next fns seem to be excess due to their safe ver performance should be the same or better:
|
|
8
6
|
* qflat, qpick
|
|
9
7
|
*/
|
|
@@ -12,7 +10,7 @@ export const qappend = curry2((s: any, xs: any[]) => {xs.push(s); return xs})
|
|
|
12
10
|
export const qassoc = curry3((prop: string, v: any, obj: AnyObject) => { obj[prop] = v; return obj })
|
|
13
11
|
export const qreduce = curry3(<T>(fn: Reducer, accum: any, arr: T[]) => arr.reduce(fn, accum))
|
|
14
12
|
// strategy is for arrays: 1->clean, 2->merge, 3->push.
|
|
15
|
-
const mergeDeep =
|
|
13
|
+
const mergeDeep = (strategy: 1|2|3) => curry2((o1: AnyObject, o2: AnyObject): AnyObject => {
|
|
16
14
|
for(let k in o2) {
|
|
17
15
|
switch(type(o2[k])) {
|
|
18
16
|
case 'Array':
|
|
@@ -21,7 +19,7 @@ const mergeDeep = curry3((strategy: 1|2|3, o1: AnyObject, o2: AnyObject): AnyObj
|
|
|
21
19
|
case 2:
|
|
22
20
|
const o1k = o1[k], o2k = o2[k]
|
|
23
21
|
for(const i in o2k)
|
|
24
|
-
if(o1k[i]) mergeDeep(strategy
|
|
22
|
+
if(o1k[i]) mergeDeep(strategy)(o1k[i], o2k[i])
|
|
25
23
|
else o1k[i] = o2k[i]
|
|
26
24
|
break
|
|
27
25
|
case 3: o1[k].push(...o2[k])
|
|
@@ -31,7 +29,7 @@ const mergeDeep = curry3((strategy: 1|2|3, o1: AnyObject, o2: AnyObject): AnyObj
|
|
|
31
29
|
break
|
|
32
30
|
case 'Object':
|
|
33
31
|
if(type(o1[k])==='Object') {
|
|
34
|
-
mergeDeep(strategy
|
|
32
|
+
mergeDeep(strategy)(o1[k], o2[k])
|
|
35
33
|
break
|
|
36
34
|
}
|
|
37
35
|
default:
|
|
@@ -65,7 +63,7 @@ export const qmapKeys = curry2(
|
|
|
65
63
|
)
|
|
66
64
|
export const qmap = curry2(
|
|
67
65
|
(pipe: (s: any, i?: number, list?: any[]) => any, arr: any[]) => {
|
|
68
|
-
for(
|
|
66
|
+
for(const i in arr) arr[i] = pipe(arr[i], +i, arr)
|
|
69
67
|
return arr
|
|
70
68
|
}
|
|
71
69
|
)
|
|
@@ -93,10 +91,10 @@ export const qfilter = curry2(
|
|
|
93
91
|
return data
|
|
94
92
|
}
|
|
95
93
|
)
|
|
96
|
-
export const qempty =
|
|
94
|
+
export const qempty = <T extends AnyObject|any[]>(o: T): T extends any[] ? [] : {} => {
|
|
97
95
|
if(isArray(o)) o.splice(0)
|
|
98
96
|
else for(const i in o) delete o[i]
|
|
99
|
-
return o
|
|
97
|
+
return o as any
|
|
100
98
|
}
|
|
101
99
|
export const qfreeze = <T extends AnyObject>(o: T): Readonly<T> => {
|
|
102
100
|
let v: any
|
|
@@ -124,4 +122,9 @@ export const qomit = curry2(
|
|
|
124
122
|
)
|
|
125
123
|
)
|
|
126
124
|
/** @param start string | any[] @param s string | any[] */
|
|
127
|
-
export const qstartsWith = qstartsWithWith(eq)
|
|
125
|
+
export const qstartsWith = qstartsWithWith(eq)
|
|
126
|
+
/** @param prop string @param pipe(data[prop]) @param data any @returns data with prop over pipe. */
|
|
127
|
+
export const qoverProp = curry3(
|
|
128
|
+
(prop: string, pipe: AnyFunc, data: any) =>
|
|
129
|
+
qassoc(prop, pipe(data[prop]), data)
|
|
130
|
+
)
|
package/src/safe.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { __, curry, curry2, curry3 } from './curry'
|
|
2
|
-
import { isNum, undef,
|
|
2
|
+
import { isNum, undef, isArray, isFunc, isObj, inf } from './utils'
|
|
3
3
|
import { qmergeDeep, qreduce, qappend, qmapKeys, qmergeDeepX, qmergeDeepAdd, qfilter, qfreeze, qfreezeShallow, qmapObj } from './quick'
|
|
4
4
|
import { AnyFunc, Cond, AnyObject, Reducer } from './types'
|
|
5
5
|
import { symbol, type, length, equals, includes, isNil, qstartsWithWith } from './common'
|
|
6
|
+
import { Split, AnyArray, IndexesOfArray } from './internal_types'
|
|
6
7
|
// over, lensProp
|
|
7
8
|
|
|
8
9
|
export const take = (argN: number) => (...args: any[]) => args[argN]
|
|
@@ -38,10 +39,8 @@ export const compose = (
|
|
|
38
39
|
return s as any as TOut
|
|
39
40
|
}
|
|
40
41
|
)
|
|
41
|
-
export const bind = curry2<AnyFunc>(
|
|
42
|
-
|
|
43
|
-
)
|
|
44
|
-
export const nth = curry2(<T=any>(i: number, data: T[] | string) => data[i])
|
|
42
|
+
export const bind = curry2<AnyFunc>((fn: AnyFunc, context: any) => fn.bind(context))
|
|
43
|
+
export const nth = curry2((i: number, data: any[] | string) => data[i])
|
|
45
44
|
export const slice = curry3(
|
|
46
45
|
(from: number, to: number, o: any[] | string) =>
|
|
47
46
|
o.slice(from, (isNum(to)?to:inf) as number)
|
|
@@ -49,10 +48,42 @@ export const slice = curry3(
|
|
|
49
48
|
export const flip = <T extends AnyFunc>(fn: T) => curry2(
|
|
50
49
|
(b: Parameters<T>[1], a: Parameters<T>[0]) => fn(a, b)
|
|
51
50
|
)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
type FirstChar<T extends string> = T extends `${infer First}${string}`
|
|
52
|
+
? Split<T>['length'] extends 1 ? T : FirstChar<First>
|
|
53
|
+
: T
|
|
54
|
+
type HeadOverload = {
|
|
55
|
+
<T extends string>(s: T): FirstChar<T>
|
|
56
|
+
<T extends readonly any[]>(s: T): T extends Array<0> ? undefined
|
|
57
|
+
: T extends readonly [infer U, ...any[]] ? U
|
|
58
|
+
: T extends (infer Y)[] ? Y : any
|
|
59
|
+
<T extends any>(s: T[]): null
|
|
60
|
+
}
|
|
61
|
+
/** @returns first element of an array or a string. */
|
|
62
|
+
export const head = nth(0) as HeadOverload
|
|
63
|
+
type Tail<T extends string> = T extends `${string}${infer Tail}`
|
|
64
|
+
? Tail : T extends '' ? '' : string
|
|
65
|
+
type TailOverload = {
|
|
66
|
+
<T extends string>(s: T): Tail<T>
|
|
67
|
+
<T extends readonly any[]>(s: T): T extends Array<0> ? []
|
|
68
|
+
: T extends readonly [any, ...infer U] ? U : T
|
|
69
|
+
<T extends any>(s: T[]): null
|
|
70
|
+
}
|
|
71
|
+
/** @returns last element of an array or a string. */
|
|
72
|
+
export const tail = slice(1, inf) as TailOverload
|
|
73
|
+
type LastChar<T extends string> = T extends `${string}${infer Rest}`
|
|
74
|
+
? (Split<T>['length'] extends 1 ? T : LastChar<Rest>) : T
|
|
75
|
+
type LastOverload = {
|
|
76
|
+
<T extends string>(s: T): LastChar<T>
|
|
77
|
+
<T extends readonly any[]>(s: T): T extends Array<0>
|
|
78
|
+
? undefined
|
|
79
|
+
: T extends readonly [...any[], infer U] ? U
|
|
80
|
+
: T extends (infer Y)[] ? Y : any
|
|
81
|
+
<T extends any>(s: T[]): null
|
|
82
|
+
}
|
|
83
|
+
/** Returns last element of an array, readonly array or a string.
|
|
84
|
+
* @param s Array to extract that element.
|
|
85
|
+
* @returns undefined if s is empty or last element. */
|
|
86
|
+
export const last: LastOverload = (s: string | AnyArray) => s[length(s)-1]
|
|
56
87
|
/** @param a @param b @returns a+b */
|
|
57
88
|
export const add = curry2((a: number, b: number) => a+b)
|
|
58
89
|
/** @param a @param b @returns b-a */
|
|
@@ -67,15 +98,15 @@ export const lt = curry2( (a: number, b: number) => a>b )
|
|
|
67
98
|
export const gte = curry2( (a: number, b: number) => a<=b )
|
|
68
99
|
/** @param a @param b @returns a≥b */
|
|
69
100
|
export const lte = curry2( (a: number, b: number) => a>=b )
|
|
70
|
-
export const sort = curry2((sortFn: any, xs: any[]) => xs.sort(sortFn))
|
|
101
|
+
export const sort = curry2((sortFn: (a: any, b: any) => number , xs: any[]) => xs.sort(sortFn))
|
|
71
102
|
export const find = curry2((fn: Cond, s: any[]) => s.find(fn))
|
|
72
103
|
export const findIndex = curry2((fn: Cond, s: any[]) => s.findIndex(fn))
|
|
73
104
|
export const indexOf = curry2((x: any, xs: any[]) => findIndex(equals(x), xs))
|
|
74
|
-
export const divide = curry2((
|
|
105
|
+
export const divide = curry2((a: number, b: number) => b/a)
|
|
75
106
|
export const always = <T=any>(s: T) => () => s
|
|
76
|
-
export const identity = (s:
|
|
107
|
+
export const identity = <T=any>(s: T) => s
|
|
77
108
|
export const trim = (s: string) => s.trim()
|
|
78
|
-
|
|
109
|
+
|
|
79
110
|
/** @param start string | any[] @param s string | any[] */
|
|
80
111
|
export const startsWith = qstartsWithWith((x: any, y: any) => equals(x, y))
|
|
81
112
|
type NotOverload = {
|
|
@@ -84,14 +115,12 @@ type NotOverload = {
|
|
|
84
115
|
(x: any): boolean
|
|
85
116
|
}
|
|
86
117
|
export const not: NotOverload = (x: any) => !x as any
|
|
87
|
-
type IndexesOfArray<A> = Exclude<keyof A, keyof []>
|
|
88
118
|
type KeysOverload = {
|
|
89
|
-
<T extends any[]>(o: T): string[]
|
|
90
119
|
<T extends readonly any[]>(o: T): IndexesOfArray<T>[]
|
|
120
|
+
<T extends any[]>(o: T): string[]
|
|
91
121
|
<T extends AnyObject>(o: T): (keyof T)[]
|
|
92
122
|
}
|
|
93
|
-
export const keys: KeysOverload = (o:
|
|
94
|
-
|
|
123
|
+
export const keys: KeysOverload = (o: any) => Object.keys(o)
|
|
95
124
|
export const values = (o: AnyObject | any[]) => Object.values(o)
|
|
96
125
|
export const toPairs = (o: AnyObject | any[]) => Object.entries(o)
|
|
97
126
|
export const test = curry2((re: RegExp, s: string) => re.test(s))
|
|
@@ -131,13 +160,12 @@ export const uniq = (xs: any[]) => qreduce(
|
|
|
131
160
|
[], xs)
|
|
132
161
|
export const intersection = curry2((xs1: any[], xs2: any[]) => xs1.filter(flip(includes)(xs2)))
|
|
133
162
|
export const diff = curry2((_xs1: any[], _xs2: any[]) => {
|
|
134
|
-
// BUG: if _xs1 is empty, results in [undefined, ...]
|
|
135
163
|
let len1 = length(_xs1)
|
|
136
|
-
let len2 = length(_xs2)
|
|
137
|
-
const xs1 = len1>len2 ? _xs1 : _xs2
|
|
138
|
-
const xs2 = len1>len2 ? _xs2 : _xs1
|
|
139
|
-
if(len1
|
|
140
|
-
const xset2 = new Set(xs2)
|
|
164
|
+
let len2 = length(_xs2)
|
|
165
|
+
const xs1 = len1>len2 ? _xs1 : _xs2
|
|
166
|
+
const xs2 = len1>len2 ? _xs2 : _xs1
|
|
167
|
+
if(len1<len2) [len1, len2] = [len2, len1]
|
|
168
|
+
const xset2 = new Set(xs2)
|
|
141
169
|
const common = new Set()
|
|
142
170
|
const out: any[] = []
|
|
143
171
|
let i: number
|
|
@@ -166,14 +194,10 @@ export const once = <Func extends AnyFunc>(fn: Func) => {
|
|
|
166
194
|
return cache = fn(...args)
|
|
167
195
|
}
|
|
168
196
|
}
|
|
169
|
-
export const reverse = (xs:
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
),
|
|
174
|
-
add(-1),
|
|
175
|
-
length
|
|
176
|
-
)(xs)
|
|
197
|
+
export const reverse = <T extends any>(xs: T[]): T[] => {
|
|
198
|
+
const ln = length(xs)-1
|
|
199
|
+
return map((_: any, i: number) => xs[ln-i], xs)
|
|
200
|
+
}
|
|
177
201
|
export const explore = (caption: string, level = 'log') => tap(
|
|
178
202
|
(v: any) => console[level](caption, v)
|
|
179
203
|
)
|
|
@@ -266,17 +290,16 @@ export const reduce = curry3(
|
|
|
266
290
|
<T = any>(reducer: Reducer<T>, accum: T, arr: any[]) =>
|
|
267
291
|
qreduce(reducer, clone(accum), arr)
|
|
268
292
|
)
|
|
269
|
-
export const pickBy = curry2(
|
|
270
|
-
(cond: Cond, o: AnyObject) => filter(cond, o)
|
|
271
|
-
)
|
|
272
293
|
export const pick = curry2(
|
|
273
294
|
(props: string[], o: AnyObject) => {
|
|
274
295
|
const out = {}
|
|
275
|
-
for(const p of props)
|
|
276
|
-
if(p in o) out[p] = o[p]
|
|
296
|
+
for(const p of props) if(p in o) out[p] = o[p]
|
|
277
297
|
return out
|
|
278
298
|
}
|
|
279
299
|
)
|
|
300
|
+
export const pickBy = curry2(
|
|
301
|
+
(cond: Cond, o: AnyObject) => compose(flip(pick)(o), qfilter(cond), keys)(o)
|
|
302
|
+
)
|
|
280
303
|
export const omit = curry2(
|
|
281
304
|
(props: string[], o: AnyObject) => filter(
|
|
282
305
|
(_: any, k: string) => !includes(k, props),
|
|
@@ -332,24 +355,37 @@ export const filter = curry2(
|
|
|
332
355
|
? data.filter(cond)
|
|
333
356
|
: qfilter(cond, {...data})
|
|
334
357
|
)
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
358
|
+
/** Saves result of a function with given key and avoids calling it again.
|
|
359
|
+
* @param {(...args: Args) string} keyGen that takes the same args and returns a key for the cache.
|
|
360
|
+
* @param {(...args: Args) any} fn to be cached.
|
|
361
|
+
*/
|
|
362
|
+
export const memoize = curry2(<Args extends any[]>(
|
|
363
|
+
keyGen: (...args: Args) => string,
|
|
364
|
+
fn: AnyFunc<any, Args>
|
|
365
|
+
) => {
|
|
366
|
+
const cache: {[key in string]: ReturnType<typeof fn>} = {}
|
|
367
|
+
return (...args: Args): ReturnType<typeof fn> => {
|
|
368
|
+
const key = keyGen(...args)
|
|
369
|
+
if(key in cache) return cache[key]
|
|
370
|
+
const res = fn(...args)
|
|
371
|
+
cache[key] = res
|
|
372
|
+
return res
|
|
373
|
+
}
|
|
374
|
+
})
|
|
340
375
|
export const mergeShallow = curry2(
|
|
341
376
|
(o1: AnyObject, o2: AnyObject): AnyObject =>
|
|
342
377
|
Object.assign({}, o1, o2)
|
|
343
378
|
)
|
|
344
379
|
export const mergeDeep = curry2(
|
|
345
|
-
(a: AnyObject, b: AnyObject) => qmergeDeep(clone(a),
|
|
380
|
+
(a: AnyObject, b: AnyObject) => qmergeDeep(clone(a), b) as AnyObject
|
|
346
381
|
)
|
|
347
382
|
export const mergeDeepX = curry2(
|
|
348
|
-
(a: AnyObject, b: AnyObject) => qmergeDeepX(clone(a),
|
|
383
|
+
(a: AnyObject, b: AnyObject) => qmergeDeepX(clone(a), b) as AnyObject
|
|
349
384
|
)
|
|
350
385
|
export const mergeDeepAdd = curry2(
|
|
351
|
-
(a: AnyObject, b: AnyObject) => qmergeDeepAdd(clone(a),
|
|
386
|
+
(a: AnyObject, b: AnyObject) => qmergeDeepAdd(clone(a), b) as AnyObject
|
|
352
387
|
)
|
|
388
|
+
/** @param prop string @param pipe(data[prop]) @param data any @returns data with prop over pipe. */
|
|
353
389
|
export const overProp = curry3(
|
|
354
390
|
(prop: string, pipe: AnyFunc, data: any) =>
|
|
355
391
|
assoc(prop, pipe(data[prop]), data)
|
package/src/strings.ts
CHANGED
|
@@ -6,13 +6,13 @@ const ecran = '\\'
|
|
|
6
6
|
|
|
7
7
|
// TODO: make it splicy, not accumulatie by symbols.
|
|
8
8
|
/** Supports ecrans: '\\{"json": {yes} \\}'
|
|
9
|
-
@returns
|
|
9
|
+
@returns getTmpl('one{meme}two')({meme: 42}) -> one42two */
|
|
10
10
|
export const getTmpl = (tmpl: string): StrTmpl => {
|
|
11
11
|
const parts: string[] = []
|
|
12
12
|
const keymap: string[] = []
|
|
13
13
|
const len = tmpl.length
|
|
14
14
|
let i = 0, s: string, ln: number, start = 0, open = false,
|
|
15
|
-
hasEcran =
|
|
15
|
+
hasEcran = false, hasEcranNext = false, nextChar: string
|
|
16
16
|
for(i=0; i<len; i++) {
|
|
17
17
|
s = tmpl[i]
|
|
18
18
|
switch(s) {
|
package/src/types.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
+
import { AnyArgs } from "./internal_types"
|
|
2
|
+
|
|
1
3
|
export type Cond = (x1?: any, x2?: any, x3?: any) => boolean
|
|
2
4
|
export interface AnyObject { [k: string]: any }
|
|
3
|
-
export type AnyArgs = any[]
|
|
4
5
|
export type Reducer<T=any> = (accum: T, cur: any, index: number) => T
|
|
5
6
|
export type AnyFunc<ReturnT = any, Args extends AnyArgs = AnyArgs> = (...args: Args) => ReturnT
|
|
6
|
-
export type
|
|
7
|
-
export type Curried<
|
|
8
|
-
Args extends AnyArgs = AnyArgs,
|
|
9
|
-
ReturnT = any
|
|
10
|
-
> = (arg: Args[number]) => Curried<Args> | ReturnT
|
|
11
|
-
export type BasicType = 'String'|'Object'|'Number'|'Symbol'|'Array'|'Null'|'Undefined'
|
|
7
|
+
export type Curried<Args extends AnyArgs = AnyArgs, ReturnT = any> = (arg: Args[number]) => Curried<Args> | ReturnT
|