@tutao/tutanota-utils 3.91.2 → 3.91.3

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.
@@ -0,0 +1,9 @@
1
+ export function mod(n, m) {
2
+ return ((n % m) + m) % m;
3
+ }
4
+ /**
5
+ * Clamp value to between min and max (inclusive)
6
+ */
7
+ export function clamp(value, min, max) {
8
+ return Math.max(min, Math.min(value, max));
9
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @file Vendored version of p-map: https://github.com/sindresorhus/p-map/
3
+ * Vendored to avoid having dependency on AggregateError.
4
+ *
5
+ * Changed: default concurrency level is 1 and not Infinite
6
+ */
7
+ export interface Options {
8
+ /**
9
+ Number of concurrently pending promises returned by `mapper`.
10
+ Must be an integer from 1 and up or `Infinity`.
11
+ @default 1
12
+ */
13
+ readonly concurrency?: number;
14
+ }
15
+ /**
16
+ Function which is called for every item in `input`. Expected to return a `Promise` or value.
17
+ @param element - Iterated element.
18
+ @param index - Index of the element in the source array.
19
+ */
20
+ export declare type Mapper<Element, NewElement> = (element: Element, index: number) => Promise<NewElement> | NewElement;
21
+ /**
22
+ @param iterable - Iterated over concurrently in the `mapper` function.
23
+ @param mapper - Function which is called for every item in `input`. Expected to return a `Promise` or value.
24
+ @param options
25
+ @returns A `Promise` that is fulfilled when all promises in `input` and ones returned from `mapper` are fulfilled, or rejects if any of the promises reject. The fulfilled value is an `Array` of the fulfilled values returned from `mapper` in `input` order.
26
+ @example
27
+ ```
28
+ import pMap from 'p-map';
29
+ import got from 'got';
30
+ const sites = [
31
+ getWebsiteFromUsername('sindresorhus'), //=> Promise
32
+ 'https://avajs.dev',
33
+ 'https://github.com'
34
+ ];
35
+ const mapper = async site => {
36
+ const {requestUrl} = await got.head(site);
37
+ return requestUrl;
38
+ };
39
+ const result = await pMap(sites, mapper, {concurrency: 2});
40
+ console.log(result);
41
+ //=> ['https://sindresorhus.com/', 'https://avajs.dev/', 'https://github.com/']
42
+ ```
43
+ */
44
+ export declare function pMap<Element, NewElement>(iterable: Iterable<Element>, mapper: Mapper<Element, NewElement>, options?: Options): Promise<Array<NewElement>>;
@@ -0,0 +1,75 @@
1
+ /**
2
+ @param iterable - Iterated over concurrently in the `mapper` function.
3
+ @param mapper - Function which is called for every item in `input`. Expected to return a `Promise` or value.
4
+ @param options
5
+ @returns A `Promise` that is fulfilled when all promises in `input` and ones returned from `mapper` are fulfilled, or rejects if any of the promises reject. The fulfilled value is an `Array` of the fulfilled values returned from `mapper` in `input` order.
6
+ @example
7
+ ```
8
+ import pMap from 'p-map';
9
+ import got from 'got';
10
+ const sites = [
11
+ getWebsiteFromUsername('sindresorhus'), //=> Promise
12
+ 'https://avajs.dev',
13
+ 'https://github.com'
14
+ ];
15
+ const mapper = async site => {
16
+ const {requestUrl} = await got.head(site);
17
+ return requestUrl;
18
+ };
19
+ const result = await pMap(sites, mapper, {concurrency: 2});
20
+ console.log(result);
21
+ //=> ['https://sindresorhus.com/', 'https://avajs.dev/', 'https://github.com/']
22
+ ```
23
+ */
24
+ export async function pMap(iterable, mapper, options = {}) {
25
+ const { concurrency = 1 } = options;
26
+ return new Promise((resolve, reject) => {
27
+ if (typeof mapper !== "function") {
28
+ throw new TypeError("Mapper function is required");
29
+ }
30
+ if (!((Number.isSafeInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency >= 1)) {
31
+ throw new TypeError(`Expected \`concurrency\` to be an integer from 1 and up or \`Infinity\`, got \`${concurrency}\` (${typeof concurrency})`);
32
+ }
33
+ const result = [];
34
+ const errors = [];
35
+ const iterator = iterable[Symbol.iterator]();
36
+ let isRejected = false;
37
+ let isIterableDone = false;
38
+ let resolvingCount = 0;
39
+ let currentIndex = 0;
40
+ const next = () => {
41
+ if (isRejected) {
42
+ return;
43
+ }
44
+ const nextItem = iterator.next();
45
+ const index = currentIndex;
46
+ currentIndex++;
47
+ if (nextItem.done) {
48
+ isIterableDone = true;
49
+ if (resolvingCount === 0) {
50
+ resolve(result);
51
+ }
52
+ return;
53
+ }
54
+ resolvingCount++;
55
+ (async () => {
56
+ try {
57
+ const element = await nextItem.value;
58
+ result[index] = await mapper(element, index);
59
+ resolvingCount--;
60
+ next();
61
+ }
62
+ catch (error) {
63
+ isRejected = true;
64
+ reject(error);
65
+ }
66
+ })();
67
+ };
68
+ for (let index = 0; index < concurrency; index++) {
69
+ next();
70
+ if (isIterableDone) {
71
+ break;
72
+ }
73
+ }
74
+ });
75
+ }
@@ -0,0 +1,48 @@
1
+ import type { Options as PromiseMapOptions } from "./PromiseMap.js";
2
+ export declare type $Promisable<T> = Promise<T> | T;
3
+ declare type PromiseMapCallback<T, U> = (el: T, index: number) => $Promisable<U>;
4
+ /**
5
+ * Map array of values to promise of arrays or array. Mapper function may return promise or value. If value is returned,
6
+ * we avoid promise scheduling.
7
+ *
8
+ * This is needed to run the whole operation in one microtask (e.g. keep IndexedDB transaction active, which is closed in
9
+ * some browsers (e.g. Safari) when event loop iteration ends).
10
+ */
11
+ export declare function mapInCallContext<T, U>(values: T[], callback: PromiseMapCallback<T, U>): PromisableWrapper<Array<U>>;
12
+ export { pMap as promiseMap } from "./PromiseMap.js";
13
+ export declare type PromiseMapFn = <T, U>(values: T[], callback: PromiseMapCallback<T, U>, options?: PromiseMapOptions) => PromisableWrapper<U[]>;
14
+ /** Factory function which gives you ack promiseMap implementation. {@see mapInCallContext} for what it means. */
15
+ export declare function promiseMapCompat(useMapInCallContext: boolean): PromiseMapFn;
16
+ export declare class PromisableWrapper<T> {
17
+ static from<U>(value: $Promisable<U>): PromisableWrapper<U>;
18
+ value: $Promisable<T>;
19
+ constructor(value: $Promisable<PromisableWrapper<T> | T>);
20
+ thenOrApply<R>(onFulfill: (arg0: T) => $Promisable<PromisableWrapper<R> | R>, onReject?: (arg0: any) => $Promisable<R | PromisableWrapper<R>>): PromisableWrapper<R>;
21
+ toPromise(): Promise<T>;
22
+ }
23
+ export declare function delay(ms: number): Promise<void>;
24
+ /**
25
+ * Pass to Promise.then to perform an action while forwarding on the result
26
+ * @param action
27
+ */
28
+ export declare function tap<T>(action: (arg0: T) => unknown): (arg0: T) => T;
29
+ /**
30
+ * Helper utility intended to be used with typed exceptions and .catch() method of promise like so:
31
+ *
32
+ * ```js
33
+ * class SpecificError extends Error {}
34
+ *
35
+ * Promise.reject(new SpecificError())
36
+ * .catch(ofClass(SpecificError, (e) => console.log("some error", e)))
37
+ * .catch((e) => console.log("generic error", e))
38
+ * ```
39
+ *
40
+ * @param cls Class which will be caught
41
+ * @param catcher to handle only errors of type cls
42
+ * @returns handler which either forwards to catcher or rethrows
43
+ */
44
+ export declare function ofClass<E, R>(cls: Class<E>, catcher: (arg0: E) => $Promisable<R>): (arg0: any) => Promise<R>;
45
+ /**
46
+ * Filter iterable. Just like Array.prototype.filter but callback can return promises
47
+ */
48
+ export declare function promiseFilter<T>(iterable: Iterable<T>, filter: (item: T, index: number) => $Promisable<boolean>): Promise<Array<T>>;
@@ -0,0 +1,127 @@
1
+ import { pMap as promiseMap } from "./PromiseMap.js";
2
+ /**
3
+ * Map array of values to promise of arrays or array. Mapper function may return promise or value. If value is returned,
4
+ * we avoid promise scheduling.
5
+ *
6
+ * This is needed to run the whole operation in one microtask (e.g. keep IndexedDB transaction active, which is closed in
7
+ * some browsers (e.g. Safari) when event loop iteration ends).
8
+ */
9
+ export function mapInCallContext(values, callback) {
10
+ return new PromisableWrapper(_mapInCallContext(values, callback, 0, []));
11
+ }
12
+ function _mapInCallContext(values, callback, index, acc) {
13
+ if (index >= values.length) {
14
+ return acc;
15
+ }
16
+ let mappedValue = callback(values[index], index);
17
+ if (mappedValue instanceof Promise) {
18
+ return mappedValue.then(v => {
19
+ acc.push(v);
20
+ return _mapInCallContext(values, callback, index + 1, acc);
21
+ });
22
+ }
23
+ else {
24
+ acc.push(mappedValue);
25
+ return _mapInCallContext(values, callback, index + 1, acc);
26
+ }
27
+ }
28
+ export { pMap as promiseMap } from "./PromiseMap.js";
29
+ function mapNoFallback(values, callback, options) {
30
+ return PromisableWrapper.from(promiseMap(values, callback, options));
31
+ }
32
+ /** Factory function which gives you ack promiseMap implementation. {@see mapInCallContext} for what it means. */
33
+ export function promiseMapCompat(useMapInCallContext) {
34
+ return useMapInCallContext ? mapInCallContext : mapNoFallback;
35
+ }
36
+ function flatWrapper(value) {
37
+ return value instanceof PromisableWrapper ? value.value : value;
38
+ }
39
+ // It kinda implements 'thenable' protocol so you can freely pass it around as a generic promise
40
+ export class PromisableWrapper {
41
+ constructor(value) {
42
+ this.value = value instanceof Promise ? value.then(flatWrapper) : flatWrapper(value);
43
+ }
44
+ static from(value) {
45
+ return new PromisableWrapper(value);
46
+ }
47
+ thenOrApply(onFulfill, onReject) {
48
+ if (this.value instanceof Promise) {
49
+ const v = this.value.then(onFulfill, onReject);
50
+ return new PromisableWrapper(v);
51
+ }
52
+ else {
53
+ try {
54
+ return new PromisableWrapper(onFulfill(this.value));
55
+ }
56
+ catch (e) {
57
+ if (onReject) {
58
+ return new PromisableWrapper(onReject(e));
59
+ }
60
+ throw e;
61
+ }
62
+ }
63
+ }
64
+ toPromise() {
65
+ return Promise.resolve(this.value);
66
+ }
67
+ }
68
+ export function delay(ms) {
69
+ if (Number.isNaN(ms) || ms < 0) {
70
+ throw new Error(`Invalid delay: ${ms}`);
71
+ }
72
+ return new Promise(resolve => {
73
+ setTimeout(resolve, ms);
74
+ });
75
+ }
76
+ /**
77
+ * Pass to Promise.then to perform an action while forwarding on the result
78
+ * @param action
79
+ */
80
+ export function tap(action) {
81
+ return function (value) {
82
+ action(value);
83
+ return value;
84
+ };
85
+ }
86
+ /**
87
+ * Helper utility intended to be used with typed exceptions and .catch() method of promise like so:
88
+ *
89
+ * ```js
90
+ * class SpecificError extends Error {}
91
+ *
92
+ * Promise.reject(new SpecificError())
93
+ * .catch(ofClass(SpecificError, (e) => console.log("some error", e)))
94
+ * .catch((e) => console.log("generic error", e))
95
+ * ```
96
+ *
97
+ * @param cls Class which will be caught
98
+ * @param catcher to handle only errors of type cls
99
+ * @returns handler which either forwards to catcher or rethrows
100
+ */
101
+ export function ofClass(cls, catcher) {
102
+ return async (e) => {
103
+ if (e instanceof cls) {
104
+ return catcher(e);
105
+ }
106
+ else {
107
+ // It's okay to rethrow because:
108
+ // 1. It preserves the original stacktrace
109
+ // 2. Because of 1. it is not that expensive
110
+ throw e;
111
+ }
112
+ };
113
+ }
114
+ /**
115
+ * Filter iterable. Just like Array.prototype.filter but callback can return promises
116
+ */
117
+ export async function promiseFilter(iterable, filter) {
118
+ let index = 0;
119
+ const result = [];
120
+ for (let item of iterable) {
121
+ if (await filter(item, index)) {
122
+ result.push(item);
123
+ }
124
+ index++;
125
+ }
126
+ return result;
127
+ }
@@ -0,0 +1,16 @@
1
+ export declare type CompareFn<T> = (arg0: T, arg1: T) => number;
2
+ /**
3
+ * An array that keeps itself sorted
4
+ */
5
+ export declare class SortedArray<T> {
6
+ readonly _contents: Array<T>;
7
+ readonly _compareFn: CompareFn<T>;
8
+ constructor(compareFn?: CompareFn<T>);
9
+ static from<U>(array: ReadonlyArray<U>, compareFn?: CompareFn<U>): SortedArray<U>;
10
+ get length(): number;
11
+ get array(): ReadonlyArray<T>;
12
+ get(index: number): T;
13
+ insertAll(array: ReadonlyArray<T>): void;
14
+ insert(item: T): void;
15
+ removeFirst(finder: (arg0: T) => boolean): boolean;
16
+ }
@@ -0,0 +1,44 @@
1
+ import { findAndRemove, insertIntoSortedArray } from "./ArrayUtils.js";
2
+ /**
3
+ * Compared based on the type's natural ordering
4
+ * @param a
5
+ * @param b
6
+ * @returns {number}
7
+ */
8
+ // It should be fine for 99% of use cases? worst case it just returns 0 always
9
+ function defaultCompare(a, b) {
10
+ return a < b ? -1 : a > b ? 1 : 0;
11
+ }
12
+ /**
13
+ * An array that keeps itself sorted
14
+ */
15
+ export class SortedArray {
16
+ constructor(compareFn = defaultCompare) {
17
+ this._contents = [];
18
+ this._compareFn = compareFn;
19
+ }
20
+ static from(array, compareFn) {
21
+ const list = new SortedArray(compareFn);
22
+ list.insertAll(array);
23
+ return list;
24
+ }
25
+ get length() {
26
+ return this._contents.length;
27
+ }
28
+ get array() {
29
+ return this._contents;
30
+ }
31
+ get(index) {
32
+ return this._contents[index];
33
+ }
34
+ insertAll(array) {
35
+ this._contents.push(...array);
36
+ this._contents.sort(this._compareFn);
37
+ }
38
+ insert(item) {
39
+ insertIntoSortedArray(item, this._contents, this._compareFn);
40
+ }
41
+ removeFirst(finder) {
42
+ return findAndRemove(this._contents, finder);
43
+ }
44
+ }
@@ -0,0 +1,58 @@
1
+ import type { lazy } from "./Utils.js";
2
+ /**
3
+ * Returns a string which contains the given number padded with 0s.
4
+ * @param num The number to pad.
5
+ * @param size The number of resulting digits.
6
+ * @return The padded number as string.
7
+ */
8
+ export declare function pad(num: number, size: number): string;
9
+ /**
10
+ * Checks if a string starts with another string.
11
+ * @param string The string to test.
12
+ * @param substring If the other string begins with this one, we return true.
13
+ * @return True if string begins with substring, false otherwise.
14
+ */
15
+ export declare function startsWith(string: string, substring: string): boolean;
16
+ /**
17
+ * uppercase the first letter of a string, lowercase the rest
18
+ * @param str string to transform
19
+ * @returns {string} str in lowercase with first letter Capitalized
20
+ */
21
+ export declare function capitalizeFirstLetter(str: string): string;
22
+ /**
23
+ * Checks if a string ends with another string.
24
+ * @param string The string to test.
25
+ * @param substring If the other string ends with this one, we return true.
26
+ * @return True if string ends with substring, false otherwise.
27
+ */
28
+ export declare function endsWith(string: string, substring: string): boolean;
29
+ export declare function lazyStringValue(valueOrLazy: string | lazy<string>): string;
30
+ export declare function repeat(value: string, length: number): string;
31
+ export declare function cleanMatch(s1: string, s2: string): boolean;
32
+ /**
33
+ * Non-breaking space character
34
+ */
35
+ export declare const NBSP = "\u00A0";
36
+ /**
37
+ * split a string at a given index
38
+ * @param str
39
+ * @param index
40
+ */
41
+ export declare function splitAt(str: string, index: number): [string, string];
42
+ /**
43
+ * Wrapper around String.prototype.toLowerCase, nice for calls to Array.prototype.map
44
+ * @param str
45
+ */
46
+ export declare function toLowerCase(str: string): string;
47
+ /**
48
+ * Wrapper around String.prototype.localeCompare, for passing to Array.prototype.sort
49
+ * @param a
50
+ * @param b
51
+ * @returns {number}
52
+ */
53
+ export declare function localeCompare(a: string, b: string): number;
54
+ export declare function byteLength(str: string | null | undefined): number;
55
+ /**
56
+ * replace all instances of substr in str with replacement
57
+ */
58
+ export declare function replaceAll(str: string, substr: string, replacement: string): string;
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Returns a string which contains the given number padded with 0s.
3
+ * @param num The number to pad.
4
+ * @param size The number of resulting digits.
5
+ * @return The padded number as string.
6
+ */
7
+ export function pad(num, size) {
8
+ var s = num + "";
9
+ while (s.length < size)
10
+ s = "0" + s;
11
+ return s;
12
+ }
13
+ /**
14
+ * Checks if a string starts with another string.
15
+ * @param string The string to test.
16
+ * @param substring If the other string begins with this one, we return true.
17
+ * @return True if string begins with substring, false otherwise.
18
+ */
19
+ export function startsWith(string, substring) {
20
+ return string.startsWith(substring);
21
+ }
22
+ /**
23
+ * uppercase the first letter of a string, lowercase the rest
24
+ * @param str string to transform
25
+ * @returns {string} str in lowercase with first letter Capitalized
26
+ */
27
+ export function capitalizeFirstLetter(str) {
28
+ return str[0].toUpperCase() + str.toLowerCase().slice(1);
29
+ }
30
+ /**
31
+ * Checks if a string ends with another string.
32
+ * @param string The string to test.
33
+ * @param substring If the other string ends with this one, we return true.
34
+ * @return True if string ends with substring, false otherwise.
35
+ */
36
+ export function endsWith(string, substring) {
37
+ return string.endsWith(substring);
38
+ }
39
+ export function lazyStringValue(valueOrLazy) {
40
+ return typeof valueOrLazy === "function" ? valueOrLazy() : valueOrLazy;
41
+ }
42
+ export function repeat(value, length) {
43
+ let result = "";
44
+ for (let i = 0; i < length; i++) {
45
+ result += value;
46
+ }
47
+ return result;
48
+ }
49
+ export function cleanMatch(s1, s2) {
50
+ return s1.toLowerCase().trim() === s2.toLowerCase().trim();
51
+ }
52
+ /**
53
+ * Non-breaking space character
54
+ */
55
+ export const NBSP = "\u00A0";
56
+ /**
57
+ * split a string at a given index
58
+ * @param str
59
+ * @param index
60
+ */
61
+ export function splitAt(str, index) {
62
+ return [str.substring(0, index), str.substring(index)];
63
+ }
64
+ /**
65
+ * Wrapper around String.prototype.toLowerCase, nice for calls to Array.prototype.map
66
+ * @param str
67
+ */
68
+ export function toLowerCase(str) {
69
+ return str.toLowerCase();
70
+ }
71
+ /**
72
+ * Wrapper around String.prototype.localeCompare, for passing to Array.prototype.sort
73
+ * @param a
74
+ * @param b
75
+ * @returns {number}
76
+ */
77
+ export function localeCompare(a, b) {
78
+ return a.localeCompare(b);
79
+ }
80
+ export function byteLength(str) {
81
+ if (str == null)
82
+ return 0;
83
+ // returns the byte length of an utf8 string
84
+ var s = str.length;
85
+ for (var i = str.length - 1; i >= 0; i--) {
86
+ var code = str.charCodeAt(i);
87
+ if (code > 0x7f && code <= 0x7ff) {
88
+ s++;
89
+ }
90
+ else if (code > 0x7ff && code <= 0xffff)
91
+ s += 2;
92
+ if (code >= 0xdc00 && code <= 0xdfff)
93
+ i--; //trail surrogate
94
+ }
95
+ return s;
96
+ }
97
+ /**
98
+ * replace all instances of substr in str with replacement
99
+ */
100
+ export function replaceAll(str, substr, replacement) {
101
+ const regex = escapedStringRegExp(substr, "g");
102
+ return str.replace(regex, replacement);
103
+ }
104
+ /**
105
+ * Create a regex to exactly match a given string, by escaping any special regex characters
106
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
107
+ * */
108
+ function escapedStringRegExp(str, flags) {
109
+ return new RegExp(str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), flags);
110
+ }
@@ -0,0 +1,12 @@
1
+ export declare class TypeRef<T> {
2
+ readonly app: string;
3
+ readonly type: string;
4
+ /**
5
+ * Field that is never set. Used to make two TypeRefs incompatible (they are structurally compared otherwise).
6
+ * Cannot be private.
7
+ */
8
+ readonly phantom: T | null;
9
+ constructor(app: string, type: string);
10
+ }
11
+ export declare function isSameTypeRefByAttr(typeRef: TypeRef<any>, app: string, type: string): boolean;
12
+ export declare function isSameTypeRef(typeRef1: TypeRef<any>, typeRef2: TypeRef<any>): boolean;
@@ -0,0 +1,19 @@
1
+ // T should be restricted to Entity
2
+ export class TypeRef {
3
+ constructor(app, type) {
4
+ /**
5
+ * Field that is never set. Used to make two TypeRefs incompatible (they are structurally compared otherwise).
6
+ * Cannot be private.
7
+ */
8
+ this.phantom = null;
9
+ this.app = app;
10
+ this.type = type;
11
+ Object.freeze(this);
12
+ }
13
+ }
14
+ export function isSameTypeRefByAttr(typeRef, app, type) {
15
+ return typeRef.app === app && typeRef.type === type;
16
+ }
17
+ export function isSameTypeRef(typeRef1, typeRef2) {
18
+ return isSameTypeRefByAttr(typeRef1, typeRef2.app, typeRef2.type);
19
+ }