@companix/utils-js 0.0.1 → 0.0.12
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 +4 -1
- package/rollup.config.ts +0 -40
- package/src/array.ts +0 -55
- package/src/bytes.ts +0 -13
- package/src/candle.ts +0 -20
- package/src/colors.ts +0 -32
- package/src/emiters.ts +0 -83
- package/src/http-api.ts +0 -43
- package/src/http-headers.ts +0 -34
- package/src/http-upload.ts +0 -23
- package/src/index.ts +0 -17
- package/src/money.ts +0 -31
- package/src/nouns.ts +0 -16
- package/src/number.ts +0 -81
- package/src/object.ts +0 -32
- package/src/queue.ts +0 -38
- package/src/random.ts +0 -49
- package/src/regex.ts +0 -6
- package/src/time.ts +0 -70
- package/src/utils.ts +0 -15
- package/tsconfig.json +0 -20
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@companix/utils-js",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"main": "dist/bundle.cjs.js",
|
|
5
5
|
"module": "dist/bundle.esm.js",
|
|
6
6
|
"types": "./src/index.ts",
|
|
7
7
|
"author": "Pavel Victorov",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
8
11
|
"scripts": {
|
|
9
12
|
"build": "rm -rf dist && rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript --bundleConfigAsCjs"
|
|
10
13
|
},
|
package/rollup.config.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import resolve from '@rollup/plugin-node-resolve'
|
|
2
|
-
import typescript from '@rollup/plugin-typescript'
|
|
3
|
-
import terser from '@rollup/plugin-terser'
|
|
4
|
-
import strip from '@rollup/plugin-strip'
|
|
5
|
-
import autoExternal from 'rollup-plugin-auto-external'
|
|
6
|
-
|
|
7
|
-
export default [
|
|
8
|
-
// EcmaScript Module (esm) build
|
|
9
|
-
{
|
|
10
|
-
input: './src/index.ts',
|
|
11
|
-
output: {
|
|
12
|
-
file: 'dist/bundle.esm.js',
|
|
13
|
-
format: 'esm'
|
|
14
|
-
},
|
|
15
|
-
external: ['react', 'react-dom'],
|
|
16
|
-
plugins: [
|
|
17
|
-
typescript({ tsconfig: './tsconfig.json', noEmitOnError: true }),
|
|
18
|
-
autoExternal(),
|
|
19
|
-
resolve(),
|
|
20
|
-
strip(),
|
|
21
|
-
terser()
|
|
22
|
-
]
|
|
23
|
-
},
|
|
24
|
-
// CommonJS (cjs) build
|
|
25
|
-
{
|
|
26
|
-
input: './src/index.ts',
|
|
27
|
-
output: {
|
|
28
|
-
file: 'dist/bundle.cjs.js',
|
|
29
|
-
format: 'cjs'
|
|
30
|
-
},
|
|
31
|
-
external: ['react', 'react-dom'],
|
|
32
|
-
plugins: [
|
|
33
|
-
typescript({ tsconfig: './tsconfig.json', noEmitOnError: true }),
|
|
34
|
-
autoExternal(),
|
|
35
|
-
resolve(),
|
|
36
|
-
strip(),
|
|
37
|
-
terser()
|
|
38
|
-
]
|
|
39
|
-
}
|
|
40
|
-
]
|
package/src/array.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Генерирует массив с диапазоном чисел. Взято с VKUI
|
|
3
|
-
*/
|
|
4
|
-
export const range = (from: number, to: number, step = 1) => {
|
|
5
|
-
const direction = from < to ? 1 : -1
|
|
6
|
-
const distance = Math.abs(from - to) + 1
|
|
7
|
-
const arrayLength = Math.ceil(distance / step)
|
|
8
|
-
|
|
9
|
-
const arr = Array<number>(arrayLength)
|
|
10
|
-
for (let index = 0; index < arr.length; index++) {
|
|
11
|
-
arr[index] = from + index * step * direction
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return arr
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const splitByChunks = <T>(items: T[], chunkSize: number): T[][] => {
|
|
18
|
-
const result: T[][] = []
|
|
19
|
-
|
|
20
|
-
for (let i = 0; i < items.length; i += chunkSize) {
|
|
21
|
-
result.push(items.slice(i, i + chunkSize))
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return result
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export const separateArray = <T>(array: T[], parts: number): T[][] => {
|
|
28
|
-
if (parts <= 0) throw new Error('Number of parts must be greater than 0')
|
|
29
|
-
|
|
30
|
-
const result: T[][] = []
|
|
31
|
-
const partSize = Math.floor(array.length / parts)
|
|
32
|
-
let remainder = array.length % parts
|
|
33
|
-
let start = 0
|
|
34
|
-
|
|
35
|
-
for (let i = 0; i < parts; i++) {
|
|
36
|
-
// Распределяем остаток по первым частям
|
|
37
|
-
const extra = remainder > 0 ? 1 : 0
|
|
38
|
-
const end = start + partSize + extra
|
|
39
|
-
const data = array.slice(start, end)
|
|
40
|
-
|
|
41
|
-
if (data.length > 0) {
|
|
42
|
-
result.push(data)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
start = end
|
|
46
|
-
remainder--
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return result
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export const roundSeparateArray = <T>(array: T[], size: number): T[][] => {
|
|
53
|
-
const n = Math.round(array.length / size)
|
|
54
|
-
return n > 1 ? separateArray(array, n) : [array]
|
|
55
|
-
}
|
package/src/bytes.ts
DELETED
package/src/candle.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export type Interval = '1s' | '1m' | '3m' | '5m'
|
|
2
|
-
|
|
3
|
-
export const intervals = {
|
|
4
|
-
'1s': 1000,
|
|
5
|
-
'1m': 1000 * 60,
|
|
6
|
-
'3m': 1000 * 60 * 3,
|
|
7
|
-
'5m': 1000 * 60 * 5
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const getLastClosedCandleTime = (timestamp: number, interval: Interval) => {
|
|
11
|
-
return getCurrentCandleTime(timestamp, interval) - intervals[interval]
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const getCurrentCandleTime = (timestamp: number, interval: Interval) => {
|
|
15
|
-
return Math.floor(timestamp / intervals[interval]) * intervals[interval]
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const getNextCandleTime = (timestamp: number, interval: Interval) => {
|
|
19
|
-
return getCurrentCandleTime(timestamp, interval) + intervals[interval]
|
|
20
|
-
}
|
package/src/colors.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
export const applyAlphaToHex = (hex: string, opacity: number) => {
|
|
2
|
-
if (hex.startsWith('#')) {
|
|
3
|
-
hex = hex.slice(1)
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
const r = parseInt(hex.slice(0, 2), 16)
|
|
7
|
-
const g = parseInt(hex.slice(2, 4), 16)
|
|
8
|
-
const b = parseInt(hex.slice(4, 6), 16)
|
|
9
|
-
const alpha = Math.max(0, Math.min(100, opacity)) / 100
|
|
10
|
-
|
|
11
|
-
return `rgba(${r}, ${g}, ${b}, ${alpha})`
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const rgbaToHex = (rgba: string) => {
|
|
15
|
-
// Извлекаем значения с помощью регулярного выражения
|
|
16
|
-
const match = rgba.match(/rgba?\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*([\d.]+)\s*\)/)
|
|
17
|
-
|
|
18
|
-
if (!match) {
|
|
19
|
-
throw new Error('Некорректный формат RGBA')
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const [, r, g, b, a] = match
|
|
23
|
-
|
|
24
|
-
const toHex = (n: string) => {
|
|
25
|
-
const hex = parseInt(n).toString(16)
|
|
26
|
-
return hex.padStart(2, '0')
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const alpha = Math.round(parseFloat(a) * 255)
|
|
30
|
-
|
|
31
|
-
return `#${toHex(r)}${toHex(g)}${toHex(b)}${toHex(alpha.toString())}`
|
|
32
|
-
}
|
package/src/emiters.ts
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
export class EventDispatcher<T> {
|
|
2
|
-
private store: Record<string, (data: T) => void> = {}
|
|
3
|
-
|
|
4
|
-
emit(event: string, data: T) {
|
|
5
|
-
if (this.store[event]) {
|
|
6
|
-
this.store[event](data)
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
on(event: string, callback: (data: T) => void) {
|
|
11
|
-
this.store[event] = callback
|
|
12
|
-
|
|
13
|
-
return () => {
|
|
14
|
-
this.rm(event)
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
rm(event: string) {
|
|
19
|
-
delete this.store[event]
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export class EventEmmiter<T> {
|
|
24
|
-
private store: Record<string, ((data: T) => void)[]> = {}
|
|
25
|
-
|
|
26
|
-
emit(event: string, data: T) {
|
|
27
|
-
if (this.store[event]) {
|
|
28
|
-
this.store[event].forEach((callback) => callback(data))
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
subscribe(event: string, callback: (data: T) => void) {
|
|
33
|
-
if (!this.store[event]) {
|
|
34
|
-
this.store[event] = []
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
this.store[event].push(callback)
|
|
38
|
-
|
|
39
|
-
return () => {
|
|
40
|
-
this.unsubscribe(event, callback)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
unsubscribe(event: string, callback: (data: T) => void) {
|
|
45
|
-
if (this.store[event]) {
|
|
46
|
-
const index = this.store[event].findIndex((u) => u === callback)
|
|
47
|
-
|
|
48
|
-
if (index !== -1) {
|
|
49
|
-
this.store[event].splice(index, 1)
|
|
50
|
-
|
|
51
|
-
if (this.store[event].length === 0) {
|
|
52
|
-
delete this.store[event]
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export class EventBroadcaster<T> {
|
|
60
|
-
public subscribers: ((data: T) => void)[] = []
|
|
61
|
-
|
|
62
|
-
emit(data: T) {
|
|
63
|
-
this.subscribers.forEach((callback) => {
|
|
64
|
-
callback(data)
|
|
65
|
-
})
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
subscribe(callback: (data: T) => void) {
|
|
69
|
-
this.subscribers.push(callback)
|
|
70
|
-
|
|
71
|
-
return () => {
|
|
72
|
-
this.unsubscribe(callback)
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
unsubscribe(callback: (data: T) => void) {
|
|
77
|
-
const index = this.subscribers.findIndex((u) => u === callback)
|
|
78
|
-
|
|
79
|
-
if (index !== -1) {
|
|
80
|
-
this.subscribers.splice(index, 1)
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
package/src/http-api.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import axios, { AxiosInstance, AxiosRequestConfig, CreateAxiosDefaults } from 'axios'
|
|
2
|
-
|
|
3
|
-
export type IOpattern<T extends IOpattern<T>> = {
|
|
4
|
-
[key in keyof T]: {
|
|
5
|
-
params: T[key]['params']
|
|
6
|
-
answer: T[key]['answer']
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
enum HttpVerb {
|
|
11
|
-
Get = 'GET',
|
|
12
|
-
Post = 'POST'
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface RequestInterface {
|
|
16
|
-
url: string
|
|
17
|
-
body?: any
|
|
18
|
-
config?: AxiosRequestConfig
|
|
19
|
-
method: HttpVerb
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export class HttpAPI<T extends IOpattern<T>> {
|
|
23
|
-
public http: AxiosInstance
|
|
24
|
-
|
|
25
|
-
constructor(config: CreateAxiosDefaults) {
|
|
26
|
-
this.http = axios.create(config)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
private async request<T>(props: RequestInterface): Promise<T> {
|
|
30
|
-
const { url, body = {}, method, config = {} } = props
|
|
31
|
-
const dataAtt = method === HttpVerb.Get ? 'params' : 'data'
|
|
32
|
-
|
|
33
|
-
return this.http({ url, method, [dataAtt]: body, ...config }).then(({ data }) => data)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
post<K extends keyof T>(url: K, body: T[K]['params'], config?: AxiosRequestConfig) {
|
|
37
|
-
return this.request<T[K]['answer']>({ method: HttpVerb.Post, url: url as string, config, body })
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
get<K extends keyof T>(url: K, body: T[K]['params'], config?: AxiosRequestConfig) {
|
|
41
|
-
return this.request<T[K]['answer']>({ method: HttpVerb.Get, url: url as string, config, body })
|
|
42
|
-
}
|
|
43
|
-
}
|
package/src/http-headers.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
interface Headers {
|
|
2
|
-
Authorization?: string
|
|
3
|
-
'Content-Type': string
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
interface Options {
|
|
7
|
-
multipart?: boolean
|
|
8
|
-
token?: string
|
|
9
|
-
tokenStore?: string
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export const getHeaders = ({ token, tokenStore, multipart }: Options = {}): Headers => {
|
|
13
|
-
const Authorization = getAuthToken(token, tokenStore)
|
|
14
|
-
|
|
15
|
-
const headers: Headers = {
|
|
16
|
-
'Content-Type': multipart ? 'multipart/form-data; charset=utf-8' : 'application/json'
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (Authorization) {
|
|
20
|
-
headers.Authorization = Authorization
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return headers
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export const getAuthToken = (token?: string, tokenStore: string = 'token') => {
|
|
27
|
-
const value = token ?? localStorage.getItem(tokenStore)
|
|
28
|
-
|
|
29
|
-
if (value) {
|
|
30
|
-
return `Bearer ${value}`
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return ''
|
|
34
|
-
}
|
package/src/http-upload.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export const transport = (file: Blob) => {
|
|
2
|
-
const data = new FormData()
|
|
3
|
-
|
|
4
|
-
data.append('file', file)
|
|
5
|
-
data.append('type', 'file')
|
|
6
|
-
|
|
7
|
-
return data
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const generatePreview = (file: File) => {
|
|
11
|
-
const url = URL.createObjectURL(file)
|
|
12
|
-
|
|
13
|
-
return {
|
|
14
|
-
url,
|
|
15
|
-
destroy: () => {
|
|
16
|
-
URL.revokeObjectURL(url)
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export const getFiles = (files: FileList) => {
|
|
22
|
-
return Array.from(files)
|
|
23
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export * from './array'
|
|
2
|
-
export * from './colors'
|
|
3
|
-
export * from './emiters'
|
|
4
|
-
export * from './number'
|
|
5
|
-
export * from './object'
|
|
6
|
-
export * from './queue'
|
|
7
|
-
export * from './random'
|
|
8
|
-
export * from './utils'
|
|
9
|
-
export * from './http-api'
|
|
10
|
-
export * from './http-headers'
|
|
11
|
-
export * from './http-upload'
|
|
12
|
-
export * from './money'
|
|
13
|
-
export * from './nouns'
|
|
14
|
-
export * from './regex'
|
|
15
|
-
export * from './bytes'
|
|
16
|
-
export * from './time'
|
|
17
|
-
export * from './candle'
|
package/src/money.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
export const bigMoneyAmount = (amount: number) => {
|
|
2
|
-
const thousand = amount / 1000
|
|
3
|
-
|
|
4
|
-
if (thousand >= 1000) {
|
|
5
|
-
const million = thousand / 1000
|
|
6
|
-
|
|
7
|
-
if (million >= 1000) {
|
|
8
|
-
return `${million / 1000} МЛРД. ₽`
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
return `${million} МЛН. ₽`
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return `${thousand} ТЫС. ₽`
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
interface CurrencyOptions {
|
|
18
|
-
noPennies?: boolean
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export const rubles = (num: number, options?: CurrencyOptions) => {
|
|
22
|
-
return num.toLocaleString('ru-RU', {
|
|
23
|
-
style: 'currency',
|
|
24
|
-
currency: 'RUB',
|
|
25
|
-
...(options?.noPennies ? { minimumFractionDigits: 0, maximumFractionDigits: 0 } : {})
|
|
26
|
-
})
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export const dollars = (value: number, options?: CurrencyOptions) => {
|
|
30
|
-
return value.toLocaleString('us-US', { style: 'currency', currency: 'USD' })
|
|
31
|
-
}
|
package/src/nouns.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
// https://gist.github.com/tomfun/830fa6d8030d16007bbab50a5b21ef97
|
|
2
|
-
export const getNoun = (number: number, one: string, two: string, five: string) => {
|
|
3
|
-
let n = Math.abs(number)
|
|
4
|
-
n %= 100
|
|
5
|
-
if (n >= 5 && n <= 20) {
|
|
6
|
-
return five
|
|
7
|
-
}
|
|
8
|
-
n %= 10
|
|
9
|
-
if (n === 1) {
|
|
10
|
-
return one
|
|
11
|
-
}
|
|
12
|
-
if (n >= 2 && n <= 4) {
|
|
13
|
-
return two
|
|
14
|
-
}
|
|
15
|
-
return five
|
|
16
|
-
}
|
package/src/number.ts
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
export const getFloatDigits = (value: string) => {
|
|
2
|
-
if (value.includes('e')) {
|
|
3
|
-
const [int, exp] = value.split('e')
|
|
4
|
-
return Math.max((int.split('.')[1]?.length || 0) - +exp, 0)
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
return value.split('.')[1]?.length || 0
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* не используйте normalize для округления, когда требуемая точность меньше точности входного значения
|
|
12
|
-
*
|
|
13
|
-
* ❌ normalize(0.000020025, 8) -> 0.00002002
|
|
14
|
-
* ❌ normalize(0.000022025, 8) -> 0.00002203 (!)
|
|
15
|
-
*
|
|
16
|
-
* использование normalize безопасно в случаях нормализации значения: normalize(a + b, precision), если a и b с точностью precision
|
|
17
|
-
*
|
|
18
|
-
* ✅ normalize(0.000020025, 9) -> 0.000020025
|
|
19
|
-
* ✅ normalize(0.000022025, 9) -> 0.000022025
|
|
20
|
-
*
|
|
21
|
-
* 0.1 + 0.2 -> 0.30000000000000004 (10^1) -> 3.0000000000000004 -> (round) 3
|
|
22
|
-
* 0.0001 + 0.0003 -> 0.00039999999999999996 -> (10^4) -> 3.9999999999999996 -> (round) 4
|
|
23
|
-
*
|
|
24
|
-
* работает корректно до precision <= 22. После: 123 / (10 ** 23) -> 1.2300000000000002e-21
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
export const normalize = (value: number, precision: number) => {
|
|
28
|
-
const factor = Math.pow(10, precision)
|
|
29
|
-
return Math.round(value * factor) / factor // 0.000020025 * 10^8 -> 2002.4999999999998
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export const cutNumber = (value: number, precision: number) => {
|
|
33
|
-
const factor = Math.pow(10, precision)
|
|
34
|
-
return Math.floor(value * factor) / factor
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export const roundUp2 = (value: number, precision: number) => {
|
|
38
|
-
const result = value.toFixed(precision)
|
|
39
|
-
|
|
40
|
-
if (value > +result) {
|
|
41
|
-
return normalize(+result + +getPrecisionStep(precision), precision)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return +result
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export const truncateNumber = (value: number, precision: number) => {
|
|
48
|
-
const result = value.toFixed(precision)
|
|
49
|
-
|
|
50
|
-
if (+result > value) {
|
|
51
|
-
return (+result - Math.sign(value) * Math.pow(0.1, precision)).toFixed(precision)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return result
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export const getPrecisionStep = (precision: number, digit: number = 1) => {
|
|
58
|
-
if (precision > 0) {
|
|
59
|
-
return [0, '.', ...new Array(precision - 1).fill(0), digit].join('')
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return `${digit}`
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export const isValidPrecision = (value: number, precision: number) => {
|
|
66
|
-
const num = value.toString()
|
|
67
|
-
|
|
68
|
-
if (num.includes('.')) {
|
|
69
|
-
if (precision === 0) {
|
|
70
|
-
return false
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return num.split('.')[1].length <= precision
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return true
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export const getNum = (value: string) => {
|
|
80
|
-
return isNaN(Number(value)) ? null : +value
|
|
81
|
-
}
|
package/src/object.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
export const keys = (object: object) => {
|
|
2
|
-
return Object.keys(object)
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export const keysLength = (object: object) => {
|
|
6
|
-
return keys(object).length
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const isEmpty = (obj: object) => {
|
|
10
|
-
for (const _ in obj) {
|
|
11
|
-
return false
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return true
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const omit = <T extends object>(object: T, key: keyof T) => {
|
|
18
|
-
delete object[key]
|
|
19
|
-
return object
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export const partial = <T extends object>(object: T): T => {
|
|
23
|
-
const response = {} as T
|
|
24
|
-
|
|
25
|
-
for (const key in object) {
|
|
26
|
-
if (object[key]) {
|
|
27
|
-
response[key] = object[key]
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return response
|
|
32
|
-
}
|
package/src/queue.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
interface Subject {
|
|
2
|
-
resolve: (value: any) => void
|
|
3
|
-
reject: (reason?: any) => void
|
|
4
|
-
target: () => Promise<any>
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export class QueueManager {
|
|
8
|
-
private active: boolean = false
|
|
9
|
-
private queue: Subject[] = []
|
|
10
|
-
|
|
11
|
-
add<T>(target: () => Promise<T>): Promise<T> {
|
|
12
|
-
return new Promise<T>((resolve, reject) => {
|
|
13
|
-
this.queue.push({ resolve, reject, target })
|
|
14
|
-
|
|
15
|
-
if (!this.active) {
|
|
16
|
-
this.next()
|
|
17
|
-
}
|
|
18
|
-
})
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
private async next() {
|
|
22
|
-
const subject = this.queue[0]
|
|
23
|
-
|
|
24
|
-
if (subject) {
|
|
25
|
-
this.active = true
|
|
26
|
-
|
|
27
|
-
await subject
|
|
28
|
-
.target()
|
|
29
|
-
.then((data) => subject.resolve(data))
|
|
30
|
-
.catch((e) => subject.reject(e))
|
|
31
|
-
.finally(() => this.queue.shift())
|
|
32
|
-
|
|
33
|
-
await this.next()
|
|
34
|
-
} else {
|
|
35
|
-
this.active = false
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
package/src/random.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
export const generateCode = (size: number) => {
|
|
2
|
-
const characters = 'A0B1C2D3E4F5G6H7W89K0L1M2N34P5Q6R7S8T9U0V3XYZ' // 33 uniq symbols
|
|
3
|
-
const result: string[] = []
|
|
4
|
-
|
|
5
|
-
for (let i = 0; i < size; i++) {
|
|
6
|
-
const randomIndex = Math.floor(Math.random() * characters.length)
|
|
7
|
-
result.push(characters[randomIndex])
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
return result.join('')
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const getRandomInt = (min: number, max: number) => {
|
|
14
|
-
return Math.floor(Math.random() * (max - min + 1)) + min
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const getRandomIntString = (n: number) => {
|
|
18
|
-
return new Array(n)
|
|
19
|
-
.fill(0)
|
|
20
|
-
.map(() => getRandomInt(0, 9))
|
|
21
|
-
.join('')
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export const hash = () => {
|
|
25
|
-
const d = typeof performance === 'undefined' ? Date.now() : performance.now() * 1000
|
|
26
|
-
|
|
27
|
-
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
28
|
-
const r = (Math.random() * 16 + d) % 16 | 0
|
|
29
|
-
|
|
30
|
-
return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16)
|
|
31
|
-
})
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
interface ArrItemOptions<T> {
|
|
35
|
-
exceptions: T[]
|
|
36
|
-
isEqual: (a: T, b: T) => boolean
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export const getRandomItemFromArray = <T>(values: T[], exception?: ArrItemOptions<T>) => {
|
|
40
|
-
const items = (() => {
|
|
41
|
-
if (exception && exception.exceptions.length < values.length) {
|
|
42
|
-
return values.filter((a) => !exception.exceptions.some((b) => exception.isEqual(a, b)))
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return values
|
|
46
|
-
})()
|
|
47
|
-
|
|
48
|
-
return items[(items.length * Math.random()) << 0] as T
|
|
49
|
-
}
|
package/src/regex.ts
DELETED
package/src/time.ts
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
export const formatTime = (value: number) => {
|
|
2
|
-
return value.toString().padStart(2, '0')
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export const getTimes = (ms: number) => {
|
|
6
|
-
if (ms < 0) {
|
|
7
|
-
ms = 0
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const totalSeconds = Math.floor(ms / 1000)
|
|
11
|
-
|
|
12
|
-
const hours = Math.floor(totalSeconds / 3600)
|
|
13
|
-
const minutes = Math.floor((totalSeconds % 3600) / 60)
|
|
14
|
-
const seconds = totalSeconds % 60
|
|
15
|
-
|
|
16
|
-
return { hours, minutes, seconds }
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export const getTime = (timestamp: number, utc: boolean = true) => {
|
|
20
|
-
const date = new Date(timestamp)
|
|
21
|
-
const prefix = utc ? 'UTC' : ''
|
|
22
|
-
|
|
23
|
-
const times = [
|
|
24
|
-
formatTime(date[`get${prefix}Hours`]()),
|
|
25
|
-
formatTime(date[`get${prefix}Minutes`]()),
|
|
26
|
-
formatTime(date[`get${prefix}Seconds`]())
|
|
27
|
-
]
|
|
28
|
-
|
|
29
|
-
return times.join(':')
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export const getDate = (timestamp: number, utc: boolean = true) => {
|
|
33
|
-
const date = new Date(timestamp)
|
|
34
|
-
const prefix = utc ? 'UTC' : ''
|
|
35
|
-
|
|
36
|
-
const times = [
|
|
37
|
-
formatTime(date[`get${prefix}Date`]()),
|
|
38
|
-
formatTime(date[`get${prefix}Month`]() + 1),
|
|
39
|
-
formatTime(date[`get${prefix}FullYear`]())
|
|
40
|
-
]
|
|
41
|
-
|
|
42
|
-
return times.join(':')
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// export const timeDuration = (ms: number) => {
|
|
46
|
-
// const hours = Math.floor(ms / (1000 * 60 * 60))
|
|
47
|
-
// const minutes = Math.floor((ms % (1000 * 60 * 60)) / (1000 * 60))
|
|
48
|
-
// const seconds = Math.floor((ms % (1000 * 60)) / 1000)
|
|
49
|
-
// const milliseconds = ms % 1000
|
|
50
|
-
|
|
51
|
-
// const parts: string[] = []
|
|
52
|
-
|
|
53
|
-
// if (hours > 0) {
|
|
54
|
-
// parts.push(`${hours} h.`)
|
|
55
|
-
// }
|
|
56
|
-
|
|
57
|
-
// if (minutes > 0) {
|
|
58
|
-
// parts.push(`${minutes} m.`)
|
|
59
|
-
// }
|
|
60
|
-
|
|
61
|
-
// if (parts.length !== 2 && seconds > 0) {
|
|
62
|
-
// parts.push(`${seconds} s.`)
|
|
63
|
-
// }
|
|
64
|
-
|
|
65
|
-
// if (parts.length === 0) {
|
|
66
|
-
// parts.push(`${milliseconds} ms`)
|
|
67
|
-
// }
|
|
68
|
-
|
|
69
|
-
// return parts.join(' ')
|
|
70
|
-
// }
|
package/src/utils.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export const sleep = (time: number) => {
|
|
2
|
-
return new Promise<void>((resolve) => setTimeout(resolve, time))
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export const stringify = (...ars: any[]) => {
|
|
6
|
-
return ars.map((value) => JSON.stringify(value)).join(' ')
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const contain = <T>(items: T[][]): T[] => {
|
|
10
|
-
return items.reduce((prev, curr) => [...prev, ...curr], [])
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const nonNullable = <T>(value: T): value is NonNullable<T> => {
|
|
14
|
-
return value !== null && value !== undefined
|
|
15
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"strictPropertyInitialization": false,
|
|
5
|
-
"module": "esnext",
|
|
6
|
-
"declaration": true,
|
|
7
|
-
"removeComments": true,
|
|
8
|
-
"allowSyntheticDefaultImports": true,
|
|
9
|
-
"experimentalDecorators": true,
|
|
10
|
-
"skipLibCheck": true,
|
|
11
|
-
"strict": true,
|
|
12
|
-
"forceConsistentCasingInFileNames": false,
|
|
13
|
-
"noFallthroughCasesInSwitch": false,
|
|
14
|
-
"moduleResolution": "node",
|
|
15
|
-
"outDir": "./dist",
|
|
16
|
-
"baseUrl": "./"
|
|
17
|
-
},
|
|
18
|
-
"include": ["./src"],
|
|
19
|
-
"exclude": ["node_modules", "dist"]
|
|
20
|
-
}
|