devix 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/.babelrc.json +14 -0
- package/.editorconfig +14 -0
- package/.eslintignore +2 -0
- package/.eslintrc.json +21 -0
- package/.prettierignore +9 -0
- package/.prettierrc.json +8 -0
- package/LICENSE +21 -0
- package/README.md +19 -0
- package/jest.config.ts +25 -0
- package/package.json +38 -10
- package/rollup.config.js +59 -0
- package/src/cache.ts +48 -0
- package/src/clone.ts +64 -0
- package/src/format.ts +65 -0
- package/src/index.ts +7 -0
- package/src/others.ts +68 -0
- package/src/retalimit.ts +100 -0
- package/src/sort.ts +32 -0
- package/src/typeof.ts +26 -0
- package/src/types.ts +22 -0
- package/test/test.js +117 -0
- package/tsconfig.json +16 -0
- /package/{dist/index.js → test/others.test.ts} +0 -0
package/.babelrc.json
ADDED
package/.editorconfig
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# http://editorconfig.org
|
|
2
|
+
root = true
|
|
3
|
+
|
|
4
|
+
[*] # 表示所有文件适用
|
|
5
|
+
charset = utf-8 # 设置文件字符集为 utf-8
|
|
6
|
+
indent_style = space # 缩进风格(tab | space)
|
|
7
|
+
indent_size = 2 # 缩进大小
|
|
8
|
+
end_of_line = lf # 控制换行类型(lf | cr | crlf)
|
|
9
|
+
trim_trailing_whitespace = true # 去除行首的任意空白字符
|
|
10
|
+
insert_final_newline = true # 始终在文件末尾插入一个新行
|
|
11
|
+
|
|
12
|
+
[*.md] # 表示仅 md 文件适用以下规则
|
|
13
|
+
max_line_length = off
|
|
14
|
+
trim_trailing_whitespace = false
|
package/.eslintignore
ADDED
package/.eslintrc.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"env": {
|
|
3
|
+
"browser": true,
|
|
4
|
+
"es2021": true
|
|
5
|
+
},
|
|
6
|
+
"extends": [
|
|
7
|
+
"eslint:recommended",
|
|
8
|
+
"plugin:@typescript-eslint/recommended",
|
|
9
|
+
"plugin:prettier/recommended"
|
|
10
|
+
],
|
|
11
|
+
"parser": "@typescript-eslint/parser",
|
|
12
|
+
"parserOptions": {
|
|
13
|
+
"ecmaVersion": "latest",
|
|
14
|
+
"sourceType": "module"
|
|
15
|
+
},
|
|
16
|
+
"plugins": ["@typescript-eslint"],
|
|
17
|
+
"rules": {
|
|
18
|
+
"@typescript-eslint/no-explicit-any": "off",
|
|
19
|
+
"@typescript-eslint/ban-types": "off"
|
|
20
|
+
}
|
|
21
|
+
}
|
package/.prettierignore
ADDED
package/.prettierrc.json
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 OpenKnights
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# devix
|
|
2
|
+
|
|
3
|
+
Devix is a comprehensive, powerful, and compact JavaScript utility library.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```shell
|
|
8
|
+
npm install --save-dev devix
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
// Using ES Module
|
|
15
|
+
import { [[ModuleName]] } from 'devix'
|
|
16
|
+
|
|
17
|
+
// Using CommonJS
|
|
18
|
+
var { [[ModuleName]] } = require('devix')
|
|
19
|
+
```
|
package/jest.config.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* For a detailed explanation regarding each configuration property, visit:
|
|
3
|
+
* https://jestjs.io/docs/configuration
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { Config } from 'jest'
|
|
7
|
+
|
|
8
|
+
const config: Config = {
|
|
9
|
+
// Automatically clear mock calls, instances, contexts and results before every test
|
|
10
|
+
clearMocks: true,
|
|
11
|
+
|
|
12
|
+
// The directory where Jest should output its coverage files
|
|
13
|
+
coverageDirectory: 'coverage',
|
|
14
|
+
|
|
15
|
+
// Tool selection for test coverage.
|
|
16
|
+
coverageProvider: 'babel',
|
|
17
|
+
|
|
18
|
+
// Optimization for the extensionsToTreatAsEsm configuration.
|
|
19
|
+
extensionsToTreatAsEsm: ['.ts'],
|
|
20
|
+
|
|
21
|
+
// Regex matching to ignore collection paths.
|
|
22
|
+
coveragePathIgnorePatterns: ['/node_modules/']
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default config
|
package/package.json
CHANGED
|
@@ -1,19 +1,47 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devix",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.12",
|
|
5
|
+
"description": "Devix is a comprehensive, powerful, and compact JavaScript utility library.",
|
|
6
|
+
"author": "",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"keywords": [],
|
|
5
9
|
"exports": {
|
|
6
10
|
".": {
|
|
7
|
-
"import": "./dist/index.js",
|
|
8
|
-
"require": "./dist/index.js"
|
|
11
|
+
"import": "./dist/index.esm.js",
|
|
12
|
+
"require": "./dist/index.cjs.js"
|
|
9
13
|
}
|
|
10
14
|
},
|
|
11
|
-
"main": "dist/index.js",
|
|
12
|
-
"module": "dist/index.js",
|
|
15
|
+
"main": "./dist/index.cjs.js",
|
|
16
|
+
"module": "./dist/index.esm.js",
|
|
17
|
+
"umd": "./dist/index.umd.js",
|
|
13
18
|
"scripts": {
|
|
14
|
-
"
|
|
19
|
+
"build": "rollup -c",
|
|
20
|
+
"dev": "yarn build --watch",
|
|
21
|
+
"test": "jest",
|
|
22
|
+
"lint": "eslint src/**/*.{js,jsx,ts,tsx,json}",
|
|
23
|
+
"prettier": "prettier --config .prettierrc.json --write ./**/**/*.{js,jsx,ts,tsx,json}"
|
|
15
24
|
},
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@babel/core": "^7.24.0",
|
|
27
|
+
"@babel/preset-env": "^7.24.0",
|
|
28
|
+
"@babel/preset-typescript": "^7.23.3",
|
|
29
|
+
"@rollup/plugin-babel": "^6.0.4",
|
|
30
|
+
"@rollup/plugin-commonjs": "^25.0.7",
|
|
31
|
+
"@rollup/plugin-json": "^6.1.0",
|
|
32
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
33
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
34
|
+
"@typescript-eslint/eslint-plugin": "^7.3.1",
|
|
35
|
+
"@typescript-eslint/parser": "^7.3.1",
|
|
36
|
+
"eslint": "^8.57.0",
|
|
37
|
+
"eslint-config-prettier": "^9.1.0",
|
|
38
|
+
"eslint-plugin-prettier": "^5.1.3",
|
|
39
|
+
"jest": "^29.7.0",
|
|
40
|
+
"prettier": "^3.2.5",
|
|
41
|
+
"rollup": "^4.13.0",
|
|
42
|
+
"rollup-plugin-dts": "^6.1.0",
|
|
43
|
+
"rollup-plugin-typescript2": "^0.36.0",
|
|
44
|
+
"tslib": "^2.6.2",
|
|
45
|
+
"typescript": "^5.4.2"
|
|
46
|
+
}
|
|
19
47
|
}
|
package/rollup.config.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import dts from 'rollup-plugin-dts'
|
|
2
|
+
import resolve from '@rollup/plugin-node-resolve'
|
|
3
|
+
import commonjs from '@rollup/plugin-commonjs'
|
|
4
|
+
import typescript from 'rollup-plugin-typescript2'
|
|
5
|
+
import json from '@rollup/plugin-json'
|
|
6
|
+
import terser from '@rollup/plugin-terser'
|
|
7
|
+
import babel from '@rollup/plugin-babel'
|
|
8
|
+
import { DEFAULT_EXTENSIONS } from '@babel/core'
|
|
9
|
+
|
|
10
|
+
const packname = 'Evenex'
|
|
11
|
+
const entries = ['src/index.ts']
|
|
12
|
+
const plugins = [
|
|
13
|
+
resolve({
|
|
14
|
+
preferBuiltins: true
|
|
15
|
+
}),
|
|
16
|
+
json(),
|
|
17
|
+
commonjs(),
|
|
18
|
+
typescript(),
|
|
19
|
+
babel({
|
|
20
|
+
babelHelpers: 'bundled',
|
|
21
|
+
exclude: 'node_modules/**',
|
|
22
|
+
extensions: [...DEFAULT_EXTENSIONS, '.ts']
|
|
23
|
+
}),
|
|
24
|
+
terser()
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
const rollup_config = [
|
|
28
|
+
...entries.map((input) => ({
|
|
29
|
+
input,
|
|
30
|
+
output: [
|
|
31
|
+
{
|
|
32
|
+
file: input.replace('src/', 'dist/').replace('.ts', '.esm.js'),
|
|
33
|
+
format: 'es'
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
file: input.replace('src/', 'dist/').replace('.ts', '.cjs.js'),
|
|
37
|
+
format: 'cjs'
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: packname,
|
|
41
|
+
file: input.replace('src/', 'dist/').replace('.ts', '.umd.js'),
|
|
42
|
+
format: 'umd'
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
plugins
|
|
46
|
+
})),
|
|
47
|
+
...entries.map((input) => ({
|
|
48
|
+
input,
|
|
49
|
+
output: [
|
|
50
|
+
{
|
|
51
|
+
file: input.replace('src/', 'dist/').replace('.ts', '.d.ts'),
|
|
52
|
+
format: 'esm'
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
plugins: [dts({ respectExternal: true })]
|
|
56
|
+
}))
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
export default rollup_config
|
package/src/cache.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { isType } from './typeof'
|
|
2
|
+
|
|
3
|
+
enum CacheType {
|
|
4
|
+
Local,
|
|
5
|
+
Session
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Encapsulate storage cache class
|
|
10
|
+
*
|
|
11
|
+
* @class StorageCache
|
|
12
|
+
* @template T
|
|
13
|
+
*/
|
|
14
|
+
class StorageCache<T = any> {
|
|
15
|
+
private storage: Storage
|
|
16
|
+
|
|
17
|
+
constructor(type: CacheType) {
|
|
18
|
+
this.storage = type === CacheType.Local ? localStorage : sessionStorage
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
getCache(key: string): T {
|
|
22
|
+
const value: any = this.storage.getItem(key)
|
|
23
|
+
return value ? JSON.parse(value) : null
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
setCache(key: string, value: T): void {
|
|
27
|
+
this.storage.setItem(key, JSON.stringify(value))
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
updateCache(key: string, property: string, value: T) {
|
|
31
|
+
const cache: any = this.getCache(key)
|
|
32
|
+
if (isType('object', cache)) {
|
|
33
|
+
cache[property] = value
|
|
34
|
+
this.setCache(key, cache)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
deleteCache(key: string): void {
|
|
39
|
+
this.storage.removeItem(key)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
clearCache(): void {
|
|
43
|
+
this.storage.clear()
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const localCache = new StorageCache(CacheType.Local)
|
|
48
|
+
export const sessionCache = new StorageCache(CacheType.Session)
|
package/src/clone.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { isType } from './typeof'
|
|
2
|
+
|
|
3
|
+
//! Function Shallow Copy
|
|
4
|
+
export function shallowClone<T = any>(source: T): T {
|
|
5
|
+
if (isType('array', source)) return (source as any[]).slice() as T
|
|
6
|
+
if (isType('object', source)) return { ...source } as T
|
|
7
|
+
|
|
8
|
+
return source
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
//! Function Deep Copy
|
|
12
|
+
const isFormat = (target: any) =>
|
|
13
|
+
isType('object', target) || isType('function', target)
|
|
14
|
+
|
|
15
|
+
function handleSpeciBoundar<T = any>(
|
|
16
|
+
source: any,
|
|
17
|
+
deepClone: Function,
|
|
18
|
+
hash: WeakMap<object, T>
|
|
19
|
+
) {
|
|
20
|
+
if (isType('symbol', source)) return Symbol(source.description)
|
|
21
|
+
|
|
22
|
+
if (!isFormat(source)) return source
|
|
23
|
+
|
|
24
|
+
if (isType('set', source)) {
|
|
25
|
+
const newSet = new Set()
|
|
26
|
+
source.forEach((value: T) => newSet.add(deepClone(value, hash)))
|
|
27
|
+
|
|
28
|
+
return newSet
|
|
29
|
+
}
|
|
30
|
+
if (isType('map', source)) {
|
|
31
|
+
const newMap = new Map()
|
|
32
|
+
source.forEach((value: T, key: T) =>
|
|
33
|
+
newMap.set(key, deepClone(value, hash))
|
|
34
|
+
)
|
|
35
|
+
return newMap
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function deepClone(source: any, hash = new WeakMap<object, any>()) {
|
|
40
|
+
if (hash.get(source)) return hash.get(source)
|
|
41
|
+
|
|
42
|
+
const result = handleSpeciBoundar(source, deepClone, hash)
|
|
43
|
+
if (result) return result
|
|
44
|
+
|
|
45
|
+
const isArray = isType('array', source)
|
|
46
|
+
const cloneObject: any = isArray ? [] : {}
|
|
47
|
+
|
|
48
|
+
hash.set(source, cloneObject)
|
|
49
|
+
|
|
50
|
+
if (isArray) {
|
|
51
|
+
;(source as Array<any>).forEach((item, index) => {
|
|
52
|
+
cloneObject[index] = deepClone(item, hash)
|
|
53
|
+
})
|
|
54
|
+
} else {
|
|
55
|
+
Object.keys(source).forEach((key) => {
|
|
56
|
+
cloneObject[key] = deepClone(source[key], hash)
|
|
57
|
+
})
|
|
58
|
+
Object.getOwnPropertySymbols(source).forEach((sym) => {
|
|
59
|
+
cloneObject[Symbol(sym.description)] = deepClone(source[sym], hash)
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return cloneObject
|
|
64
|
+
}
|
package/src/format.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { isType } from './typeof'
|
|
2
|
+
import { TFormatTimer, ITimerObj } from './types'
|
|
3
|
+
|
|
4
|
+
const formatRules = new Map<string, keyof ITimerObj>([
|
|
5
|
+
['yyyy', 'year'],
|
|
6
|
+
['MM', 'month'],
|
|
7
|
+
['dd', 'day'],
|
|
8
|
+
['HH', 'hours'],
|
|
9
|
+
['mm', 'minutes'],
|
|
10
|
+
['ss', 'seconds'],
|
|
11
|
+
['W', 'week']
|
|
12
|
+
])
|
|
13
|
+
|
|
14
|
+
const WeekList = new Map<number, string>([
|
|
15
|
+
[1, '一'],
|
|
16
|
+
[2, '二'],
|
|
17
|
+
[3, '三'],
|
|
18
|
+
[4, '四'],
|
|
19
|
+
[5, '五'],
|
|
20
|
+
[6, '六'],
|
|
21
|
+
[0, '日']
|
|
22
|
+
])
|
|
23
|
+
|
|
24
|
+
function processWeek(weekNum: number): string {
|
|
25
|
+
return WeekList.get(weekNum) || ''
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function formatNumber(value: number): string {
|
|
29
|
+
return value.toString().padStart(2, '0')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function createTimerObj(date: Date): ITimerObj {
|
|
33
|
+
const dayOfWeek = date.getDay() === 0 ? 7 : date.getDay()
|
|
34
|
+
return {
|
|
35
|
+
year: date.getFullYear().toString(),
|
|
36
|
+
month: formatNumber(date.getMonth() + 1),
|
|
37
|
+
day: formatNumber(date.getDate()),
|
|
38
|
+
hours: formatNumber(date.getHours()),
|
|
39
|
+
minutes: formatNumber(date.getMinutes()),
|
|
40
|
+
seconds: formatNumber(date.getSeconds()),
|
|
41
|
+
week: processWeek(dayOfWeek),
|
|
42
|
+
weekNum: dayOfWeek.toString()
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const formatTimer: TFormatTimer = (
|
|
47
|
+
cellValue,
|
|
48
|
+
formatType = 'yyyy-MM-dd HH:mm:ss'
|
|
49
|
+
) => {
|
|
50
|
+
if (!cellValue) return new Date().toISOString()
|
|
51
|
+
|
|
52
|
+
const date = new Date(cellValue)
|
|
53
|
+
const timerObj = createTimerObj(date)
|
|
54
|
+
|
|
55
|
+
if (isType('string', formatType) && !formatType.trim()) return timerObj
|
|
56
|
+
|
|
57
|
+
const timerStr = Array.from(formatRules).reduce(
|
|
58
|
+
(currentFormat, [rule, key]) => {
|
|
59
|
+
return currentFormat.replace(new RegExp(rule, 'g'), timerObj[key])
|
|
60
|
+
},
|
|
61
|
+
formatType
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
return timerStr
|
|
65
|
+
}
|
package/src/index.ts
ADDED
package/src/others.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export function currying(fn: Function) {
|
|
2
|
+
function curried(this: any, ...args: any[]) {
|
|
3
|
+
if (args.length >= fn.length) {
|
|
4
|
+
return fn.apply(this, args)
|
|
5
|
+
} else {
|
|
6
|
+
return function (this: any, ...args2: any[]) {
|
|
7
|
+
return curried.apply(this, args.concat(args2))
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return curried
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function compose(...fns: Function[]) {
|
|
15
|
+
const length = fns.length
|
|
16
|
+
if (length <= 0) return
|
|
17
|
+
for (let i = 0; i < length; i++) {
|
|
18
|
+
const fn = fns[i]
|
|
19
|
+
if (typeof fn !== 'function') {
|
|
20
|
+
throw new Error(`argument with index ${i} is not a function`)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return function (this: any, ...args: any[]) {
|
|
25
|
+
let index = 0
|
|
26
|
+
let result = fns[index].apply(this, args)
|
|
27
|
+
while (++index < length) {
|
|
28
|
+
result = fns[index].call(this, result)
|
|
29
|
+
}
|
|
30
|
+
return result
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function insertStr(soure: string, start: number, newStr: string) {
|
|
35
|
+
return soure.slice(0, start) + newStr + soure.slice(start)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function stringCase(soure: string, separator = '', separate = '') {
|
|
39
|
+
const newStr = soure.split(separator)
|
|
40
|
+
for (let i = 0; i < newStr.length; i++) {
|
|
41
|
+
newStr[i] =
|
|
42
|
+
newStr[i].slice(0, 1).toUpperCase() + newStr[i].slice(1).toLowerCase()
|
|
43
|
+
}
|
|
44
|
+
return newStr.join(separate)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function setTimer(
|
|
48
|
+
execute: (...args: any[]) => any,
|
|
49
|
+
delay: number,
|
|
50
|
+
immediate: boolean
|
|
51
|
+
) {
|
|
52
|
+
let timer: ReturnType<typeof setTimeout> | null = null
|
|
53
|
+
|
|
54
|
+
const interval = () => {
|
|
55
|
+
execute()
|
|
56
|
+
timer = setTimeout(interval, delay)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (immediate) execute()
|
|
60
|
+
|
|
61
|
+
setTimeout(interval, delay)
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
cancel: () => {
|
|
65
|
+
if (timer !== null) clearTimeout(timer)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
package/src/retalimit.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { ThrottleOptions } from './types'
|
|
2
|
+
|
|
3
|
+
export function debounce<T extends (...args: any[]) => any>(
|
|
4
|
+
callback: T,
|
|
5
|
+
delay: number = 0,
|
|
6
|
+
immediate: boolean = false
|
|
7
|
+
): ((...args: Parameters<T>) => Promise<ReturnType<T>>) & {
|
|
8
|
+
cancel: () => void
|
|
9
|
+
} {
|
|
10
|
+
let timer: ReturnType<typeof setTimeout> | null = null
|
|
11
|
+
let isInvoke: boolean = false
|
|
12
|
+
|
|
13
|
+
function _debounce(this: any, ...args: Parameters<T>) {
|
|
14
|
+
return new Promise<ReturnType<T>>((resolve, reject) => {
|
|
15
|
+
if (timer !== null) clearTimeout(timer)
|
|
16
|
+
|
|
17
|
+
if (immediate && !isInvoke) {
|
|
18
|
+
try {
|
|
19
|
+
const result: ReturnType<T> = callback.apply(this, args)
|
|
20
|
+
resolve(result)
|
|
21
|
+
} catch (error) {
|
|
22
|
+
reject(error)
|
|
23
|
+
}
|
|
24
|
+
isInvoke = true
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
timer = setTimeout(() => {
|
|
29
|
+
try {
|
|
30
|
+
const result: ReturnType<T> = callback.apply(this, args)
|
|
31
|
+
resolve(result)
|
|
32
|
+
} catch (error) {
|
|
33
|
+
reject(error)
|
|
34
|
+
} finally {
|
|
35
|
+
timer = null
|
|
36
|
+
isInvoke = false
|
|
37
|
+
}
|
|
38
|
+
}, delay)
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
_debounce.cancel = function (): void {
|
|
43
|
+
if (timer !== null) clearTimeout(timer)
|
|
44
|
+
timer = null
|
|
45
|
+
isInvoke = false
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return _debounce
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function throttle<T extends (...args: any[]) => any>(
|
|
52
|
+
callback: T,
|
|
53
|
+
interval: number,
|
|
54
|
+
options: ThrottleOptions = {}
|
|
55
|
+
): ((...args: Parameters<T>) => Promise<ReturnType<T>>) & {
|
|
56
|
+
cancel: () => void
|
|
57
|
+
} {
|
|
58
|
+
const { leading = true, trailing = false } = options
|
|
59
|
+
let startTime: number = 0
|
|
60
|
+
let timer: ReturnType<typeof setTimeout> | null = null
|
|
61
|
+
|
|
62
|
+
function _throttle(this: any, ...args: Parameters<T>) {
|
|
63
|
+
return new Promise<ReturnType<T>>((resolve, reject) => {
|
|
64
|
+
try {
|
|
65
|
+
const nowTime = Date.now()
|
|
66
|
+
let result: ReturnType<T>
|
|
67
|
+
if (!leading && startTime === 0) startTime = nowTime
|
|
68
|
+
|
|
69
|
+
const waitTime = interval - (nowTime - startTime)
|
|
70
|
+
if (waitTime <= 0) {
|
|
71
|
+
if (timer) clearTimeout(timer)
|
|
72
|
+
result = callback.apply(this, args)
|
|
73
|
+
resolve(result)
|
|
74
|
+
startTime = nowTime
|
|
75
|
+
timer = null
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (trailing && !timer) {
|
|
80
|
+
timer = setTimeout(() => {
|
|
81
|
+
result = callback.apply(this, args)
|
|
82
|
+
resolve(result)
|
|
83
|
+
startTime = Date.now()
|
|
84
|
+
timer = null
|
|
85
|
+
}, waitTime)
|
|
86
|
+
}
|
|
87
|
+
} catch (error) {
|
|
88
|
+
reject(error)
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
_throttle.cancel = function () {
|
|
94
|
+
if (timer) clearTimeout(timer)
|
|
95
|
+
startTime = 0
|
|
96
|
+
timer = null
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return _throttle
|
|
100
|
+
}
|
package/src/sort.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
enum SortType {
|
|
2
|
+
ASC = 'ASC',
|
|
3
|
+
DESC = 'DESC'
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
function swap<T>(array: T[], index1: number, index2: number): void {
|
|
7
|
+
;[array[index1], array[index2]] = [array[index2], array[index1]]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function compare<T>(value1: T, value2: T, type: SortType): boolean {
|
|
11
|
+
return type === SortType.ASC ? value1 > value2 : value1 < value2
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function bubblingSort<T>(
|
|
15
|
+
array: T[],
|
|
16
|
+
type: SortType = SortType.ASC,
|
|
17
|
+
key?: keyof T
|
|
18
|
+
): T[] {
|
|
19
|
+
const length = array.length
|
|
20
|
+
if (length < 2) return array
|
|
21
|
+
|
|
22
|
+
for (let i = 0; i < length - 1; i++) {
|
|
23
|
+
for (let j = 0; j < length - 1 - i; j++) {
|
|
24
|
+
const value1 = key ? array[j][key] : array[j]
|
|
25
|
+
const value2 = key ? array[j + 1][key] : array[j + 1]
|
|
26
|
+
|
|
27
|
+
if (compare(value1, value2, type)) swap(array, j, j + 1)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return array
|
|
32
|
+
}
|
package/src/typeof.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export default function getDataType(target: any) {
|
|
2
|
+
const type = typeof target
|
|
3
|
+
return type === 'object'
|
|
4
|
+
? type
|
|
5
|
+
: Object.prototype.toString.call(target).slice(8, -1).toLowerCase()
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const typeCheckers: { [key: string]: (target: any) => boolean } = {
|
|
9
|
+
string: (target) => typeof target === 'string',
|
|
10
|
+
number: (target) => typeof target === 'number',
|
|
11
|
+
boolean: (target) => typeof target === 'boolean',
|
|
12
|
+
null: (target) => target === null,
|
|
13
|
+
undefined: (target) => typeof target === 'undefined',
|
|
14
|
+
symbol: (target) => typeof target === 'symbol',
|
|
15
|
+
bigint: (target) => typeof target === 'bigint',
|
|
16
|
+
object: (target) => target !== null && typeof target === 'object',
|
|
17
|
+
array: (target) => Array.isArray(target),
|
|
18
|
+
function: (target) => typeof target === 'function',
|
|
19
|
+
set: (target) => target instanceof Set,
|
|
20
|
+
map: (target) => target instanceof Map,
|
|
21
|
+
date: (target) => target instanceof Date,
|
|
22
|
+
regexp: (target) => target instanceof RegExp
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const isType = (type: string, target: any) =>
|
|
26
|
+
typeCheckers[type]?.(target) || false
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//! format types
|
|
2
|
+
export interface ITimerObj {
|
|
3
|
+
year: string
|
|
4
|
+
month: string
|
|
5
|
+
day: string
|
|
6
|
+
hours: string
|
|
7
|
+
minutes: string
|
|
8
|
+
seconds: string
|
|
9
|
+
week: string
|
|
10
|
+
weekNum: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type TFormatTimer = (
|
|
14
|
+
cellValue: string | number | Date,
|
|
15
|
+
formatType?: string
|
|
16
|
+
) => string | ITimerObj
|
|
17
|
+
|
|
18
|
+
//! retalimit types
|
|
19
|
+
export type ThrottleOptions = {
|
|
20
|
+
leading?: boolean
|
|
21
|
+
trailing?: boolean
|
|
22
|
+
}
|
package/test/test.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { debounce } from '../dist/index.esm.js'
|
|
2
|
+
|
|
3
|
+
// function debounce(callback, delay = 0, immediate = false) {
|
|
4
|
+
// let timer = null
|
|
5
|
+
// let isInvoke = false
|
|
6
|
+
// function _debounce(...args) {
|
|
7
|
+
// return new Promise((resolve, reject) => {
|
|
8
|
+
// try {
|
|
9
|
+
// if (timer) clearTimeout(timer)
|
|
10
|
+
|
|
11
|
+
// let result = undefined
|
|
12
|
+
// if (immediate && !isInvoke) {
|
|
13
|
+
// result = callback.apply(this, args)
|
|
14
|
+
// resolve(result)
|
|
15
|
+
// isInvoke = true
|
|
16
|
+
// return
|
|
17
|
+
// }
|
|
18
|
+
|
|
19
|
+
// timer = setTimeout(() => {
|
|
20
|
+
// result = callback.apply(this, args)
|
|
21
|
+
// resolve(result)
|
|
22
|
+
// timer = null
|
|
23
|
+
// isInvoke = false
|
|
24
|
+
// }, delay)
|
|
25
|
+
// } catch (error) {
|
|
26
|
+
// reject(error)
|
|
27
|
+
// }
|
|
28
|
+
// })
|
|
29
|
+
// }
|
|
30
|
+
|
|
31
|
+
// _debounce.cancel = function () {
|
|
32
|
+
// if (timer) clearTimeout(timer)
|
|
33
|
+
// timer = null
|
|
34
|
+
// isInvoke = false
|
|
35
|
+
// }
|
|
36
|
+
|
|
37
|
+
// return _debounce
|
|
38
|
+
// }
|
|
39
|
+
|
|
40
|
+
// function throttle(
|
|
41
|
+
// callback,
|
|
42
|
+
// interval,
|
|
43
|
+
// { leading = true, trailing = false } = {}
|
|
44
|
+
// ) {
|
|
45
|
+
// let startTime = 0
|
|
46
|
+
// let timer = null
|
|
47
|
+
// function _throttle(...args) {
|
|
48
|
+
// return new Promise((resolve, reject) => {
|
|
49
|
+
// try {
|
|
50
|
+
// const nowTime = Date.now()
|
|
51
|
+
// let result = undefined
|
|
52
|
+
// if (!leading && startTime === 0) startTime = nowTime
|
|
53
|
+
|
|
54
|
+
// const waitTime = interval - (nowTime - startTime)
|
|
55
|
+
// if (waitTime <= 0) {
|
|
56
|
+
// if (timer) clearTimeout(timer)
|
|
57
|
+
// result = callback.apply(this, args)
|
|
58
|
+
// resolve(result)
|
|
59
|
+
// startTime = nowTime
|
|
60
|
+
// timer = null
|
|
61
|
+
// return
|
|
62
|
+
// }
|
|
63
|
+
|
|
64
|
+
// if (trailing && !timer) {
|
|
65
|
+
// timer = setTimeout(() => {
|
|
66
|
+
// result = callback.apply(this, args)
|
|
67
|
+
// resolve(result)
|
|
68
|
+
// startTime = Date.now()
|
|
69
|
+
// timer = null
|
|
70
|
+
// }, waitTime)
|
|
71
|
+
// }
|
|
72
|
+
// } catch (error) {
|
|
73
|
+
// reject(error)
|
|
74
|
+
// }
|
|
75
|
+
// })
|
|
76
|
+
// }
|
|
77
|
+
|
|
78
|
+
// _throttle.cancel = function () {
|
|
79
|
+
// if (timer) clearTimeout(timer)
|
|
80
|
+
// startTime = 0
|
|
81
|
+
// timer = null
|
|
82
|
+
// }
|
|
83
|
+
|
|
84
|
+
// return _throttle
|
|
85
|
+
// }
|
|
86
|
+
|
|
87
|
+
// const foo1 = debounce(
|
|
88
|
+
// (message) => {
|
|
89
|
+
// console.log('message', message)
|
|
90
|
+
// return message
|
|
91
|
+
// },
|
|
92
|
+
// 3000,
|
|
93
|
+
// true
|
|
94
|
+
// )
|
|
95
|
+
|
|
96
|
+
// const foop1 = foo1('111')
|
|
97
|
+
// foop1.then((res) => {
|
|
98
|
+
// console.log(`res:`, res)
|
|
99
|
+
// })
|
|
100
|
+
// // foo1('222')
|
|
101
|
+
// foo1('333')
|
|
102
|
+
|
|
103
|
+
// setTimeout(() => {
|
|
104
|
+
// foo1.cancel()
|
|
105
|
+
// }, 1000)
|
|
106
|
+
|
|
107
|
+
const foo3 = debounce(function (...args) {
|
|
108
|
+
console.log('this', this)
|
|
109
|
+
console.log('args', args)
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
const obj1 = {
|
|
113
|
+
name: 'obj',
|
|
114
|
+
foo3
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
obj1.foo3('333')
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "esnext",
|
|
4
|
+
"module": "esnext",
|
|
5
|
+
"lib": ["esnext", "DOM", "DOM.Iterable"],
|
|
6
|
+
"useDefineForClassFields": true,
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"moduleResolution": "node",
|
|
9
|
+
"resolveJsonModule": true,
|
|
10
|
+
"esModuleInterop": false,
|
|
11
|
+
"strict": true,
|
|
12
|
+
"strictNullChecks": true,
|
|
13
|
+
"typeRoots": ["node_modules/@types", "src/types.ts"]
|
|
14
|
+
},
|
|
15
|
+
"include": ["src/*.ts"]
|
|
16
|
+
}
|
|
File without changes
|