@zelgadis87/utils-core 4.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/dist/Lazy.d.ts +21 -0
- package/dist/LazyAsync.d.ts +23 -0
- package/dist/Logger.d.ts +21 -0
- package/dist/Optional.d.ts +70 -0
- package/dist/async/CancelableDeferred.d.ts +17 -0
- package/dist/async/Deferred.d.ts +27 -0
- package/dist/async/RateThrottler.d.ts +12 -0
- package/dist/async/Semaphore.d.ts +10 -0
- package/dist/async/index.d.ts +4 -0
- package/dist/index.d.ts +11 -0
- package/dist/random/index.d.ts +2 -0
- package/dist/random/randomInterval.d.ts +1 -0
- package/dist/random/randomPercentage.d.ts +1 -0
- package/dist/sorting/ComparisonChain.d.ts +57 -0
- package/dist/sorting/Sorter.d.ts +100 -0
- package/dist/sorting/index.d.ts +4 -0
- package/dist/sorting/types.d.ts +5 -0
- package/dist/time/RandomTimeDuration.d.ts +9 -0
- package/dist/time/TimeBase.d.ts +38 -0
- package/dist/time/TimeDuration.d.ts +81 -0
- package/dist/time/TimeFrequency.d.ts +10 -0
- package/dist/time/TimeInstant.d.ts +137 -0
- package/dist/time/TimeInstantBuilder.d.ts +77 -0
- package/dist/time/TimeUnit.d.ts +17 -0
- package/dist/time/index.d.ts +6 -0
- package/dist/time/types.d.ts +26 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/arrays.d.ts +33 -0
- package/dist/types/booleans.d.ts +2 -0
- package/dist/types/functions.d.ts +20 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/json.d.ts +6 -0
- package/dist/types/nulls.d.ts +8 -0
- package/dist/types/numbers.d.ts +31 -0
- package/dist/types/promises.d.ts +6 -0
- package/dist/types/records.d.ts +14 -0
- package/dist/types/strings.d.ts +40 -0
- package/dist/upgrade/DataUpgrader.d.ts +22 -0
- package/dist/upgrade/errors.d.ts +12 -0
- package/dist/upgrade/getTransitionsPath.d.ts +3 -0
- package/dist/upgrade/index.d.ts +2 -0
- package/dist/upgrade/types.d.ts +31 -0
- package/dist/utils/asError.d.ts +1 -0
- package/dist/utils/bindThis.d.ts +1 -0
- package/dist/utils/constant.d.ts +8 -0
- package/dist/utils/entries.d.ts +4 -0
- package/dist/utils/groupBy.d.ts +7 -0
- package/dist/utils/iff.d.ts +8 -0
- package/dist/utils/index.d.ts +22 -0
- package/dist/utils/indexBy.d.ts +7 -0
- package/dist/utils/jsonCloneDeep.d.ts +2 -0
- package/dist/utils/math.d.ts +9 -0
- package/dist/utils/noop.d.ts +1 -0
- package/dist/utils/omit.d.ts +2 -0
- package/dist/utils/pad.d.ts +3 -0
- package/dist/utils/pluralize.d.ts +1 -0
- package/dist/utils/round.d.ts +8 -0
- package/dist/utils/sortBy.d.ts +7 -0
- package/dist/utils/throttle.d.ts +3 -0
- package/dist/utils/uniq.d.ts +1 -0
- package/dist/utils/uniqBy.d.ts +2 -0
- package/dist/utils/uniqByKey.d.ts +1 -0
- package/dist/utils/upsert.d.ts +0 -0
- package/dist/utils/withTryCatch.d.ts +2 -0
- package/dist/utils/withTryCatchAsync.d.ts +2 -0
- package/dist/utils/wrap.d.ts +1 -0
- package/esbuild/index.cjs +2670 -0
- package/esbuild/index.mjs +2518 -0
- package/package.json +159 -0
- package/src/Lazy.ts +77 -0
- package/src/LazyAsync.ts +100 -0
- package/src/Logger.ts +44 -0
- package/src/Optional.ts +172 -0
- package/src/async/CancelableDeferred.ts +36 -0
- package/src/async/Deferred.ts +84 -0
- package/src/async/RateThrottler.ts +46 -0
- package/src/async/Semaphore.ts +45 -0
- package/src/async/index.ts +6 -0
- package/src/index.ts +13 -0
- package/src/random/index.ts +3 -0
- package/src/random/randomInterval.ts +4 -0
- package/src/random/randomPercentage.ts +6 -0
- package/src/sorting/ComparisonChain.ts +209 -0
- package/src/sorting/Sorter.ts +357 -0
- package/src/sorting/index.ts +5 -0
- package/src/sorting/types.ts +7 -0
- package/src/time/RandomTimeDuration.ts +21 -0
- package/src/time/TimeBase.ts +113 -0
- package/src/time/TimeDuration.ts +296 -0
- package/src/time/TimeFrequency.ts +28 -0
- package/src/time/TimeInstant.ts +488 -0
- package/src/time/TimeInstantBuilder.ts +126 -0
- package/src/time/TimeUnit.ts +43 -0
- package/src/time/index.ts +8 -0
- package/src/time/types.ts +56 -0
- package/src/types/arrays.ts +89 -0
- package/src/types/booleans.ts +8 -0
- package/src/types/functions.ts +27 -0
- package/src/types/index.ts +18 -0
- package/src/types/json.ts +5 -0
- package/src/types/nulls.ts +33 -0
- package/src/types/numbers.ts +80 -0
- package/src/types/promises.ts +23 -0
- package/src/types/records.ts +21 -0
- package/src/types/strings.ts +143 -0
- package/src/upgrade/DataUpgrader.ts +100 -0
- package/src/upgrade/errors.ts +25 -0
- package/src/upgrade/getTransitionsPath.ts +89 -0
- package/src/upgrade/index.ts +4 -0
- package/src/upgrade/types.ts +36 -0
- package/src/utils/asError.ts +12 -0
- package/src/utils/bindThis.ts +4 -0
- package/src/utils/constant.ts +9 -0
- package/src/utils/entries.ts +13 -0
- package/src/utils/groupBy.ts +39 -0
- package/src/utils/iff.ts +26 -0
- package/src/utils/index.ts +24 -0
- package/src/utils/indexBy.ts +36 -0
- package/src/utils/jsonCloneDeep.ts +31 -0
- package/src/utils/math.ts +44 -0
- package/src/utils/noop.ts +2 -0
- package/src/utils/omit.ts +8 -0
- package/src/utils/pad.ts +20 -0
- package/src/utils/pluralize.ts +20 -0
- package/src/utils/round.ts +24 -0
- package/src/utils/sortBy.ts +27 -0
- package/src/utils/throttle.ts +10 -0
- package/src/utils/uniq.ts +6 -0
- package/src/utils/uniqBy.ts +15 -0
- package/src/utils/uniqByKey.ts +5 -0
- package/src/utils/upsert.ts +2 -0
- package/src/utils/withTryCatch.ts +10 -0
- package/src/utils/withTryCatchAsync.ts +6 -0
- package/src/utils/wrap.ts +4 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { TFunction, TimeInstant } from "..";
|
|
2
|
+
import TimeFrequency from "../time/TimeFrequency";
|
|
3
|
+
import Deferred from "./Deferred";
|
|
4
|
+
|
|
5
|
+
type TPromiseFactory<T, R> = TFunction<T, Promise<R>>;
|
|
6
|
+
|
|
7
|
+
export class RateThrottler {
|
|
8
|
+
|
|
9
|
+
private readonly _availableSlots: TimeInstant[];
|
|
10
|
+
private readonly _waitingRequests: Deferred<void>[];
|
|
11
|
+
|
|
12
|
+
constructor(
|
|
13
|
+
private readonly _frequency: TimeFrequency
|
|
14
|
+
) {
|
|
15
|
+
const initialOffset = this.cooldown.divideBy( _frequency.times );
|
|
16
|
+
this._availableSlots = new Array( _frequency.times ).fill( 0 ).map( ( _, i ) => TimeInstant.now().addMs( i * initialOffset.ms ) );
|
|
17
|
+
this._waitingRequests = [];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public get cooldown() {
|
|
21
|
+
return this._frequency.period;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public async execute<T>( fn: TPromiseFactory<void, T> ) {
|
|
25
|
+
const wrappedFn = async () => {
|
|
26
|
+
const slot = this._availableSlots.shift()!;
|
|
27
|
+
try {
|
|
28
|
+
return slot.promise().then( () => fn() );
|
|
29
|
+
} finally {
|
|
30
|
+
this._availableSlots.push( TimeInstant.now().addDuration( this.cooldown ) );
|
|
31
|
+
if ( this._waitingRequests.length > 0 ) this._waitingRequests.shift()!.resolve();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
if ( this._availableSlots.length > 0 ) {
|
|
35
|
+
return wrappedFn();
|
|
36
|
+
} else {
|
|
37
|
+
// Semaphore implementation using promises.
|
|
38
|
+
const waitingRequest = new Deferred();
|
|
39
|
+
this._waitingRequests.push( waitingRequest );
|
|
40
|
+
return waitingRequest.then<T, T>( () => wrappedFn() );
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default RateThrottler;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { TAsyncProducer, TProducer, TimeDuration } from "..";
|
|
2
|
+
import Deferred from "./Deferred";
|
|
3
|
+
|
|
4
|
+
export class Semaphore {
|
|
5
|
+
|
|
6
|
+
private readonly _waitingRequests: Deferred<void>[];
|
|
7
|
+
|
|
8
|
+
constructor(
|
|
9
|
+
private _availableSlots: number = 1
|
|
10
|
+
) {
|
|
11
|
+
this._waitingRequests = [];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
private async _awaitSlot(): Promise<void> {
|
|
15
|
+
if ( this._availableSlots > 0 ) {
|
|
16
|
+
this._availableSlots -= 1;
|
|
17
|
+
return void 0;
|
|
18
|
+
} else {
|
|
19
|
+
// Semaphore implementation using promises.
|
|
20
|
+
const deferred = new Deferred();
|
|
21
|
+
this._waitingRequests.push( deferred );
|
|
22
|
+
return deferred.asPromise;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private _releaseSlot() {
|
|
27
|
+
const waitingSlotToResolve = this._waitingRequests.shift();
|
|
28
|
+
if ( waitingSlotToResolve ) {
|
|
29
|
+
waitingSlotToResolve.resolve();
|
|
30
|
+
} else {
|
|
31
|
+
this._availableSlots += 1;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public async execute<T>( fn: TAsyncProducer<T> | TProducer<T>, cooldown: TimeDuration = TimeDuration.ZERO ) {
|
|
36
|
+
return this._awaitSlot()
|
|
37
|
+
.then( () => fn() )
|
|
38
|
+
.finally( () => {
|
|
39
|
+
void cooldown.promise().then( () => this._releaseSlot() );
|
|
40
|
+
} );
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export default Semaphore;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
export { default as Lazy } from './Lazy';
|
|
3
|
+
export { default as LazyAsync } from './LazyAsync';
|
|
4
|
+
export { default as Logger } from './Logger';
|
|
5
|
+
export * from './Optional.js';
|
|
6
|
+
export * from './async';
|
|
7
|
+
export * from './random';
|
|
8
|
+
export * from './sorting/index.js';
|
|
9
|
+
export * from './time';
|
|
10
|
+
export * from './types';
|
|
11
|
+
export * from './upgrade';
|
|
12
|
+
export * from './utils';
|
|
13
|
+
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { TFunction, TKeysOfType, TReadableArray, isDefined, isNullOrUndefined } from "../types";
|
|
2
|
+
import { identity } from "../utils/constant.js";
|
|
3
|
+
import { TComparisonDirection, TComparisonFunction, TComparisonResult } from "./types.js";
|
|
4
|
+
|
|
5
|
+
type TCompareValueOptions = {
|
|
6
|
+
nullsFirst: boolean;
|
|
7
|
+
direction: TComparisonDirection;
|
|
8
|
+
}
|
|
9
|
+
const defaultCompareValueOptions: TCompareValueOptions = {
|
|
10
|
+
nullsFirst: false,
|
|
11
|
+
direction: 'ASC',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type TLooseCompareValueOptions = Partial<TCompareValueOptions> | TComparisonDirection;
|
|
15
|
+
|
|
16
|
+
function looseOptionsToStrict( x: TLooseCompareValueOptions | undefined ): TCompareValueOptions {
|
|
17
|
+
return { ...defaultCompareValueOptions, ...( typeof x === 'string' ? { direction: x } : x ) };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function compareValues<V>( a: V, b: V, options: Omit<TCompareValueOptions, "direction"> ): TComparisonResult {
|
|
21
|
+
if ( a === b )
|
|
22
|
+
return 0;
|
|
23
|
+
|
|
24
|
+
const nullA = ( a === null || a === undefined );
|
|
25
|
+
const nullB = ( b === null || b === undefined );
|
|
26
|
+
if ( nullA && nullB )
|
|
27
|
+
return 0;
|
|
28
|
+
if ( nullA !== nullB )
|
|
29
|
+
return ( nullA === options.nullsFirst ) ? -1 : 1;
|
|
30
|
+
|
|
31
|
+
// A & B are defined and are different.
|
|
32
|
+
return ( a < b ? -1 : 1 );
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function compareFunction<T, V>( fn: TFunction<T, V>, options: TCompareValueOptions ): TComparisonFunction<T> {
|
|
36
|
+
return ( a: T, b: T ) => applyDirection( compareValues<V>( fn( a ), fn( b ), options ), options.direction );
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function applyDirection( res: TComparisonResult, direction: TComparisonDirection ): TComparisonResult {
|
|
40
|
+
return res * ( direction === 'ASC' ? 1 : -1 ) as TComparisonResult
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function compareUsingGetter<T>( getter: TFunction<T, string>, options?: TLooseCompareValueOptions ): TComparisonFunction<T>;
|
|
44
|
+
function compareUsingGetter<T>( getter: TFunction<T, number>, options?: TLooseCompareValueOptions ): TComparisonFunction<T>;
|
|
45
|
+
function compareUsingGetter<T>( getter: TFunction<T, Date>, options?: TLooseCompareValueOptions ): TComparisonFunction<T>;
|
|
46
|
+
function compareUsingGetter<T>( getter: TFunction<T, string | number | Date>, options?: TLooseCompareValueOptions ): TComparisonFunction<T> {
|
|
47
|
+
return compareFunction( getter, looseOptionsToStrict( options ) )
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function compareUsingField<T>( field: keyof T & TKeysOfType<T, string | number | Date>, options?: TLooseCompareValueOptions ): TComparisonFunction<T> {
|
|
51
|
+
return compareFunction( t => t[ field ], looseOptionsToStrict( options ) );
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function compareUsingNaturalOrder<T>( options?: TLooseCompareValueOptions ): TComparisonFunction<T> {
|
|
55
|
+
return compareFunction( identity, looseOptionsToStrict( options ) );
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function compareStrings( options?: TLooseCompareValueOptions & { ignoreCase?: boolean } ): TComparisonFunction<string> {
|
|
59
|
+
return compareFunction<string, string>( t => options?.ignoreCase === true ? t.toLowerCase() : t, looseOptionsToStrict( options ) );
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function compareBooleans( options: Partial<TCompareValueOptions> & { truesFirst: boolean } ): TComparisonFunction<boolean> {
|
|
63
|
+
const opts = { ...defaultCompareValueOptions, ...options };
|
|
64
|
+
const fn: TComparisonFunction<boolean> = ( a: boolean, b: boolean ) => {
|
|
65
|
+
if ( a === b )
|
|
66
|
+
return 0 as const;
|
|
67
|
+
if ( isNullOrUndefined( a ) ) return opts.nullsFirst ? -1 : 1;
|
|
68
|
+
if ( isNullOrUndefined( b ) ) return opts.nullsFirst ? 1 : -1;
|
|
69
|
+
return ( ( a === true && opts.truesFirst ) || ( a === false && !opts.truesFirst ) ) ? -1 : 1;
|
|
70
|
+
}
|
|
71
|
+
return ( a, b ) => applyDirection( fn( a, b ), opts.direction );
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function compareUsingFunction<T>( fn: TComparisonFunction<T> ): TComparisonFunction<T> {
|
|
75
|
+
return fn;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function compareUsingSet<T>( arr: Array<T> ): TComparisonFunction<T> {
|
|
79
|
+
const fn: TComparisonFunction<T> = ( a: T, b: T ) => {
|
|
80
|
+
if ( a === b )
|
|
81
|
+
return 0 as const;
|
|
82
|
+
const aIncluded = isDefined( a ) && arr.includes( a );
|
|
83
|
+
const bIncluded = isDefined( b ) && arr.includes( b );
|
|
84
|
+
if ( aIncluded === bIncluded ) {
|
|
85
|
+
return 0 as const;
|
|
86
|
+
} else {
|
|
87
|
+
return ( aIncluded ? -1 as const : 1 as const );
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return fn;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function compareUsingArray<T>( arr: Array<T> ): TComparisonFunction<T> {
|
|
94
|
+
const fn: TComparisonFunction<T> = ( a: T, b: T ) => {
|
|
95
|
+
if ( a === b )
|
|
96
|
+
return 0 as const;
|
|
97
|
+
const aIncluded = isDefined( a ) && arr.includes( a );
|
|
98
|
+
const bIncluded = isDefined( b ) && arr.includes( b );
|
|
99
|
+
if ( !aIncluded && !bIncluded ) {
|
|
100
|
+
return 0 as const;
|
|
101
|
+
} else if ( aIncluded && bIncluded ) {
|
|
102
|
+
return ( arr.indexOf( a ) < arr.indexOf( b ) ? -1 as const : 1 as const );
|
|
103
|
+
} else {
|
|
104
|
+
return ( aIncluded ? -1 as const : 1 as const );
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return fn;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function reverse<T>( fn: TComparisonFunction<T> ): TComparisonFunction<T> {
|
|
111
|
+
return ( a: T, b: T ) => fn( a, b ) * -1 as TComparisonResult;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Creates a ComparisonChain V1.
|
|
116
|
+
* Usage: ComparisonChain.createWith<number>( c => c.compareUsingNumbers() ).sort( [ 100, 1, 10, 5 ] );
|
|
117
|
+
* @deprecated[2023-10-22]: Use createSorterFor instead.
|
|
118
|
+
**/
|
|
119
|
+
export class ComparisonChain<T> {
|
|
120
|
+
|
|
121
|
+
private constructor(
|
|
122
|
+
private readonly _fns: TComparisonFunction<T>[],
|
|
123
|
+
private readonly _reversed: boolean = false
|
|
124
|
+
) {}
|
|
125
|
+
|
|
126
|
+
public compare = ( a: T, b: T ): TComparisonResult => {
|
|
127
|
+
return this.doCompare( a, b ) * ( this._reversed ? -1 : 1 ) as TComparisonResult;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
public sort = <A extends TReadableArray<T>>( arr: A ): A extends Array<T> ? Array<T> : ReadonlyArray<T> => {
|
|
131
|
+
return [ ...arr ].sort( this.compare );
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
public then( getFn: ( compare: TChain<T> ) => TComparisonFunction<T> ): ComparisonChain<T> {
|
|
135
|
+
const cmp = getFn( createCompare<T>() );
|
|
136
|
+
return this.thenBy( cmp );
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
public thenBy( cmp: ComparisonChain<T> | TComparisonFunction<T> ): ComparisonChain<T> {
|
|
140
|
+
return new ComparisonChain<T>( [ ...this._fns, getComparisonFunction( cmp ) ] );
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
public thenChain<R>( transform: TFunction<T, R>, getFn: ( compare: TChain<R> ) => TComparisonFunction<R> ): ComparisonChain<T> {
|
|
144
|
+
const cmp = getFn( createCompare<R>() );
|
|
145
|
+
return this.thenChainBy( transform, cmp );
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
public thenChainBy<R>( transform: TFunction<T, R>, cmp: ComparisonChain<R> | TComparisonFunction<R> ): ComparisonChain<T> {
|
|
149
|
+
return new ComparisonChain<T>( [ ...this._fns, applyTransformationBeforeComparison( transform, getComparisonFunction( cmp ) ) ] );
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
public reversed(): ComparisonChain<T> {
|
|
153
|
+
return new ComparisonChain<T>( [ ...this._fns ], !this._reversed );
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private doCompare( this: ComparisonChain<T>, a: T, b: T ): TComparisonResult {
|
|
157
|
+
return this._fns.reduce( ( ret: TComparisonResult, fn: TComparisonFunction<T> ) => {
|
|
158
|
+
return ret !== 0 ? ret : fn( a, b );
|
|
159
|
+
}, 0 );
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
public static create<T>() {
|
|
163
|
+
return {
|
|
164
|
+
using: ( getFn: ( chainable: TChain<T> ) => TComparisonFunction<T> ) => {
|
|
165
|
+
return new ComparisonChain<T>( [] ).then( getFn );
|
|
166
|
+
},
|
|
167
|
+
usingTransformation: <R>( transform: TFunction<T, R>, getFn: ( chainable: TChain<R> ) => TComparisonFunction<R> ) => {
|
|
168
|
+
return new ComparisonChain<T>( [] ).thenChain( transform, getFn );
|
|
169
|
+
},
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
public static createWith<T>( getFn: ( chainable: TChain<T> ) => TComparisonFunction<T> ) {
|
|
174
|
+
return this.create<T>().using( getFn );
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
public static createWithTransformation<T, R>( transform: TFunction<T, R>, getFn: ( chainable: TChain<R> ) => TComparisonFunction<R> ) {
|
|
178
|
+
return this.create<T>().usingTransformation( transform, getFn );
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
}
|
|
182
|
+
export default ComparisonChain;
|
|
183
|
+
|
|
184
|
+
function createCompare<T>() {
|
|
185
|
+
return {
|
|
186
|
+
compareUsingGetter: compareUsingGetter<T>,
|
|
187
|
+
compareUsingField: compareUsingField<T>,
|
|
188
|
+
compareUsingStrings: compareStrings,
|
|
189
|
+
compareUsingStringsIgnoringCase: ( options?: TLooseCompareValueOptions ) => compareStrings( { ...looseOptionsToStrict( options ), ignoreCase: true } ),
|
|
190
|
+
compareUsingBooleans: compareBooleans,
|
|
191
|
+
compareUsingNumbers: compareUsingNaturalOrder<number>,
|
|
192
|
+
compareUsingDates: compareUsingNaturalOrder<Date>,
|
|
193
|
+
compareUsingFunction: compareUsingFunction<T>,
|
|
194
|
+
placeFirst: ( arr: Array<T> ) => compareUsingSet( arr ),
|
|
195
|
+
placeFirstInOrder: ( arr: Array<T> ) => compareUsingArray( arr ),
|
|
196
|
+
placeLast: ( arr: Array<T> ) => reverse( compareUsingSet( arr ) ),
|
|
197
|
+
placeLastInOrder: ( arr: Array<T> ) => reverse( compareUsingArray( [ ...arr ].reverse() ) ),
|
|
198
|
+
} satisfies Record<string, ( ...args: any[] ) => TComparisonFunction<any>>;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function applyTransformationBeforeComparison<T, R>( transform: TFunction<T, R>, fn: TComparisonFunction<R> ): TComparisonFunction<T> {
|
|
202
|
+
return ( a: T, b: T ) => fn( transform( a ), transform( b ) );
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function getComparisonFunction<T>( arg: ComparisonChain<T> | TComparisonFunction<T> ): TComparisonFunction<T> {
|
|
206
|
+
return ( arg instanceof ComparisonChain ) ? arg.compare : arg;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
type TChain<T> = ReturnType<typeof createCompare<T>>
|