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 @@
|
|
|
1
|
+
export const HEX_SYMBOLS = '0123456789abcdef';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { HEX_SYMBOLS } from './HEX_SYMBOLS';
|
|
2
|
+
import { HexString } from './HexString';
|
|
3
|
+
|
|
4
|
+
export function isHexString(str: unknown): str is HexString {
|
|
5
|
+
if (typeof str !== 'string') {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
for (let key = 0; key < str.length; key++) {
|
|
10
|
+
if (HEX_SYMBOLS.indexOf(str[key].toLowerCase()) < 0) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { isString } from '../isString';
|
|
2
|
+
|
|
3
|
+
export type NonEmptyString = string;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Проверяет, что аргумент - строка, причем непустая
|
|
7
|
+
*/
|
|
8
|
+
export function isNonEmptyString (str: unknown): str is string {
|
|
9
|
+
return isString(str) && str.length > 0;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function assertNonEmptyString(value: unknown, errorMessage?: string): asserts value is NonEmptyString {
|
|
13
|
+
if (!isNonEmptyString(value)) {
|
|
14
|
+
let message = `value=[${value}] is not a string or empty`;
|
|
15
|
+
|
|
16
|
+
if (errorMessage) {
|
|
17
|
+
message += ` message=[${errorMessage}]`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
throw new Error(message);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function binarySearch(sortedArray: number[], key: number): number {
|
|
2
|
+
let left = 0;
|
|
3
|
+
let right = sortedArray.length - 1;
|
|
4
|
+
|
|
5
|
+
while (left <= right) {
|
|
6
|
+
const middle = Math.floor((left + right) / 2);
|
|
7
|
+
|
|
8
|
+
if (sortedArray[middle] === key) {
|
|
9
|
+
return middle;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (sortedArray[middle] < key) {
|
|
13
|
+
left = middle + 1;
|
|
14
|
+
} else {
|
|
15
|
+
right = middle - 1;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return -1;
|
|
20
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { UnsignedInteger } from '../../types/Number/UnsignedInteger';
|
|
2
|
+
|
|
3
|
+
export function binarySearchClosest<T>(
|
|
4
|
+
sortedArray: T[],
|
|
5
|
+
/**
|
|
6
|
+
* return positive to search left, negative to search right, 0 to return index
|
|
7
|
+
* for equal distances, returns lower index
|
|
8
|
+
*/
|
|
9
|
+
compareFunction: (a: T) => number
|
|
10
|
+
): UnsignedInteger {
|
|
11
|
+
if (sortedArray.length === 0) {
|
|
12
|
+
throw new Error('Array must not be empty for binarySearchClosest function');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let left = 0;
|
|
16
|
+
let right = sortedArray.length - 1;
|
|
17
|
+
|
|
18
|
+
while (left < right - 1) {
|
|
19
|
+
const midIndex = Math.floor((left + right) / 2);
|
|
20
|
+
const midValue = sortedArray[midIndex];
|
|
21
|
+
|
|
22
|
+
const compareResult = compareFunction(midValue);
|
|
23
|
+
|
|
24
|
+
if (compareResult === 0) {
|
|
25
|
+
return midIndex;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (compareResult > 0) {
|
|
29
|
+
right = midIndex;
|
|
30
|
+
} else {
|
|
31
|
+
left = midIndex;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const leftDistance = Math.abs(compareFunction(sortedArray[left]));
|
|
36
|
+
const rightDistance = Math.abs(compareFunction(sortedArray[right]));
|
|
37
|
+
|
|
38
|
+
if (leftDistance > rightDistance) {
|
|
39
|
+
return right;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return left;
|
|
43
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { assertPositiveInteger, PositiveInteger } from '../../types/Number/PositiveInteger';
|
|
2
|
+
import { CircularBuffer } from '../CircularBuffer/CircularBuffer';
|
|
3
|
+
import { noop } from '../Function/noop';
|
|
4
|
+
import { restrictParallelCalls } from '../Promise/restrictParallelCalls/restrictParallelCalls';
|
|
5
|
+
|
|
6
|
+
export type RemoteDataProcessingWindowLoadNextItemsReturnType<T> = {
|
|
7
|
+
items: T[];
|
|
8
|
+
isLast: boolean;
|
|
9
|
+
};
|
|
10
|
+
export type RemoteDataProcessingWindowExtractItemsFunction<T> = (requestedItemsCount: PositiveInteger) => Promise<RemoteDataProcessingWindowLoadNextItemsReturnType<T>>;
|
|
11
|
+
|
|
12
|
+
export type RemoteDataProcessingWindowLoadNextItemsParams<T> = {
|
|
13
|
+
lastItem: T | undefined;
|
|
14
|
+
count: PositiveInteger;
|
|
15
|
+
};
|
|
16
|
+
export type RemoteDataProcessingWindowLoadNextItemsFunction<T> = (params: RemoteDataProcessingWindowLoadNextItemsParams<T>) => Promise<RemoteDataProcessingWindowLoadNextItemsReturnType<T>>;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The function receives a buffer size and a function for loading data from remote source
|
|
20
|
+
*
|
|
21
|
+
* The function is dedicated to fill the buffer in the beginning and every time when the client extracts data from it,
|
|
22
|
+
* until the remote data is finished
|
|
23
|
+
*/
|
|
24
|
+
export function createRemoteDataProcessingWindow<T>({
|
|
25
|
+
bufferSize,
|
|
26
|
+
loadNextItems,
|
|
27
|
+
}: {
|
|
28
|
+
/**
|
|
29
|
+
* The size of the buffer (how many items are kept in the memory)
|
|
30
|
+
*/
|
|
31
|
+
bufferSize: PositiveInteger;
|
|
32
|
+
/**
|
|
33
|
+
* The method for requesting data from local buffer or from server.
|
|
34
|
+
*/
|
|
35
|
+
loadNextItems: RemoteDataProcessingWindowLoadNextItemsFunction<T>;
|
|
36
|
+
}): RemoteDataProcessingWindowExtractItemsFunction<T> {
|
|
37
|
+
const buffer = new CircularBuffer<T>(bufferSize);
|
|
38
|
+
|
|
39
|
+
let isRemoteDataFinished = false;
|
|
40
|
+
let lastItemPushedToBuffer: T | undefined = undefined;
|
|
41
|
+
|
|
42
|
+
let processingCallback: VoidFunction = noop;
|
|
43
|
+
|
|
44
|
+
// One error is enough to stop the whole process
|
|
45
|
+
let error: {
|
|
46
|
+
error: Error;
|
|
47
|
+
} | undefined = undefined;
|
|
48
|
+
|
|
49
|
+
let isRequestInProgress = false;
|
|
50
|
+
|
|
51
|
+
async function requestRemoteItemsToFillBuffer() {
|
|
52
|
+
if (isRequestInProgress || isRemoteDataFinished) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const countToLoad = bufferSize - buffer.length;
|
|
57
|
+
|
|
58
|
+
if (countToLoad === 0) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
isRequestInProgress = true;
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
const { isLast, items } = await loadNextItems({
|
|
66
|
+
count: countToLoad,
|
|
67
|
+
lastItem: lastItemPushedToBuffer,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
isRequestInProgress = false;
|
|
71
|
+
|
|
72
|
+
if (isLast) {
|
|
73
|
+
isRemoteDataFinished = true;
|
|
74
|
+
} else if (items.length !== countToLoad) {
|
|
75
|
+
throw new Error(`createRemoteDataProcessingWindow: loadNextItems for isLast=false returned wrong items count=[${items.length}] expected=[${countToLoad}]`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
for (const item of items) {
|
|
79
|
+
buffer.push(item);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
lastItemPushedToBuffer = items.at(-1);
|
|
83
|
+
|
|
84
|
+
requestRemoteItemsToFillBuffer();
|
|
85
|
+
} catch (e) {
|
|
86
|
+
isRequestInProgress = false;
|
|
87
|
+
error = {
|
|
88
|
+
error: e as Error,
|
|
89
|
+
};
|
|
90
|
+
} finally {
|
|
91
|
+
processingCallback();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
requestRemoteItemsToFillBuffer();
|
|
96
|
+
|
|
97
|
+
// eslint-disable-next-line require-await
|
|
98
|
+
return restrictParallelCalls(async (requestedItemsCount): Promise<RemoteDataProcessingWindowLoadNextItemsReturnType<T>> => {
|
|
99
|
+
if (error) {
|
|
100
|
+
throw error.error;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
assertPositiveInteger(requestedItemsCount);
|
|
104
|
+
|
|
105
|
+
if (requestedItemsCount > bufferSize) {
|
|
106
|
+
throw new Error(`createRemoteDataProcessingWindow: requestedItemsCount=[${requestedItemsCount}] must be less than bufferSize=[${bufferSize}]`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Has enough items to extract
|
|
110
|
+
if (buffer.length >= requestedItemsCount) {
|
|
111
|
+
const items = buffer.shiftCount(requestedItemsCount);
|
|
112
|
+
|
|
113
|
+
requestRemoteItemsToFillBuffer();
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
items,
|
|
117
|
+
isLast: isRemoteDataFinished && buffer.length === 0,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// No more data in remote, nothing to wait
|
|
122
|
+
if (isRemoteDataFinished) {
|
|
123
|
+
const items = buffer.shiftCount(requestedItemsCount);
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
items,
|
|
127
|
+
isLast: buffer.length === 0,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return new Promise<RemoteDataProcessingWindowLoadNextItemsReturnType<T>>((resolve, reject) => {
|
|
132
|
+
processingCallback = () => {
|
|
133
|
+
if (error) {
|
|
134
|
+
reject(error.error);
|
|
135
|
+
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (buffer.length < requestedItemsCount && !isRemoteDataFinished) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
processingCallback = noop;
|
|
144
|
+
|
|
145
|
+
const items = buffer.shiftCount(requestedItemsCount);
|
|
146
|
+
const isLast = isRemoteDataFinished && buffer.length === 0;
|
|
147
|
+
|
|
148
|
+
requestRemoteItemsToFillBuffer();
|
|
149
|
+
|
|
150
|
+
resolve({
|
|
151
|
+
items,
|
|
152
|
+
isLast,
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
});
|
|
156
|
+
}, 'createRemoteDataProcessingWindow');
|
|
157
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { UnsignedInteger } from '../../types/Number/UnsignedInteger';
|
|
2
|
+
|
|
3
|
+
export type SimultaneousOperationsHandlerParams<T> = {
|
|
4
|
+
index: UnsignedInteger;
|
|
5
|
+
param: T;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type SimultaneousOperationsHandlerParamsWithResult<T, R> = {
|
|
9
|
+
paramsList: SimultaneousOperationsHandlerParams<T>[];
|
|
10
|
+
result: R;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type SimultaneousOperationCall<T, R> = {
|
|
14
|
+
param: T;
|
|
15
|
+
resolve: (result: SimultaneousOperationsHandlerParamsWithResult<T, R>) => void;
|
|
16
|
+
reject: (error: Error) => void;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export function createSimultaneousOperationsHandler<T, R>(callback: (syncParamsToCall: SimultaneousOperationsHandlerParams<T>[]) => R): (
|
|
20
|
+
param: T,
|
|
21
|
+
index: UnsignedInteger
|
|
22
|
+
) => Promise<SimultaneousOperationsHandlerParamsWithResult<T, R>> {
|
|
23
|
+
let expectedNextIndex: UnsignedInteger = 0;
|
|
24
|
+
const queuedOperationsStore = new Map<UnsignedInteger, SimultaneousOperationCall<T, R>>();
|
|
25
|
+
|
|
26
|
+
return (param: T, index: UnsignedInteger): Promise<SimultaneousOperationsHandlerParamsWithResult<T, R>> => {
|
|
27
|
+
const promise = new Promise<SimultaneousOperationsHandlerParamsWithResult<T, R>>((resolve, reject) => {
|
|
28
|
+
queuedOperationsStore.set(index, {
|
|
29
|
+
param,
|
|
30
|
+
resolve,
|
|
31
|
+
reject,
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const syncParamsToCall: SimultaneousOperationsHandlerParams<T>[] = [];
|
|
36
|
+
const operationCalls: SimultaneousOperationCall<T, R>[] = [];
|
|
37
|
+
|
|
38
|
+
while (queuedOperationsStore.has(expectedNextIndex)) {
|
|
39
|
+
const nextOperation = queuedOperationsStore.get(expectedNextIndex)!;
|
|
40
|
+
|
|
41
|
+
syncParamsToCall.push({
|
|
42
|
+
index: expectedNextIndex,
|
|
43
|
+
param: nextOperation.param,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
operationCalls.push(nextOperation);
|
|
47
|
+
|
|
48
|
+
queuedOperationsStore.delete(expectedNextIndex);
|
|
49
|
+
expectedNextIndex++;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (syncParamsToCall.length > 0) {
|
|
53
|
+
const result = callback(syncParamsToCall);
|
|
54
|
+
|
|
55
|
+
for (const operation of operationCalls) {
|
|
56
|
+
operation.resolve({
|
|
57
|
+
paramsList: syncParamsToCall,
|
|
58
|
+
result,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return promise;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
base64url,
|
|
3
|
+
EncryptJWT,
|
|
4
|
+
jwtDecrypt,
|
|
5
|
+
} from 'jose';
|
|
6
|
+
|
|
7
|
+
export function encryptString({
|
|
8
|
+
string,
|
|
9
|
+
secret,
|
|
10
|
+
}: {
|
|
11
|
+
string: string;
|
|
12
|
+
secret: string;
|
|
13
|
+
}): Promise<string> {
|
|
14
|
+
return new EncryptJWT({
|
|
15
|
+
string,
|
|
16
|
+
})
|
|
17
|
+
.setProtectedHeader({
|
|
18
|
+
alg: 'dir',
|
|
19
|
+
enc: 'A128CBC-HS256',
|
|
20
|
+
})
|
|
21
|
+
.encrypt(base64url.decode(secret));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function decryptString({
|
|
25
|
+
string,
|
|
26
|
+
secret,
|
|
27
|
+
}: {
|
|
28
|
+
string: string;
|
|
29
|
+
secret: string;
|
|
30
|
+
}): Promise<string> {
|
|
31
|
+
const { payload } = await jwtDecrypt(string, base64url.decode(secret));
|
|
32
|
+
|
|
33
|
+
return payload.string as string;
|
|
34
|
+
}
|
package/src/utils/getPrimeNumbersWithEratosthenesSieve/getPrimeNumbersWithEratosthenesSieve.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { PositiveInteger } from '../../types/Number/PositiveInteger';
|
|
2
|
+
|
|
3
|
+
export function getPrimeNumbersWithEratosthenesSieve(max: PositiveInteger): PositiveInteger[] {
|
|
4
|
+
const sieve = Array.from({ length: max + 1 });
|
|
5
|
+
|
|
6
|
+
for (let base = 2; base <= max ** 0.5; base++) {
|
|
7
|
+
for (let i = base ** 2; i <= max; i += base) {
|
|
8
|
+
sieve[i] = true;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const primes = [];
|
|
13
|
+
|
|
14
|
+
for (let i = 2; i <= max; i++) {
|
|
15
|
+
if (!sieve[i]) {
|
|
16
|
+
primes.push(i);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return primes;
|
|
21
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { isObject } from '../../types/Object/Object';
|
|
2
|
+
import { isFunction } from '../Function/isFunction';
|
|
3
|
+
|
|
4
|
+
const isPromiseLike = (maybePromise: unknown): boolean => {
|
|
5
|
+
if (!isObject(maybePromise)) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
if (!isFunction(maybePromise.then)) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (!isFunction(maybePromise.catch)) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (!isFunction(maybePromise.finally)) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return true;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const isPromise = <T extends Promise<PT>, PT>(maybePromise: unknown): maybePromise is T => {
|
|
25
|
+
if (maybePromise instanceof Promise) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return isPromiseLike(maybePromise);
|
|
30
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { isPromise } from '../isPromise/isPromise';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates a wrapper that ensures async function calls are executed sequentially
|
|
5
|
+
* even when called simultaneously. Maintains order of execution by using a queue.
|
|
6
|
+
*
|
|
7
|
+
* @param callback The async function to be wrapped
|
|
8
|
+
* @returns A function that queues and executes the async operations sequentially
|
|
9
|
+
*/
|
|
10
|
+
export function makeAsyncFunctionCallsSimultaneous<T, R>(callback: (param: T) => (R | Promise<R>)): (param: T) => Promise<R> {
|
|
11
|
+
let isAsyncOperationRunning = false;
|
|
12
|
+
const operationsQueue: {
|
|
13
|
+
resolve: (value: R) => void;
|
|
14
|
+
reject: (error: Error) => void;
|
|
15
|
+
param: T;
|
|
16
|
+
}[] = [];
|
|
17
|
+
|
|
18
|
+
function runAsyncOperations() {
|
|
19
|
+
isAsyncOperationRunning = true;
|
|
20
|
+
|
|
21
|
+
const operation = operationsQueue.shift();
|
|
22
|
+
|
|
23
|
+
if (!operation) {
|
|
24
|
+
isAsyncOperationRunning = false;
|
|
25
|
+
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const returnValue = callback(operation.param);
|
|
31
|
+
|
|
32
|
+
if (isPromise(returnValue)) {
|
|
33
|
+
returnValue
|
|
34
|
+
.then(operation.resolve)
|
|
35
|
+
.catch(operation.reject)
|
|
36
|
+
.finally(runAsyncOperations);
|
|
37
|
+
} else {
|
|
38
|
+
operation.resolve(returnValue);
|
|
39
|
+
runAsyncOperations();
|
|
40
|
+
}
|
|
41
|
+
} catch (error) {
|
|
42
|
+
operation.reject(error as Error);
|
|
43
|
+
runAsyncOperations();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return (param: T): Promise<R> => {
|
|
48
|
+
const promise = new Promise<R>((resolve, reject) => {
|
|
49
|
+
operationsQueue.push({
|
|
50
|
+
resolve,
|
|
51
|
+
reject,
|
|
52
|
+
param,
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
if (isAsyncOperationRunning) {
|
|
57
|
+
return promise;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
runAsyncOperations();
|
|
61
|
+
|
|
62
|
+
return promise;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { parallelLimit } from 'async';
|
|
2
|
+
|
|
3
|
+
import { PositiveInteger } from '../../types/Number/PositiveInteger';
|
|
4
|
+
|
|
5
|
+
export function parallelsLimitPromise<T>(functions: (() => Promise<T>)[], limit: PositiveInteger): Promise<T[]> {
|
|
6
|
+
return new Promise<T[]>((resolve, reject) => {
|
|
7
|
+
parallelLimit<T>(
|
|
8
|
+
functions.map((asyncFunction) => (callback) => {
|
|
9
|
+
asyncFunction()
|
|
10
|
+
.then((result) => {
|
|
11
|
+
callback(null, result);
|
|
12
|
+
})
|
|
13
|
+
.catch((error) => {
|
|
14
|
+
callback(error);
|
|
15
|
+
});
|
|
16
|
+
}),
|
|
17
|
+
limit,
|
|
18
|
+
(error, result) => {
|
|
19
|
+
if (error) {
|
|
20
|
+
error.message = `parallelsLimitPromise error=[${error.message}]`;
|
|
21
|
+
reject(error);
|
|
22
|
+
} else {
|
|
23
|
+
resolve(result as T[]);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { PositiveInteger } from '../../types/Number/PositiveInteger';
|
|
2
|
+
import { UnsignedInteger } from '../../types/Number/UnsignedInteger';
|
|
3
|
+
import { isPromise } from '../isPromise/isPromise';
|
|
4
|
+
|
|
5
|
+
export function parallelsLimitQueue<T, R>({
|
|
6
|
+
callback,
|
|
7
|
+
limit,
|
|
8
|
+
}: {
|
|
9
|
+
callback: (param: T) => R | Promise<R>;
|
|
10
|
+
limit: PositiveInteger;
|
|
11
|
+
}): (param: T) => Promise<R> {
|
|
12
|
+
let operationsRunning: UnsignedInteger = 0;
|
|
13
|
+
const queue: {
|
|
14
|
+
param: T;
|
|
15
|
+
resolve: (result: R) => void;
|
|
16
|
+
reject: (error: Error) => void;
|
|
17
|
+
}[] = [];
|
|
18
|
+
|
|
19
|
+
async function runOperations() {
|
|
20
|
+
if (operationsRunning >= limit) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const operation = queue.shift();
|
|
25
|
+
|
|
26
|
+
if (!operation) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const {
|
|
31
|
+
param,
|
|
32
|
+
resolve,
|
|
33
|
+
reject,
|
|
34
|
+
} = operation;
|
|
35
|
+
|
|
36
|
+
operationsRunning++;
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const resultValue = callback(param);
|
|
40
|
+
|
|
41
|
+
if (isPromise(resultValue)) {
|
|
42
|
+
const result = await resultValue;
|
|
43
|
+
|
|
44
|
+
resolve(result);
|
|
45
|
+
} else {
|
|
46
|
+
resolve(resultValue);
|
|
47
|
+
}
|
|
48
|
+
} catch (error) {
|
|
49
|
+
reject(error as Error);
|
|
50
|
+
} finally {
|
|
51
|
+
operationsRunning--;
|
|
52
|
+
runOperations();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return (param: T) => {
|
|
57
|
+
const promise = new Promise<R>((resolve, reject) => {
|
|
58
|
+
queue.push({
|
|
59
|
+
param,
|
|
60
|
+
resolve,
|
|
61
|
+
reject,
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
runOperations();
|
|
66
|
+
|
|
67
|
+
return promise;
|
|
68
|
+
};
|
|
69
|
+
}
|