@tutao/tutanota-utils 3.89.24 → 3.91.2
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/README.md +1 -6
- package/package.json +8 -16
- package/lib/ArrayUtils.js +0 -444
- package/lib/AsyncResult.js +0 -37
- package/lib/CollectionUtils.js +0 -10
- package/lib/DateUtils.js +0 -134
- package/lib/Encoding.js +0 -329
- package/lib/LazyLoaded.js +0 -87
- package/lib/MapUtils.js +0 -42
- package/lib/MathUtils.js +0 -12
- package/lib/PromiseMap.js +0 -121
- package/lib/PromiseUtils.js +0 -144
- package/lib/SortedArray.js +0 -66
- package/lib/StringUtils.js +0 -126
- package/lib/TypeRef.js +0 -25
- package/lib/Utils.js +0 -416
- package/lib/index.js +0 -207
package/lib/PromiseUtils.js
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
//@flow
|
|
2
|
-
import type {Options as PromiseMapOptions} from "./PromiseMap"
|
|
3
|
-
import {pMap as promiseMap} from "./PromiseMap"
|
|
4
|
-
|
|
5
|
-
export type $Promisable<+T> = Promise<T> | T;
|
|
6
|
-
type PromiseMapCallback<T, U> = (el: T, index: number) => $Promisable<U>
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Map array of values to promise of arrays or array. Mapper function may return promise or value. If value is returned,
|
|
11
|
-
* we avoid promise scheduling.
|
|
12
|
-
*
|
|
13
|
-
* This is needed to run the whole operation in one microtask (e.g. keep IndexedDB transaction active, which is closed in
|
|
14
|
-
* some browsers (e.g. Safari) when event loop iteration ends).
|
|
15
|
-
*/
|
|
16
|
-
export function mapInCallContext<T, U>(values: T[], callback: PromiseMapCallback<T, U>): PromisableWrapper<Array<U>> {
|
|
17
|
-
return new PromisableWrapper(_mapInCallContext(values, callback, 0, []))
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function _mapInCallContext<T, U>(values: T[], callback: PromiseMapCallback<T, U>, index: number, acc: U[]): $Promisable<Array<U>> {
|
|
21
|
-
if (index >= values.length) {
|
|
22
|
-
return acc
|
|
23
|
-
}
|
|
24
|
-
let mappedValue = callback(values[index], index)
|
|
25
|
-
if (mappedValue instanceof Promise) {
|
|
26
|
-
return mappedValue.then((v) => {
|
|
27
|
-
acc.push(v)
|
|
28
|
-
return _mapInCallContext(values, callback, index + 1, acc)
|
|
29
|
-
})
|
|
30
|
-
} else {
|
|
31
|
-
acc.push(mappedValue)
|
|
32
|
-
return _mapInCallContext(values, callback, index + 1, acc)
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export {pMap as promiseMap} from "./PromiseMap"
|
|
37
|
-
|
|
38
|
-
export type PromiseMapFn = <T, U>(values: T[], callback: PromiseMapCallback<T, U>, options?: PromiseMapOptions) => PromisableWrapper<U[]>
|
|
39
|
-
|
|
40
|
-
function mapNoFallback<T, U>(values: Array<T>, callback: PromiseMapCallback<T, U>, options?: PromiseMapOptions) {
|
|
41
|
-
return PromisableWrapper.from(promiseMap(values, callback, options))
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/** Factory function which gives you ack promiseMap implementation. {@see mapInCallContext} for what it means. */
|
|
45
|
-
export function promiseMapCompat(useMapInCallContext: boolean): PromiseMapFn {
|
|
46
|
-
return useMapInCallContext ? mapInCallContext : mapNoFallback
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function flatWrapper<T>(value: PromisableWrapper<T> | T): $Promisable<T> {
|
|
50
|
-
return value instanceof PromisableWrapper ? value.value : value
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// It kinda implements 'thenable' protocol so you can freely pass it around as a generic promise
|
|
54
|
-
export class PromisableWrapper<T> {
|
|
55
|
-
static from(value: $Promisable<T>): PromisableWrapper<T> {
|
|
56
|
-
return new PromisableWrapper(value)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
value: $Promisable<T>;
|
|
60
|
-
|
|
61
|
-
constructor(value: $Promisable<PromisableWrapper<T> | T>) {
|
|
62
|
-
this.value = value instanceof Promise ? value.then(flatWrapper) : flatWrapper(value);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
thenOrApply<R>(onFulfill: (T) => $Promisable<PromisableWrapper<R> | R>, onReject?: (any) => $Promisable<R | PromisableWrapper<R>>): PromisableWrapper<R> {
|
|
66
|
-
if (this.value instanceof Promise) {
|
|
67
|
-
const v: Promise<PromisableWrapper<R> | R> = this.value.then(onFulfill, onReject)
|
|
68
|
-
return new PromisableWrapper(v)
|
|
69
|
-
} else {
|
|
70
|
-
try {
|
|
71
|
-
return new PromisableWrapper(onFulfill(this.value))
|
|
72
|
-
} catch (e) {
|
|
73
|
-
if (onReject) {
|
|
74
|
-
return new PromisableWrapper<R>(onReject(e))
|
|
75
|
-
}
|
|
76
|
-
throw e
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
toPromise(): Promise<T> {
|
|
82
|
-
return Promise.resolve(this.value)
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export function delay(ms: number): Promise<void> {
|
|
87
|
-
return new Promise((resolve) => {
|
|
88
|
-
setTimeout(resolve, ms)
|
|
89
|
-
})
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Pass to Promise.then to perform an action while forwarding on the result
|
|
94
|
-
* @param action
|
|
95
|
-
*/
|
|
96
|
-
export function tap<T>(action: T => mixed): T => T {
|
|
97
|
-
return function (value) {
|
|
98
|
-
action(value)
|
|
99
|
-
return value
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Helper utility intended to be used with typed excpetions and .catch() method of promise like so:
|
|
105
|
-
*
|
|
106
|
-
* ```js
|
|
107
|
-
* class SpecificError extends Error {}
|
|
108
|
-
*
|
|
109
|
-
* Promise.reject(new SpecificError())
|
|
110
|
-
* .catch(ofClass(SpecificError, (e) => console.log("some error", e)))
|
|
111
|
-
* .catch((e) => console.log("generic error", e))
|
|
112
|
-
* ```
|
|
113
|
-
*
|
|
114
|
-
* @param cls Class which will be caught
|
|
115
|
-
* @param catcher to handle only errors of type cls
|
|
116
|
-
* @returns handler which either forwards to catcher or rethrows
|
|
117
|
-
*/
|
|
118
|
-
export function ofClass<E, R>(cls: Class<E>, catcher: (E) => $Promisable<R>): ((any) => Promise<R>) {
|
|
119
|
-
return async (e) => {
|
|
120
|
-
if (e instanceof cls) {
|
|
121
|
-
return catcher(e)
|
|
122
|
-
} else {
|
|
123
|
-
// It's okay to rethrow because:
|
|
124
|
-
// 1. It preserves the original stacktrace
|
|
125
|
-
// 2. Because of 1. it is not that expensive
|
|
126
|
-
throw e
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Filter iterable. Just like Array.prototype.filter but callback can return promises
|
|
133
|
-
*/
|
|
134
|
-
export async function promiseFilter<T>(iterable: Iterable<T>, filter: (item: T, index: number) => $Promisable<boolean>): Promise<Array<T>> {
|
|
135
|
-
let index = 0
|
|
136
|
-
const result = []
|
|
137
|
-
for (let item of iterable) {
|
|
138
|
-
if (await filter(item, index)) {
|
|
139
|
-
result.push(item)
|
|
140
|
-
}
|
|
141
|
-
index++
|
|
142
|
-
}
|
|
143
|
-
return result
|
|
144
|
-
}
|
package/lib/SortedArray.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
|
|
3
|
-
import {findAndRemove, insertIntoSortedArray} from "./ArrayUtils"
|
|
4
|
-
|
|
5
|
-
export type CompareFn<T> = (T, T) => number
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Compared based on the type's natural ordering
|
|
9
|
-
* @param a
|
|
10
|
-
* @param b
|
|
11
|
-
* @returns {number}
|
|
12
|
-
*/
|
|
13
|
-
// <T: Object> to get flow off my back about using comparison operator
|
|
14
|
-
// It should be fine for 99% of use cases? worst case it just returns 0 always
|
|
15
|
-
function defaultCompare<T: Object>(a: T, b: T): number {
|
|
16
|
-
return a < b
|
|
17
|
-
? -1
|
|
18
|
-
: a > b
|
|
19
|
-
? 1 : 0
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* An array that keeps itself sorted
|
|
24
|
-
*/
|
|
25
|
-
export class SortedArray<T> {
|
|
26
|
-
+_contents: Array<T>
|
|
27
|
-
+_compareFn: CompareFn<T>
|
|
28
|
-
|
|
29
|
-
constructor(compareFn: CompareFn<T> = defaultCompare) {
|
|
30
|
-
this._contents = []
|
|
31
|
-
this._compareFn = compareFn
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
static from(array: $ReadOnlyArray<T>, compareFn?: CompareFn<T>): SortedArray<T> {
|
|
35
|
-
const list = new SortedArray<T>(compareFn)
|
|
36
|
-
list.insertAll(array)
|
|
37
|
-
return list
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
get length(): number {
|
|
41
|
-
return this._contents.length
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
get array(): $ReadOnlyArray<T> {
|
|
45
|
-
return this._contents
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
get(index: number): T {
|
|
49
|
-
return this._contents[index]
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
insertAll(array: $ReadOnlyArray<T>) {
|
|
53
|
-
this._contents.push(...array)
|
|
54
|
-
this._contents.sort(this._compareFn)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
insert(item: T): void {
|
|
58
|
-
insertIntoSortedArray(item, this._contents, this._compareFn)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
removeFirst(finder: (T) => boolean): boolean {
|
|
62
|
-
return findAndRemove(this._contents, finder)
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
package/lib/StringUtils.js
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
|
|
3
|
-
import type {lazy} from "./Utils.js"
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Returns a string which contains the given number padded with 0s.
|
|
7
|
-
* @param num The number to pad.
|
|
8
|
-
* @param size The number of resulting digits.
|
|
9
|
-
* @return The padded number as string.
|
|
10
|
-
*/
|
|
11
|
-
export function pad(num: number, size: number): string {
|
|
12
|
-
var s = num + "";
|
|
13
|
-
while (s.length < size)
|
|
14
|
-
s = "0" + s;
|
|
15
|
-
return s;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Checks if a string starts with another string.
|
|
20
|
-
* @param string The string to test.
|
|
21
|
-
* @param substring If the other string begins with this one, we return true.
|
|
22
|
-
* @return True if string begins with substring, false otherwise.
|
|
23
|
-
*/
|
|
24
|
-
export function startsWith(string: string, substring: string): boolean {
|
|
25
|
-
return string.startsWith(substring)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* uppercase the first letter of a string, lowercase the rest
|
|
30
|
-
* @param str string to transform
|
|
31
|
-
* @returns {string} str in lowercase with first letter Capitalized
|
|
32
|
-
*/
|
|
33
|
-
export function capitalizeFirstLetter(str: string): string {
|
|
34
|
-
return str[0].toUpperCase() + str.toLowerCase().slice(1);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Checks if a string ends with another string.
|
|
39
|
-
* @param string The string to test.
|
|
40
|
-
* @param substring If the other string ends with this one, we return true.
|
|
41
|
-
* @return True if string ends with substring, false otherwise.
|
|
42
|
-
*/
|
|
43
|
-
export function endsWith(string: string, substring: string): boolean {
|
|
44
|
-
return string.endsWith(substring)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
export function lazyStringValue(valueOrLazy: string | lazy<string>): string {
|
|
49
|
-
return typeof valueOrLazy === "function"
|
|
50
|
-
? valueOrLazy()
|
|
51
|
-
: valueOrLazy
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function repeat(value: string, length: number): string {
|
|
55
|
-
let result = ""
|
|
56
|
-
for (let i = 0; i < length; i++) {
|
|
57
|
-
result += value;
|
|
58
|
-
}
|
|
59
|
-
return result
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function cleanMatch(s1: string, s2: string): boolean {
|
|
63
|
-
return s1.toLowerCase().trim() === s2.toLowerCase().trim()
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Non-breaking space character
|
|
68
|
-
*/
|
|
69
|
-
export const NBSP = "\u00A0";
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* split a string at a given index
|
|
73
|
-
* @param str
|
|
74
|
-
* @param index
|
|
75
|
-
*/
|
|
76
|
-
export function splitAt(str: string, index: number): [string, string] {
|
|
77
|
-
return [str.substring(0, index), str.substring(index)]
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Wrapper around String.prototype.toLowerCase, nice for calls to Array.prototype.map
|
|
82
|
-
* @param str
|
|
83
|
-
*/
|
|
84
|
-
export function toLowerCase(str: string): string {
|
|
85
|
-
return str.toLowerCase()
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Wrapper around String.prototype.localeCompare, for passing to Array.prototype.sort
|
|
90
|
-
* @param a
|
|
91
|
-
* @param b
|
|
92
|
-
* @returns {number}
|
|
93
|
-
*/
|
|
94
|
-
export function localeCompare(a: string, b: string): number {
|
|
95
|
-
return a.localeCompare(b)
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export function byteLength(str: ?string): number {
|
|
99
|
-
if (str == null) return 0
|
|
100
|
-
// returns the byte length of an utf8 string
|
|
101
|
-
var s = str.length;
|
|
102
|
-
for (var i = str.length - 1; i >= 0; i--) {
|
|
103
|
-
var code = str.charCodeAt(i);
|
|
104
|
-
if (code > 0x7f && code <= 0x7ff) {
|
|
105
|
-
s++;
|
|
106
|
-
} else if (code > 0x7ff && code <= 0xffff) s += 2;
|
|
107
|
-
if (code >= 0xDC00 && code <= 0xDFFF) i--; //trail surrogate
|
|
108
|
-
}
|
|
109
|
-
return s;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* replace all instances of substr in str with replacement
|
|
114
|
-
*/
|
|
115
|
-
export function replaceAll(str: string, substr: string, replacement: string): string {
|
|
116
|
-
const regex = escapedStringRegExp(substr, 'g')
|
|
117
|
-
return str.replace(regex, replacement)
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Create a regex to exactly match a given string, by escaping any special regex characters
|
|
122
|
-
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
|
|
123
|
-
* */
|
|
124
|
-
function escapedStringRegExp(str: string, flags: string): RegExp {
|
|
125
|
-
return new RegExp(str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), flags)
|
|
126
|
-
}
|
package/lib/TypeRef.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
//@flow
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Attention: TypeRef must be defined as class and not as Flow type because object types use structural typing and TypeRef does not
|
|
5
|
-
* reference T. See https://github.com/facebook/flow/issues/3348
|
|
6
|
-
* T should be bound to entities but we have no type to define them yet.
|
|
7
|
-
*/
|
|
8
|
-
export class TypeRef<+T> {
|
|
9
|
-
+app: string;
|
|
10
|
-
+type: string;
|
|
11
|
-
|
|
12
|
-
constructor(app: string, type: string) {
|
|
13
|
-
this.app = app
|
|
14
|
-
this.type = type
|
|
15
|
-
Object.freeze(this)
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function isSameTypeRefByAttr(typeRef: TypeRef<any>, app: string, type: string): boolean {
|
|
20
|
-
return typeRef.app === app && typeRef.type === type
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function isSameTypeRef(typeRef1: TypeRef<any>, typeRef2: TypeRef<any>): boolean {
|
|
24
|
-
return isSameTypeRefByAttr(typeRef1, typeRef2.app, typeRef2.type)
|
|
25
|
-
}
|