@revolugo/common 6.10.7-beta.1 → 6.10.7-beta.10
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/package.json +1 -2
- package/src/cancellation-policies.ts +1 -1
- package/src/currencies/index.ts +1 -1
- package/src/utils/{math.ts → amount-from-percentage.ts} +0 -10
- package/src/utils/case-transformers.ts +0 -1
- package/src/utils/chunk.ts +7 -0
- package/src/utils/colors.ts +1 -1
- package/src/utils/compact-object.ts +7 -0
- package/src/utils/compact.ts +28 -0
- package/src/utils/compute-margin-rate.ts +13 -0
- package/src/utils/compute-selling-price.ts +12 -0
- package/src/utils/defaults-deep.ts +85 -0
- package/src/utils/delay.ts +5 -0
- package/src/utils/generate-numbers-from-str.ts +15 -0
- package/src/utils/generate-pseudo-random-string.ts +3 -0
- package/src/utils/get-guest-count.ts +1 -2
- package/src/utils/get-random-element-from-array.ts +10 -0
- package/src/utils/get-random-hex-color.ts +5 -0
- package/src/utils/{random.ts → get-random-int.ts} +0 -6
- package/src/utils/index.ts +31 -12
- package/src/utils/key-by.ts +25 -0
- package/src/utils/merge.ts +140 -0
- package/src/utils/omit-by.ts +37 -0
- package/src/utils/omit.ts +39 -0
- package/src/utils/pick.ts +12 -0
- package/src/utils/poller.ts +0 -1
- package/src/utils/{strings.ts → prepare-ts-query.ts} +0 -6
- package/src/utils/{promise-tools.ts → promise-timeout.ts} +0 -6
- package/src/utils/random-int.ts +3 -0
- package/src/utils/shuffle-array.ts +13 -0
- package/src/utils/{array-tools.ts → sort-by.ts} +0 -103
- package/src/utils/sum-by.ts +23 -0
- package/src/utils/uniq-with.ts +16 -0
- package/src/utils/validators.ts +0 -1
- package/src/utils/weighted-mean.ts +9 -0
- package/src/utils/numbers.ts +0 -46
- package/src/utils/object-tools.ts +0 -166
- /package/src/utils/{value-tools.ts → is-nil.ts} +0 -0
- /package/src/utils/{children-tools.ts → parse-children.ts} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revolugo/common",
|
|
3
|
-
"version": "6.10.7-beta.
|
|
3
|
+
"version": "6.10.7-beta.10",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Revolugo common",
|
|
6
6
|
"author": "Revolugo",
|
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
"change-case": "5.4.4",
|
|
27
27
|
"dayjs": "1.11.18",
|
|
28
28
|
"ky": "1.11.0",
|
|
29
|
-
"lodash-es": "4.17.21",
|
|
30
29
|
"slugify": "1.6.6",
|
|
31
30
|
"uuid": "13.0.0"
|
|
32
31
|
},
|
package/src/currencies/index.ts
CHANGED
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
export function weightedMean(values: number[], weights: number[]): number {
|
|
2
|
-
const sum = values.reduce(
|
|
3
|
-
(acc: number, val: number, i: number) => acc + val * (weights[i] ?? 0),
|
|
4
|
-
0,
|
|
5
|
-
)
|
|
6
|
-
const sumWeights = weights.reduce((acc: number, val: number) => acc + val, 0)
|
|
7
|
-
|
|
8
|
-
return sum / sumWeights
|
|
9
|
-
}
|
|
10
|
-
|
|
11
1
|
export function amountFromPercentage(
|
|
12
2
|
percentage: number,
|
|
13
3
|
amount: number,
|
package/src/utils/colors.ts
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function compact<T>(
|
|
2
|
+
array: (T | null | undefined)[] | null | undefined,
|
|
3
|
+
): Exclude<T, null | undefined>[] {
|
|
4
|
+
const length = array === null || array === undefined ? 0 : array.length
|
|
5
|
+
let index = -1
|
|
6
|
+
let resIndex = 0
|
|
7
|
+
const result: Exclude<T, null | undefined>[] = []
|
|
8
|
+
|
|
9
|
+
while (index < length) {
|
|
10
|
+
index += 1
|
|
11
|
+
if (array !== null && array !== undefined) {
|
|
12
|
+
const value = array[index]
|
|
13
|
+
|
|
14
|
+
if (
|
|
15
|
+
value !== null &&
|
|
16
|
+
value !== undefined &&
|
|
17
|
+
value !== false &&
|
|
18
|
+
value !== 0 &&
|
|
19
|
+
value !== ''
|
|
20
|
+
) {
|
|
21
|
+
result[resIndex] = value as Exclude<T, null | undefined>
|
|
22
|
+
resIndex += 1
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return result
|
|
28
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function computeMarginRate(
|
|
2
|
+
buyingPrice: number | string,
|
|
3
|
+
sellingPrice: number | string,
|
|
4
|
+
): number {
|
|
5
|
+
const buyingPriceNum = Number(buyingPrice)
|
|
6
|
+
const sellingPriceNum = Number(sellingPrice)
|
|
7
|
+
|
|
8
|
+
if (Number.isNaN(sellingPriceNum) || Number.isNaN(buyingPriceNum)) {
|
|
9
|
+
throw new TypeError('sellingPrice or buyingPrice is NaN')
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return Number((1 - buyingPriceNum / sellingPriceNum).toPrecision(10))
|
|
13
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function computeSellingPrice(
|
|
2
|
+
buyingPrice: number | string | null = 0,
|
|
3
|
+
rate: number | string | null = 0,
|
|
4
|
+
): number {
|
|
5
|
+
if (Number.isNaN(Number(buyingPrice)) || Number.isNaN(Number(rate))) {
|
|
6
|
+
throw new TypeError('price or rate is NaN')
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const sellingPrice = Number(buyingPrice) / (1 - Number(rate))
|
|
10
|
+
|
|
11
|
+
return Math.ceil(Math.floor(sellingPrice * 100) / 100)
|
|
12
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drop-in native TypeScript replacement for `lodash-es` `defaultsDeep`.
|
|
3
|
+
*
|
|
4
|
+
* Behaviour matched (carefully):
|
|
5
|
+
* - Mutates and returns the first argument (target).
|
|
6
|
+
* - Assigns own and *inherited* enumerable **string-keyed** properties from sources
|
|
7
|
+
* to the target only when the target's property is `undefined`.
|
|
8
|
+
* - Recursively assigns (deep) when both target and source values are objects/arrays.
|
|
9
|
+
* - Does not copy symbol-keyed properties (matches the "string keyed" behaviour).
|
|
10
|
+
* - Preserves `null` (i.e. `null` is NOT considered `undefined` so it won't be overwritten).
|
|
11
|
+
* - Avoids infinite recursion for circular source structures.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
15
|
+
type AnyObject = Record<string, any>
|
|
16
|
+
|
|
17
|
+
function isObject(value: any): value is AnyObject {
|
|
18
|
+
return value !== null && typeof value === 'object'
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function defaultsDeep<T>(
|
|
22
|
+
object: T,
|
|
23
|
+
...sources: any[]
|
|
24
|
+
): T extends AnyObject ? T : any {
|
|
25
|
+
// Ensure we always return an object reference we can mutate (lodash creates/uses {} when target is falsy)
|
|
26
|
+
const target: AnyObject = (
|
|
27
|
+
object === null || object === undefined ? {} : object
|
|
28
|
+
) as AnyObject
|
|
29
|
+
|
|
30
|
+
// WeakMap to track already-cloned source objects so circular refs won't blow the stack
|
|
31
|
+
const seen = new WeakMap<object, object>()
|
|
32
|
+
|
|
33
|
+
function applyDefaults(dst: AnyObject, src: any) {
|
|
34
|
+
// Only iterate string-keyed enumerable properties (own + inherited) => for...in
|
|
35
|
+
for (const key in src) {
|
|
36
|
+
if (Object.hasOwn(src, key)) {
|
|
37
|
+
const srcVal = src[key]
|
|
38
|
+
const dstVal = dst[key]
|
|
39
|
+
|
|
40
|
+
// only apply when destination is strictly `undefined` (lodash semantics)
|
|
41
|
+
if (dstVal === undefined) {
|
|
42
|
+
// eslint-disable-next-line max-depth
|
|
43
|
+
if (isObject(srcVal)) {
|
|
44
|
+
// If we've already cloned this source object (circular), reuse it
|
|
45
|
+
// eslint-disable-next-line max-depth
|
|
46
|
+
if (seen.has(srcVal)) {
|
|
47
|
+
dst[key] = seen.get(srcVal)
|
|
48
|
+
} else {
|
|
49
|
+
// Prepare new container (array vs object)
|
|
50
|
+
const created = Array.isArray(srcVal)
|
|
51
|
+
? ([] as unknown[])
|
|
52
|
+
: ({} as AnyObject)
|
|
53
|
+
// remember mapping to handle circular refs
|
|
54
|
+
seen.set(srcVal, created)
|
|
55
|
+
|
|
56
|
+
// Recursively fill created from srcVal
|
|
57
|
+
applyDefaults(created, srcVal)
|
|
58
|
+
|
|
59
|
+
// assign the created clone as the default
|
|
60
|
+
dst[key] = created
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
// Primitive or function: assign directly
|
|
64
|
+
dst[key] = srcVal
|
|
65
|
+
}
|
|
66
|
+
} else if (isObject(dstVal) && isObject(srcVal)) {
|
|
67
|
+
// destination already has a value (not undefined) and both are objects => recurse
|
|
68
|
+
// (do not overwrite existing non-undefined values)
|
|
69
|
+
// Note: do not treat arrays specially here; Array.isArray check only used when creating new value
|
|
70
|
+
applyDefaults(dstVal, srcVal)
|
|
71
|
+
}
|
|
72
|
+
// else: destination has a non-undefined primitive or non-object - skip (do not overwrite)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
for (const src of sources) {
|
|
78
|
+
if (src !== null && src !== undefined) {
|
|
79
|
+
// If source itself has been seen (unlikely across top-level sources), we still traverse it
|
|
80
|
+
applyDefaults(target, src)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return target as any
|
|
85
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function generateNumbersFromStr(str: string): [number, number] {
|
|
2
|
+
let hash = 5381
|
|
3
|
+
for (let i = 0; i < str.length; i++) {
|
|
4
|
+
// eslint-disable-next-line no-bitwise
|
|
5
|
+
hash = (hash << 5) + hash + str.charCodeAt(i)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// Generate two numbers using the hash
|
|
9
|
+
// eslint-disable-next-line no-bitwise
|
|
10
|
+
const num1 = (hash & 0xff_ff) / 0xff_ff
|
|
11
|
+
// eslint-disable-next-line no-bitwise
|
|
12
|
+
const num2 = ((hash >> 16) & 0xff_ff) / 0xff_ff
|
|
13
|
+
|
|
14
|
+
return [num1, num2]
|
|
15
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function getRandomElementFromArray<T>(array: readonly T[]): T {
|
|
2
|
+
if (array.length === 0) {
|
|
3
|
+
throw new Error('Cannot get random element from empty array')
|
|
4
|
+
}
|
|
5
|
+
const element = array[Math.floor(Math.random() * array.length)]
|
|
6
|
+
if (element === undefined) {
|
|
7
|
+
throw new Error('Array element is undefined')
|
|
8
|
+
}
|
|
9
|
+
return element
|
|
10
|
+
}
|
|
@@ -4,9 +4,3 @@ export function getRandomInt(min: number, max: number): number {
|
|
|
4
4
|
|
|
5
5
|
return Math.floor(Math.random() * (roundedMax - roundedMin + 1)) + roundedMin
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
export function getRandomHexColor(): string {
|
|
9
|
-
const hex = Math.floor(Math.random() * 0xffffff).toString(16)
|
|
10
|
-
|
|
11
|
-
return hex.padStart(6, '0').toUpperCase()
|
|
12
|
-
}
|
package/src/utils/index.ts
CHANGED
|
@@ -1,31 +1,50 @@
|
|
|
1
1
|
export * from './add-classes.ts'
|
|
2
|
-
export * from './
|
|
2
|
+
export * from './amount-from-percentage.ts'
|
|
3
3
|
export * from './case-transformers.ts'
|
|
4
|
+
export * from './chunk.ts'
|
|
4
5
|
export * from './colors.ts'
|
|
6
|
+
export * from './compact-object.ts'
|
|
7
|
+
export * from './compact.ts'
|
|
8
|
+
export * from './compute-margin-rate.ts'
|
|
9
|
+
export * from './compute-selling-price.ts'
|
|
10
|
+
export * from './create-composite-key.ts'
|
|
5
11
|
export * from './currency.ts'
|
|
6
12
|
export * from './dates.ts'
|
|
7
13
|
export * from './dayjs.ts'
|
|
8
14
|
export * from './debounce.ts'
|
|
15
|
+
export * from './defaults-deep.ts'
|
|
16
|
+
export * from './delay.ts'
|
|
9
17
|
export * from './find-unique-keys.ts'
|
|
18
|
+
export * from './generate-numbers-from-str.ts'
|
|
19
|
+
export * from './generate-pseudo-random-string.ts'
|
|
10
20
|
export * from './get-guest-count.ts'
|
|
21
|
+
export * from './get-random-element-from-array.ts'
|
|
22
|
+
export * from './get-random-hex-color.ts'
|
|
23
|
+
export * from './get-random-int.ts'
|
|
11
24
|
export * from './group-by.ts'
|
|
25
|
+
export * from './images.ts'
|
|
12
26
|
export * from './is-empty.ts'
|
|
13
27
|
export * from './is-equal.ts'
|
|
28
|
+
export * from './is-nil.ts'
|
|
29
|
+
export * from './key-by.ts'
|
|
14
30
|
export * from './lang-default-fallbacks.ts'
|
|
15
|
-
export * from './
|
|
16
|
-
export * from './
|
|
17
|
-
export * from './
|
|
31
|
+
export * from './merge.ts'
|
|
32
|
+
export * from './omit-by.ts'
|
|
33
|
+
export * from './omit.ts'
|
|
34
|
+
export * from './parse-children.ts'
|
|
35
|
+
export * from './pick.ts'
|
|
18
36
|
export * from './poller.ts'
|
|
19
|
-
export * from './
|
|
20
|
-
export * from './
|
|
37
|
+
export * from './prepare-ts-query.ts'
|
|
38
|
+
export * from './promise-timeout.ts'
|
|
39
|
+
export * from './random-int.ts'
|
|
21
40
|
export * from './range.ts'
|
|
22
|
-
export * from './
|
|
41
|
+
export * from './shake.ts'
|
|
42
|
+
export * from './shuffle-array.ts'
|
|
43
|
+
export * from './sort-by.ts'
|
|
44
|
+
export * from './sum-by.ts'
|
|
23
45
|
export * from './sum.ts'
|
|
24
46
|
export * from './to-boolean.ts'
|
|
25
47
|
export * from './uniq-by.ts'
|
|
48
|
+
export * from './uniq-with.ts'
|
|
26
49
|
export * from './validators.ts'
|
|
27
|
-
export * from './
|
|
28
|
-
export * from './create-composite-key.ts'
|
|
29
|
-
export * from './children-tools.ts'
|
|
30
|
-
export * from './shake.ts'
|
|
31
|
-
export * from './images.ts'
|
|
50
|
+
export * from './weighted-mean.ts'
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates an object composed of keys generated from the results of running each element of collection through iteratee.
|
|
3
|
+
* The corresponding value of each key is the last element responsible for generating the key.
|
|
4
|
+
*
|
|
5
|
+
* @param collection - The collection to iterate over
|
|
6
|
+
* @param iteratee - The iteratee to transform keys. Can be a function or a property name
|
|
7
|
+
* @returns Returns the composed aggregate object
|
|
8
|
+
*/
|
|
9
|
+
export function keyBy<T>(
|
|
10
|
+
collection: T[] | null | undefined,
|
|
11
|
+
iteratee: ((value: T) => string | number) | keyof T,
|
|
12
|
+
): Record<string, T> {
|
|
13
|
+
return (
|
|
14
|
+
collection?.reduce<Record<string, T>>((acc, item) => {
|
|
15
|
+
if (item === undefined || item === null) {
|
|
16
|
+
return acc
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const key =
|
|
20
|
+
typeof iteratee === 'function' ? iteratee(item) : String(item[iteratee])
|
|
21
|
+
acc[key] = item
|
|
22
|
+
return acc
|
|
23
|
+
}, {}) || {}
|
|
24
|
+
)
|
|
25
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks if a value is a plain object (created via {} or new Object).
|
|
3
|
+
* Lodash treats only plain objects as recursively mergable.
|
|
4
|
+
*/
|
|
5
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
6
|
+
if (value === null || typeof value !== 'object') {
|
|
7
|
+
return false
|
|
8
|
+
}
|
|
9
|
+
const proto = Object.getPrototypeOf(value)
|
|
10
|
+
return proto === Object.prototype || proto === null
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Deep clones an object, handling arrays and plain objects
|
|
15
|
+
*/
|
|
16
|
+
function cloneDeep<T>(value: T, seen = new WeakSet()): T {
|
|
17
|
+
if (value === null || value === undefined || typeof value !== 'object') {
|
|
18
|
+
return value
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Handle circular references
|
|
22
|
+
if (seen.has(value as object)) {
|
|
23
|
+
return value
|
|
24
|
+
}
|
|
25
|
+
seen.add(value as object)
|
|
26
|
+
|
|
27
|
+
if (Array.isArray(value)) {
|
|
28
|
+
return value.map(item => cloneDeep(item, seen)) as T
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (isPlainObject(value)) {
|
|
32
|
+
const cloned: Record<string, unknown> = {}
|
|
33
|
+
for (const key in value) {
|
|
34
|
+
if (Object.hasOwn(value, key)) {
|
|
35
|
+
cloned[key] = cloneDeep(value[key], seen)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return cloned as T
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// For other object types (Date, RegExp, etc.), return as-is
|
|
42
|
+
return value
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Recursively merges source into target, following lodash.merge semantics.
|
|
47
|
+
*/
|
|
48
|
+
function mergeObject(
|
|
49
|
+
target: Record<string, unknown>,
|
|
50
|
+
source: Record<string, unknown>,
|
|
51
|
+
seen = new WeakSet<object>(),
|
|
52
|
+
): void {
|
|
53
|
+
if (!isPlainObject(source) || !isPlainObject(target)) {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Circular reference guard
|
|
58
|
+
if (source === target || seen.has(source)) {
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
seen.add(source)
|
|
62
|
+
|
|
63
|
+
// Lodash merges own + inherited enumerable string-keyed props
|
|
64
|
+
for (const key in source) {
|
|
65
|
+
if (Object.hasOwn(source, key)) {
|
|
66
|
+
const srcVal = source[key]
|
|
67
|
+
const tgtVal = target[key]
|
|
68
|
+
|
|
69
|
+
if (isPlainObject(srcVal) && isPlainObject(tgtVal)) {
|
|
70
|
+
mergeObject(tgtVal as Record<string, unknown>, srcVal, seen)
|
|
71
|
+
} else if (Array.isArray(srcVal) && Array.isArray(tgtVal)) {
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
73
|
+
target[key] = mergeArrays(tgtVal, srcVal, seen)
|
|
74
|
+
} else {
|
|
75
|
+
// Override with source value - this is the key fix
|
|
76
|
+
target[key] = cloneDeep(srcVal, seen)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Merges two arrays by index, lodash style.
|
|
84
|
+
* - Recursively merges plain objects/arrays
|
|
85
|
+
* - Overwrites with source otherwise
|
|
86
|
+
*/
|
|
87
|
+
function mergeArrays(
|
|
88
|
+
target: unknown[],
|
|
89
|
+
source: unknown[],
|
|
90
|
+
seen: WeakSet<object>,
|
|
91
|
+
): unknown[] {
|
|
92
|
+
const result = target.slice()
|
|
93
|
+
|
|
94
|
+
for (let i = 0; i < source.length; i++) {
|
|
95
|
+
const srcVal = source[i]
|
|
96
|
+
const tgtVal = result[i]
|
|
97
|
+
|
|
98
|
+
if (isPlainObject(srcVal) && isPlainObject(tgtVal)) {
|
|
99
|
+
const merged: Record<string, unknown> = { ...tgtVal }
|
|
100
|
+
mergeObject(merged, srcVal, seen)
|
|
101
|
+
result[i] = merged
|
|
102
|
+
} else if (Array.isArray(srcVal) && Array.isArray(tgtVal)) {
|
|
103
|
+
result[i] = mergeArrays(tgtVal, srcVal, seen)
|
|
104
|
+
} else {
|
|
105
|
+
result[i] = cloneDeep(srcVal, seen)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return result
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* A drop-in replacement for lodash-es merge.
|
|
114
|
+
*
|
|
115
|
+
* - Recursively merges own and inherited enumerable string-keyed properties.
|
|
116
|
+
* - Arrays and plain objects are merged by index/key.
|
|
117
|
+
* - Non-plain objects (Date, RegExp, Map, Set, custom classes, etc.)
|
|
118
|
+
* are assigned by reference (not cloned).
|
|
119
|
+
* - `undefined` does not overwrite an existing value.
|
|
120
|
+
* - Symbols and non-enumerables are ignored.
|
|
121
|
+
* - Prototype pollution is *not* prevented (matches lodash behavior).
|
|
122
|
+
*/
|
|
123
|
+
export function merge<T extends Record<string, unknown>>(
|
|
124
|
+
object: T,
|
|
125
|
+
...sources: unknown[]
|
|
126
|
+
): T {
|
|
127
|
+
if (!isPlainObject(object)) {
|
|
128
|
+
throw new TypeError('Target must be a plain object')
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const seen = new WeakSet<object>()
|
|
132
|
+
|
|
133
|
+
for (const src of sources) {
|
|
134
|
+
if (src !== null && src !== undefined) {
|
|
135
|
+
mergeObject(object, src as Record<string, unknown>, seen)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return object
|
|
140
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates an object composed of the own enumerable properties of object that predicate doesn't return truthy for.
|
|
3
|
+
* The predicate is invoked with two arguments: (value, key).
|
|
4
|
+
* If predicate is a string, it omits the property with that key name.
|
|
5
|
+
*
|
|
6
|
+
* @param object - The source object
|
|
7
|
+
* @param predicate - The function invoked per property or a string key to omit
|
|
8
|
+
* @returns Returns the new object
|
|
9
|
+
*/
|
|
10
|
+
export function omitBy<T extends object>(
|
|
11
|
+
object: T,
|
|
12
|
+
predicate: ((value: T[keyof T], key: keyof T) => boolean) | string,
|
|
13
|
+
): Partial<T> {
|
|
14
|
+
const result = {} as Partial<T>
|
|
15
|
+
|
|
16
|
+
for (const key in object) {
|
|
17
|
+
if (Object.hasOwn(object, key)) {
|
|
18
|
+
const value = object[key]
|
|
19
|
+
|
|
20
|
+
// If predicate is a string, check if key matches
|
|
21
|
+
if (typeof predicate === 'string') {
|
|
22
|
+
// eslint-disable-next-line max-depth
|
|
23
|
+
if (key !== predicate) {
|
|
24
|
+
result[key] = value
|
|
25
|
+
}
|
|
26
|
+
} else if (typeof predicate === 'function') {
|
|
27
|
+
// If predicate is a function, use it
|
|
28
|
+
// eslint-disable-next-line max-depth
|
|
29
|
+
if (!predicate(value, key)) {
|
|
30
|
+
result[key] = value
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return result
|
|
37
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a shallow clone of `object` excluding the given own enumerable keys.
|
|
3
|
+
* Accepts a single key or an array of keys. Symbol keys are supported.
|
|
4
|
+
* If `object` is nullish, returns an empty object.
|
|
5
|
+
*/
|
|
6
|
+
export function omit<T extends object, K extends keyof T>(
|
|
7
|
+
object: T | null | undefined,
|
|
8
|
+
keys: readonly K[] | K,
|
|
9
|
+
): Omit<T, K> {
|
|
10
|
+
if (object === null || object === undefined) {
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
+
return {} as any
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const keysArray = (
|
|
16
|
+
Array.isArray(keys) ? keys : [keys]
|
|
17
|
+
) as readonly (keyof T)[]
|
|
18
|
+
const keysSet = new Set<keyof T>(keysArray as (keyof T)[])
|
|
19
|
+
|
|
20
|
+
const result: Partial<T> = {}
|
|
21
|
+
|
|
22
|
+
// Copy string/number keys
|
|
23
|
+
for (const key in object) {
|
|
24
|
+
if (Object.hasOwn(object, key) && !keysSet.has(key as keyof T)) {
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
26
|
+
;(result as any)[key] = object[key as keyof T]
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Copy symbol keys
|
|
31
|
+
for (const sym of Object.getOwnPropertySymbols(object)) {
|
|
32
|
+
if (!keysSet.has(sym as keyof T)) {
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34
|
+
;(result as any)[sym as unknown as keyof T] = (object as any)[sym]
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return result as Omit<T, K>
|
|
39
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function pick<T extends object, K extends keyof T>(
|
|
2
|
+
obj: T,
|
|
3
|
+
keys: readonly K[],
|
|
4
|
+
): Pick<T, K> {
|
|
5
|
+
const result = {} as Pick<T, K>
|
|
6
|
+
for (const key of keys) {
|
|
7
|
+
if (Object.hasOwn(obj, key)) {
|
|
8
|
+
result[key] = obj[key]
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return result
|
|
12
|
+
}
|
package/src/utils/poller.ts
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
export function generatePseudoRandomString(length: number): string {
|
|
2
|
-
return Array.from({ length }, () => Math.random().toString(36)[2]).join('')
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
/* @__PURE__ */
|
|
6
1
|
const TS_QUERY_SPECIAL_CHARS = new Set([
|
|
7
2
|
'&',
|
|
8
3
|
'|',
|
|
@@ -15,7 +10,6 @@ const TS_QUERY_SPECIAL_CHARS = new Set([
|
|
|
15
10
|
'@',
|
|
16
11
|
])
|
|
17
12
|
|
|
18
|
-
/* @__PURE__ */
|
|
19
13
|
const REGEX_SPECIAL_CHARS = new Set(['|', '(', ')'])
|
|
20
14
|
|
|
21
15
|
export function prepareTsQuery(query: string): string | null {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function shuffleArray<T>(array: T[]): T[] {
|
|
2
|
+
const shuffled = [...array]
|
|
3
|
+
for (let i = shuffled.length - 1; i > 0; i--) {
|
|
4
|
+
const j = Math.floor(Math.random() * (i + 1))
|
|
5
|
+
const temp = shuffled[i]
|
|
6
|
+
const swap = shuffled[j]
|
|
7
|
+
if (temp !== undefined && swap !== undefined) {
|
|
8
|
+
shuffled[i] = swap
|
|
9
|
+
shuffled[j] = temp
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return shuffled
|
|
13
|
+
}
|
|
@@ -1,106 +1,3 @@
|
|
|
1
|
-
export function chunk<T>(array: T[], size: number): T[][] {
|
|
2
|
-
const chunks: T[][] = []
|
|
3
|
-
for (let i = 0; i < array.length; i += size) {
|
|
4
|
-
chunks.push(array.slice(i, i + size))
|
|
5
|
-
}
|
|
6
|
-
return chunks
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function getRandomElementFromArray<T>(array: readonly T[]): T {
|
|
10
|
-
if (array.length === 0) {
|
|
11
|
-
throw new Error('Cannot get random element from empty array')
|
|
12
|
-
}
|
|
13
|
-
const element = array[Math.floor(Math.random() * array.length)]
|
|
14
|
-
if (element === undefined) {
|
|
15
|
-
throw new Error('Array element is undefined')
|
|
16
|
-
}
|
|
17
|
-
return element
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function shuffleArray<T>(array: T[]): T[] {
|
|
21
|
-
const shuffled = [...array]
|
|
22
|
-
for (let i = shuffled.length - 1; i > 0; i--) {
|
|
23
|
-
const j = Math.floor(Math.random() * (i + 1))
|
|
24
|
-
const temp = shuffled[i]
|
|
25
|
-
const swap = shuffled[j]
|
|
26
|
-
if (temp !== undefined && swap !== undefined) {
|
|
27
|
-
shuffled[i] = swap
|
|
28
|
-
shuffled[j] = temp
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return shuffled
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
type Comparator<T> = (a: T, b: T) => boolean
|
|
35
|
-
|
|
36
|
-
export function uniqWith<T>(array: T[], comparator: Comparator<T>): T[] {
|
|
37
|
-
if (!Array.isArray(array) || typeof comparator !== 'function') {
|
|
38
|
-
throw new TypeError(
|
|
39
|
-
'First argument must be an array and second argument must be a function',
|
|
40
|
-
)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return array.reduce((unique: T[], current: T) => {
|
|
44
|
-
// Check if current item matches any existing item in unique array based on comparator
|
|
45
|
-
const hasDuplicate = unique.some(item => comparator(item, current))
|
|
46
|
-
// If no duplicate found, add current item to unique array
|
|
47
|
-
return hasDuplicate ? unique : [...unique, current]
|
|
48
|
-
}, [])
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function compact<T>(
|
|
52
|
-
array: (T | null | undefined)[] | null | undefined,
|
|
53
|
-
): Exclude<T, null | undefined>[] {
|
|
54
|
-
const length = array === null || array === undefined ? 0 : array.length
|
|
55
|
-
let index = -1
|
|
56
|
-
let resIndex = 0
|
|
57
|
-
const result: Exclude<T, null | undefined>[] = []
|
|
58
|
-
|
|
59
|
-
while (index < length) {
|
|
60
|
-
index += 1
|
|
61
|
-
if (array !== null && array !== undefined) {
|
|
62
|
-
const value = array[index]
|
|
63
|
-
|
|
64
|
-
if (
|
|
65
|
-
value !== null &&
|
|
66
|
-
value !== undefined &&
|
|
67
|
-
value !== false &&
|
|
68
|
-
value !== 0 &&
|
|
69
|
-
value !== ''
|
|
70
|
-
) {
|
|
71
|
-
result[resIndex] = value as Exclude<T, null | undefined>
|
|
72
|
-
resIndex += 1
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return result
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export function sumBy<T>(
|
|
81
|
-
array: T[] | null | undefined,
|
|
82
|
-
iteratee: ((value: T) => number) | keyof T,
|
|
83
|
-
): number {
|
|
84
|
-
if (!array || !array.length) {
|
|
85
|
-
return 0
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const getValue =
|
|
89
|
-
typeof iteratee === 'function'
|
|
90
|
-
? iteratee
|
|
91
|
-
: (item: T) => item[iteratee] as unknown as number
|
|
92
|
-
|
|
93
|
-
let result: number | undefined = undefined
|
|
94
|
-
for (const item of array) {
|
|
95
|
-
const current = getValue(item)
|
|
96
|
-
if (current !== undefined) {
|
|
97
|
-
result = result === undefined ? current : result + current
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return result ?? 0
|
|
102
|
-
}
|
|
103
|
-
|
|
104
1
|
type Iteratee<T> = ((item: T) => unknown) | keyof T
|
|
105
2
|
type SortOrder = 'asc' | 'desc'
|
|
106
3
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function sumBy<T>(
|
|
2
|
+
array: T[] | null | undefined,
|
|
3
|
+
iteratee: ((value: T) => number) | keyof T,
|
|
4
|
+
): number {
|
|
5
|
+
if (!array || !array.length) {
|
|
6
|
+
return 0
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const getValue =
|
|
10
|
+
typeof iteratee === 'function'
|
|
11
|
+
? iteratee
|
|
12
|
+
: (item: T) => item[iteratee] as unknown as number
|
|
13
|
+
|
|
14
|
+
let result: number | undefined = undefined
|
|
15
|
+
for (const item of array) {
|
|
16
|
+
const current = getValue(item)
|
|
17
|
+
if (current !== undefined) {
|
|
18
|
+
result = result === undefined ? current : result + current
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return result ?? 0
|
|
23
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type Comparator<T> = (a: T, b: T) => boolean
|
|
2
|
+
|
|
3
|
+
export function uniqWith<T>(array: T[], comparator: Comparator<T>): T[] {
|
|
4
|
+
if (!Array.isArray(array) || typeof comparator !== 'function') {
|
|
5
|
+
throw new TypeError(
|
|
6
|
+
'First argument must be an array and second argument must be a function',
|
|
7
|
+
)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return array.reduce((unique: T[], current: T) => {
|
|
11
|
+
// Check if current item matches any existing item in unique array based on comparator
|
|
12
|
+
const hasDuplicate = unique.some(item => comparator(item, current))
|
|
13
|
+
// If no duplicate found, add current item to unique array
|
|
14
|
+
return hasDuplicate ? unique : [...unique, current]
|
|
15
|
+
}, [])
|
|
16
|
+
}
|
package/src/utils/validators.ts
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function weightedMean(values: number[], weights: number[]): number {
|
|
2
|
+
const sum = values.reduce(
|
|
3
|
+
(acc: number, val: number, i: number) => acc + val * (weights[i] ?? 0),
|
|
4
|
+
0,
|
|
5
|
+
)
|
|
6
|
+
const sumWeights = weights.reduce((acc: number, val: number) => acc + val, 0)
|
|
7
|
+
|
|
8
|
+
return sum / sumWeights
|
|
9
|
+
}
|
package/src/utils/numbers.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
export function generateNumbersFromStr(str: string): [number, number] {
|
|
2
|
-
let hash = 5381
|
|
3
|
-
for (let i = 0; i < str.length; i++) {
|
|
4
|
-
// eslint-disable-next-line no-bitwise
|
|
5
|
-
hash = (hash << 5) + hash + str.charCodeAt(i)
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
// Generate two numbers using the hash
|
|
9
|
-
// eslint-disable-next-line no-bitwise
|
|
10
|
-
const num1 = (hash & 0xff_ff) / 0xff_ff
|
|
11
|
-
// eslint-disable-next-line no-bitwise
|
|
12
|
-
const num2 = ((hash >> 16) & 0xff_ff) / 0xff_ff
|
|
13
|
-
|
|
14
|
-
return [num1, num2]
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function randomInt(min: number, max: number): number {
|
|
18
|
-
return Math.floor(Math.random() * (max - min + 1) + min)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function computeSellingPrice(
|
|
22
|
-
buyingPrice: number | string | null = 0,
|
|
23
|
-
rate: number | string | null = 0,
|
|
24
|
-
): number {
|
|
25
|
-
if (Number.isNaN(Number(buyingPrice)) || Number.isNaN(Number(rate))) {
|
|
26
|
-
throw new TypeError('price or rate is NaN')
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const sellingPrice = Number(buyingPrice) / (1 - Number(rate))
|
|
30
|
-
|
|
31
|
-
return Math.ceil(Math.floor(sellingPrice * 100) / 100)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function computeMarginRate(
|
|
35
|
-
buyingPrice: number | string,
|
|
36
|
-
sellingPrice: number | string,
|
|
37
|
-
): number {
|
|
38
|
-
const buyingPriceNum = Number(buyingPrice)
|
|
39
|
-
const sellingPriceNum = Number(sellingPrice)
|
|
40
|
-
|
|
41
|
-
if (Number.isNaN(sellingPriceNum) || Number.isNaN(buyingPriceNum)) {
|
|
42
|
-
throw new TypeError('sellingPrice or buyingPrice is NaN')
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return Number((1 - buyingPriceNum / sellingPriceNum).toPrecision(10))
|
|
46
|
-
}
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import { isNil } from './value-tools.ts'
|
|
2
|
-
|
|
3
|
-
// Utility type to merge T and S, allowing S to add/override properties in T
|
|
4
|
-
type Merge<T, S> = {
|
|
5
|
-
[K in keyof T | keyof S]: K extends keyof S
|
|
6
|
-
? S[K] extends object
|
|
7
|
-
? K extends keyof T
|
|
8
|
-
? T[K] extends object
|
|
9
|
-
? Merge<T[K], S[K]>
|
|
10
|
-
: S[K]
|
|
11
|
-
: S[K]
|
|
12
|
-
: S[K]
|
|
13
|
-
: K extends keyof T
|
|
14
|
-
? T[K]
|
|
15
|
-
: never
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function customMerge<T extends object, S extends object>(
|
|
19
|
-
target: T,
|
|
20
|
-
source: S,
|
|
21
|
-
): Merge<T, S> {
|
|
22
|
-
for (const key of Object.keys(source)) {
|
|
23
|
-
const sourceValue = source[key as keyof S]
|
|
24
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
|
-
const targetValue = (target as any)[key]
|
|
26
|
-
|
|
27
|
-
if (sourceValue !== undefined && sourceValue !== null) {
|
|
28
|
-
if (
|
|
29
|
-
targetValue &&
|
|
30
|
-
typeof targetValue === 'object' &&
|
|
31
|
-
!Array.isArray(targetValue) &&
|
|
32
|
-
typeof sourceValue === 'object' &&
|
|
33
|
-
!Array.isArray(sourceValue)
|
|
34
|
-
) {
|
|
35
|
-
customMerge(targetValue as object, sourceValue as object)
|
|
36
|
-
} else {
|
|
37
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38
|
-
;(target as any)[key] = sourceValue
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return target as Merge<T, S>
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function pick<T extends object, K extends keyof T>(
|
|
46
|
-
obj: T,
|
|
47
|
-
keys: readonly K[],
|
|
48
|
-
): Pick<T, K> {
|
|
49
|
-
const result = {} as Pick<T, K>
|
|
50
|
-
for (const key of keys) {
|
|
51
|
-
if (Object.hasOwn(obj, key)) {
|
|
52
|
-
result[key] = obj[key]
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return result
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function compactObject<T extends object>(obj: T): Partial<T> {
|
|
59
|
-
return Object.fromEntries(
|
|
60
|
-
Object.entries(obj).filter(([, value]) => !isNil(value)),
|
|
61
|
-
) as Partial<T>
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Creates an object composed of keys generated from the results of running each element of collection through iteratee.
|
|
66
|
-
* The corresponding value of each key is the last element responsible for generating the key.
|
|
67
|
-
*
|
|
68
|
-
* @param collection - The collection to iterate over
|
|
69
|
-
* @param iteratee - The iteratee to transform keys. Can be a function or a property name
|
|
70
|
-
* @returns Returns the composed aggregate object
|
|
71
|
-
*/
|
|
72
|
-
export function keyBy<T>(
|
|
73
|
-
collection: T[] | null | undefined,
|
|
74
|
-
iteratee: ((value: T) => string | number) | keyof T,
|
|
75
|
-
): Record<string, T> {
|
|
76
|
-
return (
|
|
77
|
-
collection?.reduce<Record<string, T>>((acc, item) => {
|
|
78
|
-
if (item === undefined || item === null) {
|
|
79
|
-
return acc
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const key =
|
|
83
|
-
typeof iteratee === 'function' ? iteratee(item) : String(item[iteratee])
|
|
84
|
-
acc[key] = item
|
|
85
|
-
return acc
|
|
86
|
-
}, {}) || {}
|
|
87
|
-
)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Creates an object composed of the own enumerable properties of object that predicate doesn't return truthy for.
|
|
92
|
-
* The predicate is invoked with two arguments: (value, key).
|
|
93
|
-
* If predicate is a string, it omits the property with that key name.
|
|
94
|
-
*
|
|
95
|
-
* @param object - The source object
|
|
96
|
-
* @param predicate - The function invoked per property or a string key to omit
|
|
97
|
-
* @returns Returns the new object
|
|
98
|
-
*/
|
|
99
|
-
export function omitBy<T extends object>(
|
|
100
|
-
object: T,
|
|
101
|
-
predicate: ((value: T[keyof T], key: keyof T) => boolean) | string,
|
|
102
|
-
): Partial<T> {
|
|
103
|
-
const result = {} as Partial<T>
|
|
104
|
-
|
|
105
|
-
for (const key in object) {
|
|
106
|
-
if (Object.hasOwn(object, key)) {
|
|
107
|
-
const value = object[key]
|
|
108
|
-
|
|
109
|
-
// If predicate is a string, check if key matches
|
|
110
|
-
if (typeof predicate === 'string') {
|
|
111
|
-
// eslint-disable-next-line max-depth
|
|
112
|
-
if (key !== predicate) {
|
|
113
|
-
result[key] = value
|
|
114
|
-
}
|
|
115
|
-
} else if (typeof predicate === 'function') {
|
|
116
|
-
// If predicate is a function, use it
|
|
117
|
-
// eslint-disable-next-line max-depth
|
|
118
|
-
if (!predicate(value, key)) {
|
|
119
|
-
result[key] = value
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return result
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Creates a shallow clone of `object` excluding the given own enumerable keys.
|
|
130
|
-
* Accepts a single key or an array of keys. Symbol keys are supported.
|
|
131
|
-
* If `object` is nullish, returns an empty object.
|
|
132
|
-
*/
|
|
133
|
-
export function omit<T extends object, K extends keyof T>(
|
|
134
|
-
object: T | null | undefined,
|
|
135
|
-
keys: readonly K[] | K,
|
|
136
|
-
): Omit<T, K> {
|
|
137
|
-
if (object === null || object === undefined) {
|
|
138
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
139
|
-
return {} as any
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const keysArray = (
|
|
143
|
-
Array.isArray(keys) ? keys : [keys]
|
|
144
|
-
) as readonly (keyof T)[]
|
|
145
|
-
const keysSet = new Set<keyof T>(keysArray as (keyof T)[])
|
|
146
|
-
|
|
147
|
-
const result: Partial<T> = {}
|
|
148
|
-
|
|
149
|
-
// Copy string/number keys
|
|
150
|
-
for (const key in object) {
|
|
151
|
-
if (Object.hasOwn(object, key) && !keysSet.has(key as keyof T)) {
|
|
152
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
153
|
-
;(result as any)[key] = object[key as keyof T]
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Copy symbol keys
|
|
158
|
-
for (const sym of Object.getOwnPropertySymbols(object)) {
|
|
159
|
-
if (!keysSet.has(sym as keyof T)) {
|
|
160
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
161
|
-
;(result as any)[sym as unknown as keyof T] = (object as any)[sym]
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return result as Omit<T, K>
|
|
166
|
-
}
|
|
File without changes
|
|
File without changes
|