@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.
Files changed (39) hide show
  1. package/package.json +1 -2
  2. package/src/cancellation-policies.ts +1 -1
  3. package/src/currencies/index.ts +1 -1
  4. package/src/utils/{math.ts → amount-from-percentage.ts} +0 -10
  5. package/src/utils/case-transformers.ts +0 -1
  6. package/src/utils/chunk.ts +7 -0
  7. package/src/utils/colors.ts +1 -1
  8. package/src/utils/compact-object.ts +7 -0
  9. package/src/utils/compact.ts +28 -0
  10. package/src/utils/compute-margin-rate.ts +13 -0
  11. package/src/utils/compute-selling-price.ts +12 -0
  12. package/src/utils/defaults-deep.ts +85 -0
  13. package/src/utils/delay.ts +5 -0
  14. package/src/utils/generate-numbers-from-str.ts +15 -0
  15. package/src/utils/generate-pseudo-random-string.ts +3 -0
  16. package/src/utils/get-guest-count.ts +1 -2
  17. package/src/utils/get-random-element-from-array.ts +10 -0
  18. package/src/utils/get-random-hex-color.ts +5 -0
  19. package/src/utils/{random.ts → get-random-int.ts} +0 -6
  20. package/src/utils/index.ts +31 -12
  21. package/src/utils/key-by.ts +25 -0
  22. package/src/utils/merge.ts +140 -0
  23. package/src/utils/omit-by.ts +37 -0
  24. package/src/utils/omit.ts +39 -0
  25. package/src/utils/pick.ts +12 -0
  26. package/src/utils/poller.ts +0 -1
  27. package/src/utils/{strings.ts → prepare-ts-query.ts} +0 -6
  28. package/src/utils/{promise-tools.ts → promise-timeout.ts} +0 -6
  29. package/src/utils/random-int.ts +3 -0
  30. package/src/utils/shuffle-array.ts +13 -0
  31. package/src/utils/{array-tools.ts → sort-by.ts} +0 -103
  32. package/src/utils/sum-by.ts +23 -0
  33. package/src/utils/uniq-with.ts +16 -0
  34. package/src/utils/validators.ts +0 -1
  35. package/src/utils/weighted-mean.ts +9 -0
  36. package/src/utils/numbers.ts +0 -46
  37. package/src/utils/object-tools.ts +0 -166
  38. /package/src/utils/{value-tools.ts → is-nil.ts} +0 -0
  39. /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.1",
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
  },
@@ -1,4 +1,4 @@
1
- import { compact } from './utils/array-tools.ts'
1
+ import { compact } from './utils/compact.ts'
2
2
  import { type Dayjs, dayjs } from './utils/dayjs.ts'
3
3
  import { isEmpty } from './utils/is-empty.ts'
4
4
 
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable max-lines */
2
2
  import { Currency } from '../constants/currencies.ts'
3
- import { pick } from '../utils/object-tools.ts'
3
+ import { pick } from '../utils/pick.ts'
4
4
 
5
5
  import type { ICurrency } from '../types/currency.ts'
6
6
 
@@ -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,
@@ -23,7 +23,6 @@ export enum CaseTransformer {
23
23
  Snake = 'snakeCase',
24
24
  }
25
25
 
26
- /* @__PURE__ */
27
26
  const CASE_TRANSORMERS_MAPPING = {
28
27
  [CaseTransformer.Camel]: camelCase,
29
28
  [CaseTransformer.Capital]: capitalCase,
@@ -0,0 +1,7 @@
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
+ }
@@ -1,4 +1,4 @@
1
- import { generateNumbersFromStr } from './numbers.ts'
1
+ import { generateNumbersFromStr } from './generate-numbers-from-str.ts'
2
2
 
3
3
  export function generateRandomColorFromString(
4
4
  str: string,
@@ -0,0 +1,7 @@
1
+ import { isNil } from './is-nil.ts'
2
+
3
+ export function compactObject<T extends object>(obj: T): Partial<T> {
4
+ return Object.fromEntries(
5
+ Object.entries(obj).filter(([, value]) => !isNil(value)),
6
+ ) as Partial<T>
7
+ }
@@ -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,5 @@
1
+ export function delay(duration: number): Promise<void> {
2
+ return new Promise(resolve => {
3
+ setTimeout(resolve, duration)
4
+ })
5
+ }
@@ -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,3 @@
1
+ export function generatePseudoRandomString(length: number): string {
2
+ return Array.from({ length }, () => Math.random().toString(36)[2]).join('')
3
+ }
@@ -1,6 +1,5 @@
1
- import { parseChildren } from './children-tools.ts'
1
+ import { parseChildren } from './parse-children.ts'
2
2
 
3
- /* @__PURE__ */
4
3
  export const CHILDREN_FREE_BREAKFAST_AGE_LIMIT = 4
5
4
 
6
5
  export function getGuestCount(
@@ -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
+ }
@@ -0,0 +1,5 @@
1
+ export function getRandomHexColor(): string {
2
+ const hex = Math.floor(Math.random() * 0xffffff).toString(16)
3
+
4
+ return hex.padStart(6, '0').toUpperCase()
5
+ }
@@ -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
- }
@@ -1,31 +1,50 @@
1
1
  export * from './add-classes.ts'
2
- export * from './array-tools.ts'
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 './math.ts'
16
- export * from './numbers.ts'
17
- export * from './object-tools.ts'
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 './promise-tools.ts'
20
- export * from './random.ts'
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 './strings.ts'
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 './value-tools.ts'
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
+ }
@@ -21,7 +21,6 @@ export type TPollerEvents<V extends IPollerResponse = IPollerResponse> = {
21
21
  [k in TPollerEventName]: TPollerEventCallback<V>
22
22
  }
23
23
 
24
- /* @__PURE__ */
25
24
  const INTERVAL = 1500
26
25
 
27
26
  export interface IPollerOptions<U> {
@@ -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 {
@@ -1,9 +1,3 @@
1
- export function delay(duration: number): Promise<void> {
2
- return new Promise(resolve => {
3
- setTimeout(resolve, duration)
4
- })
5
- }
6
-
7
1
  export function promiseTimeout<T>(
8
2
  delayAmount: number,
9
3
  valueToReturn: T,
@@ -0,0 +1,3 @@
1
+ export function randomInt(min: number, max: number): number {
2
+ return Math.floor(Math.random() * (max - min + 1) + min)
3
+ }
@@ -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
+ }
@@ -1,4 +1,3 @@
1
- /* @__PURE__ */
2
1
  export const validators = {
3
2
  alpha: (value: string): boolean => /[a-zA-Z]/u.test(value),
4
3
  email: (value: string): boolean => /.+@.+\..+/u.test(value),
@@ -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
+ }
@@ -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