senaev-utils 1.0.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/README.md +11 -0
- package/package.json +66 -0
- package/src/reactHooks/setDeepEqualState.ts +19 -0
- package/src/reactHooks/useLocationParameter.ts +46 -0
- package/src/reactHooks/useObjectDeepChangesCounter.ts +22 -0
- package/src/reactHooks/useObservableMap/useObservableMap.ts +21 -0
- package/src/reactHooks/useRecentChangeTimer.ts +42 -0
- package/src/reactHooks/useReload.ts +17 -0
- package/src/reactHooks/useVisualizedProcessesTree.ts +202 -0
- package/src/types/Boolean.ts +9 -0
- package/src/types/DeepPartial.ts +1 -0
- package/src/types/GlobalContext.ts +8 -0
- package/src/types/HexColorString.ts +9 -0
- package/src/types/ISOLang.ts +5 -0
- package/src/types/IsEqualUnion.ts +1 -0
- package/src/types/IterableWithIndexAccess.ts +4 -0
- package/src/types/Kilobits.ts +4 -0
- package/src/types/Network/Bits.ts +4 -0
- package/src/types/Network/Bps.ts +4 -0
- package/src/types/Network/Kbps.ts +4 -0
- package/src/types/Network/Mbps.ts +4 -0
- package/src/types/Number/AngleInDegrees.ts +3 -0
- package/src/types/Number/FiniteNumber.ts +11 -0
- package/src/types/Number/Integer.ts +14 -0
- package/src/types/Number/IntegerInString.ts +13 -0
- package/src/types/Number/Number.ts +15 -0
- package/src/types/Number/Portion.ts +4 -0
- package/src/types/Number/PositiveInteger.ts +30 -0
- package/src/types/Number/PositiveNumber.ts +4 -0
- package/src/types/Number/StringUnsignedInteger.ts +4 -0
- package/src/types/Number/UnsignedFiniteNumber.ts +13 -0
- package/src/types/Number/UnsignedInteger.ts +28 -0
- package/src/types/Object/Object.ts +20 -0
- package/src/types/Percent.ts +4 -0
- package/src/types/PixelPosition.ts +9 -0
- package/src/types/PixelSize.ts +9 -0
- package/src/types/Pixels.ts +4 -0
- package/src/types/RangeTuple.ts +1 -0
- package/src/types/Size.ts +8 -0
- package/src/types/Time/DaysCount.ts +6 -0
- package/src/types/Time/Hours.ts +4 -0
- package/src/types/Time/ISODateString/ISODateString.ts +16 -0
- package/src/types/Time/Milliseconds.ts +4 -0
- package/src/types/Time/Minutes.ts +4 -0
- package/src/types/Time/Seconds.ts +5 -0
- package/src/types/Time/Time.ts +13 -0
- package/src/types/Time/Timestamp.ts +6 -0
- package/src/types/Time/UnixTimeMs.ts +6 -0
- package/src/types/Time/UnixTimeSec.ts +11 -0
- package/src/types/Time/const.ts +24 -0
- package/src/types/any/AnyAsyncFunction.ts +2 -0
- package/src/types/any/AnyFunction.ts +2 -0
- package/src/types/assertions/ANY_VALUE.ts +2 -0
- package/src/types/assertions/isNever/isNever.ts +34 -0
- package/src/types/assertions/isTrue/isTrue.ts +13 -0
- package/src/utils/AbortableProcess.ts +160 -0
- package/src/utils/Array/createArray/createArray.ts +8 -0
- package/src/utils/Array/createIntegerSequenceArray/createIntegerSequenceArray.ts +3 -0
- package/src/utils/Array/getUniqueValues/getUniqueValues.ts +3 -0
- package/src/utils/Array/separateToArrays/separateToArrays.ts +24 -0
- package/src/utils/Array/shuffleArray/shuffleArray.ts +18 -0
- package/src/utils/CircularBuffer/CircularBuffer.ts +117 -0
- package/src/utils/DOM/blurDocument.ts +3 -0
- package/src/utils/DOM/unfocusDocument.ts +3 -0
- package/src/utils/Date/dateToUnixTimeSec/dateToUnixTimeSec.ts +6 -0
- package/src/utils/Date/isoDateStringToUnixTimeMs/isoDateStringToUnixTimeMs.ts +6 -0
- package/src/utils/Date/isoDateStringToUnixTimeSec/isoDateStringToUnixTimeSec.ts +7 -0
- package/src/utils/Date/unixTimeSecToIsoDateString/unixTimeSecToIsoDateString.ts +6 -0
- package/src/utils/Deque/Deque.ts +530 -0
- package/src/utils/DeviceDetection/isTouchScreenDevice/isTouchScreenDevice.ts +16 -0
- package/src/utils/Error/rethrowError/rethrowError.ts +8 -0
- package/src/utils/Error/wrapError.ts +32 -0
- package/src/utils/Function/callFirstThenOther/callFirstThenOther.ts +24 -0
- package/src/utils/Function/callFunctions/callFunctions.ts +11 -0
- package/src/utils/Function/callTimes/callTimes.ts +5 -0
- package/src/utils/Function/isFunction.ts +3 -0
- package/src/utils/Function/noop/index.ts +4 -0
- package/src/utils/Function/once/once.ts +32 -0
- package/src/utils/Function/subscribeUpdatesWithTimeout/index.ts +44 -0
- package/src/utils/Function/throttleFunction/throttleFunction.ts +18 -0
- package/src/utils/Function/throttleWithPromiseFunction/throttleWithPromiseFunction.ts +19 -0
- package/src/utils/Function/tryCatch/tryCatch.ts +13 -0
- package/src/utils/Latch/Latch.ts +63 -0
- package/src/utils/Map/ObservableMap/ObservableMap.ts +55 -0
- package/src/utils/Map/findMapsDifferences/findMapsDifferences.ts +35 -0
- package/src/utils/Map/mapGetOrSet/mapGetOrSet.ts +7 -0
- package/src/utils/Map/mapMapToArray/mapMapToArray.ts +6 -0
- package/src/utils/Map/mapMapValues/mapMapValues.ts +9 -0
- package/src/utils/Math/createSimpleMovingAverageSeries/createSimpleMovingAverageSeries.ts +22 -0
- package/src/utils/Math/mean/mean.ts +14 -0
- package/src/utils/Math/simpleMovingAverageUsingAccFabric/simpleMovingAverageUsingAccFabric.ts +29 -0
- package/src/utils/Math/sum/sum.ts +45 -0
- package/src/utils/MinHeap/MinHeap.ts +88 -0
- package/src/utils/MinHeapUniqueNumber/MinHeapUniqueNumber.ts +105 -0
- package/src/utils/MinMaxHeap/MinMaxHeap.ts +91 -0
- package/src/utils/Number/collectIntegerSequences/collectIntegerSequences.ts +36 -0
- package/src/utils/Number/numberToFixedPrecision/numberToFixedPrecision.ts +13 -0
- package/src/utils/Object/cloneObject/cloneObject.ts +3 -0
- package/src/utils/Object/deepEqual/deepEqual.ts +45 -0
- package/src/utils/Object/deleteUndefinedProperties/index.ts +13 -0
- package/src/utils/Object/entriesToObject/entriesToObject.ts +12 -0
- package/src/utils/Object/filterObject/filterObject.ts +18 -0
- package/src/utils/Object/forOwn/forOwn.ts +12 -0
- package/src/utils/Object/getObjectEntries/getObjectEntries.ts +3 -0
- package/src/utils/Object/getObjectKeys/getObjectKeys.ts +3 -0
- package/src/utils/Object/getObjectValues/index.ts +3 -0
- package/src/utils/Object/hasOwnProperty/hasOwnProperty.ts +3 -0
- package/src/utils/Object/invertObject/InvertedObject.ts +3 -0
- package/src/utils/Object/invertObject/invertObject.ts +15 -0
- package/src/utils/Object/isEmptyObject/index.ts +5 -0
- package/src/utils/Object/isObject/index.ts +8 -0
- package/src/utils/Object/mapObjectKeys/mapObjectKeys.ts +25 -0
- package/src/utils/Object/mapObjectValues/mapObjectValues.ts +16 -0
- package/src/utils/Object/mirrorObject/ObjectKeysMirror.ts +1 -0
- package/src/utils/Object/mirrorObject/mirrorObject.ts +7 -0
- package/src/utils/Pagination/DEFAULT_PAGE.ts +1 -0
- package/src/utils/Pagination/calculatePaginationParameters.ts +29 -0
- package/src/utils/Promise/promiseAll/promiseAll.ts +6 -0
- package/src/utils/Promise/restrictParallelCalls/restrictParallelCalls.ts +18 -0
- package/src/utils/Ranges/checkRangesAdjacent/checkRangesAdjacent.ts +23 -0
- package/src/utils/Ranges/checkRangesIntersection/checkRangesIntersection.ts +8 -0
- package/src/utils/Ranges/excludeRanges/excludeRanges.ts +42 -0
- package/src/utils/Ranges/getDistanceToRange/getDistanceToRange.ts +14 -0
- package/src/utils/Ranges/isRangeWithinRanges.ts +14 -0
- package/src/utils/Ranges/mapDateRangeToISODateStringRange/mapDateRangeToISODateStringRange.ts +7 -0
- package/src/utils/Ranges/mapISODateStringRangeToUnixTimeMsRange/mapISODateStringRangeToUnixTimeMsRange.ts +8 -0
- package/src/utils/Ranges/mapRange/mapRange.ts +13 -0
- package/src/utils/Ranges/mapUnixTimeMsRangeToISODateStringRange/mapUnixTimeMsRangeToISODateStringRange.ts +8 -0
- package/src/utils/Ranges/mergeRanges/mergeRanges.ts +34 -0
- package/src/utils/Signal/Signal.ts +47 -0
- package/src/utils/Signal/SignalCallback.ts +1 -0
- package/src/utils/Signal/combineSignalsIntoNewOne/combineSignalsIntoNewOne.ts +75 -0
- package/src/utils/Signal/subscribeSignalAndCallWithCurrentValue/subscribeSignalAndCallWithCurrentValue.ts +7 -0
- package/src/utils/Signal/useSignal.ts +10 -0
- package/src/utils/String/HexString/HEX_SYMBOLS.ts +1 -0
- package/src/utils/String/HexString/HexString.ts +2 -0
- package/src/utils/String/HexString/isHexString.ts +16 -0
- package/src/utils/String/NonEmptyString/NonEmptyString.ts +22 -0
- package/src/utils/String/endsWith/index.ts +6 -0
- package/src/utils/String/isString.ts +3 -0
- package/src/utils/binarySearch/binarySearch.ts +20 -0
- package/src/utils/binarySearchClosest/binarySearchClosest.ts +43 -0
- package/src/utils/createIncrementalIntegerGenerator.ts +7 -0
- package/src/utils/createRemoteDataProcessingWindow/createRemoteDataProcessingWindow.ts +157 -0
- package/src/utils/createSimultaneousOperationsHandler/createSimultaneousOperationsHandler.ts +65 -0
- package/src/utils/encryptDecryptString/encryptDecryptString.ts +34 -0
- package/src/utils/getPrimeNumbersWithEratosthenesSieve/getPrimeNumbersWithEratosthenesSieve.ts +21 -0
- package/src/utils/isPromise/isPromise.ts +30 -0
- package/src/utils/makeAsyncFunctionCallsSimultaneous/makeAsyncFunctionCallsSimultaneous.ts +64 -0
- package/src/utils/parallelsLimitPromise/index.ts +28 -0
- package/src/utils/parallelsLimitQueue/parallelsLimitQueue.ts +69 -0
- package/src/utils/prettyStringify/index.ts +3 -0
- package/src/utils/random/fnv1a/fnv1a.ts +87 -0
- package/src/utils/random/generateHashedFloats/generateHashedFloats.ts +28 -0
- package/src/utils/random/getRandomIntegerInARange/getRandomIntegerInARange.ts +3 -0
- package/src/utils/random/getSampleIndexByStringHash/getSampleIndexByStringHash.ts +10 -0
- package/src/utils/random/randomBoolean/randomBoolean.ts +3 -0
- package/src/utils/random/randomHexString/randomHexString.ts +12 -0
- package/src/utils/requestAnimationFrame/requestAnimationFramePromise/requestAnimationFramePromise.ts +7 -0
- package/src/utils/requestAnimationFrame/requestAnimationFrameThrottle/requestAnimationFrameThrottle.ts +6 -0
- package/src/utils/retryFunctionWrapper/retryFunctionWrapper.ts +40 -0
- package/src/utils/runParallelTimescalesProcessing/runParallelTimescalesProcessing.ts +113 -0
- package/src/utils/stringifyError.ts +3 -0
- package/src/utils/timers/promiseTimeout/promiseTimeout.ts +26 -0
- package/src/utils/timers/subscribeSyntheticInterval/subscribeSyntheticInterval.ts +47 -0
- package/src/utils/waitForFunction/waitForFunction.ts +50 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Integer } from '../../../types/Number/Integer';
|
|
2
|
+
import { PositiveInteger } from '../../../types/Number/PositiveInteger';
|
|
3
|
+
import { UnsignedInteger } from '../../../types/Number/UnsignedInteger';
|
|
4
|
+
|
|
5
|
+
type IntegerSequence = {
|
|
6
|
+
start: UnsignedInteger;
|
|
7
|
+
length: PositiveInteger;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export function collectIntegerSequences(integers: Integer[]): IntegerSequence[] {
|
|
11
|
+
if (!integers.length) {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const sequences: IntegerSequence[] = [
|
|
16
|
+
{
|
|
17
|
+
start: integers[0],
|
|
18
|
+
length: 1,
|
|
19
|
+
},
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
for (let i = 1; i < integers.length; i += 1) {
|
|
23
|
+
const lastSequence = sequences.at(-1)!;
|
|
24
|
+
|
|
25
|
+
if (lastSequence.start + lastSequence.length === integers[i]) {
|
|
26
|
+
lastSequence.length += 1;
|
|
27
|
+
} else {
|
|
28
|
+
sequences.push({
|
|
29
|
+
start: integers[i],
|
|
30
|
+
length: 1,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return sequences;
|
|
36
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function numberToFixedPrecision(number: number, precision = 4): string {
|
|
2
|
+
// Handle zero as a special case since Math.log10(0) returns -Infinity
|
|
3
|
+
if (number === 0) {
|
|
4
|
+
return '0';
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const absNumber = Math.abs(number);
|
|
8
|
+
const log10 = Math.log10(absNumber);
|
|
9
|
+
const log10Int = Math.floor(log10);
|
|
10
|
+
const toFixed = Math.max(0, precision - log10Int);
|
|
11
|
+
|
|
12
|
+
return number.toFixed(toFixed);
|
|
13
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { isObject } from '../../../types/Object/Object';
|
|
2
|
+
import { getObjectKeys } from '../getObjectKeys/getObjectKeys';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Код взят отсюда https://gist.github.com/egardner/efd34f270cc33db67c0246e837689cb9
|
|
6
|
+
*
|
|
7
|
+
* Функция подходит только для сравнения объектов и массивов любой вложенности с примитивами внутри
|
|
8
|
+
*
|
|
9
|
+
* Не подходит для сравнения сложных объектов типа Date, Function, RegExp и т.п.
|
|
10
|
+
* Воспринимает их как простые объекты и сравнивает собственные перечисляемые свойства
|
|
11
|
+
*
|
|
12
|
+
* Выдает false при сравнении двух NaN
|
|
13
|
+
*/
|
|
14
|
+
export function deepEqual<T>(actual: unknown, expected: T): actual is T {
|
|
15
|
+
if (actual === expected) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (!isObject(actual) || !isObject(expected)) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (Array.isArray(actual) !== Array.isArray(expected)) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const actualKeys = getObjectKeys(actual);
|
|
28
|
+
const expectedKeys = getObjectKeys(expected);
|
|
29
|
+
|
|
30
|
+
if (actualKeys.length !== expectedKeys.length) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
for (const key of expectedKeys) {
|
|
35
|
+
if (!((key as string) in actual)) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (!deepEqual((actual as T)[key as keyof T], expected[key])) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { hasOwnProperty } from '../hasOwnProperty/hasOwnProperty';
|
|
2
|
+
|
|
3
|
+
export function deleteUndefinedProperties<T extends Record<string, unknown>>(obj: T): Partial<T> {
|
|
4
|
+
const result: Partial<T> = {};
|
|
5
|
+
|
|
6
|
+
for (const key in obj) {
|
|
7
|
+
if (hasOwnProperty(obj, key) && obj[key] !== undefined) {
|
|
8
|
+
result[key] = obj[key];
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { getObjectKeys } from '../getObjectKeys/getObjectKeys';
|
|
2
|
+
|
|
3
|
+
export function filterObject<O extends Record<string, unknown>>(
|
|
4
|
+
object: O,
|
|
5
|
+
filterFunction: (value: O[keyof O], key: keyof O) => boolean
|
|
6
|
+
): O {
|
|
7
|
+
const resultObject = {} as O;
|
|
8
|
+
|
|
9
|
+
getObjectKeys(object).forEach((key) => {
|
|
10
|
+
const shouldRemainProperty = filterFunction(object[key], key);
|
|
11
|
+
|
|
12
|
+
if (shouldRemainProperty) {
|
|
13
|
+
resultObject[key] = object[key];
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
return resultObject;
|
|
18
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { hasOwnProperty } from '../hasOwnProperty/hasOwnProperty';
|
|
2
|
+
|
|
3
|
+
export function forOwn<Obj extends {}>(
|
|
4
|
+
obj: Obj,
|
|
5
|
+
fn: (value: Obj[keyof Obj], key: keyof Obj, sourceObj: Obj) => void
|
|
6
|
+
): void {
|
|
7
|
+
for (const key in obj) {
|
|
8
|
+
if (hasOwnProperty(obj, key)) {
|
|
9
|
+
fn(obj[key], key, obj);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { InvertedObject } from './InvertedObject';
|
|
2
|
+
|
|
3
|
+
export function invertObject<T extends Record<string, string>>(object: T): InvertedObject<T> {
|
|
4
|
+
const nextObject = {} as InvertedObject<T>;
|
|
5
|
+
|
|
6
|
+
for (const key in object) {
|
|
7
|
+
if (Object.prototype.hasOwnProperty.call(object, key)) {
|
|
8
|
+
const value = object[key];
|
|
9
|
+
|
|
10
|
+
(nextObject as Record<T[keyof T], keyof T>)[value] = key;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return nextObject;
|
|
15
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns 'true' if {@param value} is {@type object}
|
|
3
|
+
*/
|
|
4
|
+
export function isObject<T extends Record<string, unknown> = Record<string, unknown>>(value: unknown): value is T {
|
|
5
|
+
const type = typeof value;
|
|
6
|
+
|
|
7
|
+
return Boolean(value) && (type === 'object' || type === 'function');
|
|
8
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { getObjectKeys } from '../getObjectKeys/getObjectKeys';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Функция принимает на вход первым агрументом объект и прогоняет все собственные свойства
|
|
5
|
+
* (ключ и значение в качестве аргументов) через функцию, которая приходит вторым аргументом.
|
|
6
|
+
* Эта функция для каждого свойства должна вернуть новый ключ для
|
|
7
|
+
* конкретного значения объекта.
|
|
8
|
+
*
|
|
9
|
+
* Функция возвращает новый объект, со старыми значениями и новыми ключами.
|
|
10
|
+
*/
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
+
export function mapObjectKeys<T extends Record<string, any>, S extends string>(
|
|
13
|
+
object: T,
|
|
14
|
+
mapFunction: (key: keyof T, value: T[keyof T]) => S
|
|
15
|
+
): Record<S, T[keyof T]> {
|
|
16
|
+
const resultObject = {} as Record<S, T[keyof T]>;
|
|
17
|
+
|
|
18
|
+
getObjectKeys(object).forEach((key) => {
|
|
19
|
+
const newKey = mapFunction(key, object[key]);
|
|
20
|
+
|
|
21
|
+
resultObject[newKey] = object[key];
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return resultObject;
|
|
25
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { getObjectKeys } from '../getObjectKeys/getObjectKeys';
|
|
2
|
+
|
|
3
|
+
export function mapObjectValues<
|
|
4
|
+
T extends Record<string, unknown>,
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- only for util snd better typing
|
|
6
|
+
TMapFunc extends (value: T[keyof T], key: keyof T) => any,
|
|
7
|
+
R extends { [P in keyof T]: ReturnType<TMapFunc> },
|
|
8
|
+
>(object: T, mapFunction: TMapFunc): R {
|
|
9
|
+
const resultObject = {} as Record<string, unknown>;
|
|
10
|
+
|
|
11
|
+
getObjectKeys(object).forEach((key) => {
|
|
12
|
+
resultObject[key as string] = mapFunction(object[key], key);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
return resultObject as R;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type ObjectKeysMirror<T extends Record<string, unknown>> = { [key in keyof T]: key };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { mapObjectValues } from '../mapObjectValues/mapObjectValues';
|
|
2
|
+
|
|
3
|
+
import { ObjectKeysMirror } from './ObjectKeysMirror';
|
|
4
|
+
|
|
5
|
+
export function mirrorObject<T extends Record<string, unknown>>(object: T): ObjectKeysMirror<T> {
|
|
6
|
+
return mapObjectValues(object, (_value, key) => key) as ObjectKeysMirror<T>;
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const DEFAULT_PAGE = 1;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { PositiveInteger } from '../../types/Number/PositiveInteger';
|
|
2
|
+
import { UnsignedInteger } from '../../types/Number/UnsignedInteger';
|
|
3
|
+
|
|
4
|
+
import { DEFAULT_PAGE } from './DEFAULT_PAGE';
|
|
5
|
+
|
|
6
|
+
export const calculatePaginationParameters = ({
|
|
7
|
+
page,
|
|
8
|
+
pageSize,
|
|
9
|
+
totalCount,
|
|
10
|
+
}: {
|
|
11
|
+
page: UnsignedInteger;
|
|
12
|
+
pageSize: PositiveInteger;
|
|
13
|
+
totalCount: UnsignedInteger;
|
|
14
|
+
}): {
|
|
15
|
+
canGoToPreviousPage: boolean;
|
|
16
|
+
canGoToNextPage: boolean;
|
|
17
|
+
totalPages: UnsignedInteger;
|
|
18
|
+
} => {
|
|
19
|
+
const canGoToPreviousPage = page > DEFAULT_PAGE;
|
|
20
|
+
|
|
21
|
+
const totalPages = Math.ceil(totalCount / pageSize);
|
|
22
|
+
const isLastPage = page >= totalPages;
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
canGoToPreviousPage,
|
|
26
|
+
canGoToNextPage: !isLastPage,
|
|
27
|
+
totalPages,
|
|
28
|
+
};
|
|
29
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { AnyAsyncFunction } from '../../../types/any/AnyAsyncFunction';
|
|
2
|
+
|
|
3
|
+
export function restrictParallelCalls<T extends AnyAsyncFunction>(callback: T, errorMessage?: string): T {
|
|
4
|
+
let isRunning = false;
|
|
5
|
+
|
|
6
|
+
return ((...args: Parameters<T>) => {
|
|
7
|
+
if (isRunning) {
|
|
8
|
+
throw new Error(`restrictParallelCalls${errorMessage ? ` errorMessage=[${errorMessage}]` : ''} previous call is not finished, do not call function in parallel`);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
isRunning = true;
|
|
12
|
+
const promise = callback(...args);
|
|
13
|
+
|
|
14
|
+
return promise.finally(() => {
|
|
15
|
+
isRunning = false;
|
|
16
|
+
});
|
|
17
|
+
}) as T;
|
|
18
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RangeTuple } from '../../../types/RangeTuple';
|
|
2
|
+
|
|
3
|
+
export function checkRangesAdjacent(
|
|
4
|
+
range1: RangeTuple<number>,
|
|
5
|
+
range2: RangeTuple<number>
|
|
6
|
+
): boolean {
|
|
7
|
+
const [
|
|
8
|
+
min1,
|
|
9
|
+
max1,
|
|
10
|
+
] = [
|
|
11
|
+
Math.min(range1[0], range1[1]),
|
|
12
|
+
Math.max(range1[0], range1[1]),
|
|
13
|
+
];
|
|
14
|
+
const [
|
|
15
|
+
min2,
|
|
16
|
+
max2,
|
|
17
|
+
] = [
|
|
18
|
+
Math.min(range2[0], range2[1]),
|
|
19
|
+
Math.max(range2[0], range2[1]),
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
return max1 === min2 || max2 === min1;
|
|
23
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
type Range = [number, number];
|
|
2
|
+
|
|
3
|
+
export function excludeRanges(initialRange: Range, sortedRangesToExclude: Range[]): Range[] {
|
|
4
|
+
const [
|
|
5
|
+
start,
|
|
6
|
+
end,
|
|
7
|
+
] = initialRange;
|
|
8
|
+
|
|
9
|
+
const result: Range[] = [];
|
|
10
|
+
let currentNumber = start;
|
|
11
|
+
|
|
12
|
+
for (const [
|
|
13
|
+
meetingStart,
|
|
14
|
+
meetingEnd,
|
|
15
|
+
] of sortedRangesToExclude) {
|
|
16
|
+
if (meetingStart >= end) {
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (meetingEnd <= start) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (meetingStart > currentNumber) {
|
|
25
|
+
result.push([
|
|
26
|
+
currentNumber,
|
|
27
|
+
meetingStart,
|
|
28
|
+
]);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
currentNumber = Math.max(currentNumber, meetingEnd);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (currentNumber < end) {
|
|
35
|
+
result.push([
|
|
36
|
+
currentNumber,
|
|
37
|
+
end,
|
|
38
|
+
]);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FiniteNumber } from '../../../types/Number/FiniteNumber';
|
|
2
|
+
import { RangeTuple } from '../../../types/RangeTuple';
|
|
3
|
+
|
|
4
|
+
export function getDistanceToRange(range: RangeTuple<FiniteNumber>, value: FiniteNumber): FiniteNumber {
|
|
5
|
+
if (value >= range[0] && value <= range[1]) {
|
|
6
|
+
return 0;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
if (value < range[0]) {
|
|
10
|
+
return range[0] - value;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return range[1] - value;
|
|
14
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { RangeTuple } from '../../../types/RangeTuple';
|
|
2
|
+
import { ISODateString } from '../../../types/Time/ISODateString/ISODateString';
|
|
3
|
+
import { mapRange } from '../mapRange/mapRange';
|
|
4
|
+
|
|
5
|
+
export function mapDateRangeToISODateStringRange(range: RangeTuple<Date>): RangeTuple<ISODateString> {
|
|
6
|
+
return mapRange(range, (date) => date.toISOString());
|
|
7
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { RangeTuple } from '../../../types/RangeTuple';
|
|
2
|
+
import { ISODateString } from '../../../types/Time/ISODateString/ISODateString';
|
|
3
|
+
import { UnixTimeMs } from '../../../types/Time/UnixTimeMs';
|
|
4
|
+
import { mapRange } from '../mapRange/mapRange';
|
|
5
|
+
|
|
6
|
+
export function mapISODateStringRangeToUnixTimeMsRange(range: RangeTuple<ISODateString>): RangeTuple<UnixTimeMs> {
|
|
7
|
+
return mapRange(range, (isoDateString) => new Date(isoDateString).getTime());
|
|
8
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { RangeTuple } from '../../../types/RangeTuple';
|
|
2
|
+
|
|
3
|
+
export function mapRange<A, F extends (
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
|
+
a: A, index: 0 | 1) => any, B extends ReturnType<F>>(
|
|
6
|
+
range: RangeTuple<A>,
|
|
7
|
+
func: F
|
|
8
|
+
): RangeTuple<B> {
|
|
9
|
+
return [
|
|
10
|
+
func(range[0], 0),
|
|
11
|
+
func(range[1], 1),
|
|
12
|
+
];
|
|
13
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { RangeTuple } from '../../../types/RangeTuple';
|
|
2
|
+
import { ISODateString } from '../../../types/Time/ISODateString/ISODateString';
|
|
3
|
+
import { UnixTimeMs } from '../../../types/Time/UnixTimeMs';
|
|
4
|
+
import { mapRange } from '../mapRange/mapRange';
|
|
5
|
+
|
|
6
|
+
export function mapUnixTimeMsRangeToISODateStringRange(range: RangeTuple<UnixTimeMs>): RangeTuple<ISODateString> {
|
|
7
|
+
return mapRange(range, (timestamp) => new Date(timestamp).toISOString());
|
|
8
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
type Range = [number, number];
|
|
2
|
+
|
|
3
|
+
export function mergeRanges(ranges: Range[]): Range[] {
|
|
4
|
+
if (!ranges.length) {
|
|
5
|
+
return [];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const stack: Range[] = [];
|
|
9
|
+
|
|
10
|
+
const sorted = [...ranges].sort((a, b) => a[0] - b[0]);
|
|
11
|
+
|
|
12
|
+
const firstRange = sorted[0];
|
|
13
|
+
|
|
14
|
+
stack.push([
|
|
15
|
+
firstRange[0],
|
|
16
|
+
firstRange[1],
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
20
|
+
const range = sorted[i];
|
|
21
|
+
const lastRange = stack.at(-1)!;
|
|
22
|
+
|
|
23
|
+
if (lastRange[1] < range[0]) {
|
|
24
|
+
stack.push([
|
|
25
|
+
range[0],
|
|
26
|
+
range[1],
|
|
27
|
+
]);
|
|
28
|
+
} else if (lastRange[1] < range[1]) {
|
|
29
|
+
lastRange[1] = range[1];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return stack;
|
|
34
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { SignalCallback } from './SignalCallback';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* EventEmitter with consistent value, alternative to BehaviorSubject from RxJS
|
|
5
|
+
*
|
|
6
|
+
* This class has been designed on a base of SolidJS reactive signal pattern https://www.solidjs.com/docs/latest/api#createsignal
|
|
7
|
+
* and signal-js EventEmitter library https://www.npmjs.com/package/signal-js
|
|
8
|
+
*
|
|
9
|
+
* Allows to create and combine business logic into reactive Signals and use them in React.context via useSignal hook
|
|
10
|
+
*/
|
|
11
|
+
export class Signal<T> {
|
|
12
|
+
private readonly callbacks: Set<SignalCallback<T>> = new Set<SignalCallback<T>>();
|
|
13
|
+
|
|
14
|
+
public constructor(
|
|
15
|
+
private _value: T,
|
|
16
|
+
private readonly checkToEqualFunction: (currentValue: T, nextValue: T) => boolean = (currentValue, nextValue) =>
|
|
17
|
+
currentValue === nextValue
|
|
18
|
+
) { }
|
|
19
|
+
|
|
20
|
+
public value(): T {
|
|
21
|
+
return this._value;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public subscribe(callback: SignalCallback<T>): VoidFunction {
|
|
25
|
+
this.callbacks.add(callback);
|
|
26
|
+
|
|
27
|
+
return () => {
|
|
28
|
+
this.unsubscribe(callback);
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public next(nextValue: T): void {
|
|
33
|
+
if (this.checkToEqualFunction(this._value, nextValue)) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
this._value = nextValue;
|
|
38
|
+
|
|
39
|
+
for (const callback of this.callbacks.values()) {
|
|
40
|
+
callback(nextValue);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public unsubscribe(callback: SignalCallback<T>): void {
|
|
45
|
+
this.callbacks.delete(callback);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type SignalCallback<T> = (this: unknown, param: T) => void;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Signal } from '../Signal';
|
|
2
|
+
|
|
3
|
+
export type CombineSignalsIntoNewOneResult<T> = {
|
|
4
|
+
signal: Signal<T>;
|
|
5
|
+
teardown: VoidFunction;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export function combineSignalsIntoNewOne<T, A, B, C, D, E, F, G>(
|
|
9
|
+
signals: [Signal<A>, Signal<B>, Signal<C>, Signal<D>, Signal<E>, Signal<F>, Signal<G>],
|
|
10
|
+
combinator: (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => T,
|
|
11
|
+
checkToEqualFunction?: (currentValue: T, nextValue: T) => boolean,
|
|
12
|
+
): CombineSignalsIntoNewOneResult<T>;
|
|
13
|
+
|
|
14
|
+
export function combineSignalsIntoNewOne<T, A, B, C, D, E, F>(
|
|
15
|
+
signals: [Signal<A>, Signal<B>, Signal<C>, Signal<D>, Signal<E>, Signal<F>],
|
|
16
|
+
combinator: (a: A, b: B, c: C, d: D, e: E, f: F) => T,
|
|
17
|
+
checkToEqualFunction?: (currentValue: T, nextValue: T) => boolean,
|
|
18
|
+
): CombineSignalsIntoNewOneResult<T>;
|
|
19
|
+
|
|
20
|
+
export function combineSignalsIntoNewOne<T, A, B, C, D, E>(
|
|
21
|
+
signals: [Signal<A>, Signal<B>, Signal<C>, Signal<D>, Signal<E>],
|
|
22
|
+
combinator: (a: A, b: B, c: C, d: D, e: E) => T,
|
|
23
|
+
checkToEqualFunction?: (currentValue: T, nextValue: T) => boolean,
|
|
24
|
+
): CombineSignalsIntoNewOneResult<T>;
|
|
25
|
+
|
|
26
|
+
export function combineSignalsIntoNewOne<T, A, B, C, D>(
|
|
27
|
+
signals: [Signal<A>, Signal<B>, Signal<C>, Signal<D>],
|
|
28
|
+
combinator: (a: A, b: B, c: C, d: D) => T,
|
|
29
|
+
checkToEqualFunction?: (currentValue: T, nextValue: T) => boolean,
|
|
30
|
+
): CombineSignalsIntoNewOneResult<T>;
|
|
31
|
+
|
|
32
|
+
export function combineSignalsIntoNewOne<T, A, B, C>(
|
|
33
|
+
signals: [Signal<A>, Signal<B>, Signal<C>],
|
|
34
|
+
combinator: (a: A, b: B, c: C) => T,
|
|
35
|
+
checkToEqualFunction?: (currentValue: T, nextValue: T) => boolean,
|
|
36
|
+
): CombineSignalsIntoNewOneResult<T>;
|
|
37
|
+
|
|
38
|
+
export function combineSignalsIntoNewOne<T, A, B>(
|
|
39
|
+
signals: [Signal<A>, Signal<B>],
|
|
40
|
+
combinator: (a: A, b: B) => T,
|
|
41
|
+
checkToEqualFunction?: (currentValue: T, nextValue: T) => boolean,
|
|
42
|
+
): CombineSignalsIntoNewOneResult<T>;
|
|
43
|
+
|
|
44
|
+
export function combineSignalsIntoNewOne<T, A>(
|
|
45
|
+
signals: [Signal<A>],
|
|
46
|
+
combinator: (a: A) => T,
|
|
47
|
+
checkToEqualFunction?: (currentValue: T, nextValue: T) => boolean,
|
|
48
|
+
): CombineSignalsIntoNewOneResult<T>;
|
|
49
|
+
|
|
50
|
+
export function combineSignalsIntoNewOne<T>(
|
|
51
|
+
signals: Signal<unknown>[],
|
|
52
|
+
combinator: (...args: unknown[]) => T,
|
|
53
|
+
checkToEqualFunction?: (currentValue: T, nextValue: T) => boolean
|
|
54
|
+
): CombineSignalsIntoNewOneResult<T> {
|
|
55
|
+
const getAllValues = () => signals.map((signal) => signal.value());
|
|
56
|
+
|
|
57
|
+
const initialValue = combinator(...getAllValues());
|
|
58
|
+
const combinedSignal = new Signal(initialValue, checkToEqualFunction);
|
|
59
|
+
|
|
60
|
+
const unsubscribeFunctions: VoidFunction[] = signals.map((signal) =>
|
|
61
|
+
signal.subscribe(() => {
|
|
62
|
+
const nextValue = combinator(...getAllValues());
|
|
63
|
+
|
|
64
|
+
combinedSignal.next(nextValue);
|
|
65
|
+
}));
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
signal: combinedSignal,
|
|
69
|
+
teardown() {
|
|
70
|
+
unsubscribeFunctions.forEach((unsubscribeFunction) => {
|
|
71
|
+
unsubscribeFunction();
|
|
72
|
+
});
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|