@tutao/tutanota-utils 3.91.2 → 3.91.6
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/ArrayUtils.d.ts +148 -0
- package/dist/ArrayUtils.js +410 -0
- package/dist/AsyncResult.d.ts +23 -0
- package/dist/AsyncResult.js +31 -0
- package/dist/CollectionUtils.d.ts +5 -0
- package/dist/CollectionUtils.js +7 -0
- package/dist/DateUtils.d.ts +60 -0
- package/dist/DateUtils.js +114 -0
- package/dist/Encoding.d.ts +103 -0
- package/dist/Encoding.js +306 -0
- package/dist/LazyLoaded.d.ts +38 -0
- package/dist/LazyLoaded.js +72 -0
- package/dist/MapUtils.d.ts +9 -0
- package/dist/MapUtils.js +38 -0
- package/dist/MathUtils.d.ts +5 -0
- package/dist/MathUtils.js +9 -0
- package/dist/PromiseMap.d.ts +44 -0
- package/dist/PromiseMap.js +75 -0
- package/dist/PromiseUtils.d.ts +48 -0
- package/dist/PromiseUtils.js +127 -0
- package/dist/SortedArray.d.ts +16 -0
- package/dist/SortedArray.js +44 -0
- package/dist/StringUtils.d.ts +58 -0
- package/dist/StringUtils.js +110 -0
- package/dist/TypeRef.d.ts +12 -0
- package/dist/TypeRef.js +19 -0
- package/dist/Utils.d.ts +125 -0
- package/dist/Utils.js +359 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +14 -0
- package/package.json +2 -2
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
export declare function concat(...arrays: Uint8Array[]): Uint8Array;
|
|
2
|
+
export declare function numberRange(min: number, max: number): Array<number>;
|
|
3
|
+
/**
|
|
4
|
+
* Compares two arrays for equality based on ===.
|
|
5
|
+
* @param {Array} a1 The first array.
|
|
6
|
+
* @param {Array} a2 The second array.
|
|
7
|
+
* @return {boolean} True if the arrays are equal, false otherwise.
|
|
8
|
+
*
|
|
9
|
+
* It is valid to compare Uint8Array to Array<T>, don't restrict it to be one type
|
|
10
|
+
*/
|
|
11
|
+
export declare function arrayEquals<T, A extends Uint8Array | Array<T>>(a1: A, a2: A): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Compares two arrays for equality based on a predicate
|
|
14
|
+
* @param a1
|
|
15
|
+
* @param a2
|
|
16
|
+
* @param predicate
|
|
17
|
+
* @returns {boolean}
|
|
18
|
+
*/
|
|
19
|
+
export declare function arrayEqualsWithPredicate<T>(a1: ReadonlyArray<T>, a2: ReadonlyArray<T>, predicate: (arg0: T, arg1: T) => boolean): boolean;
|
|
20
|
+
export declare function arrayHash(array: Uint8Array): number;
|
|
21
|
+
/**
|
|
22
|
+
* Remove the element from theArray if it is contained in the array.
|
|
23
|
+
* @param theArray The array to remove the element from.
|
|
24
|
+
* @param elementToRemove The element to remove from the array.
|
|
25
|
+
* @return True if the element was removed, false otherwise.
|
|
26
|
+
*/
|
|
27
|
+
export declare function remove<T>(theArray: Array<T>, elementToRemove: T): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Find all items in an array that pass the given predicate
|
|
30
|
+
*/
|
|
31
|
+
export declare function findAll<T>(theArray: Array<T>, finder: (arg0: T) => boolean): Array<T>;
|
|
32
|
+
/**
|
|
33
|
+
* @param theArray
|
|
34
|
+
* @param finder
|
|
35
|
+
* @return {boolean} if the element was found
|
|
36
|
+
*/
|
|
37
|
+
export declare function findAndRemove<T>(theArray: Array<T>, finder: (arg0: T) => boolean): boolean;
|
|
38
|
+
export declare function findAllAndRemove<T>(theArray: Array<T>, finder: (arg0: T) => boolean, startIndex?: number): boolean;
|
|
39
|
+
export declare function replace(theArray: Array<any>, oldElement: any, newElement: any): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Same as filterMap in some languages. Apply mapper and then only include non-nullable items.
|
|
42
|
+
*/
|
|
43
|
+
export declare function mapAndFilterNull<T, R>(array: ReadonlyArray<T>, mapper: (arg0: T) => R | null | undefined): Array<R>;
|
|
44
|
+
export declare function filterNull<T>(array: ReadonlyArray<T | null | undefined>): Array<T>;
|
|
45
|
+
/**
|
|
46
|
+
* Provides the last element of the given array.
|
|
47
|
+
* @param theArray The array.
|
|
48
|
+
* @return The last element of the array.
|
|
49
|
+
*/
|
|
50
|
+
export declare function last<T>(theArray: ReadonlyArray<T>): T | null | undefined;
|
|
51
|
+
export declare function isEmpty<T>(array: ReadonlyArray<T>): boolean;
|
|
52
|
+
export declare function lastThrow<T>(array: ReadonlyArray<T>): T;
|
|
53
|
+
export declare function firstThrow<T>(array: ReadonlyArray<T>): T;
|
|
54
|
+
export declare function first<T>(array: ReadonlyArray<T>): T | null;
|
|
55
|
+
export declare function findLast<T>(array: Array<T>, predicate: (arg0: T) => boolean): T | null | undefined;
|
|
56
|
+
export declare function findLastIndex<T>(array: Array<T>, predicate: (arg0: T) => boolean): number;
|
|
57
|
+
export declare function contains(theArray: Array<any>, elementToCheck: any): boolean;
|
|
58
|
+
export declare function addAll(array: Array<any>, elements: Array<any>): void;
|
|
59
|
+
export declare function removeAll(array: Array<any>, elements: Array<any>): void;
|
|
60
|
+
/**
|
|
61
|
+
* Group an array based on the given discriminator, but each group will have only unique items
|
|
62
|
+
*/
|
|
63
|
+
export declare function groupByAndMapUniquely<T, R, E>(iterable: Iterable<T>, discriminator: (arg0: T) => R, mapper: (arg0: T) => E): Map<R, Set<E>>;
|
|
64
|
+
/**
|
|
65
|
+
* convert an Array of T's into a Map of Arrays of E's by
|
|
66
|
+
* * grouping them based on a discriminator
|
|
67
|
+
* * mapping them from T to E
|
|
68
|
+
* @param iterable the array to split into groups
|
|
69
|
+
* @param discriminator a function that produces the keys to group the elements by
|
|
70
|
+
* @param mapper a function that maps the array elements before they get added to the group
|
|
71
|
+
* @returns {Map<R, Array<E>>}
|
|
72
|
+
*/
|
|
73
|
+
export declare function groupByAndMap<T, R, E>(iterable: Iterable<T>, discriminator: (arg0: T) => R, mapper: (arg0: T) => E): Map<R, Array<E>>;
|
|
74
|
+
/**
|
|
75
|
+
* Group array elements based on keys produced by a discriminator
|
|
76
|
+
* @param iterable the array to split into groups
|
|
77
|
+
* @param discriminator a function that produces the keys to group the elements by
|
|
78
|
+
* @returns {NodeJS.Global.Map<R, Array<T>>}
|
|
79
|
+
*/
|
|
80
|
+
export declare function groupBy<T, R>(iterable: Iterable<T>, discriminator: (arg0: T) => R): Map<R, Array<T>>;
|
|
81
|
+
/**
|
|
82
|
+
* split an array into chunks of a given size.
|
|
83
|
+
* the last chunk will be smaller if there are less than chunkSize elements left.
|
|
84
|
+
* @param chunkSize
|
|
85
|
+
* @param array
|
|
86
|
+
* @returns {Array<Array<T>>}
|
|
87
|
+
*/
|
|
88
|
+
export declare function splitInChunks<T>(chunkSize: number, array: Array<T>): Array<Array<T>>;
|
|
89
|
+
export declare function flat<T>(arrays: ReadonlyArray<ReadonlyArray<T>>): Array<T>;
|
|
90
|
+
/**
|
|
91
|
+
* Maps an array into a nested array and then flattens it
|
|
92
|
+
* @param array
|
|
93
|
+
* @param mapper
|
|
94
|
+
* @returns {T|*[]}
|
|
95
|
+
*/
|
|
96
|
+
export declare function flatMap<T, U>(array: ReadonlyArray<T>, mapper: (arg0: T) => Array<U>): Array<U>;
|
|
97
|
+
/**
|
|
98
|
+
* Inserts element into the sorted array. Will find <b>the last</b> matching position.
|
|
99
|
+
* Might add or replace element based on {@param replaceIf} identity check.
|
|
100
|
+
* Equality per {@param comparator} is precondition for replacement.
|
|
101
|
+
* @param element to place
|
|
102
|
+
* @param array where element should be placed
|
|
103
|
+
* @param comparator for sorting
|
|
104
|
+
* @param replaceIf identity comparison for replacement
|
|
105
|
+
*/
|
|
106
|
+
export declare function insertIntoSortedArray<T>(element: T, array: Array<T>, comparator: (left: T, right: T) => number, replaceIf?: (newElement: T, existing: T) => boolean): void;
|
|
107
|
+
export declare function zip<A, B>(arr1: Array<A>, arr2: Array<B>): Array<[A, B]>;
|
|
108
|
+
export declare function deduplicate<T>(arr: Array<T>, comp?: (arg0: T, arg1: T) => boolean): Array<T>;
|
|
109
|
+
/**
|
|
110
|
+
* http://jsfiddle.net/aryzhov/pkfst550/
|
|
111
|
+
* Binary search in JavaScript.
|
|
112
|
+
* Returns the index of of the element in a sorted array or (-n-1) where n is the insertion point for the new element.
|
|
113
|
+
* Parameters:
|
|
114
|
+
* ar - A sorted array
|
|
115
|
+
* el - An element to search for
|
|
116
|
+
* compare_fn - A comparator function. The function takes two arguments: (a, b) and returns:
|
|
117
|
+
* a negative number if a is less than b;
|
|
118
|
+
* 0 if a is equal to b;
|
|
119
|
+
* a positive number of a is greater than b.
|
|
120
|
+
* The array may contain duplicate elements. If there are more than one equal elements in the array,
|
|
121
|
+
* the returned value can be the index of any one of the equal elements.
|
|
122
|
+
*/
|
|
123
|
+
export declare function binarySearch<T>(ar: Array<T>, el: T, compare_fn: (arg0: T, arg1: T) => number): number;
|
|
124
|
+
export declare function lastIndex<T>(array: ReadonlyArray<T>): number;
|
|
125
|
+
/**
|
|
126
|
+
* All of the elements in all of the arguments combined, and deduplicated
|
|
127
|
+
*/
|
|
128
|
+
export declare function union<T>(...iterables: Array<Iterable<T>>): Set<T>;
|
|
129
|
+
/**
|
|
130
|
+
* return a new array containing every item from array1 that isn't in array2
|
|
131
|
+
* @param array1
|
|
132
|
+
* @param array2
|
|
133
|
+
* @param compare: compare items in the array for equality
|
|
134
|
+
* @returns {Array<$NonMaybeType<T>>|Array<T>}
|
|
135
|
+
*/
|
|
136
|
+
export declare function difference<T>(array1: ReadonlyArray<T>, array2: ReadonlyArray<T>, compare?: (arg0: T, arg1: T) => boolean): Array<T>;
|
|
137
|
+
/**
|
|
138
|
+
* Returns a set with elements that are *not* in both sets.
|
|
139
|
+
*
|
|
140
|
+
* {a, b, c} △ {b, c, d} == {a, d}
|
|
141
|
+
*/
|
|
142
|
+
export declare function symmetricDifference<T>(set1: ReadonlySet<T>, set2: ReadonlySet<T>): Set<T>;
|
|
143
|
+
/**
|
|
144
|
+
* Splits an array into two based on a predicate, where elements that match the predicate go into the left side
|
|
145
|
+
* @param array
|
|
146
|
+
* @param predicate
|
|
147
|
+
*/
|
|
148
|
+
export declare function partition<T>(array: Array<T>, predicate: (arg0: T) => boolean): [Array<T>, Array<T>];
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
import { downcast, identity, neverNull } from "./Utils.js";
|
|
2
|
+
import { getFromMap } from "./MapUtils.js";
|
|
3
|
+
export function concat(...arrays) {
|
|
4
|
+
let length = arrays.reduce((previous, current) => previous + current.length, 0);
|
|
5
|
+
let result = new Uint8Array(length);
|
|
6
|
+
let index = 0;
|
|
7
|
+
arrays.forEach(array => {
|
|
8
|
+
result.set(array, index);
|
|
9
|
+
index += array.length;
|
|
10
|
+
});
|
|
11
|
+
return result;
|
|
12
|
+
}
|
|
13
|
+
export function numberRange(min, max) {
|
|
14
|
+
return [...Array(max + 1).keys()].slice(min);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Compares two arrays for equality based on ===.
|
|
18
|
+
* @param {Array} a1 The first array.
|
|
19
|
+
* @param {Array} a2 The second array.
|
|
20
|
+
* @return {boolean} True if the arrays are equal, false otherwise.
|
|
21
|
+
*
|
|
22
|
+
* It is valid to compare Uint8Array to Array<T>, don't restrict it to be one type
|
|
23
|
+
*/
|
|
24
|
+
export function arrayEquals(a1, a2) {
|
|
25
|
+
if (a1 === a2) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
if (a1.length === a2.length) {
|
|
29
|
+
for (let i = 0; i < a1.length; i++) {
|
|
30
|
+
if (a1[i] !== a2[i]) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Compares two arrays for equality based on a predicate
|
|
40
|
+
* @param a1
|
|
41
|
+
* @param a2
|
|
42
|
+
* @param predicate
|
|
43
|
+
* @returns {boolean}
|
|
44
|
+
*/
|
|
45
|
+
export function arrayEqualsWithPredicate(a1, a2, predicate) {
|
|
46
|
+
if (a1.length === a2.length) {
|
|
47
|
+
for (let i = 0; i < a1.length; i++) {
|
|
48
|
+
if (!predicate(a1[i], a2[i])) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
export function arrayHash(array) {
|
|
57
|
+
let hash = 0;
|
|
58
|
+
hash |= 0;
|
|
59
|
+
for (let i = 0; i < array.length; i++) {
|
|
60
|
+
hash = (hash << 5) - hash + array[i];
|
|
61
|
+
hash |= 0; // Convert to 32bit integer
|
|
62
|
+
}
|
|
63
|
+
return hash;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Remove the element from theArray if it is contained in the array.
|
|
67
|
+
* @param theArray The array to remove the element from.
|
|
68
|
+
* @param elementToRemove The element to remove from the array.
|
|
69
|
+
* @return True if the element was removed, false otherwise.
|
|
70
|
+
*/
|
|
71
|
+
export function remove(theArray, elementToRemove) {
|
|
72
|
+
let i = theArray.indexOf(elementToRemove);
|
|
73
|
+
if (i !== -1) {
|
|
74
|
+
theArray.splice(i, 1);
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Find all items in an array that pass the given predicate
|
|
83
|
+
*/
|
|
84
|
+
export function findAll(theArray, finder) {
|
|
85
|
+
const found = [];
|
|
86
|
+
for (let element of theArray) {
|
|
87
|
+
if (finder(element)) {
|
|
88
|
+
found.push(element);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return found;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* @param theArray
|
|
95
|
+
* @param finder
|
|
96
|
+
* @return {boolean} if the element was found
|
|
97
|
+
*/
|
|
98
|
+
export function findAndRemove(theArray, finder) {
|
|
99
|
+
const index = theArray.findIndex(finder);
|
|
100
|
+
if (index !== -1) {
|
|
101
|
+
theArray.splice(index, 1);
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
export function findAllAndRemove(theArray, finder, startIndex = 0) {
|
|
109
|
+
var removedElement = false;
|
|
110
|
+
for (let i = theArray.length - 1; i >= startIndex; i--) {
|
|
111
|
+
if (finder(theArray[i])) {
|
|
112
|
+
theArray.splice(i, 1);
|
|
113
|
+
removedElement = true;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return removedElement;
|
|
117
|
+
}
|
|
118
|
+
export function replace(theArray, oldElement, newElement) {
|
|
119
|
+
let i = theArray.indexOf(oldElement);
|
|
120
|
+
if (i !== -1) {
|
|
121
|
+
theArray.splice(i, 1, newElement);
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Same as filterMap in some languages. Apply mapper and then only include non-nullable items.
|
|
130
|
+
*/
|
|
131
|
+
export function mapAndFilterNull(array, mapper) {
|
|
132
|
+
const resultList = [];
|
|
133
|
+
for (const item of array) {
|
|
134
|
+
const resultItem = mapper(item);
|
|
135
|
+
if (resultItem != null) {
|
|
136
|
+
resultList.push(resultItem);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return resultList;
|
|
140
|
+
}
|
|
141
|
+
export function filterNull(array) {
|
|
142
|
+
return downcast(array.filter(item => item != null));
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Provides the last element of the given array.
|
|
146
|
+
* @param theArray The array.
|
|
147
|
+
* @return The last element of the array.
|
|
148
|
+
*/
|
|
149
|
+
export function last(theArray) {
|
|
150
|
+
return theArray[theArray.length - 1];
|
|
151
|
+
}
|
|
152
|
+
export function isEmpty(array) {
|
|
153
|
+
return array.length === 0;
|
|
154
|
+
}
|
|
155
|
+
export function lastThrow(array) {
|
|
156
|
+
if (isEmpty(array)) {
|
|
157
|
+
throw new RangeError("Array is empty");
|
|
158
|
+
}
|
|
159
|
+
return neverNull(last(array));
|
|
160
|
+
}
|
|
161
|
+
export function firstThrow(array) {
|
|
162
|
+
if (isEmpty(array)) {
|
|
163
|
+
throw new RangeError("Array is empty");
|
|
164
|
+
}
|
|
165
|
+
return array[0];
|
|
166
|
+
}
|
|
167
|
+
export function first(array) {
|
|
168
|
+
return array[0] || null;
|
|
169
|
+
}
|
|
170
|
+
export function findLast(array, predicate) {
|
|
171
|
+
const index = findLastIndex(array, predicate);
|
|
172
|
+
if (index !== -1) {
|
|
173
|
+
return array[index];
|
|
174
|
+
}
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
export function findLastIndex(array, predicate) {
|
|
178
|
+
for (let i = array.length - 1; i >= 0; i--) {
|
|
179
|
+
if (predicate(array[i])) {
|
|
180
|
+
return i;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return -1;
|
|
184
|
+
}
|
|
185
|
+
export function contains(theArray, elementToCheck) {
|
|
186
|
+
return theArray.indexOf(elementToCheck) !== -1;
|
|
187
|
+
}
|
|
188
|
+
export function addAll(array, elements) {
|
|
189
|
+
array.push(...elements);
|
|
190
|
+
}
|
|
191
|
+
export function removeAll(array, elements) {
|
|
192
|
+
elements.forEach(element => {
|
|
193
|
+
remove(array, element);
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Group an array based on the given discriminator, but each group will have only unique items
|
|
198
|
+
*/
|
|
199
|
+
export function groupByAndMapUniquely(iterable, discriminator, mapper) {
|
|
200
|
+
const map = new Map();
|
|
201
|
+
for (let el of iterable) {
|
|
202
|
+
const key = discriminator(el);
|
|
203
|
+
getFromMap(map, key, () => new Set()).add(mapper(el));
|
|
204
|
+
}
|
|
205
|
+
return map;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* convert an Array of T's into a Map of Arrays of E's by
|
|
209
|
+
* * grouping them based on a discriminator
|
|
210
|
+
* * mapping them from T to E
|
|
211
|
+
* @param iterable the array to split into groups
|
|
212
|
+
* @param discriminator a function that produces the keys to group the elements by
|
|
213
|
+
* @param mapper a function that maps the array elements before they get added to the group
|
|
214
|
+
* @returns {Map<R, Array<E>>}
|
|
215
|
+
*/
|
|
216
|
+
export function groupByAndMap(iterable, discriminator, mapper) {
|
|
217
|
+
const map = new Map();
|
|
218
|
+
for (let el of iterable) {
|
|
219
|
+
const key = discriminator(el);
|
|
220
|
+
getFromMap(map, key, () => []).push(mapper(el));
|
|
221
|
+
}
|
|
222
|
+
return map;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Group array elements based on keys produced by a discriminator
|
|
226
|
+
* @param iterable the array to split into groups
|
|
227
|
+
* @param discriminator a function that produces the keys to group the elements by
|
|
228
|
+
* @returns {NodeJS.Global.Map<R, Array<T>>}
|
|
229
|
+
*/
|
|
230
|
+
export function groupBy(iterable, discriminator) {
|
|
231
|
+
return groupByAndMap(iterable, discriminator, identity);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* split an array into chunks of a given size.
|
|
235
|
+
* the last chunk will be smaller if there are less than chunkSize elements left.
|
|
236
|
+
* @param chunkSize
|
|
237
|
+
* @param array
|
|
238
|
+
* @returns {Array<Array<T>>}
|
|
239
|
+
*/
|
|
240
|
+
export function splitInChunks(chunkSize, array) {
|
|
241
|
+
if (chunkSize < 1) {
|
|
242
|
+
return [];
|
|
243
|
+
}
|
|
244
|
+
let chunkNum = 0;
|
|
245
|
+
const chunks = [];
|
|
246
|
+
let end;
|
|
247
|
+
do {
|
|
248
|
+
let start = chunkNum * chunkSize;
|
|
249
|
+
end = start + chunkSize;
|
|
250
|
+
chunks[chunkNum] = array.slice(start, end);
|
|
251
|
+
chunkNum++;
|
|
252
|
+
} while (end < array.length);
|
|
253
|
+
return chunks;
|
|
254
|
+
}
|
|
255
|
+
export function flat(arrays) {
|
|
256
|
+
return arrays.flat();
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Maps an array into a nested array and then flattens it
|
|
260
|
+
* @param array
|
|
261
|
+
* @param mapper
|
|
262
|
+
* @returns {T|*[]}
|
|
263
|
+
*/
|
|
264
|
+
export function flatMap(array, mapper) {
|
|
265
|
+
const result = [];
|
|
266
|
+
for (const item of array) {
|
|
267
|
+
const mapped = mapper(item);
|
|
268
|
+
result.push(...mapped);
|
|
269
|
+
}
|
|
270
|
+
return result;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Inserts element into the sorted array. Will find <b>the last</b> matching position.
|
|
274
|
+
* Might add or replace element based on {@param replaceIf} identity check.
|
|
275
|
+
* Equality per {@param comparator} is precondition for replacement.
|
|
276
|
+
* @param element to place
|
|
277
|
+
* @param array where element should be placed
|
|
278
|
+
* @param comparator for sorting
|
|
279
|
+
* @param replaceIf identity comparison for replacement
|
|
280
|
+
*/
|
|
281
|
+
export function insertIntoSortedArray(element, array, comparator, replaceIf = () => false) {
|
|
282
|
+
let i = 0;
|
|
283
|
+
while (i < array.length) {
|
|
284
|
+
const compareResult = comparator(array[i], element);
|
|
285
|
+
// We need to check for replacement for each element that is equal or we might miss it
|
|
286
|
+
if (compareResult === 0 && replaceIf(element, array[i])) {
|
|
287
|
+
array.splice(i, 1, element);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
else if (compareResult <= 0) {
|
|
291
|
+
// We continue searching until the last suitable position
|
|
292
|
+
i++;
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
// This also handles empty array
|
|
299
|
+
array.splice(i, 0, element);
|
|
300
|
+
}
|
|
301
|
+
export function zip(arr1, arr2) {
|
|
302
|
+
const zipped = [];
|
|
303
|
+
for (let i = 0; i < Math.min(arr1.length, arr2.length); i++) {
|
|
304
|
+
zipped.push([arr1[i], arr2[i]]);
|
|
305
|
+
}
|
|
306
|
+
return zipped;
|
|
307
|
+
}
|
|
308
|
+
export function deduplicate(arr, comp = (a, b) => a === b) {
|
|
309
|
+
const deduplicated = [];
|
|
310
|
+
arr.forEach(a => {
|
|
311
|
+
const isDuplicate = deduplicated.some(b => comp(a, b));
|
|
312
|
+
if (!isDuplicate) {
|
|
313
|
+
deduplicated.push(a);
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
return deduplicated;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* http://jsfiddle.net/aryzhov/pkfst550/
|
|
320
|
+
* Binary search in JavaScript.
|
|
321
|
+
* Returns the index of of the element in a sorted array or (-n-1) where n is the insertion point for the new element.
|
|
322
|
+
* Parameters:
|
|
323
|
+
* ar - A sorted array
|
|
324
|
+
* el - An element to search for
|
|
325
|
+
* compare_fn - A comparator function. The function takes two arguments: (a, b) and returns:
|
|
326
|
+
* a negative number if a is less than b;
|
|
327
|
+
* 0 if a is equal to b;
|
|
328
|
+
* a positive number of a is greater than b.
|
|
329
|
+
* The array may contain duplicate elements. If there are more than one equal elements in the array,
|
|
330
|
+
* the returned value can be the index of any one of the equal elements.
|
|
331
|
+
*/
|
|
332
|
+
export function binarySearch(ar, el, compare_fn) {
|
|
333
|
+
var m = 0;
|
|
334
|
+
var n = ar.length - 1;
|
|
335
|
+
while (m <= n) {
|
|
336
|
+
var k = (n + m) >> 1;
|
|
337
|
+
var cmp = compare_fn(el, ar[k]);
|
|
338
|
+
if (cmp > 0) {
|
|
339
|
+
m = k + 1;
|
|
340
|
+
}
|
|
341
|
+
else if (cmp < 0) {
|
|
342
|
+
n = k - 1;
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
return k;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return -m - 1;
|
|
349
|
+
}
|
|
350
|
+
export function lastIndex(array) {
|
|
351
|
+
if (array.length === 0) {
|
|
352
|
+
return 0;
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
return array.length - 1;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* All of the elements in all of the arguments combined, and deduplicated
|
|
360
|
+
*/
|
|
361
|
+
export function union(...iterables) {
|
|
362
|
+
return new Set(...iterables.map(iterable => Array.from(iterable)));
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* return a new array containing every item from array1 that isn't in array2
|
|
366
|
+
* @param array1
|
|
367
|
+
* @param array2
|
|
368
|
+
* @param compare: compare items in the array for equality
|
|
369
|
+
* @returns {Array<$NonMaybeType<T>>|Array<T>}
|
|
370
|
+
*/
|
|
371
|
+
export function difference(array1, array2, compare = (a, b) => a === b) {
|
|
372
|
+
return array1.filter(element1 => !array2.some(element2 => compare(element1, element2)));
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Returns a set with elements that are *not* in both sets.
|
|
376
|
+
*
|
|
377
|
+
* {a, b, c} △ {b, c, d} == {a, d}
|
|
378
|
+
*/
|
|
379
|
+
export function symmetricDifference(set1, set2) {
|
|
380
|
+
const diff = new Set();
|
|
381
|
+
for (const el of set1) {
|
|
382
|
+
if (!set2.has(el)) {
|
|
383
|
+
diff.add(el);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
for (const el of set2) {
|
|
387
|
+
if (!set1.has(el)) {
|
|
388
|
+
diff.add(el);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return diff;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Splits an array into two based on a predicate, where elements that match the predicate go into the left side
|
|
395
|
+
* @param array
|
|
396
|
+
* @param predicate
|
|
397
|
+
*/
|
|
398
|
+
export function partition(array, predicate) {
|
|
399
|
+
const left = [];
|
|
400
|
+
const right = [];
|
|
401
|
+
for (let item of array) {
|
|
402
|
+
if (predicate(item)) {
|
|
403
|
+
left.push(item);
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
right.push(item);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return [left, right];
|
|
410
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
declare type StatePending<T> = {
|
|
2
|
+
status: "pending";
|
|
3
|
+
promise: Promise<T>;
|
|
4
|
+
};
|
|
5
|
+
declare type StateComplete<T> = {
|
|
6
|
+
status: "complete";
|
|
7
|
+
result: T;
|
|
8
|
+
};
|
|
9
|
+
declare type StateFailure = {
|
|
10
|
+
status: "failure";
|
|
11
|
+
error: any;
|
|
12
|
+
};
|
|
13
|
+
declare type AsyncResultState<T> = StatePending<T> | StateComplete<T> | StateFailure;
|
|
14
|
+
/**
|
|
15
|
+
* Represents a resource that is either not ready, ready, or error
|
|
16
|
+
* Sort of fills a similar role to LazyLoaded, usage is more verbose but also more typesafe. maybe this should be reconciled.
|
|
17
|
+
*/
|
|
18
|
+
export declare class AsyncResult<T> {
|
|
19
|
+
_state: AsyncResultState<T>;
|
|
20
|
+
constructor(promise: Promise<T>);
|
|
21
|
+
state(): Readonly<AsyncResultState<T>>;
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a resource that is either not ready, ready, or error
|
|
3
|
+
* Sort of fills a similar role to LazyLoaded, usage is more verbose but also more typesafe. maybe this should be reconciled.
|
|
4
|
+
*/
|
|
5
|
+
export class AsyncResult {
|
|
6
|
+
constructor(promise) {
|
|
7
|
+
this._state = pending(promise);
|
|
8
|
+
promise.then(result => (this._state = complete(result))).catch(error => (this._state = failure(error)));
|
|
9
|
+
}
|
|
10
|
+
state() {
|
|
11
|
+
return this._state;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function pending(promise) {
|
|
15
|
+
return {
|
|
16
|
+
status: "pending",
|
|
17
|
+
promise,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function complete(result) {
|
|
21
|
+
return {
|
|
22
|
+
status: "complete",
|
|
23
|
+
result,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function failure(error) {
|
|
27
|
+
return {
|
|
28
|
+
status: "failure",
|
|
29
|
+
error,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file DateUtils which do not use Luxon. Used in worker as well as in client parts.
|
|
3
|
+
* As functions here do not use Luxon it cannot be used for calculating things in different time zones, they
|
|
4
|
+
* are dependent on the system time zone.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DAY_IN_MILLIS: number;
|
|
7
|
+
/**
|
|
8
|
+
* Provides a date representing the beginning of the next day of the given date in local time.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getStartOfNextDay(date: Date): Date;
|
|
11
|
+
/**
|
|
12
|
+
* Provides a date representing the end of the given date in local time.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getEndOfDay(date: Date): Date;
|
|
15
|
+
/**
|
|
16
|
+
* Provides a date representing the beginning of the given date in local time.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getStartOfDay(date: Date): Date;
|
|
19
|
+
/**
|
|
20
|
+
* Provides a date representing the day of the given date at the given hour in local time.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getHourOfDay(date: Date, hour: number): Date;
|
|
23
|
+
export declare function isStartOfDay(date: Date): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Returns true if the given date is today in local time.
|
|
26
|
+
*/
|
|
27
|
+
export declare function isToday(date: Date): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Returns true if the given dates represent the same day (time of day is ignored).
|
|
30
|
+
*/
|
|
31
|
+
export declare function isSameDay(date1: Date, date2: Date): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Creates new date in with {@param days} added to it as if the days are just fixed
|
|
34
|
+
* periods of time and are not subject to daylight saving.
|
|
35
|
+
*/
|
|
36
|
+
export declare function getDayShifted(date: Date, days: number): Date;
|
|
37
|
+
/**
|
|
38
|
+
* Increment the date in place and return it
|
|
39
|
+
*/
|
|
40
|
+
export declare function incrementDate(date: Date, byValue: number): Date;
|
|
41
|
+
export declare function incrementMonth(d: Date, byValue: number): Date;
|
|
42
|
+
export declare function isSameDayOfDate(date1: Date | null | undefined, date2: Date | null | undefined): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Formats as yyyy-mm-dd
|
|
45
|
+
*/
|
|
46
|
+
export declare function formatSortableDate(date: Date): string;
|
|
47
|
+
/**
|
|
48
|
+
* Formats as yyyy-mm-dd-<hh>h-<mm>m-<ss>
|
|
49
|
+
*/
|
|
50
|
+
export declare function formatSortableDateTime(date: Date): string;
|
|
51
|
+
/**
|
|
52
|
+
* @returns {string} sortableDateTime of the current time
|
|
53
|
+
*/
|
|
54
|
+
export declare function sortableTimestamp(): string;
|
|
55
|
+
export declare function isValidDate(date: Date): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* not interested in any fancy calendar edge cases, only use this where approximation is ok
|
|
58
|
+
*/
|
|
59
|
+
export declare function millisToDays(millis: number): number;
|
|
60
|
+
export declare function daysToMillis(days: number): number;
|