Compare commits
3 Commits
zhouludong
...
main
Author | SHA1 | Date |
---|---|---|
hhy | 93f88aa77e | 6 days ago |
hhy | 26d44d58b6 | 6 days ago |
hhy | 2158dd3674 | 6 days ago |
After Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 74 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 150 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 455 KiB |
After Width: | Height: | Size: 134 KiB |
After Width: | Height: | Size: 122 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 2.5 MiB |
@ -1 +1 @@
|
|||||||
333
|
3
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"version" : "1.0",
|
||||||
|
"configurations" : [
|
||||||
|
{
|
||||||
|
"playground" : "custom",
|
||||||
|
"type" : "uni-app:app-android"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "pwa-chrome",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Launch Chrome against localhost",
|
||||||
|
"url": "http://localhost:8080",
|
||||||
|
"webRoot": "${workspaceFolder}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
onLaunch: function() {
|
||||||
|
console.log('App Launch')
|
||||||
|
},
|
||||||
|
onShow: function() {
|
||||||
|
console.log('App Show')
|
||||||
|
},
|
||||||
|
onHide: function() {
|
||||||
|
console.log('App Hide')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/*每个页面公共css */
|
||||||
|
</style>
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"prompt": "template"
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<script>
|
||||||
|
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||||
|
CSS.supports('top: constant(a)'))
|
||||||
|
document.write(
|
||||||
|
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||||
|
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||||
|
</script>
|
||||||
|
<title></title>
|
||||||
|
<!--preload-links-->
|
||||||
|
<!--app-context-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"><!--app-html--></div>
|
||||||
|
<script type="module" src="/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,22 @@
|
|||||||
|
import App from './App'
|
||||||
|
|
||||||
|
// #ifndef VUE3
|
||||||
|
import Vue from 'vue'
|
||||||
|
import './uni.promisify.adaptor'
|
||||||
|
Vue.config.productionTip = false
|
||||||
|
App.mpType = 'app'
|
||||||
|
const app = new Vue({
|
||||||
|
...App
|
||||||
|
})
|
||||||
|
app.$mount()
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef VUE3
|
||||||
|
import { createSSRApp } from 'vue'
|
||||||
|
export function createApp() {
|
||||||
|
const app = createSSRApp(App)
|
||||||
|
return {
|
||||||
|
app
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #endif
|
@ -0,0 +1,78 @@
|
|||||||
|
{
|
||||||
|
"name" : "健康青年",
|
||||||
|
"appid" : "__UNI__3A6C46C",
|
||||||
|
"description" : "",
|
||||||
|
"versionName" : "1.0.0",
|
||||||
|
"versionCode" : "100",
|
||||||
|
"transformPx" : false,
|
||||||
|
/* 5+App特有相关 */
|
||||||
|
"app-plus" : {
|
||||||
|
"usingComponents" : true,
|
||||||
|
"nvueStyleCompiler" : "uni-app",
|
||||||
|
"compilerVersion" : 3,
|
||||||
|
"splashscreen" : {
|
||||||
|
"alwaysShowBeforeRender" : true,
|
||||||
|
"waiting" : true,
|
||||||
|
"autoclose" : true,
|
||||||
|
"delay" : 0
|
||||||
|
},
|
||||||
|
/* 模块配置 */
|
||||||
|
"modules" : {},
|
||||||
|
/* 应用发布信息 */
|
||||||
|
"distribute" : {
|
||||||
|
/* android打包配置 */
|
||||||
|
"android" : {
|
||||||
|
"permissions" : [
|
||||||
|
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||||
|
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||||
|
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||||
|
],
|
||||||
|
"abiFilters" : [ "arm64-v8a", "x86" ]
|
||||||
|
},
|
||||||
|
/* ios打包配置 */
|
||||||
|
"ios" : {
|
||||||
|
"dSYMs" : false
|
||||||
|
},
|
||||||
|
/* SDK配置 */
|
||||||
|
"sdkConfigs" : {},
|
||||||
|
"splashscreen" : {
|
||||||
|
"useOriginalMsgbox" : true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/* 快应用特有相关 */
|
||||||
|
"quickapp" : {},
|
||||||
|
/* 小程序特有相关 */
|
||||||
|
"mp-weixin" : {
|
||||||
|
"appid" : "",
|
||||||
|
"setting" : {
|
||||||
|
"urlCheck" : false
|
||||||
|
},
|
||||||
|
"usingComponents" : true
|
||||||
|
},
|
||||||
|
"mp-alipay" : {
|
||||||
|
"usingComponents" : true
|
||||||
|
},
|
||||||
|
"mp-baidu" : {
|
||||||
|
"usingComponents" : true
|
||||||
|
},
|
||||||
|
"mp-toutiao" : {
|
||||||
|
"usingComponents" : true
|
||||||
|
},
|
||||||
|
"uniStatistics" : {
|
||||||
|
"enable" : false
|
||||||
|
},
|
||||||
|
"vueVersion" : "3"
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||||
|
|
||||||
|
case `uname` in
|
||||||
|
*CYGWIN*|*MINGW*|*MSYS*)
|
||||||
|
if command -v cygpath > /dev/null 2>&1; then
|
||||||
|
basedir=`cygpath -w "$basedir"`
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -x "$basedir/node" ]; then
|
||||||
|
exec "$basedir/node" "$basedir/../acorn/bin/acorn" "$@"
|
||||||
|
else
|
||||||
|
exec node "$basedir/../acorn/bin/acorn" "$@"
|
||||||
|
fi
|
@ -0,0 +1,17 @@
|
|||||||
|
@ECHO off
|
||||||
|
GOTO start
|
||||||
|
:find_dp0
|
||||||
|
SET dp0=%~dp0
|
||||||
|
EXIT /b
|
||||||
|
:start
|
||||||
|
SETLOCAL
|
||||||
|
CALL :find_dp0
|
||||||
|
|
||||||
|
IF EXIST "%dp0%\node.exe" (
|
||||||
|
SET "_prog=%dp0%\node.exe"
|
||||||
|
) ELSE (
|
||||||
|
SET "_prog=node"
|
||||||
|
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||||
|
)
|
||||||
|
|
||||||
|
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\acorn\bin\acorn" %*
|
@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env pwsh
|
||||||
|
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||||
|
|
||||||
|
$exe=""
|
||||||
|
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||||
|
# Fix case when both the Windows and Linux builds of Node
|
||||||
|
# are installed in the same directory
|
||||||
|
$exe=".exe"
|
||||||
|
}
|
||||||
|
$ret=0
|
||||||
|
if (Test-Path "$basedir/node$exe") {
|
||||||
|
# Support pipeline input
|
||||||
|
if ($MyInvocation.ExpectingInput) {
|
||||||
|
$input | & "$basedir/node$exe" "$basedir/../acorn/bin/acorn" $args
|
||||||
|
} else {
|
||||||
|
& "$basedir/node$exe" "$basedir/../acorn/bin/acorn" $args
|
||||||
|
}
|
||||||
|
$ret=$LASTEXITCODE
|
||||||
|
} else {
|
||||||
|
# Support pipeline input
|
||||||
|
if ($MyInvocation.ExpectingInput) {
|
||||||
|
$input | & "node$exe" "$basedir/../acorn/bin/acorn" $args
|
||||||
|
} else {
|
||||||
|
& "node$exe" "$basedir/../acorn/bin/acorn" $args
|
||||||
|
}
|
||||||
|
$ret=$LASTEXITCODE
|
||||||
|
}
|
||||||
|
exit $ret
|
@ -0,0 +1,516 @@
|
|||||||
|
{
|
||||||
|
"name": "健康测试",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"node_modules/@antfu/utils": {
|
||||||
|
"version": "0.7.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz",
|
||||||
|
"integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@jridgewell/sourcemap-codec": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@nodelib/fs.scandir": {
|
||||||
|
"version": "2.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
|
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@nodelib/fs.stat": "2.0.5",
|
||||||
|
"run-parallel": "^1.1.9"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@nodelib/fs.stat": {
|
||||||
|
"version": "2.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
|
||||||
|
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@nodelib/fs.walk": {
|
||||||
|
"version": "1.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
|
||||||
|
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@nodelib/fs.scandir": "2.1.5",
|
||||||
|
"fastq": "^1.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@rollup/pluginutils": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/estree": "^1.0.0",
|
||||||
|
"estree-walker": "^2.0.2",
|
||||||
|
"picomatch": "^2.3.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"rollup": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/estree": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/acorn": {
|
||||||
|
"version": "8.13.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz",
|
||||||
|
"integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"acorn": "bin/acorn"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/balanced-match": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/brace-expansion": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/braces": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fill-range": "^7.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/confbox": {
|
||||||
|
"version": "0.1.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz",
|
||||||
|
"integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/escape-string-regexp": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/estree-walker": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/fast-glob": {
|
||||||
|
"version": "3.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
|
||||||
|
"integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@nodelib/fs.stat": "^2.0.2",
|
||||||
|
"@nodelib/fs.walk": "^1.2.3",
|
||||||
|
"glob-parent": "^5.1.2",
|
||||||
|
"merge2": "^1.3.0",
|
||||||
|
"micromatch": "^4.0.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fastq": {
|
||||||
|
"version": "1.17.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
|
||||||
|
"integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"reusify": "^1.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fill-range": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"to-regex-range": "^5.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/glob-parent": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"is-glob": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-extglob": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-glob": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-extglob": "^2.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-number": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/js-tokens": {
|
||||||
|
"version": "9.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz",
|
||||||
|
"integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/local-pkg": {
|
||||||
|
"version": "0.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz",
|
||||||
|
"integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mlly": "^1.4.2",
|
||||||
|
"pkg-types": "^1.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/magic-string": {
|
||||||
|
"version": "0.30.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz",
|
||||||
|
"integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@jridgewell/sourcemap-codec": "^1.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/merge2": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/micromatch": {
|
||||||
|
"version": "4.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||||
|
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"braces": "^3.0.3",
|
||||||
|
"picomatch": "^2.3.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/minimatch": {
|
||||||
|
"version": "9.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||||
|
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16 || 14 >=14.17"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mlly": {
|
||||||
|
"version": "1.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.2.tgz",
|
||||||
|
"integrity": "sha512-tN3dvVHYVz4DhSXinXIk7u9syPYaJvio118uomkovAtWBT+RdbP6Lfh/5Lvo519YMmwBafwlh20IPTXIStscpA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"acorn": "^8.12.1",
|
||||||
|
"pathe": "^1.1.2",
|
||||||
|
"pkg-types": "^1.2.0",
|
||||||
|
"ufo": "^1.5.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pathe": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/picomatch": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pkg-types": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"confbox": "^0.1.8",
|
||||||
|
"mlly": "^1.7.2",
|
||||||
|
"pathe": "^1.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/queue-microtask": {
|
||||||
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/reusify": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"iojs": ">=1.0.0",
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/run-parallel": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"queue-microtask": "^1.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/scule": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/scule/-/scule-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/strip-literal": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"js-tokens": "^9.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/to-regex-range": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-number": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ufo": {
|
||||||
|
"version": "1.5.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz",
|
||||||
|
"integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/unimport": {
|
||||||
|
"version": "3.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/unimport/-/unimport-3.13.1.tgz",
|
||||||
|
"integrity": "sha512-nNrVzcs93yrZQOW77qnyOVHtb68LegvhYFwxFMfuuWScmwQmyVCG/NBuN8tYsaGzgQUVYv34E/af+Cc9u4og4A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@rollup/pluginutils": "^5.1.2",
|
||||||
|
"acorn": "^8.12.1",
|
||||||
|
"escape-string-regexp": "^5.0.0",
|
||||||
|
"estree-walker": "^3.0.3",
|
||||||
|
"fast-glob": "^3.3.2",
|
||||||
|
"local-pkg": "^0.5.0",
|
||||||
|
"magic-string": "^0.30.11",
|
||||||
|
"mlly": "^1.7.1",
|
||||||
|
"pathe": "^1.1.2",
|
||||||
|
"pkg-types": "^1.2.0",
|
||||||
|
"scule": "^1.3.0",
|
||||||
|
"strip-literal": "^2.1.0",
|
||||||
|
"unplugin": "^1.14.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/unimport/node_modules/estree-walker": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/estree": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/unplugin": {
|
||||||
|
"version": "1.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.14.1.tgz",
|
||||||
|
"integrity": "sha512-lBlHbfSFPToDYp9pjXlUEFVxYLaue9f9T1HC+4OHlmj+HnMDdz9oZY+erXfoCe/5V/7gKUSY2jpXPb9S7f0f/w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"acorn": "^8.12.1",
|
||||||
|
"webpack-virtual-modules": "^0.6.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"webpack-sources": "^3"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"webpack-sources": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/unplugin-auto-import": {
|
||||||
|
"version": "0.18.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/unplugin-auto-import/-/unplugin-auto-import-0.18.3.tgz",
|
||||||
|
"integrity": "sha512-q3FUtGQjYA2e+kb1WumyiQMjHM27MrTQ05QfVwtLRVhyYe+KF6TblBYaEX9L6Z0EibsqaXAiW+RFfkcQpfaXzg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@antfu/utils": "^0.7.10",
|
||||||
|
"@rollup/pluginutils": "^5.1.0",
|
||||||
|
"fast-glob": "^3.3.2",
|
||||||
|
"local-pkg": "^0.5.0",
|
||||||
|
"magic-string": "^0.30.11",
|
||||||
|
"minimatch": "^9.0.5",
|
||||||
|
"unimport": "^3.12.0",
|
||||||
|
"unplugin": "^1.14.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@nuxt/kit": "^3.2.2",
|
||||||
|
"@vueuse/core": "*"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@nuxt/kit": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@vueuse/core": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/webpack-virtual-modules": {
|
||||||
|
"version": "0.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
|
||||||
|
"integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Anthony Fu <https://github.com/antfu>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
@ -0,0 +1,24 @@
|
|||||||
|
# @antfu/utils
|
||||||
|
|
||||||
|
[![NPM version](https://img.shields.io/npm/v/@antfu/utils?color=a1b858&label=)](https://www.npmjs.com/package/@antfu/utils)
|
||||||
|
[![Docs](https://img.shields.io/badge/docs-green)](https://www.jsdocs.io/package/@antfu/utils)
|
||||||
|
|
||||||
|
Opinionated collection of common JavaScript / TypeScript utils by [@antfu](https://github.com/antfu).
|
||||||
|
|
||||||
|
- Tree-shakable ESM
|
||||||
|
- Fully typed - with TSDocs
|
||||||
|
- Type utilities - `Arrayable<T>`, `ElementOf<T>`, etc.
|
||||||
|
|
||||||
|
> This package is designed to be used as `devDependencies` and bundled into your dist.
|
||||||
|
|
||||||
|
## Sponsors
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg">
|
||||||
|
<img src='https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg'/>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](./LICENSE) License © 2021-PRESENT [Anthony Fu](https://github.com/antfu)
|
@ -0,0 +1,844 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
function clamp(n, min, max) {
|
||||||
|
return Math.min(max, Math.max(min, n));
|
||||||
|
}
|
||||||
|
function sum(...args) {
|
||||||
|
return flattenArrayable(args).reduce((a, b) => a + b, 0);
|
||||||
|
}
|
||||||
|
function lerp(min, max, t) {
|
||||||
|
const interpolation = clamp(t, 0, 1);
|
||||||
|
return min + (max - min) * interpolation;
|
||||||
|
}
|
||||||
|
function remap(n, inMin, inMax, outMin, outMax) {
|
||||||
|
const interpolation = (n - inMin) / (inMax - inMin);
|
||||||
|
return lerp(outMin, outMax, interpolation);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toArray(array) {
|
||||||
|
array = array ?? [];
|
||||||
|
return Array.isArray(array) ? array : [array];
|
||||||
|
}
|
||||||
|
function flattenArrayable(array) {
|
||||||
|
return toArray(array).flat(1);
|
||||||
|
}
|
||||||
|
function mergeArrayable(...args) {
|
||||||
|
return args.flatMap((i) => toArray(i));
|
||||||
|
}
|
||||||
|
function partition(array, ...filters) {
|
||||||
|
const result = Array.from({ length: filters.length + 1 }).fill(null).map(() => []);
|
||||||
|
array.forEach((e, idx, arr) => {
|
||||||
|
let i = 0;
|
||||||
|
for (const filter of filters) {
|
||||||
|
if (filter(e, idx, arr)) {
|
||||||
|
result[i].push(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
result[i].push(e);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
function uniq(array) {
|
||||||
|
return Array.from(new Set(array));
|
||||||
|
}
|
||||||
|
function uniqueBy(array, equalFn) {
|
||||||
|
return array.reduce((acc, cur) => {
|
||||||
|
const index = acc.findIndex((item) => equalFn(cur, item));
|
||||||
|
if (index === -1)
|
||||||
|
acc.push(cur);
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
function last(array) {
|
||||||
|
return at(array, -1);
|
||||||
|
}
|
||||||
|
function remove(array, value) {
|
||||||
|
if (!array)
|
||||||
|
return false;
|
||||||
|
const index = array.indexOf(value);
|
||||||
|
if (index >= 0) {
|
||||||
|
array.splice(index, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function at(array, index) {
|
||||||
|
const len = array.length;
|
||||||
|
if (!len)
|
||||||
|
return void 0;
|
||||||
|
if (index < 0)
|
||||||
|
index += len;
|
||||||
|
return array[index];
|
||||||
|
}
|
||||||
|
function range(...args) {
|
||||||
|
let start, stop, step;
|
||||||
|
if (args.length === 1) {
|
||||||
|
start = 0;
|
||||||
|
step = 1;
|
||||||
|
[stop] = args;
|
||||||
|
} else {
|
||||||
|
[start, stop, step = 1] = args;
|
||||||
|
}
|
||||||
|
const arr = [];
|
||||||
|
let current = start;
|
||||||
|
while (current < stop) {
|
||||||
|
arr.push(current);
|
||||||
|
current += step || 1;
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
function move(arr, from, to) {
|
||||||
|
arr.splice(to, 0, arr.splice(from, 1)[0]);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
function clampArrayRange(n, arr) {
|
||||||
|
return clamp(n, 0, arr.length - 1);
|
||||||
|
}
|
||||||
|
function sample(arr, quantity) {
|
||||||
|
return Array.from({ length: quantity }, (_) => arr[Math.round(Math.random() * (arr.length - 1))]);
|
||||||
|
}
|
||||||
|
function shuffle(array) {
|
||||||
|
for (let i = array.length - 1; i > 0; i--) {
|
||||||
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
|
[array[i], array[j]] = [array[j], array[i]];
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
function assert(condition, message) {
|
||||||
|
if (!condition)
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
const toString = (v) => Object.prototype.toString.call(v);
|
||||||
|
function getTypeName(v) {
|
||||||
|
if (v === null)
|
||||||
|
return "null";
|
||||||
|
const type = toString(v).slice(8, -1).toLowerCase();
|
||||||
|
return typeof v === "object" || typeof v === "function" ? type : typeof v;
|
||||||
|
}
|
||||||
|
function noop() {
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDeepEqual(value1, value2) {
|
||||||
|
const type1 = getTypeName(value1);
|
||||||
|
const type2 = getTypeName(value2);
|
||||||
|
if (type1 !== type2)
|
||||||
|
return false;
|
||||||
|
if (type1 === "array") {
|
||||||
|
if (value1.length !== value2.length)
|
||||||
|
return false;
|
||||||
|
return value1.every((item, i) => {
|
||||||
|
return isDeepEqual(item, value2[i]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (type1 === "object") {
|
||||||
|
const keyArr = Object.keys(value1);
|
||||||
|
if (keyArr.length !== Object.keys(value2).length)
|
||||||
|
return false;
|
||||||
|
return keyArr.every((key) => {
|
||||||
|
return isDeepEqual(value1[key], value2[key]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Object.is(value1, value2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function notNullish(v) {
|
||||||
|
return v != null;
|
||||||
|
}
|
||||||
|
function noNull(v) {
|
||||||
|
return v !== null;
|
||||||
|
}
|
||||||
|
function notUndefined(v) {
|
||||||
|
return v !== void 0;
|
||||||
|
}
|
||||||
|
function isTruthy(v) {
|
||||||
|
return Boolean(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isDef = (val) => typeof val !== "undefined";
|
||||||
|
const isBoolean = (val) => typeof val === "boolean";
|
||||||
|
const isFunction = (val) => typeof val === "function";
|
||||||
|
const isNumber = (val) => typeof val === "number";
|
||||||
|
const isString = (val) => typeof val === "string";
|
||||||
|
const isObject = (val) => toString(val) === "[object Object]";
|
||||||
|
const isUndefined = (val) => toString(val) === "[object Undefined]";
|
||||||
|
const isNull = (val) => toString(val) === "[object Null]";
|
||||||
|
const isRegExp = (val) => toString(val) === "[object RegExp]";
|
||||||
|
const isDate = (val) => toString(val) === "[object Date]";
|
||||||
|
const isWindow = (val) => typeof window !== "undefined" && toString(val) === "[object Window]";
|
||||||
|
const isBrowser = typeof window !== "undefined";
|
||||||
|
|
||||||
|
function slash(str) {
|
||||||
|
return str.replace(/\\/g, "/");
|
||||||
|
}
|
||||||
|
function ensurePrefix(prefix, str) {
|
||||||
|
if (!str.startsWith(prefix))
|
||||||
|
return prefix + str;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
function ensureSuffix(suffix, str) {
|
||||||
|
if (!str.endsWith(suffix))
|
||||||
|
return str + suffix;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
function template(str, ...args) {
|
||||||
|
const [firstArg, fallback] = args;
|
||||||
|
if (isObject(firstArg)) {
|
||||||
|
const vars = firstArg;
|
||||||
|
return str.replace(/{([\w\d]+)}/g, (_, key) => vars[key] || ((typeof fallback === "function" ? fallback(key) : fallback) ?? key));
|
||||||
|
} else {
|
||||||
|
return str.replace(/{(\d+)}/g, (_, key) => {
|
||||||
|
const index = Number(key);
|
||||||
|
if (Number.isNaN(index))
|
||||||
|
return key;
|
||||||
|
return args[index];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
|
||||||
|
function randomStr(size = 16, dict = urlAlphabet) {
|
||||||
|
let id = "";
|
||||||
|
let i = size;
|
||||||
|
const len = dict.length;
|
||||||
|
while (i--)
|
||||||
|
id += dict[Math.random() * len | 0];
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
function capitalize(str) {
|
||||||
|
return str[0].toUpperCase() + str.slice(1).toLowerCase();
|
||||||
|
}
|
||||||
|
const _reFullWs = /^\s*$/;
|
||||||
|
function unindent(str) {
|
||||||
|
const lines = (typeof str === "string" ? str : str[0]).split("\n");
|
||||||
|
const whitespaceLines = lines.map((line) => _reFullWs.test(line));
|
||||||
|
const commonIndent = lines.reduce((min, line, idx) => {
|
||||||
|
var _a;
|
||||||
|
if (whitespaceLines[idx])
|
||||||
|
return min;
|
||||||
|
const indent = (_a = line.match(/^\s*/)) == null ? void 0 : _a[0].length;
|
||||||
|
return indent === void 0 ? min : Math.min(min, indent);
|
||||||
|
}, Number.POSITIVE_INFINITY);
|
||||||
|
let emptyLinesHead = 0;
|
||||||
|
while (emptyLinesHead < lines.length && whitespaceLines[emptyLinesHead])
|
||||||
|
emptyLinesHead++;
|
||||||
|
let emptyLinesTail = 0;
|
||||||
|
while (emptyLinesTail < lines.length && whitespaceLines[lines.length - emptyLinesTail - 1])
|
||||||
|
emptyLinesTail++;
|
||||||
|
return lines.slice(emptyLinesHead, lines.length - emptyLinesTail).map((line) => line.slice(commonIndent)).join("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
const timestamp = () => +Date.now();
|
||||||
|
|
||||||
|
function batchInvoke(functions) {
|
||||||
|
functions.forEach((fn) => fn && fn());
|
||||||
|
}
|
||||||
|
function invoke(fn) {
|
||||||
|
return fn();
|
||||||
|
}
|
||||||
|
function tap(value, callback) {
|
||||||
|
callback(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function objectMap(obj, fn) {
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(obj).map(([k, v]) => fn(k, v)).filter(notNullish)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
function isKeyOf(obj, k) {
|
||||||
|
return k in obj;
|
||||||
|
}
|
||||||
|
function objectKeys(obj) {
|
||||||
|
return Object.keys(obj);
|
||||||
|
}
|
||||||
|
function objectEntries(obj) {
|
||||||
|
return Object.entries(obj);
|
||||||
|
}
|
||||||
|
function deepMerge(target, ...sources) {
|
||||||
|
if (!sources.length)
|
||||||
|
return target;
|
||||||
|
const source = sources.shift();
|
||||||
|
if (source === void 0)
|
||||||
|
return target;
|
||||||
|
if (isMergableObject(target) && isMergableObject(source)) {
|
||||||
|
objectKeys(source).forEach((key) => {
|
||||||
|
if (key === "__proto__" || key === "constructor" || key === "prototype")
|
||||||
|
return;
|
||||||
|
if (isMergableObject(source[key])) {
|
||||||
|
if (!target[key])
|
||||||
|
target[key] = {};
|
||||||
|
if (isMergableObject(target[key])) {
|
||||||
|
deepMerge(target[key], source[key]);
|
||||||
|
} else {
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return deepMerge(target, ...sources);
|
||||||
|
}
|
||||||
|
function deepMergeWithArray(target, ...sources) {
|
||||||
|
if (!sources.length)
|
||||||
|
return target;
|
||||||
|
const source = sources.shift();
|
||||||
|
if (source === void 0)
|
||||||
|
return target;
|
||||||
|
if (Array.isArray(target) && Array.isArray(source))
|
||||||
|
target.push(...source);
|
||||||
|
if (isMergableObject(target) && isMergableObject(source)) {
|
||||||
|
objectKeys(source).forEach((key) => {
|
||||||
|
if (key === "__proto__" || key === "constructor" || key === "prototype")
|
||||||
|
return;
|
||||||
|
if (Array.isArray(source[key])) {
|
||||||
|
if (!target[key])
|
||||||
|
target[key] = [];
|
||||||
|
deepMergeWithArray(target[key], source[key]);
|
||||||
|
} else if (isMergableObject(source[key])) {
|
||||||
|
if (!target[key])
|
||||||
|
target[key] = {};
|
||||||
|
deepMergeWithArray(target[key], source[key]);
|
||||||
|
} else {
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return deepMergeWithArray(target, ...sources);
|
||||||
|
}
|
||||||
|
function isMergableObject(item) {
|
||||||
|
return isObject(item) && !Array.isArray(item);
|
||||||
|
}
|
||||||
|
function objectPick(obj, keys, omitUndefined = false) {
|
||||||
|
return keys.reduce((n, k) => {
|
||||||
|
if (k in obj) {
|
||||||
|
if (!omitUndefined || obj[k] !== void 0)
|
||||||
|
n[k] = obj[k];
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
function clearUndefined(obj) {
|
||||||
|
Object.keys(obj).forEach((key) => obj[key] === void 0 ? delete obj[key] : {});
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
function hasOwnProperty(obj, v) {
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
return Object.prototype.hasOwnProperty.call(obj, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createSingletonPromise(fn) {
|
||||||
|
let _promise;
|
||||||
|
function wrapper() {
|
||||||
|
if (!_promise)
|
||||||
|
_promise = fn();
|
||||||
|
return _promise;
|
||||||
|
}
|
||||||
|
wrapper.reset = async () => {
|
||||||
|
const _prev = _promise;
|
||||||
|
_promise = void 0;
|
||||||
|
if (_prev)
|
||||||
|
await _prev;
|
||||||
|
};
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
function sleep(ms, callback) {
|
||||||
|
return new Promise(
|
||||||
|
(resolve) => setTimeout(async () => {
|
||||||
|
await (callback == null ? void 0 : callback());
|
||||||
|
resolve();
|
||||||
|
}, ms)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
function createPromiseLock() {
|
||||||
|
const locks = [];
|
||||||
|
return {
|
||||||
|
async run(fn) {
|
||||||
|
const p = fn();
|
||||||
|
locks.push(p);
|
||||||
|
try {
|
||||||
|
return await p;
|
||||||
|
} finally {
|
||||||
|
remove(locks, p);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async wait() {
|
||||||
|
await Promise.allSettled(locks);
|
||||||
|
},
|
||||||
|
isWaiting() {
|
||||||
|
return Boolean(locks.length);
|
||||||
|
},
|
||||||
|
clear() {
|
||||||
|
locks.length = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function createControlledPromise() {
|
||||||
|
let resolve, reject;
|
||||||
|
const promise = new Promise((_resolve, _reject) => {
|
||||||
|
resolve = _resolve;
|
||||||
|
reject = _reject;
|
||||||
|
});
|
||||||
|
promise.resolve = resolve;
|
||||||
|
promise.reject = reject;
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-disable no-undefined,no-param-reassign,no-shadow */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throttle execution of a function. Especially useful for rate limiting
|
||||||
|
* execution of handlers on events like resize and scroll.
|
||||||
|
*
|
||||||
|
* @param {number} delay - A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher)
|
||||||
|
* are most useful.
|
||||||
|
* @param {Function} callback - A function to be executed after delay milliseconds. The `this` context and all arguments are passed through,
|
||||||
|
* as-is, to `callback` when the throttled-function is executed.
|
||||||
|
* @param {object} [options] - An object to configure options.
|
||||||
|
* @param {boolean} [options.noTrailing] - Optional, defaults to false. If noTrailing is true, callback will only execute every `delay` milliseconds
|
||||||
|
* while the throttled-function is being called. If noTrailing is false or unspecified, callback will be executed
|
||||||
|
* one final time after the last throttled-function call. (After the throttled-function has not been called for
|
||||||
|
* `delay` milliseconds, the internal counter is reset).
|
||||||
|
* @param {boolean} [options.noLeading] - Optional, defaults to false. If noLeading is false, the first throttled-function call will execute callback
|
||||||
|
* immediately. If noLeading is true, the first the callback execution will be skipped. It should be noted that
|
||||||
|
* callback will never executed if both noLeading = true and noTrailing = true.
|
||||||
|
* @param {boolean} [options.debounceMode] - If `debounceMode` is true (at begin), schedule `clear` to execute after `delay` ms. If `debounceMode` is
|
||||||
|
* false (at end), schedule `callback` to execute after `delay` ms.
|
||||||
|
*
|
||||||
|
* @returns {Function} A new, throttled, function.
|
||||||
|
*/
|
||||||
|
function throttle (delay, callback, options) {
|
||||||
|
var _ref = options || {},
|
||||||
|
_ref$noTrailing = _ref.noTrailing,
|
||||||
|
noTrailing = _ref$noTrailing === void 0 ? false : _ref$noTrailing,
|
||||||
|
_ref$noLeading = _ref.noLeading,
|
||||||
|
noLeading = _ref$noLeading === void 0 ? false : _ref$noLeading,
|
||||||
|
_ref$debounceMode = _ref.debounceMode,
|
||||||
|
debounceMode = _ref$debounceMode === void 0 ? undefined : _ref$debounceMode;
|
||||||
|
/*
|
||||||
|
* After wrapper has stopped being called, this timeout ensures that
|
||||||
|
* `callback` is executed at the proper times in `throttle` and `end`
|
||||||
|
* debounce modes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
var timeoutID;
|
||||||
|
var cancelled = false; // Keep track of the last time `callback` was executed.
|
||||||
|
|
||||||
|
var lastExec = 0; // Function to clear existing timeout
|
||||||
|
|
||||||
|
function clearExistingTimeout() {
|
||||||
|
if (timeoutID) {
|
||||||
|
clearTimeout(timeoutID);
|
||||||
|
}
|
||||||
|
} // Function to cancel next exec
|
||||||
|
|
||||||
|
|
||||||
|
function cancel(options) {
|
||||||
|
var _ref2 = options || {},
|
||||||
|
_ref2$upcomingOnly = _ref2.upcomingOnly,
|
||||||
|
upcomingOnly = _ref2$upcomingOnly === void 0 ? false : _ref2$upcomingOnly;
|
||||||
|
|
||||||
|
clearExistingTimeout();
|
||||||
|
cancelled = !upcomingOnly;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* The `wrapper` function encapsulates all of the throttling / debouncing
|
||||||
|
* functionality and when executed will limit the rate at which `callback`
|
||||||
|
* is executed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
function wrapper() {
|
||||||
|
for (var _len = arguments.length, arguments_ = new Array(_len), _key = 0; _key < _len; _key++) {
|
||||||
|
arguments_[_key] = arguments[_key];
|
||||||
|
}
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
var elapsed = Date.now() - lastExec;
|
||||||
|
|
||||||
|
if (cancelled) {
|
||||||
|
return;
|
||||||
|
} // Execute `callback` and update the `lastExec` timestamp.
|
||||||
|
|
||||||
|
|
||||||
|
function exec() {
|
||||||
|
lastExec = Date.now();
|
||||||
|
callback.apply(self, arguments_);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If `debounceMode` is true (at begin) this is used to clear the flag
|
||||||
|
* to allow future `callback` executions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
function clear() {
|
||||||
|
timeoutID = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!noLeading && debounceMode && !timeoutID) {
|
||||||
|
/*
|
||||||
|
* Since `wrapper` is being called for the first time and
|
||||||
|
* `debounceMode` is true (at begin), execute `callback`
|
||||||
|
* and noLeading != true.
|
||||||
|
*/
|
||||||
|
exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
clearExistingTimeout();
|
||||||
|
|
||||||
|
if (debounceMode === undefined && elapsed > delay) {
|
||||||
|
if (noLeading) {
|
||||||
|
/*
|
||||||
|
* In throttle mode with noLeading, if `delay` time has
|
||||||
|
* been exceeded, update `lastExec` and schedule `callback`
|
||||||
|
* to execute after `delay` ms.
|
||||||
|
*/
|
||||||
|
lastExec = Date.now();
|
||||||
|
|
||||||
|
if (!noTrailing) {
|
||||||
|
timeoutID = setTimeout(debounceMode ? clear : exec, delay);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* In throttle mode without noLeading, if `delay` time has been exceeded, execute
|
||||||
|
* `callback`.
|
||||||
|
*/
|
||||||
|
exec();
|
||||||
|
}
|
||||||
|
} else if (noTrailing !== true) {
|
||||||
|
/*
|
||||||
|
* In trailing throttle mode, since `delay` time has not been
|
||||||
|
* exceeded, schedule `callback` to execute `delay` ms after most
|
||||||
|
* recent execution.
|
||||||
|
*
|
||||||
|
* If `debounceMode` is true (at begin), schedule `clear` to execute
|
||||||
|
* after `delay` ms.
|
||||||
|
*
|
||||||
|
* If `debounceMode` is false (at end), schedule `callback` to
|
||||||
|
* execute after `delay` ms.
|
||||||
|
*/
|
||||||
|
timeoutID = setTimeout(debounceMode ? clear : exec, debounceMode === undefined ? delay - elapsed : delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper.cancel = cancel; // Return the wrapper function.
|
||||||
|
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-disable no-undefined */
|
||||||
|
/**
|
||||||
|
* Debounce execution of a function. Debouncing, unlike throttling,
|
||||||
|
* guarantees that a function is only executed a single time, either at the
|
||||||
|
* very beginning of a series of calls, or at the very end.
|
||||||
|
*
|
||||||
|
* @param {number} delay - A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.
|
||||||
|
* @param {Function} callback - A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is,
|
||||||
|
* to `callback` when the debounced-function is executed.
|
||||||
|
* @param {object} [options] - An object to configure options.
|
||||||
|
* @param {boolean} [options.atBegin] - Optional, defaults to false. If atBegin is false or unspecified, callback will only be executed `delay` milliseconds
|
||||||
|
* after the last debounced-function call. If atBegin is true, callback will be executed only at the first debounced-function call.
|
||||||
|
* (After the throttled-function has not been called for `delay` milliseconds, the internal counter is reset).
|
||||||
|
*
|
||||||
|
* @returns {Function} A new, debounced function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function debounce (delay, callback, options) {
|
||||||
|
var _ref = options || {},
|
||||||
|
_ref$atBegin = _ref.atBegin,
|
||||||
|
atBegin = _ref$atBegin === void 0 ? false : _ref$atBegin;
|
||||||
|
|
||||||
|
return throttle(delay, callback, {
|
||||||
|
debounceMode: atBegin !== false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
How it works:
|
||||||
|
`this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Node {
|
||||||
|
value;
|
||||||
|
next;
|
||||||
|
|
||||||
|
constructor(value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Queue {
|
||||||
|
#head;
|
||||||
|
#tail;
|
||||||
|
#size;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
enqueue(value) {
|
||||||
|
const node = new Node(value);
|
||||||
|
|
||||||
|
if (this.#head) {
|
||||||
|
this.#tail.next = node;
|
||||||
|
this.#tail = node;
|
||||||
|
} else {
|
||||||
|
this.#head = node;
|
||||||
|
this.#tail = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dequeue() {
|
||||||
|
const current = this.#head;
|
||||||
|
if (!current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#head = this.#head.next;
|
||||||
|
this.#size--;
|
||||||
|
return current.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.#head = undefined;
|
||||||
|
this.#tail = undefined;
|
||||||
|
this.#size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get size() {
|
||||||
|
return this.#size;
|
||||||
|
}
|
||||||
|
|
||||||
|
* [Symbol.iterator]() {
|
||||||
|
let current = this.#head;
|
||||||
|
|
||||||
|
while (current) {
|
||||||
|
yield current.value;
|
||||||
|
current = current.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const AsyncResource = {
|
||||||
|
bind(fn, _type, thisArg) {
|
||||||
|
return fn.bind(thisArg);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function pLimit(concurrency) {
|
||||||
|
if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {
|
||||||
|
throw new TypeError('Expected `concurrency` to be a number from 1 and up');
|
||||||
|
}
|
||||||
|
|
||||||
|
const queue = new Queue();
|
||||||
|
let activeCount = 0;
|
||||||
|
|
||||||
|
const next = () => {
|
||||||
|
activeCount--;
|
||||||
|
|
||||||
|
if (queue.size > 0) {
|
||||||
|
queue.dequeue()();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const run = async (function_, resolve, arguments_) => {
|
||||||
|
activeCount++;
|
||||||
|
|
||||||
|
const result = (async () => function_(...arguments_))();
|
||||||
|
|
||||||
|
resolve(result);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await result;
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
|
||||||
|
const enqueue = (function_, resolve, arguments_) => {
|
||||||
|
queue.enqueue(
|
||||||
|
AsyncResource.bind(run.bind(undefined, function_, resolve, arguments_)),
|
||||||
|
);
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
// This function needs to wait until the next microtask before comparing
|
||||||
|
// `activeCount` to `concurrency`, because `activeCount` is updated asynchronously
|
||||||
|
// when the run function is dequeued and called. The comparison in the if-statement
|
||||||
|
// needs to happen asynchronously as well to get an up-to-date value for `activeCount`.
|
||||||
|
await Promise.resolve();
|
||||||
|
|
||||||
|
if (activeCount < concurrency && queue.size > 0) {
|
||||||
|
queue.dequeue()();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
|
||||||
|
const generator = (function_, ...arguments_) => new Promise(resolve => {
|
||||||
|
enqueue(function_, resolve, arguments_);
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperties(generator, {
|
||||||
|
activeCount: {
|
||||||
|
get: () => activeCount,
|
||||||
|
},
|
||||||
|
pendingCount: {
|
||||||
|
get: () => queue.size,
|
||||||
|
},
|
||||||
|
clearQueue: {
|
||||||
|
value() {
|
||||||
|
queue.clear();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return generator;
|
||||||
|
}
|
||||||
|
|
||||||
|
const VOID = Symbol("p-void");
|
||||||
|
class PInstance extends Promise {
|
||||||
|
constructor(items = [], options) {
|
||||||
|
super(() => {
|
||||||
|
});
|
||||||
|
this.items = items;
|
||||||
|
this.options = options;
|
||||||
|
this.promises = /* @__PURE__ */ new Set();
|
||||||
|
}
|
||||||
|
get promise() {
|
||||||
|
var _a;
|
||||||
|
let batch;
|
||||||
|
const items = [...Array.from(this.items), ...Array.from(this.promises)];
|
||||||
|
if ((_a = this.options) == null ? void 0 : _a.concurrency) {
|
||||||
|
const limit = pLimit(this.options.concurrency);
|
||||||
|
batch = Promise.all(items.map((p2) => limit(() => p2)));
|
||||||
|
} else {
|
||||||
|
batch = Promise.all(items);
|
||||||
|
}
|
||||||
|
return batch.then((l) => l.filter((i) => i !== VOID));
|
||||||
|
}
|
||||||
|
add(...args) {
|
||||||
|
args.forEach((i) => {
|
||||||
|
this.promises.add(i);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
map(fn) {
|
||||||
|
return new PInstance(
|
||||||
|
Array.from(this.items).map(async (i, idx) => {
|
||||||
|
const v = await i;
|
||||||
|
if (v === VOID)
|
||||||
|
return VOID;
|
||||||
|
return fn(v, idx);
|
||||||
|
}),
|
||||||
|
this.options
|
||||||
|
);
|
||||||
|
}
|
||||||
|
filter(fn) {
|
||||||
|
return new PInstance(
|
||||||
|
Array.from(this.items).map(async (i, idx) => {
|
||||||
|
const v = await i;
|
||||||
|
const r = await fn(v, idx);
|
||||||
|
if (!r)
|
||||||
|
return VOID;
|
||||||
|
return v;
|
||||||
|
}),
|
||||||
|
this.options
|
||||||
|
);
|
||||||
|
}
|
||||||
|
forEach(fn) {
|
||||||
|
return this.map(fn).then();
|
||||||
|
}
|
||||||
|
reduce(fn, initialValue) {
|
||||||
|
return this.promise.then((array) => array.reduce(fn, initialValue));
|
||||||
|
}
|
||||||
|
clear() {
|
||||||
|
this.promises.clear();
|
||||||
|
}
|
||||||
|
then(fn) {
|
||||||
|
const p2 = this.promise;
|
||||||
|
if (fn)
|
||||||
|
return p2.then(fn);
|
||||||
|
else
|
||||||
|
return p2;
|
||||||
|
}
|
||||||
|
catch(fn) {
|
||||||
|
return this.promise.catch(fn);
|
||||||
|
}
|
||||||
|
finally(fn) {
|
||||||
|
return this.promise.finally(fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function p(items, options) {
|
||||||
|
return new PInstance(items, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.assert = assert;
|
||||||
|
exports.at = at;
|
||||||
|
exports.batchInvoke = batchInvoke;
|
||||||
|
exports.capitalize = capitalize;
|
||||||
|
exports.clamp = clamp;
|
||||||
|
exports.clampArrayRange = clampArrayRange;
|
||||||
|
exports.clearUndefined = clearUndefined;
|
||||||
|
exports.createControlledPromise = createControlledPromise;
|
||||||
|
exports.createPromiseLock = createPromiseLock;
|
||||||
|
exports.createSingletonPromise = createSingletonPromise;
|
||||||
|
exports.debounce = debounce;
|
||||||
|
exports.deepMerge = deepMerge;
|
||||||
|
exports.deepMergeWithArray = deepMergeWithArray;
|
||||||
|
exports.ensurePrefix = ensurePrefix;
|
||||||
|
exports.ensureSuffix = ensureSuffix;
|
||||||
|
exports.flattenArrayable = flattenArrayable;
|
||||||
|
exports.getTypeName = getTypeName;
|
||||||
|
exports.hasOwnProperty = hasOwnProperty;
|
||||||
|
exports.invoke = invoke;
|
||||||
|
exports.isBoolean = isBoolean;
|
||||||
|
exports.isBrowser = isBrowser;
|
||||||
|
exports.isDate = isDate;
|
||||||
|
exports.isDeepEqual = isDeepEqual;
|
||||||
|
exports.isDef = isDef;
|
||||||
|
exports.isFunction = isFunction;
|
||||||
|
exports.isKeyOf = isKeyOf;
|
||||||
|
exports.isNull = isNull;
|
||||||
|
exports.isNumber = isNumber;
|
||||||
|
exports.isObject = isObject;
|
||||||
|
exports.isRegExp = isRegExp;
|
||||||
|
exports.isString = isString;
|
||||||
|
exports.isTruthy = isTruthy;
|
||||||
|
exports.isUndefined = isUndefined;
|
||||||
|
exports.isWindow = isWindow;
|
||||||
|
exports.last = last;
|
||||||
|
exports.lerp = lerp;
|
||||||
|
exports.mergeArrayable = mergeArrayable;
|
||||||
|
exports.move = move;
|
||||||
|
exports.noNull = noNull;
|
||||||
|
exports.noop = noop;
|
||||||
|
exports.notNullish = notNullish;
|
||||||
|
exports.notUndefined = notUndefined;
|
||||||
|
exports.objectEntries = objectEntries;
|
||||||
|
exports.objectKeys = objectKeys;
|
||||||
|
exports.objectMap = objectMap;
|
||||||
|
exports.objectPick = objectPick;
|
||||||
|
exports.p = p;
|
||||||
|
exports.partition = partition;
|
||||||
|
exports.randomStr = randomStr;
|
||||||
|
exports.range = range;
|
||||||
|
exports.remap = remap;
|
||||||
|
exports.remove = remove;
|
||||||
|
exports.sample = sample;
|
||||||
|
exports.shuffle = shuffle;
|
||||||
|
exports.slash = slash;
|
||||||
|
exports.sleep = sleep;
|
||||||
|
exports.sum = sum;
|
||||||
|
exports.tap = tap;
|
||||||
|
exports.template = template;
|
||||||
|
exports.throttle = throttle;
|
||||||
|
exports.timestamp = timestamp;
|
||||||
|
exports.toArray = toArray;
|
||||||
|
exports.toString = toString;
|
||||||
|
exports.unindent = unindent;
|
||||||
|
exports.uniq = uniq;
|
||||||
|
exports.uniqueBy = uniqueBy;
|
@ -0,0 +1,614 @@
|
|||||||
|
/**
|
||||||
|
* Promise, or maybe not
|
||||||
|
*/
|
||||||
|
type Awaitable<T> = T | PromiseLike<T>;
|
||||||
|
/**
|
||||||
|
* Null or whatever
|
||||||
|
*/
|
||||||
|
type Nullable<T> = T | null | undefined;
|
||||||
|
/**
|
||||||
|
* Array, or not yet
|
||||||
|
*/
|
||||||
|
type Arrayable<T> = T | Array<T>;
|
||||||
|
/**
|
||||||
|
* Function
|
||||||
|
*/
|
||||||
|
type Fn<T = void> = () => T;
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
type Constructor<T = void> = new (...args: any[]) => T;
|
||||||
|
/**
|
||||||
|
* Infers the element type of an array
|
||||||
|
*/
|
||||||
|
type ElementOf<T> = T extends (infer E)[] ? E : never;
|
||||||
|
/**
|
||||||
|
* Defines an intersection type of all union items.
|
||||||
|
*
|
||||||
|
* @param U Union of any types that will be intersected.
|
||||||
|
* @returns U items intersected
|
||||||
|
* @see https://stackoverflow.com/a/50375286/9259330
|
||||||
|
*/
|
||||||
|
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
|
||||||
|
/**
|
||||||
|
* Infers the arguments type of a function
|
||||||
|
*/
|
||||||
|
type ArgumentsType<T> = T extends ((...args: infer A) => any) ? A : never;
|
||||||
|
type MergeInsertions<T> = T extends object ? {
|
||||||
|
[K in keyof T]: MergeInsertions<T[K]>;
|
||||||
|
} : T;
|
||||||
|
type DeepMerge<F, S> = MergeInsertions<{
|
||||||
|
[K in keyof F | keyof S]: K extends keyof S & keyof F ? DeepMerge<F[K], S[K]> : K extends keyof S ? S[K] : K extends keyof F ? F[K] : never;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert `Arrayable<T>` to `Array<T>`
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function toArray<T>(array?: Nullable<Arrayable<T>>): Array<T>;
|
||||||
|
/**
|
||||||
|
* Convert `Arrayable<T>` to `Array<T>` and flatten it
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function flattenArrayable<T>(array?: Nullable<Arrayable<T | Array<T>>>): Array<T>;
|
||||||
|
/**
|
||||||
|
* Use rest arguments to merge arrays
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function mergeArrayable<T>(...args: Nullable<Arrayable<T>>[]): Array<T>;
|
||||||
|
type PartitionFilter<T> = (i: T, idx: number, arr: readonly T[]) => any;
|
||||||
|
/**
|
||||||
|
* Divide an array into two parts by a filter function
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
* @example const [odd, even] = partition([1, 2, 3, 4], i => i % 2 != 0)
|
||||||
|
*/
|
||||||
|
declare function partition<T>(array: readonly T[], f1: PartitionFilter<T>): [T[], T[]];
|
||||||
|
declare function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>): [T[], T[], T[]];
|
||||||
|
declare function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>, f3: PartitionFilter<T>): [T[], T[], T[], T[]];
|
||||||
|
declare function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>, f3: PartitionFilter<T>, f4: PartitionFilter<T>): [T[], T[], T[], T[], T[]];
|
||||||
|
declare function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>, f3: PartitionFilter<T>, f4: PartitionFilter<T>, f5: PartitionFilter<T>): [T[], T[], T[], T[], T[], T[]];
|
||||||
|
declare function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>, f3: PartitionFilter<T>, f4: PartitionFilter<T>, f5: PartitionFilter<T>, f6: PartitionFilter<T>): [T[], T[], T[], T[], T[], T[], T[]];
|
||||||
|
/**
|
||||||
|
* Unique an Array
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function uniq<T>(array: readonly T[]): T[];
|
||||||
|
/**
|
||||||
|
* Unique an Array by a custom equality function
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function uniqueBy<T>(array: readonly T[], equalFn: (a: any, b: any) => boolean): T[];
|
||||||
|
/**
|
||||||
|
* Get last item
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function last(array: readonly []): undefined;
|
||||||
|
declare function last<T>(array: readonly T[]): T;
|
||||||
|
/**
|
||||||
|
* Remove an item from Array
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function remove<T>(array: T[], value: T): boolean;
|
||||||
|
/**
|
||||||
|
* Get nth item of Array. Negative for backward
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function at(array: readonly [], index: number): undefined;
|
||||||
|
declare function at<T>(array: readonly T[], index: number): T;
|
||||||
|
/**
|
||||||
|
* Genrate a range array of numbers. The `stop` is exclusive.
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function range(stop: number): number[];
|
||||||
|
declare function range(start: number, stop: number, step?: number): number[];
|
||||||
|
/**
|
||||||
|
* Move element in an Array
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
* @param arr
|
||||||
|
* @param from
|
||||||
|
* @param to
|
||||||
|
*/
|
||||||
|
declare function move<T>(arr: T[], from: number, to: number): T[];
|
||||||
|
/**
|
||||||
|
* Clamp a number to the index range of an array
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function clampArrayRange(n: number, arr: readonly unknown[]): number;
|
||||||
|
/**
|
||||||
|
* Get random item(s) from an array
|
||||||
|
*
|
||||||
|
* @param arr
|
||||||
|
* @param quantity - quantity of random items which will be returned
|
||||||
|
*/
|
||||||
|
declare function sample<T>(arr: T[], quantity: number): T[];
|
||||||
|
/**
|
||||||
|
* Shuffle an array. This function mutates the array.
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function shuffle<T>(array: T[]): T[];
|
||||||
|
|
||||||
|
declare function assert(condition: boolean, message: string): asserts condition;
|
||||||
|
declare const toString: (v: any) => string;
|
||||||
|
declare function getTypeName(v: any): string;
|
||||||
|
declare function noop(): void;
|
||||||
|
|
||||||
|
declare function isDeepEqual(value1: any, value2: any): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type guard to filter out null-ish values
|
||||||
|
*
|
||||||
|
* @category Guards
|
||||||
|
* @example array.filter(notNullish)
|
||||||
|
*/
|
||||||
|
declare function notNullish<T>(v: T | null | undefined): v is NonNullable<T>;
|
||||||
|
/**
|
||||||
|
* Type guard to filter out null values
|
||||||
|
*
|
||||||
|
* @category Guards
|
||||||
|
* @example array.filter(noNull)
|
||||||
|
*/
|
||||||
|
declare function noNull<T>(v: T | null): v is Exclude<T, null>;
|
||||||
|
/**
|
||||||
|
* Type guard to filter out null-ish values
|
||||||
|
*
|
||||||
|
* @category Guards
|
||||||
|
* @example array.filter(notUndefined)
|
||||||
|
*/
|
||||||
|
declare function notUndefined<T>(v: T): v is Exclude<T, undefined>;
|
||||||
|
/**
|
||||||
|
* Type guard to filter out falsy values
|
||||||
|
*
|
||||||
|
* @category Guards
|
||||||
|
* @example array.filter(isTruthy)
|
||||||
|
*/
|
||||||
|
declare function isTruthy<T>(v: T): v is NonNullable<T>;
|
||||||
|
|
||||||
|
declare const isDef: <T = any>(val?: T) => val is T;
|
||||||
|
declare const isBoolean: (val: any) => val is boolean;
|
||||||
|
declare const isFunction: <T extends Function>(val: any) => val is T;
|
||||||
|
declare const isNumber: (val: any) => val is number;
|
||||||
|
declare const isString: (val: unknown) => val is string;
|
||||||
|
declare const isObject: (val: any) => val is object;
|
||||||
|
declare const isUndefined: (val: any) => val is undefined;
|
||||||
|
declare const isNull: (val: any) => val is null;
|
||||||
|
declare const isRegExp: (val: any) => val is RegExp;
|
||||||
|
declare const isDate: (val: any) => val is Date;
|
||||||
|
declare const isWindow: (val: any) => boolean;
|
||||||
|
declare const isBrowser: boolean;
|
||||||
|
|
||||||
|
declare function clamp(n: number, min: number, max: number): number;
|
||||||
|
declare function sum(...args: number[] | number[][]): number;
|
||||||
|
/**
|
||||||
|
* Linearly interpolates between `min` and `max` based on `t`
|
||||||
|
*
|
||||||
|
* @category Math
|
||||||
|
* @param min The minimum value
|
||||||
|
* @param max The maximum value
|
||||||
|
* @param t The interpolation value clamped between 0 and 1
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* const value = lerp(0, 2, 0.5) // value will be 1
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function lerp(min: number, max: number, t: number): number;
|
||||||
|
/**
|
||||||
|
* Linearly remaps a clamped value from its source range [`inMin`, `inMax`] to the destination range [`outMin`, `outMax`]
|
||||||
|
*
|
||||||
|
* @category Math
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* const value = remap(0.5, 0, 1, 200, 400) // value will be 300
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function remap(n: number, inMin: number, inMax: number, outMin: number, outMax: number): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace backslash to slash
|
||||||
|
*
|
||||||
|
* @category String
|
||||||
|
*/
|
||||||
|
declare function slash(str: string): string;
|
||||||
|
/**
|
||||||
|
* Ensure prefix of a string
|
||||||
|
*
|
||||||
|
* @category String
|
||||||
|
*/
|
||||||
|
declare function ensurePrefix(prefix: string, str: string): string;
|
||||||
|
/**
|
||||||
|
* Ensure suffix of a string
|
||||||
|
*
|
||||||
|
* @category String
|
||||||
|
*/
|
||||||
|
declare function ensureSuffix(suffix: string, str: string): string;
|
||||||
|
/**
|
||||||
|
* Dead simple template engine, just like Python's `.format()`
|
||||||
|
* Support passing variables as either in index based or object/name based approach
|
||||||
|
* While using object/name based approach, you can pass a fallback value as the third argument
|
||||||
|
*
|
||||||
|
* @category String
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* const result = template(
|
||||||
|
* 'Hello {0}! My name is {1}.',
|
||||||
|
* 'Inès',
|
||||||
|
* 'Anthony'
|
||||||
|
* ) // Hello Inès! My name is Anthony.
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* const result = namedTemplate(
|
||||||
|
* '{greet}! My name is {name}.',
|
||||||
|
* { greet: 'Hello', name: 'Anthony' }
|
||||||
|
* ) // Hello! My name is Anthony.
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* const result = namedTemplate(
|
||||||
|
* '{greet}! My name is {name}.',
|
||||||
|
* { greet: 'Hello' }, // name isn't passed hence fallback will be used for name
|
||||||
|
* 'placeholder'
|
||||||
|
* ) // Hello! My name is placeholder.
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function template(str: string, object: Record<string | number, any>, fallback?: string | ((key: string) => string)): string;
|
||||||
|
declare function template(str: string, ...args: (string | number | bigint | undefined | null)[]): string;
|
||||||
|
/**
|
||||||
|
* Generate a random string
|
||||||
|
* @category String
|
||||||
|
*/
|
||||||
|
declare function randomStr(size?: number, dict?: string): string;
|
||||||
|
/**
|
||||||
|
* First letter uppercase, other lowercase
|
||||||
|
* @category string
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* capitalize('hello') => 'Hello'
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function capitalize(str: string): string;
|
||||||
|
/**
|
||||||
|
* Remove common leading whitespace from a template string.
|
||||||
|
* Will also remove empty lines at the beginning and end.
|
||||||
|
* @category string
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* const str = unindent`
|
||||||
|
* if (a) {
|
||||||
|
* b()
|
||||||
|
* }
|
||||||
|
* `
|
||||||
|
*/
|
||||||
|
declare function unindent(str: TemplateStringsArray | string): string;
|
||||||
|
|
||||||
|
declare const timestamp: () => number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call every function in an array
|
||||||
|
*/
|
||||||
|
declare function batchInvoke(functions: Nullable<Fn>[]): void;
|
||||||
|
/**
|
||||||
|
* Call the function
|
||||||
|
*/
|
||||||
|
declare function invoke(fn: Fn): void;
|
||||||
|
/**
|
||||||
|
* Pass the value through the callback, and return the value
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* function createUser(name: string): User {
|
||||||
|
* return tap(new User, user => {
|
||||||
|
* user.name = name
|
||||||
|
* })
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function tap<T>(value: T, callback: (value: T) => void): T;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map key/value pairs for an object, and construct a new one
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*
|
||||||
|
* Transform:
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* objectMap({ a: 1, b: 2 }, (k, v) => [k.toString().toUpperCase(), v.toString()])
|
||||||
|
* // { A: '1', B: '2' }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Swap key/value:
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* objectMap({ a: 1, b: 2 }, (k, v) => [v, k])
|
||||||
|
* // { 1: 'a', 2: 'b' }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Filter keys:
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* objectMap({ a: 1, b: 2 }, (k, v) => k === 'a' ? undefined : [k, v])
|
||||||
|
* // { b: 2 }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function objectMap<K extends string, V, NK extends string | number | symbol = K, NV = V>(obj: Record<K, V>, fn: (key: K, value: V) => [NK, NV] | undefined): Record<NK, NV>;
|
||||||
|
/**
|
||||||
|
* Type guard for any key, `k`.
|
||||||
|
* Marks `k` as a key of `T` if `k` is in `obj`.
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
* @param obj object to query for key `k`
|
||||||
|
* @param k key to check existence in `obj`
|
||||||
|
*/
|
||||||
|
declare function isKeyOf<T extends object>(obj: T, k: keyof any): k is keyof T;
|
||||||
|
/**
|
||||||
|
* Strict typed `Object.keys`
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function objectKeys<T extends object>(obj: T): (`${keyof T & undefined}` | `${keyof T & null}` | `${keyof T & string}` | `${keyof T & number}` | `${keyof T & false}` | `${keyof T & true}`)[];
|
||||||
|
/**
|
||||||
|
* Strict typed `Object.entries`
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function objectEntries<T extends object>(obj: T): [keyof T, T[keyof T]][];
|
||||||
|
/**
|
||||||
|
* Deep merge
|
||||||
|
*
|
||||||
|
* The first argument is the target object, the rest are the sources.
|
||||||
|
* The target object will be mutated and returned.
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function deepMerge<T extends object = object, S extends object = T>(target: T, ...sources: S[]): DeepMerge<T, S>;
|
||||||
|
/**
|
||||||
|
* Deep merge
|
||||||
|
*
|
||||||
|
* Differs from `deepMerge` in that it merges arrays instead of overriding them.
|
||||||
|
*
|
||||||
|
* The first argument is the target object, the rest are the sources.
|
||||||
|
* The target object will be mutated and returned.
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function deepMergeWithArray<T extends object = object, S extends object = T>(target: T, ...sources: S[]): DeepMerge<T, S>;
|
||||||
|
/**
|
||||||
|
* Create a new subset object by giving keys
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function objectPick<O extends object, T extends keyof O>(obj: O, keys: T[], omitUndefined?: boolean): Pick<O, T>;
|
||||||
|
/**
|
||||||
|
* Clear undefined fields from an object. It mutates the object
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function clearUndefined<T extends object>(obj: T): T;
|
||||||
|
/**
|
||||||
|
* Determines whether an object has a property with the specified name
|
||||||
|
*
|
||||||
|
* @see https://eslint.org/docs/rules/no-prototype-builtins
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function hasOwnProperty<T>(obj: T, v: PropertyKey): boolean;
|
||||||
|
|
||||||
|
interface SingletonPromiseReturn<T> {
|
||||||
|
(): Promise<T>;
|
||||||
|
/**
|
||||||
|
* Reset current staled promise.
|
||||||
|
* Await it to have proper shutdown.
|
||||||
|
*/
|
||||||
|
reset: () => Promise<void>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create singleton promise function
|
||||||
|
*
|
||||||
|
* @category Promise
|
||||||
|
*/
|
||||||
|
declare function createSingletonPromise<T>(fn: () => Promise<T>): SingletonPromiseReturn<T>;
|
||||||
|
/**
|
||||||
|
* Promised `setTimeout`
|
||||||
|
*
|
||||||
|
* @category Promise
|
||||||
|
*/
|
||||||
|
declare function sleep(ms: number, callback?: Fn<any>): Promise<void>;
|
||||||
|
/**
|
||||||
|
* Create a promise lock
|
||||||
|
*
|
||||||
|
* @category Promise
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* const lock = createPromiseLock()
|
||||||
|
*
|
||||||
|
* lock.run(async () => {
|
||||||
|
* await doSomething()
|
||||||
|
* })
|
||||||
|
*
|
||||||
|
* // in anther context:
|
||||||
|
* await lock.wait() // it will wait all tasking finished
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function createPromiseLock(): {
|
||||||
|
run<T = void>(fn: () => Promise<T>): Promise<T>;
|
||||||
|
wait(): Promise<void>;
|
||||||
|
isWaiting(): boolean;
|
||||||
|
clear(): void;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Promise with `resolve` and `reject` methods of itself
|
||||||
|
*/
|
||||||
|
interface ControlledPromise<T = void> extends Promise<T> {
|
||||||
|
resolve: (value: T | PromiseLike<T>) => void;
|
||||||
|
reject: (reason?: any) => void;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Return a Promise with `resolve` and `reject` methods
|
||||||
|
*
|
||||||
|
* @category Promise
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* const promise = createControlledPromise()
|
||||||
|
*
|
||||||
|
* await promise
|
||||||
|
*
|
||||||
|
* // in anther context:
|
||||||
|
* promise.resolve(data)
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function createControlledPromise<T>(): ControlledPromise<T>;
|
||||||
|
|
||||||
|
interface CancelOptions {
|
||||||
|
upcomingOnly?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Cancel {
|
||||||
|
cancel: (options?: CancelOptions) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NoReturn<T extends (...args: any[]) => any> {
|
||||||
|
(...args: Parameters<T>): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ThrottleOptions {
|
||||||
|
noTrailing?: boolean;
|
||||||
|
noLeading?: boolean;
|
||||||
|
debounceMode?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DebounceOptions {
|
||||||
|
atBegin?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
type throttle<T extends (...args: any[]) => any> = NoReturn<T> & Cancel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throttle execution of a function. Especially useful for rate limiting
|
||||||
|
* execution of handlers on events like resize and scroll.
|
||||||
|
*
|
||||||
|
* @param delay
|
||||||
|
* A zero-or-greater delay in milliseconds. For event callbacks, values around
|
||||||
|
* 100 or 250 (or even higher) are most useful.
|
||||||
|
*
|
||||||
|
* @param callback
|
||||||
|
* A function to be executed after delay milliseconds. The `this` context and
|
||||||
|
* all arguments are passed through, as-is, to `callback` when the
|
||||||
|
* throttled-function is executed.
|
||||||
|
*
|
||||||
|
* @param options
|
||||||
|
* An object to configure options.
|
||||||
|
*
|
||||||
|
* @param options.noTrailing
|
||||||
|
* Optional, defaults to false. If noTrailing is true, callback will only execute
|
||||||
|
* every `delay` milliseconds while the throttled-function is being called. If
|
||||||
|
* noTrailing is false or unspecified, callback will be executed one final time
|
||||||
|
* after the last throttled-function call. (After the throttled-function has not
|
||||||
|
* been called for `delay` milliseconds, the internal counter is reset)
|
||||||
|
*
|
||||||
|
* @param options.noLeading
|
||||||
|
* Optional, defaults to false. If noLeading is false, the first throttled-function
|
||||||
|
* call will execute callback immediately. If noLeading is true, the first the
|
||||||
|
* callback execution will be skipped. It should be noted that callback will never
|
||||||
|
* executed if both noLeading = true and noTrailing = true.
|
||||||
|
*
|
||||||
|
* @param options.debounceMode If `debounceMode` is true (at begin), schedule
|
||||||
|
* `callback` to execute after `delay` ms. If `debounceMode` is false (at end),
|
||||||
|
* schedule `callback` to execute after `delay` ms.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new, throttled, function.
|
||||||
|
*/
|
||||||
|
declare function throttle<T extends (...args: any[]) => any>(
|
||||||
|
delay: number,
|
||||||
|
callback: T,
|
||||||
|
options?: ThrottleOptions,
|
||||||
|
): throttle<T>;
|
||||||
|
type debounce<T extends (...args: any[]) => any> = NoReturn<T> & Cancel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debounce execution of a function. Debouncing, unlike throttling,
|
||||||
|
* guarantees that a function is only executed a single time, either at the
|
||||||
|
* very beginning of a series of calls, or at the very end.
|
||||||
|
*
|
||||||
|
* @param delay
|
||||||
|
* A zero-or-greater delay in milliseconds. For event callbacks, values around
|
||||||
|
* 100 or 250 (or even higher) are most useful.
|
||||||
|
*
|
||||||
|
* @param callback
|
||||||
|
* A function to be executed after delay milliseconds. The `this` context and
|
||||||
|
* all arguments are passed through, as-is, to `callback` when the
|
||||||
|
* debounced-function is executed.
|
||||||
|
*
|
||||||
|
* @param options
|
||||||
|
* An object to configure options.
|
||||||
|
*
|
||||||
|
* @param options.atBegin
|
||||||
|
* If atBegin is false or unspecified, callback will only be executed `delay`
|
||||||
|
* milliseconds after the last debounced-function call. If atBegin is true,
|
||||||
|
* callback will be executed only at the first debounced-function call. (After
|
||||||
|
* the throttled-function has not been called for `delay` milliseconds, the
|
||||||
|
* internal counter is reset).
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new, debounced function.
|
||||||
|
*/
|
||||||
|
declare function debounce<T extends (...args: any[]) => any>(
|
||||||
|
delay: number,
|
||||||
|
callback: T,
|
||||||
|
options?: DebounceOptions,
|
||||||
|
): debounce<T>;
|
||||||
|
|
||||||
|
interface POptions {
|
||||||
|
/**
|
||||||
|
* How many promises are resolved at the same time.
|
||||||
|
*/
|
||||||
|
concurrency?: number | undefined;
|
||||||
|
}
|
||||||
|
declare class PInstance<T = any> extends Promise<Awaited<T>[]> {
|
||||||
|
items: Iterable<T>;
|
||||||
|
options?: POptions | undefined;
|
||||||
|
private promises;
|
||||||
|
get promise(): Promise<Awaited<T>[]>;
|
||||||
|
constructor(items?: Iterable<T>, options?: POptions | undefined);
|
||||||
|
add(...args: (T | Promise<T>)[]): void;
|
||||||
|
map<U>(fn: (value: Awaited<T>, index: number) => U): PInstance<Promise<U>>;
|
||||||
|
filter(fn: (value: Awaited<T>, index: number) => boolean | Promise<boolean>): PInstance<Promise<T>>;
|
||||||
|
forEach(fn: (value: Awaited<T>, index: number) => void): Promise<void>;
|
||||||
|
reduce<U>(fn: (previousValue: U, currentValue: Awaited<T>, currentIndex: number, array: Awaited<T>[]) => U, initialValue: U): Promise<U>;
|
||||||
|
clear(): void;
|
||||||
|
then(fn?: () => PromiseLike<any>): Promise<any>;
|
||||||
|
catch(fn?: (err: unknown) => PromiseLike<any>): Promise<any>;
|
||||||
|
finally(fn?: () => void): Promise<Awaited<T>[]>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Utility for managing multiple promises.
|
||||||
|
*
|
||||||
|
* @see https://github.com/antfu/utils/tree/main/docs/p.md
|
||||||
|
* @category Promise
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* import { p } from '@antfu/utils'
|
||||||
|
*
|
||||||
|
* const items = [1, 2, 3, 4, 5]
|
||||||
|
*
|
||||||
|
* await p(items)
|
||||||
|
* .map(async i => await multiply(i, 3))
|
||||||
|
* .filter(async i => await isEven(i))
|
||||||
|
* // [6, 12]
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function p<T = any>(items?: Iterable<T>, options?: POptions): PInstance<T>;
|
||||||
|
|
||||||
|
export { type ArgumentsType, type Arrayable, type Awaitable, type Constructor, type ControlledPromise, type DeepMerge, type ElementOf, type Fn, type MergeInsertions, type Nullable, type PartitionFilter, type SingletonPromiseReturn, type UnionToIntersection, assert, at, batchInvoke, capitalize, clamp, clampArrayRange, clearUndefined, createControlledPromise, createPromiseLock, createSingletonPromise, debounce, deepMerge, deepMergeWithArray, ensurePrefix, ensureSuffix, flattenArrayable, getTypeName, hasOwnProperty, invoke, isBoolean, isBrowser, isDate, isDeepEqual, isDef, isFunction, isKeyOf, isNull, isNumber, isObject, isRegExp, isString, isTruthy, isUndefined, isWindow, last, lerp, mergeArrayable, move, noNull, noop, notNullish, notUndefined, objectEntries, objectKeys, objectMap, objectPick, p, partition, randomStr, range, remap, remove, sample, shuffle, slash, sleep, sum, tap, template, throttle, timestamp, toArray, toString, unindent, uniq, uniqueBy };
|
@ -0,0 +1,614 @@
|
|||||||
|
/**
|
||||||
|
* Promise, or maybe not
|
||||||
|
*/
|
||||||
|
type Awaitable<T> = T | PromiseLike<T>;
|
||||||
|
/**
|
||||||
|
* Null or whatever
|
||||||
|
*/
|
||||||
|
type Nullable<T> = T | null | undefined;
|
||||||
|
/**
|
||||||
|
* Array, or not yet
|
||||||
|
*/
|
||||||
|
type Arrayable<T> = T | Array<T>;
|
||||||
|
/**
|
||||||
|
* Function
|
||||||
|
*/
|
||||||
|
type Fn<T = void> = () => T;
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
type Constructor<T = void> = new (...args: any[]) => T;
|
||||||
|
/**
|
||||||
|
* Infers the element type of an array
|
||||||
|
*/
|
||||||
|
type ElementOf<T> = T extends (infer E)[] ? E : never;
|
||||||
|
/**
|
||||||
|
* Defines an intersection type of all union items.
|
||||||
|
*
|
||||||
|
* @param U Union of any types that will be intersected.
|
||||||
|
* @returns U items intersected
|
||||||
|
* @see https://stackoverflow.com/a/50375286/9259330
|
||||||
|
*/
|
||||||
|
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
|
||||||
|
/**
|
||||||
|
* Infers the arguments type of a function
|
||||||
|
*/
|
||||||
|
type ArgumentsType<T> = T extends ((...args: infer A) => any) ? A : never;
|
||||||
|
type MergeInsertions<T> = T extends object ? {
|
||||||
|
[K in keyof T]: MergeInsertions<T[K]>;
|
||||||
|
} : T;
|
||||||
|
type DeepMerge<F, S> = MergeInsertions<{
|
||||||
|
[K in keyof F | keyof S]: K extends keyof S & keyof F ? DeepMerge<F[K], S[K]> : K extends keyof S ? S[K] : K extends keyof F ? F[K] : never;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert `Arrayable<T>` to `Array<T>`
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function toArray<T>(array?: Nullable<Arrayable<T>>): Array<T>;
|
||||||
|
/**
|
||||||
|
* Convert `Arrayable<T>` to `Array<T>` and flatten it
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function flattenArrayable<T>(array?: Nullable<Arrayable<T | Array<T>>>): Array<T>;
|
||||||
|
/**
|
||||||
|
* Use rest arguments to merge arrays
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function mergeArrayable<T>(...args: Nullable<Arrayable<T>>[]): Array<T>;
|
||||||
|
type PartitionFilter<T> = (i: T, idx: number, arr: readonly T[]) => any;
|
||||||
|
/**
|
||||||
|
* Divide an array into two parts by a filter function
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
* @example const [odd, even] = partition([1, 2, 3, 4], i => i % 2 != 0)
|
||||||
|
*/
|
||||||
|
declare function partition<T>(array: readonly T[], f1: PartitionFilter<T>): [T[], T[]];
|
||||||
|
declare function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>): [T[], T[], T[]];
|
||||||
|
declare function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>, f3: PartitionFilter<T>): [T[], T[], T[], T[]];
|
||||||
|
declare function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>, f3: PartitionFilter<T>, f4: PartitionFilter<T>): [T[], T[], T[], T[], T[]];
|
||||||
|
declare function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>, f3: PartitionFilter<T>, f4: PartitionFilter<T>, f5: PartitionFilter<T>): [T[], T[], T[], T[], T[], T[]];
|
||||||
|
declare function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>, f3: PartitionFilter<T>, f4: PartitionFilter<T>, f5: PartitionFilter<T>, f6: PartitionFilter<T>): [T[], T[], T[], T[], T[], T[], T[]];
|
||||||
|
/**
|
||||||
|
* Unique an Array
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function uniq<T>(array: readonly T[]): T[];
|
||||||
|
/**
|
||||||
|
* Unique an Array by a custom equality function
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function uniqueBy<T>(array: readonly T[], equalFn: (a: any, b: any) => boolean): T[];
|
||||||
|
/**
|
||||||
|
* Get last item
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function last(array: readonly []): undefined;
|
||||||
|
declare function last<T>(array: readonly T[]): T;
|
||||||
|
/**
|
||||||
|
* Remove an item from Array
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function remove<T>(array: T[], value: T): boolean;
|
||||||
|
/**
|
||||||
|
* Get nth item of Array. Negative for backward
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function at(array: readonly [], index: number): undefined;
|
||||||
|
declare function at<T>(array: readonly T[], index: number): T;
|
||||||
|
/**
|
||||||
|
* Genrate a range array of numbers. The `stop` is exclusive.
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function range(stop: number): number[];
|
||||||
|
declare function range(start: number, stop: number, step?: number): number[];
|
||||||
|
/**
|
||||||
|
* Move element in an Array
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
* @param arr
|
||||||
|
* @param from
|
||||||
|
* @param to
|
||||||
|
*/
|
||||||
|
declare function move<T>(arr: T[], from: number, to: number): T[];
|
||||||
|
/**
|
||||||
|
* Clamp a number to the index range of an array
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function clampArrayRange(n: number, arr: readonly unknown[]): number;
|
||||||
|
/**
|
||||||
|
* Get random item(s) from an array
|
||||||
|
*
|
||||||
|
* @param arr
|
||||||
|
* @param quantity - quantity of random items which will be returned
|
||||||
|
*/
|
||||||
|
declare function sample<T>(arr: T[], quantity: number): T[];
|
||||||
|
/**
|
||||||
|
* Shuffle an array. This function mutates the array.
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function shuffle<T>(array: T[]): T[];
|
||||||
|
|
||||||
|
declare function assert(condition: boolean, message: string): asserts condition;
|
||||||
|
declare const toString: (v: any) => string;
|
||||||
|
declare function getTypeName(v: any): string;
|
||||||
|
declare function noop(): void;
|
||||||
|
|
||||||
|
declare function isDeepEqual(value1: any, value2: any): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type guard to filter out null-ish values
|
||||||
|
*
|
||||||
|
* @category Guards
|
||||||
|
* @example array.filter(notNullish)
|
||||||
|
*/
|
||||||
|
declare function notNullish<T>(v: T | null | undefined): v is NonNullable<T>;
|
||||||
|
/**
|
||||||
|
* Type guard to filter out null values
|
||||||
|
*
|
||||||
|
* @category Guards
|
||||||
|
* @example array.filter(noNull)
|
||||||
|
*/
|
||||||
|
declare function noNull<T>(v: T | null): v is Exclude<T, null>;
|
||||||
|
/**
|
||||||
|
* Type guard to filter out null-ish values
|
||||||
|
*
|
||||||
|
* @category Guards
|
||||||
|
* @example array.filter(notUndefined)
|
||||||
|
*/
|
||||||
|
declare function notUndefined<T>(v: T): v is Exclude<T, undefined>;
|
||||||
|
/**
|
||||||
|
* Type guard to filter out falsy values
|
||||||
|
*
|
||||||
|
* @category Guards
|
||||||
|
* @example array.filter(isTruthy)
|
||||||
|
*/
|
||||||
|
declare function isTruthy<T>(v: T): v is NonNullable<T>;
|
||||||
|
|
||||||
|
declare const isDef: <T = any>(val?: T) => val is T;
|
||||||
|
declare const isBoolean: (val: any) => val is boolean;
|
||||||
|
declare const isFunction: <T extends Function>(val: any) => val is T;
|
||||||
|
declare const isNumber: (val: any) => val is number;
|
||||||
|
declare const isString: (val: unknown) => val is string;
|
||||||
|
declare const isObject: (val: any) => val is object;
|
||||||
|
declare const isUndefined: (val: any) => val is undefined;
|
||||||
|
declare const isNull: (val: any) => val is null;
|
||||||
|
declare const isRegExp: (val: any) => val is RegExp;
|
||||||
|
declare const isDate: (val: any) => val is Date;
|
||||||
|
declare const isWindow: (val: any) => boolean;
|
||||||
|
declare const isBrowser: boolean;
|
||||||
|
|
||||||
|
declare function clamp(n: number, min: number, max: number): number;
|
||||||
|
declare function sum(...args: number[] | number[][]): number;
|
||||||
|
/**
|
||||||
|
* Linearly interpolates between `min` and `max` based on `t`
|
||||||
|
*
|
||||||
|
* @category Math
|
||||||
|
* @param min The minimum value
|
||||||
|
* @param max The maximum value
|
||||||
|
* @param t The interpolation value clamped between 0 and 1
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* const value = lerp(0, 2, 0.5) // value will be 1
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function lerp(min: number, max: number, t: number): number;
|
||||||
|
/**
|
||||||
|
* Linearly remaps a clamped value from its source range [`inMin`, `inMax`] to the destination range [`outMin`, `outMax`]
|
||||||
|
*
|
||||||
|
* @category Math
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* const value = remap(0.5, 0, 1, 200, 400) // value will be 300
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function remap(n: number, inMin: number, inMax: number, outMin: number, outMax: number): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace backslash to slash
|
||||||
|
*
|
||||||
|
* @category String
|
||||||
|
*/
|
||||||
|
declare function slash(str: string): string;
|
||||||
|
/**
|
||||||
|
* Ensure prefix of a string
|
||||||
|
*
|
||||||
|
* @category String
|
||||||
|
*/
|
||||||
|
declare function ensurePrefix(prefix: string, str: string): string;
|
||||||
|
/**
|
||||||
|
* Ensure suffix of a string
|
||||||
|
*
|
||||||
|
* @category String
|
||||||
|
*/
|
||||||
|
declare function ensureSuffix(suffix: string, str: string): string;
|
||||||
|
/**
|
||||||
|
* Dead simple template engine, just like Python's `.format()`
|
||||||
|
* Support passing variables as either in index based or object/name based approach
|
||||||
|
* While using object/name based approach, you can pass a fallback value as the third argument
|
||||||
|
*
|
||||||
|
* @category String
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* const result = template(
|
||||||
|
* 'Hello {0}! My name is {1}.',
|
||||||
|
* 'Inès',
|
||||||
|
* 'Anthony'
|
||||||
|
* ) // Hello Inès! My name is Anthony.
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* const result = namedTemplate(
|
||||||
|
* '{greet}! My name is {name}.',
|
||||||
|
* { greet: 'Hello', name: 'Anthony' }
|
||||||
|
* ) // Hello! My name is Anthony.
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* const result = namedTemplate(
|
||||||
|
* '{greet}! My name is {name}.',
|
||||||
|
* { greet: 'Hello' }, // name isn't passed hence fallback will be used for name
|
||||||
|
* 'placeholder'
|
||||||
|
* ) // Hello! My name is placeholder.
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function template(str: string, object: Record<string | number, any>, fallback?: string | ((key: string) => string)): string;
|
||||||
|
declare function template(str: string, ...args: (string | number | bigint | undefined | null)[]): string;
|
||||||
|
/**
|
||||||
|
* Generate a random string
|
||||||
|
* @category String
|
||||||
|
*/
|
||||||
|
declare function randomStr(size?: number, dict?: string): string;
|
||||||
|
/**
|
||||||
|
* First letter uppercase, other lowercase
|
||||||
|
* @category string
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* capitalize('hello') => 'Hello'
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function capitalize(str: string): string;
|
||||||
|
/**
|
||||||
|
* Remove common leading whitespace from a template string.
|
||||||
|
* Will also remove empty lines at the beginning and end.
|
||||||
|
* @category string
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* const str = unindent`
|
||||||
|
* if (a) {
|
||||||
|
* b()
|
||||||
|
* }
|
||||||
|
* `
|
||||||
|
*/
|
||||||
|
declare function unindent(str: TemplateStringsArray | string): string;
|
||||||
|
|
||||||
|
declare const timestamp: () => number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call every function in an array
|
||||||
|
*/
|
||||||
|
declare function batchInvoke(functions: Nullable<Fn>[]): void;
|
||||||
|
/**
|
||||||
|
* Call the function
|
||||||
|
*/
|
||||||
|
declare function invoke(fn: Fn): void;
|
||||||
|
/**
|
||||||
|
* Pass the value through the callback, and return the value
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* function createUser(name: string): User {
|
||||||
|
* return tap(new User, user => {
|
||||||
|
* user.name = name
|
||||||
|
* })
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function tap<T>(value: T, callback: (value: T) => void): T;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map key/value pairs for an object, and construct a new one
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*
|
||||||
|
* Transform:
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* objectMap({ a: 1, b: 2 }, (k, v) => [k.toString().toUpperCase(), v.toString()])
|
||||||
|
* // { A: '1', B: '2' }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Swap key/value:
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* objectMap({ a: 1, b: 2 }, (k, v) => [v, k])
|
||||||
|
* // { 1: 'a', 2: 'b' }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Filter keys:
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* objectMap({ a: 1, b: 2 }, (k, v) => k === 'a' ? undefined : [k, v])
|
||||||
|
* // { b: 2 }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function objectMap<K extends string, V, NK extends string | number | symbol = K, NV = V>(obj: Record<K, V>, fn: (key: K, value: V) => [NK, NV] | undefined): Record<NK, NV>;
|
||||||
|
/**
|
||||||
|
* Type guard for any key, `k`.
|
||||||
|
* Marks `k` as a key of `T` if `k` is in `obj`.
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
* @param obj object to query for key `k`
|
||||||
|
* @param k key to check existence in `obj`
|
||||||
|
*/
|
||||||
|
declare function isKeyOf<T extends object>(obj: T, k: keyof any): k is keyof T;
|
||||||
|
/**
|
||||||
|
* Strict typed `Object.keys`
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function objectKeys<T extends object>(obj: T): (`${keyof T & undefined}` | `${keyof T & null}` | `${keyof T & string}` | `${keyof T & number}` | `${keyof T & false}` | `${keyof T & true}`)[];
|
||||||
|
/**
|
||||||
|
* Strict typed `Object.entries`
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function objectEntries<T extends object>(obj: T): [keyof T, T[keyof T]][];
|
||||||
|
/**
|
||||||
|
* Deep merge
|
||||||
|
*
|
||||||
|
* The first argument is the target object, the rest are the sources.
|
||||||
|
* The target object will be mutated and returned.
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function deepMerge<T extends object = object, S extends object = T>(target: T, ...sources: S[]): DeepMerge<T, S>;
|
||||||
|
/**
|
||||||
|
* Deep merge
|
||||||
|
*
|
||||||
|
* Differs from `deepMerge` in that it merges arrays instead of overriding them.
|
||||||
|
*
|
||||||
|
* The first argument is the target object, the rest are the sources.
|
||||||
|
* The target object will be mutated and returned.
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function deepMergeWithArray<T extends object = object, S extends object = T>(target: T, ...sources: S[]): DeepMerge<T, S>;
|
||||||
|
/**
|
||||||
|
* Create a new subset object by giving keys
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function objectPick<O extends object, T extends keyof O>(obj: O, keys: T[], omitUndefined?: boolean): Pick<O, T>;
|
||||||
|
/**
|
||||||
|
* Clear undefined fields from an object. It mutates the object
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function clearUndefined<T extends object>(obj: T): T;
|
||||||
|
/**
|
||||||
|
* Determines whether an object has a property with the specified name
|
||||||
|
*
|
||||||
|
* @see https://eslint.org/docs/rules/no-prototype-builtins
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function hasOwnProperty<T>(obj: T, v: PropertyKey): boolean;
|
||||||
|
|
||||||
|
interface SingletonPromiseReturn<T> {
|
||||||
|
(): Promise<T>;
|
||||||
|
/**
|
||||||
|
* Reset current staled promise.
|
||||||
|
* Await it to have proper shutdown.
|
||||||
|
*/
|
||||||
|
reset: () => Promise<void>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create singleton promise function
|
||||||
|
*
|
||||||
|
* @category Promise
|
||||||
|
*/
|
||||||
|
declare function createSingletonPromise<T>(fn: () => Promise<T>): SingletonPromiseReturn<T>;
|
||||||
|
/**
|
||||||
|
* Promised `setTimeout`
|
||||||
|
*
|
||||||
|
* @category Promise
|
||||||
|
*/
|
||||||
|
declare function sleep(ms: number, callback?: Fn<any>): Promise<void>;
|
||||||
|
/**
|
||||||
|
* Create a promise lock
|
||||||
|
*
|
||||||
|
* @category Promise
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* const lock = createPromiseLock()
|
||||||
|
*
|
||||||
|
* lock.run(async () => {
|
||||||
|
* await doSomething()
|
||||||
|
* })
|
||||||
|
*
|
||||||
|
* // in anther context:
|
||||||
|
* await lock.wait() // it will wait all tasking finished
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function createPromiseLock(): {
|
||||||
|
run<T = void>(fn: () => Promise<T>): Promise<T>;
|
||||||
|
wait(): Promise<void>;
|
||||||
|
isWaiting(): boolean;
|
||||||
|
clear(): void;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Promise with `resolve` and `reject` methods of itself
|
||||||
|
*/
|
||||||
|
interface ControlledPromise<T = void> extends Promise<T> {
|
||||||
|
resolve: (value: T | PromiseLike<T>) => void;
|
||||||
|
reject: (reason?: any) => void;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Return a Promise with `resolve` and `reject` methods
|
||||||
|
*
|
||||||
|
* @category Promise
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* const promise = createControlledPromise()
|
||||||
|
*
|
||||||
|
* await promise
|
||||||
|
*
|
||||||
|
* // in anther context:
|
||||||
|
* promise.resolve(data)
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function createControlledPromise<T>(): ControlledPromise<T>;
|
||||||
|
|
||||||
|
interface CancelOptions {
|
||||||
|
upcomingOnly?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Cancel {
|
||||||
|
cancel: (options?: CancelOptions) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NoReturn<T extends (...args: any[]) => any> {
|
||||||
|
(...args: Parameters<T>): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ThrottleOptions {
|
||||||
|
noTrailing?: boolean;
|
||||||
|
noLeading?: boolean;
|
||||||
|
debounceMode?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DebounceOptions {
|
||||||
|
atBegin?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
type throttle<T extends (...args: any[]) => any> = NoReturn<T> & Cancel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throttle execution of a function. Especially useful for rate limiting
|
||||||
|
* execution of handlers on events like resize and scroll.
|
||||||
|
*
|
||||||
|
* @param delay
|
||||||
|
* A zero-or-greater delay in milliseconds. For event callbacks, values around
|
||||||
|
* 100 or 250 (or even higher) are most useful.
|
||||||
|
*
|
||||||
|
* @param callback
|
||||||
|
* A function to be executed after delay milliseconds. The `this` context and
|
||||||
|
* all arguments are passed through, as-is, to `callback` when the
|
||||||
|
* throttled-function is executed.
|
||||||
|
*
|
||||||
|
* @param options
|
||||||
|
* An object to configure options.
|
||||||
|
*
|
||||||
|
* @param options.noTrailing
|
||||||
|
* Optional, defaults to false. If noTrailing is true, callback will only execute
|
||||||
|
* every `delay` milliseconds while the throttled-function is being called. If
|
||||||
|
* noTrailing is false or unspecified, callback will be executed one final time
|
||||||
|
* after the last throttled-function call. (After the throttled-function has not
|
||||||
|
* been called for `delay` milliseconds, the internal counter is reset)
|
||||||
|
*
|
||||||
|
* @param options.noLeading
|
||||||
|
* Optional, defaults to false. If noLeading is false, the first throttled-function
|
||||||
|
* call will execute callback immediately. If noLeading is true, the first the
|
||||||
|
* callback execution will be skipped. It should be noted that callback will never
|
||||||
|
* executed if both noLeading = true and noTrailing = true.
|
||||||
|
*
|
||||||
|
* @param options.debounceMode If `debounceMode` is true (at begin), schedule
|
||||||
|
* `callback` to execute after `delay` ms. If `debounceMode` is false (at end),
|
||||||
|
* schedule `callback` to execute after `delay` ms.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new, throttled, function.
|
||||||
|
*/
|
||||||
|
declare function throttle<T extends (...args: any[]) => any>(
|
||||||
|
delay: number,
|
||||||
|
callback: T,
|
||||||
|
options?: ThrottleOptions,
|
||||||
|
): throttle<T>;
|
||||||
|
type debounce<T extends (...args: any[]) => any> = NoReturn<T> & Cancel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debounce execution of a function. Debouncing, unlike throttling,
|
||||||
|
* guarantees that a function is only executed a single time, either at the
|
||||||
|
* very beginning of a series of calls, or at the very end.
|
||||||
|
*
|
||||||
|
* @param delay
|
||||||
|
* A zero-or-greater delay in milliseconds. For event callbacks, values around
|
||||||
|
* 100 or 250 (or even higher) are most useful.
|
||||||
|
*
|
||||||
|
* @param callback
|
||||||
|
* A function to be executed after delay milliseconds. The `this` context and
|
||||||
|
* all arguments are passed through, as-is, to `callback` when the
|
||||||
|
* debounced-function is executed.
|
||||||
|
*
|
||||||
|
* @param options
|
||||||
|
* An object to configure options.
|
||||||
|
*
|
||||||
|
* @param options.atBegin
|
||||||
|
* If atBegin is false or unspecified, callback will only be executed `delay`
|
||||||
|
* milliseconds after the last debounced-function call. If atBegin is true,
|
||||||
|
* callback will be executed only at the first debounced-function call. (After
|
||||||
|
* the throttled-function has not been called for `delay` milliseconds, the
|
||||||
|
* internal counter is reset).
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new, debounced function.
|
||||||
|
*/
|
||||||
|
declare function debounce<T extends (...args: any[]) => any>(
|
||||||
|
delay: number,
|
||||||
|
callback: T,
|
||||||
|
options?: DebounceOptions,
|
||||||
|
): debounce<T>;
|
||||||
|
|
||||||
|
interface POptions {
|
||||||
|
/**
|
||||||
|
* How many promises are resolved at the same time.
|
||||||
|
*/
|
||||||
|
concurrency?: number | undefined;
|
||||||
|
}
|
||||||
|
declare class PInstance<T = any> extends Promise<Awaited<T>[]> {
|
||||||
|
items: Iterable<T>;
|
||||||
|
options?: POptions | undefined;
|
||||||
|
private promises;
|
||||||
|
get promise(): Promise<Awaited<T>[]>;
|
||||||
|
constructor(items?: Iterable<T>, options?: POptions | undefined);
|
||||||
|
add(...args: (T | Promise<T>)[]): void;
|
||||||
|
map<U>(fn: (value: Awaited<T>, index: number) => U): PInstance<Promise<U>>;
|
||||||
|
filter(fn: (value: Awaited<T>, index: number) => boolean | Promise<boolean>): PInstance<Promise<T>>;
|
||||||
|
forEach(fn: (value: Awaited<T>, index: number) => void): Promise<void>;
|
||||||
|
reduce<U>(fn: (previousValue: U, currentValue: Awaited<T>, currentIndex: number, array: Awaited<T>[]) => U, initialValue: U): Promise<U>;
|
||||||
|
clear(): void;
|
||||||
|
then(fn?: () => PromiseLike<any>): Promise<any>;
|
||||||
|
catch(fn?: (err: unknown) => PromiseLike<any>): Promise<any>;
|
||||||
|
finally(fn?: () => void): Promise<Awaited<T>[]>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Utility for managing multiple promises.
|
||||||
|
*
|
||||||
|
* @see https://github.com/antfu/utils/tree/main/docs/p.md
|
||||||
|
* @category Promise
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* import { p } from '@antfu/utils'
|
||||||
|
*
|
||||||
|
* const items = [1, 2, 3, 4, 5]
|
||||||
|
*
|
||||||
|
* await p(items)
|
||||||
|
* .map(async i => await multiply(i, 3))
|
||||||
|
* .filter(async i => await isEven(i))
|
||||||
|
* // [6, 12]
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function p<T = any>(items?: Iterable<T>, options?: POptions): PInstance<T>;
|
||||||
|
|
||||||
|
export { type ArgumentsType, type Arrayable, type Awaitable, type Constructor, type ControlledPromise, type DeepMerge, type ElementOf, type Fn, type MergeInsertions, type Nullable, type PartitionFilter, type SingletonPromiseReturn, type UnionToIntersection, assert, at, batchInvoke, capitalize, clamp, clampArrayRange, clearUndefined, createControlledPromise, createPromiseLock, createSingletonPromise, debounce, deepMerge, deepMergeWithArray, ensurePrefix, ensureSuffix, flattenArrayable, getTypeName, hasOwnProperty, invoke, isBoolean, isBrowser, isDate, isDeepEqual, isDef, isFunction, isKeyOf, isNull, isNumber, isObject, isRegExp, isString, isTruthy, isUndefined, isWindow, last, lerp, mergeArrayable, move, noNull, noop, notNullish, notUndefined, objectEntries, objectKeys, objectMap, objectPick, p, partition, randomStr, range, remap, remove, sample, shuffle, slash, sleep, sum, tap, template, throttle, timestamp, toArray, toString, unindent, uniq, uniqueBy };
|
@ -0,0 +1,614 @@
|
|||||||
|
/**
|
||||||
|
* Promise, or maybe not
|
||||||
|
*/
|
||||||
|
type Awaitable<T> = T | PromiseLike<T>;
|
||||||
|
/**
|
||||||
|
* Null or whatever
|
||||||
|
*/
|
||||||
|
type Nullable<T> = T | null | undefined;
|
||||||
|
/**
|
||||||
|
* Array, or not yet
|
||||||
|
*/
|
||||||
|
type Arrayable<T> = T | Array<T>;
|
||||||
|
/**
|
||||||
|
* Function
|
||||||
|
*/
|
||||||
|
type Fn<T = void> = () => T;
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
type Constructor<T = void> = new (...args: any[]) => T;
|
||||||
|
/**
|
||||||
|
* Infers the element type of an array
|
||||||
|
*/
|
||||||
|
type ElementOf<T> = T extends (infer E)[] ? E : never;
|
||||||
|
/**
|
||||||
|
* Defines an intersection type of all union items.
|
||||||
|
*
|
||||||
|
* @param U Union of any types that will be intersected.
|
||||||
|
* @returns U items intersected
|
||||||
|
* @see https://stackoverflow.com/a/50375286/9259330
|
||||||
|
*/
|
||||||
|
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
|
||||||
|
/**
|
||||||
|
* Infers the arguments type of a function
|
||||||
|
*/
|
||||||
|
type ArgumentsType<T> = T extends ((...args: infer A) => any) ? A : never;
|
||||||
|
type MergeInsertions<T> = T extends object ? {
|
||||||
|
[K in keyof T]: MergeInsertions<T[K]>;
|
||||||
|
} : T;
|
||||||
|
type DeepMerge<F, S> = MergeInsertions<{
|
||||||
|
[K in keyof F | keyof S]: K extends keyof S & keyof F ? DeepMerge<F[K], S[K]> : K extends keyof S ? S[K] : K extends keyof F ? F[K] : never;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert `Arrayable<T>` to `Array<T>`
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function toArray<T>(array?: Nullable<Arrayable<T>>): Array<T>;
|
||||||
|
/**
|
||||||
|
* Convert `Arrayable<T>` to `Array<T>` and flatten it
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function flattenArrayable<T>(array?: Nullable<Arrayable<T | Array<T>>>): Array<T>;
|
||||||
|
/**
|
||||||
|
* Use rest arguments to merge arrays
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function mergeArrayable<T>(...args: Nullable<Arrayable<T>>[]): Array<T>;
|
||||||
|
type PartitionFilter<T> = (i: T, idx: number, arr: readonly T[]) => any;
|
||||||
|
/**
|
||||||
|
* Divide an array into two parts by a filter function
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
* @example const [odd, even] = partition([1, 2, 3, 4], i => i % 2 != 0)
|
||||||
|
*/
|
||||||
|
declare function partition<T>(array: readonly T[], f1: PartitionFilter<T>): [T[], T[]];
|
||||||
|
declare function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>): [T[], T[], T[]];
|
||||||
|
declare function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>, f3: PartitionFilter<T>): [T[], T[], T[], T[]];
|
||||||
|
declare function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>, f3: PartitionFilter<T>, f4: PartitionFilter<T>): [T[], T[], T[], T[], T[]];
|
||||||
|
declare function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>, f3: PartitionFilter<T>, f4: PartitionFilter<T>, f5: PartitionFilter<T>): [T[], T[], T[], T[], T[], T[]];
|
||||||
|
declare function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>, f3: PartitionFilter<T>, f4: PartitionFilter<T>, f5: PartitionFilter<T>, f6: PartitionFilter<T>): [T[], T[], T[], T[], T[], T[], T[]];
|
||||||
|
/**
|
||||||
|
* Unique an Array
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function uniq<T>(array: readonly T[]): T[];
|
||||||
|
/**
|
||||||
|
* Unique an Array by a custom equality function
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function uniqueBy<T>(array: readonly T[], equalFn: (a: any, b: any) => boolean): T[];
|
||||||
|
/**
|
||||||
|
* Get last item
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function last(array: readonly []): undefined;
|
||||||
|
declare function last<T>(array: readonly T[]): T;
|
||||||
|
/**
|
||||||
|
* Remove an item from Array
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function remove<T>(array: T[], value: T): boolean;
|
||||||
|
/**
|
||||||
|
* Get nth item of Array. Negative for backward
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function at(array: readonly [], index: number): undefined;
|
||||||
|
declare function at<T>(array: readonly T[], index: number): T;
|
||||||
|
/**
|
||||||
|
* Genrate a range array of numbers. The `stop` is exclusive.
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function range(stop: number): number[];
|
||||||
|
declare function range(start: number, stop: number, step?: number): number[];
|
||||||
|
/**
|
||||||
|
* Move element in an Array
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
* @param arr
|
||||||
|
* @param from
|
||||||
|
* @param to
|
||||||
|
*/
|
||||||
|
declare function move<T>(arr: T[], from: number, to: number): T[];
|
||||||
|
/**
|
||||||
|
* Clamp a number to the index range of an array
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function clampArrayRange(n: number, arr: readonly unknown[]): number;
|
||||||
|
/**
|
||||||
|
* Get random item(s) from an array
|
||||||
|
*
|
||||||
|
* @param arr
|
||||||
|
* @param quantity - quantity of random items which will be returned
|
||||||
|
*/
|
||||||
|
declare function sample<T>(arr: T[], quantity: number): T[];
|
||||||
|
/**
|
||||||
|
* Shuffle an array. This function mutates the array.
|
||||||
|
*
|
||||||
|
* @category Array
|
||||||
|
*/
|
||||||
|
declare function shuffle<T>(array: T[]): T[];
|
||||||
|
|
||||||
|
declare function assert(condition: boolean, message: string): asserts condition;
|
||||||
|
declare const toString: (v: any) => string;
|
||||||
|
declare function getTypeName(v: any): string;
|
||||||
|
declare function noop(): void;
|
||||||
|
|
||||||
|
declare function isDeepEqual(value1: any, value2: any): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type guard to filter out null-ish values
|
||||||
|
*
|
||||||
|
* @category Guards
|
||||||
|
* @example array.filter(notNullish)
|
||||||
|
*/
|
||||||
|
declare function notNullish<T>(v: T | null | undefined): v is NonNullable<T>;
|
||||||
|
/**
|
||||||
|
* Type guard to filter out null values
|
||||||
|
*
|
||||||
|
* @category Guards
|
||||||
|
* @example array.filter(noNull)
|
||||||
|
*/
|
||||||
|
declare function noNull<T>(v: T | null): v is Exclude<T, null>;
|
||||||
|
/**
|
||||||
|
* Type guard to filter out null-ish values
|
||||||
|
*
|
||||||
|
* @category Guards
|
||||||
|
* @example array.filter(notUndefined)
|
||||||
|
*/
|
||||||
|
declare function notUndefined<T>(v: T): v is Exclude<T, undefined>;
|
||||||
|
/**
|
||||||
|
* Type guard to filter out falsy values
|
||||||
|
*
|
||||||
|
* @category Guards
|
||||||
|
* @example array.filter(isTruthy)
|
||||||
|
*/
|
||||||
|
declare function isTruthy<T>(v: T): v is NonNullable<T>;
|
||||||
|
|
||||||
|
declare const isDef: <T = any>(val?: T) => val is T;
|
||||||
|
declare const isBoolean: (val: any) => val is boolean;
|
||||||
|
declare const isFunction: <T extends Function>(val: any) => val is T;
|
||||||
|
declare const isNumber: (val: any) => val is number;
|
||||||
|
declare const isString: (val: unknown) => val is string;
|
||||||
|
declare const isObject: (val: any) => val is object;
|
||||||
|
declare const isUndefined: (val: any) => val is undefined;
|
||||||
|
declare const isNull: (val: any) => val is null;
|
||||||
|
declare const isRegExp: (val: any) => val is RegExp;
|
||||||
|
declare const isDate: (val: any) => val is Date;
|
||||||
|
declare const isWindow: (val: any) => boolean;
|
||||||
|
declare const isBrowser: boolean;
|
||||||
|
|
||||||
|
declare function clamp(n: number, min: number, max: number): number;
|
||||||
|
declare function sum(...args: number[] | number[][]): number;
|
||||||
|
/**
|
||||||
|
* Linearly interpolates between `min` and `max` based on `t`
|
||||||
|
*
|
||||||
|
* @category Math
|
||||||
|
* @param min The minimum value
|
||||||
|
* @param max The maximum value
|
||||||
|
* @param t The interpolation value clamped between 0 and 1
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* const value = lerp(0, 2, 0.5) // value will be 1
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function lerp(min: number, max: number, t: number): number;
|
||||||
|
/**
|
||||||
|
* Linearly remaps a clamped value from its source range [`inMin`, `inMax`] to the destination range [`outMin`, `outMax`]
|
||||||
|
*
|
||||||
|
* @category Math
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* const value = remap(0.5, 0, 1, 200, 400) // value will be 300
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function remap(n: number, inMin: number, inMax: number, outMin: number, outMax: number): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace backslash to slash
|
||||||
|
*
|
||||||
|
* @category String
|
||||||
|
*/
|
||||||
|
declare function slash(str: string): string;
|
||||||
|
/**
|
||||||
|
* Ensure prefix of a string
|
||||||
|
*
|
||||||
|
* @category String
|
||||||
|
*/
|
||||||
|
declare function ensurePrefix(prefix: string, str: string): string;
|
||||||
|
/**
|
||||||
|
* Ensure suffix of a string
|
||||||
|
*
|
||||||
|
* @category String
|
||||||
|
*/
|
||||||
|
declare function ensureSuffix(suffix: string, str: string): string;
|
||||||
|
/**
|
||||||
|
* Dead simple template engine, just like Python's `.format()`
|
||||||
|
* Support passing variables as either in index based or object/name based approach
|
||||||
|
* While using object/name based approach, you can pass a fallback value as the third argument
|
||||||
|
*
|
||||||
|
* @category String
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* const result = template(
|
||||||
|
* 'Hello {0}! My name is {1}.',
|
||||||
|
* 'Inès',
|
||||||
|
* 'Anthony'
|
||||||
|
* ) // Hello Inès! My name is Anthony.
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* const result = namedTemplate(
|
||||||
|
* '{greet}! My name is {name}.',
|
||||||
|
* { greet: 'Hello', name: 'Anthony' }
|
||||||
|
* ) // Hello! My name is Anthony.
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* const result = namedTemplate(
|
||||||
|
* '{greet}! My name is {name}.',
|
||||||
|
* { greet: 'Hello' }, // name isn't passed hence fallback will be used for name
|
||||||
|
* 'placeholder'
|
||||||
|
* ) // Hello! My name is placeholder.
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function template(str: string, object: Record<string | number, any>, fallback?: string | ((key: string) => string)): string;
|
||||||
|
declare function template(str: string, ...args: (string | number | bigint | undefined | null)[]): string;
|
||||||
|
/**
|
||||||
|
* Generate a random string
|
||||||
|
* @category String
|
||||||
|
*/
|
||||||
|
declare function randomStr(size?: number, dict?: string): string;
|
||||||
|
/**
|
||||||
|
* First letter uppercase, other lowercase
|
||||||
|
* @category string
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* capitalize('hello') => 'Hello'
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function capitalize(str: string): string;
|
||||||
|
/**
|
||||||
|
* Remove common leading whitespace from a template string.
|
||||||
|
* Will also remove empty lines at the beginning and end.
|
||||||
|
* @category string
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* const str = unindent`
|
||||||
|
* if (a) {
|
||||||
|
* b()
|
||||||
|
* }
|
||||||
|
* `
|
||||||
|
*/
|
||||||
|
declare function unindent(str: TemplateStringsArray | string): string;
|
||||||
|
|
||||||
|
declare const timestamp: () => number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call every function in an array
|
||||||
|
*/
|
||||||
|
declare function batchInvoke(functions: Nullable<Fn>[]): void;
|
||||||
|
/**
|
||||||
|
* Call the function
|
||||||
|
*/
|
||||||
|
declare function invoke(fn: Fn): void;
|
||||||
|
/**
|
||||||
|
* Pass the value through the callback, and return the value
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* function createUser(name: string): User {
|
||||||
|
* return tap(new User, user => {
|
||||||
|
* user.name = name
|
||||||
|
* })
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function tap<T>(value: T, callback: (value: T) => void): T;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map key/value pairs for an object, and construct a new one
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*
|
||||||
|
* Transform:
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* objectMap({ a: 1, b: 2 }, (k, v) => [k.toString().toUpperCase(), v.toString()])
|
||||||
|
* // { A: '1', B: '2' }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Swap key/value:
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* objectMap({ a: 1, b: 2 }, (k, v) => [v, k])
|
||||||
|
* // { 1: 'a', 2: 'b' }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Filter keys:
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* objectMap({ a: 1, b: 2 }, (k, v) => k === 'a' ? undefined : [k, v])
|
||||||
|
* // { b: 2 }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function objectMap<K extends string, V, NK extends string | number | symbol = K, NV = V>(obj: Record<K, V>, fn: (key: K, value: V) => [NK, NV] | undefined): Record<NK, NV>;
|
||||||
|
/**
|
||||||
|
* Type guard for any key, `k`.
|
||||||
|
* Marks `k` as a key of `T` if `k` is in `obj`.
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
* @param obj object to query for key `k`
|
||||||
|
* @param k key to check existence in `obj`
|
||||||
|
*/
|
||||||
|
declare function isKeyOf<T extends object>(obj: T, k: keyof any): k is keyof T;
|
||||||
|
/**
|
||||||
|
* Strict typed `Object.keys`
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function objectKeys<T extends object>(obj: T): (`${keyof T & undefined}` | `${keyof T & null}` | `${keyof T & string}` | `${keyof T & number}` | `${keyof T & false}` | `${keyof T & true}`)[];
|
||||||
|
/**
|
||||||
|
* Strict typed `Object.entries`
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function objectEntries<T extends object>(obj: T): [keyof T, T[keyof T]][];
|
||||||
|
/**
|
||||||
|
* Deep merge
|
||||||
|
*
|
||||||
|
* The first argument is the target object, the rest are the sources.
|
||||||
|
* The target object will be mutated and returned.
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function deepMerge<T extends object = object, S extends object = T>(target: T, ...sources: S[]): DeepMerge<T, S>;
|
||||||
|
/**
|
||||||
|
* Deep merge
|
||||||
|
*
|
||||||
|
* Differs from `deepMerge` in that it merges arrays instead of overriding them.
|
||||||
|
*
|
||||||
|
* The first argument is the target object, the rest are the sources.
|
||||||
|
* The target object will be mutated and returned.
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function deepMergeWithArray<T extends object = object, S extends object = T>(target: T, ...sources: S[]): DeepMerge<T, S>;
|
||||||
|
/**
|
||||||
|
* Create a new subset object by giving keys
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function objectPick<O extends object, T extends keyof O>(obj: O, keys: T[], omitUndefined?: boolean): Pick<O, T>;
|
||||||
|
/**
|
||||||
|
* Clear undefined fields from an object. It mutates the object
|
||||||
|
*
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function clearUndefined<T extends object>(obj: T): T;
|
||||||
|
/**
|
||||||
|
* Determines whether an object has a property with the specified name
|
||||||
|
*
|
||||||
|
* @see https://eslint.org/docs/rules/no-prototype-builtins
|
||||||
|
* @category Object
|
||||||
|
*/
|
||||||
|
declare function hasOwnProperty<T>(obj: T, v: PropertyKey): boolean;
|
||||||
|
|
||||||
|
interface SingletonPromiseReturn<T> {
|
||||||
|
(): Promise<T>;
|
||||||
|
/**
|
||||||
|
* Reset current staled promise.
|
||||||
|
* Await it to have proper shutdown.
|
||||||
|
*/
|
||||||
|
reset: () => Promise<void>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create singleton promise function
|
||||||
|
*
|
||||||
|
* @category Promise
|
||||||
|
*/
|
||||||
|
declare function createSingletonPromise<T>(fn: () => Promise<T>): SingletonPromiseReturn<T>;
|
||||||
|
/**
|
||||||
|
* Promised `setTimeout`
|
||||||
|
*
|
||||||
|
* @category Promise
|
||||||
|
*/
|
||||||
|
declare function sleep(ms: number, callback?: Fn<any>): Promise<void>;
|
||||||
|
/**
|
||||||
|
* Create a promise lock
|
||||||
|
*
|
||||||
|
* @category Promise
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* const lock = createPromiseLock()
|
||||||
|
*
|
||||||
|
* lock.run(async () => {
|
||||||
|
* await doSomething()
|
||||||
|
* })
|
||||||
|
*
|
||||||
|
* // in anther context:
|
||||||
|
* await lock.wait() // it will wait all tasking finished
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function createPromiseLock(): {
|
||||||
|
run<T = void>(fn: () => Promise<T>): Promise<T>;
|
||||||
|
wait(): Promise<void>;
|
||||||
|
isWaiting(): boolean;
|
||||||
|
clear(): void;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Promise with `resolve` and `reject` methods of itself
|
||||||
|
*/
|
||||||
|
interface ControlledPromise<T = void> extends Promise<T> {
|
||||||
|
resolve: (value: T | PromiseLike<T>) => void;
|
||||||
|
reject: (reason?: any) => void;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Return a Promise with `resolve` and `reject` methods
|
||||||
|
*
|
||||||
|
* @category Promise
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* const promise = createControlledPromise()
|
||||||
|
*
|
||||||
|
* await promise
|
||||||
|
*
|
||||||
|
* // in anther context:
|
||||||
|
* promise.resolve(data)
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function createControlledPromise<T>(): ControlledPromise<T>;
|
||||||
|
|
||||||
|
interface CancelOptions {
|
||||||
|
upcomingOnly?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Cancel {
|
||||||
|
cancel: (options?: CancelOptions) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NoReturn<T extends (...args: any[]) => any> {
|
||||||
|
(...args: Parameters<T>): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ThrottleOptions {
|
||||||
|
noTrailing?: boolean;
|
||||||
|
noLeading?: boolean;
|
||||||
|
debounceMode?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DebounceOptions {
|
||||||
|
atBegin?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
type throttle<T extends (...args: any[]) => any> = NoReturn<T> & Cancel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throttle execution of a function. Especially useful for rate limiting
|
||||||
|
* execution of handlers on events like resize and scroll.
|
||||||
|
*
|
||||||
|
* @param delay
|
||||||
|
* A zero-or-greater delay in milliseconds. For event callbacks, values around
|
||||||
|
* 100 or 250 (or even higher) are most useful.
|
||||||
|
*
|
||||||
|
* @param callback
|
||||||
|
* A function to be executed after delay milliseconds. The `this` context and
|
||||||
|
* all arguments are passed through, as-is, to `callback` when the
|
||||||
|
* throttled-function is executed.
|
||||||
|
*
|
||||||
|
* @param options
|
||||||
|
* An object to configure options.
|
||||||
|
*
|
||||||
|
* @param options.noTrailing
|
||||||
|
* Optional, defaults to false. If noTrailing is true, callback will only execute
|
||||||
|
* every `delay` milliseconds while the throttled-function is being called. If
|
||||||
|
* noTrailing is false or unspecified, callback will be executed one final time
|
||||||
|
* after the last throttled-function call. (After the throttled-function has not
|
||||||
|
* been called for `delay` milliseconds, the internal counter is reset)
|
||||||
|
*
|
||||||
|
* @param options.noLeading
|
||||||
|
* Optional, defaults to false. If noLeading is false, the first throttled-function
|
||||||
|
* call will execute callback immediately. If noLeading is true, the first the
|
||||||
|
* callback execution will be skipped. It should be noted that callback will never
|
||||||
|
* executed if both noLeading = true and noTrailing = true.
|
||||||
|
*
|
||||||
|
* @param options.debounceMode If `debounceMode` is true (at begin), schedule
|
||||||
|
* `callback` to execute after `delay` ms. If `debounceMode` is false (at end),
|
||||||
|
* schedule `callback` to execute after `delay` ms.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new, throttled, function.
|
||||||
|
*/
|
||||||
|
declare function throttle<T extends (...args: any[]) => any>(
|
||||||
|
delay: number,
|
||||||
|
callback: T,
|
||||||
|
options?: ThrottleOptions,
|
||||||
|
): throttle<T>;
|
||||||
|
type debounce<T extends (...args: any[]) => any> = NoReturn<T> & Cancel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debounce execution of a function. Debouncing, unlike throttling,
|
||||||
|
* guarantees that a function is only executed a single time, either at the
|
||||||
|
* very beginning of a series of calls, or at the very end.
|
||||||
|
*
|
||||||
|
* @param delay
|
||||||
|
* A zero-or-greater delay in milliseconds. For event callbacks, values around
|
||||||
|
* 100 or 250 (or even higher) are most useful.
|
||||||
|
*
|
||||||
|
* @param callback
|
||||||
|
* A function to be executed after delay milliseconds. The `this` context and
|
||||||
|
* all arguments are passed through, as-is, to `callback` when the
|
||||||
|
* debounced-function is executed.
|
||||||
|
*
|
||||||
|
* @param options
|
||||||
|
* An object to configure options.
|
||||||
|
*
|
||||||
|
* @param options.atBegin
|
||||||
|
* If atBegin is false or unspecified, callback will only be executed `delay`
|
||||||
|
* milliseconds after the last debounced-function call. If atBegin is true,
|
||||||
|
* callback will be executed only at the first debounced-function call. (After
|
||||||
|
* the throttled-function has not been called for `delay` milliseconds, the
|
||||||
|
* internal counter is reset).
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new, debounced function.
|
||||||
|
*/
|
||||||
|
declare function debounce<T extends (...args: any[]) => any>(
|
||||||
|
delay: number,
|
||||||
|
callback: T,
|
||||||
|
options?: DebounceOptions,
|
||||||
|
): debounce<T>;
|
||||||
|
|
||||||
|
interface POptions {
|
||||||
|
/**
|
||||||
|
* How many promises are resolved at the same time.
|
||||||
|
*/
|
||||||
|
concurrency?: number | undefined;
|
||||||
|
}
|
||||||
|
declare class PInstance<T = any> extends Promise<Awaited<T>[]> {
|
||||||
|
items: Iterable<T>;
|
||||||
|
options?: POptions | undefined;
|
||||||
|
private promises;
|
||||||
|
get promise(): Promise<Awaited<T>[]>;
|
||||||
|
constructor(items?: Iterable<T>, options?: POptions | undefined);
|
||||||
|
add(...args: (T | Promise<T>)[]): void;
|
||||||
|
map<U>(fn: (value: Awaited<T>, index: number) => U): PInstance<Promise<U>>;
|
||||||
|
filter(fn: (value: Awaited<T>, index: number) => boolean | Promise<boolean>): PInstance<Promise<T>>;
|
||||||
|
forEach(fn: (value: Awaited<T>, index: number) => void): Promise<void>;
|
||||||
|
reduce<U>(fn: (previousValue: U, currentValue: Awaited<T>, currentIndex: number, array: Awaited<T>[]) => U, initialValue: U): Promise<U>;
|
||||||
|
clear(): void;
|
||||||
|
then(fn?: () => PromiseLike<any>): Promise<any>;
|
||||||
|
catch(fn?: (err: unknown) => PromiseLike<any>): Promise<any>;
|
||||||
|
finally(fn?: () => void): Promise<Awaited<T>[]>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Utility for managing multiple promises.
|
||||||
|
*
|
||||||
|
* @see https://github.com/antfu/utils/tree/main/docs/p.md
|
||||||
|
* @category Promise
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* import { p } from '@antfu/utils'
|
||||||
|
*
|
||||||
|
* const items = [1, 2, 3, 4, 5]
|
||||||
|
*
|
||||||
|
* await p(items)
|
||||||
|
* .map(async i => await multiply(i, 3))
|
||||||
|
* .filter(async i => await isEven(i))
|
||||||
|
* // [6, 12]
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function p<T = any>(items?: Iterable<T>, options?: POptions): PInstance<T>;
|
||||||
|
|
||||||
|
export { type ArgumentsType, type Arrayable, type Awaitable, type Constructor, type ControlledPromise, type DeepMerge, type ElementOf, type Fn, type MergeInsertions, type Nullable, type PartitionFilter, type SingletonPromiseReturn, type UnionToIntersection, assert, at, batchInvoke, capitalize, clamp, clampArrayRange, clearUndefined, createControlledPromise, createPromiseLock, createSingletonPromise, debounce, deepMerge, deepMergeWithArray, ensurePrefix, ensureSuffix, flattenArrayable, getTypeName, hasOwnProperty, invoke, isBoolean, isBrowser, isDate, isDeepEqual, isDef, isFunction, isKeyOf, isNull, isNumber, isObject, isRegExp, isString, isTruthy, isUndefined, isWindow, last, lerp, mergeArrayable, move, noNull, noop, notNullish, notUndefined, objectEntries, objectKeys, objectMap, objectPick, p, partition, randomStr, range, remap, remove, sample, shuffle, slash, sleep, sum, tap, template, throttle, timestamp, toArray, toString, unindent, uniq, uniqueBy };
|
@ -0,0 +1,777 @@
|
|||||||
|
function clamp(n, min, max) {
|
||||||
|
return Math.min(max, Math.max(min, n));
|
||||||
|
}
|
||||||
|
function sum(...args) {
|
||||||
|
return flattenArrayable(args).reduce((a, b) => a + b, 0);
|
||||||
|
}
|
||||||
|
function lerp(min, max, t) {
|
||||||
|
const interpolation = clamp(t, 0, 1);
|
||||||
|
return min + (max - min) * interpolation;
|
||||||
|
}
|
||||||
|
function remap(n, inMin, inMax, outMin, outMax) {
|
||||||
|
const interpolation = (n - inMin) / (inMax - inMin);
|
||||||
|
return lerp(outMin, outMax, interpolation);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toArray(array) {
|
||||||
|
array = array ?? [];
|
||||||
|
return Array.isArray(array) ? array : [array];
|
||||||
|
}
|
||||||
|
function flattenArrayable(array) {
|
||||||
|
return toArray(array).flat(1);
|
||||||
|
}
|
||||||
|
function mergeArrayable(...args) {
|
||||||
|
return args.flatMap((i) => toArray(i));
|
||||||
|
}
|
||||||
|
function partition(array, ...filters) {
|
||||||
|
const result = Array.from({ length: filters.length + 1 }).fill(null).map(() => []);
|
||||||
|
array.forEach((e, idx, arr) => {
|
||||||
|
let i = 0;
|
||||||
|
for (const filter of filters) {
|
||||||
|
if (filter(e, idx, arr)) {
|
||||||
|
result[i].push(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
result[i].push(e);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
function uniq(array) {
|
||||||
|
return Array.from(new Set(array));
|
||||||
|
}
|
||||||
|
function uniqueBy(array, equalFn) {
|
||||||
|
return array.reduce((acc, cur) => {
|
||||||
|
const index = acc.findIndex((item) => equalFn(cur, item));
|
||||||
|
if (index === -1)
|
||||||
|
acc.push(cur);
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
function last(array) {
|
||||||
|
return at(array, -1);
|
||||||
|
}
|
||||||
|
function remove(array, value) {
|
||||||
|
if (!array)
|
||||||
|
return false;
|
||||||
|
const index = array.indexOf(value);
|
||||||
|
if (index >= 0) {
|
||||||
|
array.splice(index, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function at(array, index) {
|
||||||
|
const len = array.length;
|
||||||
|
if (!len)
|
||||||
|
return void 0;
|
||||||
|
if (index < 0)
|
||||||
|
index += len;
|
||||||
|
return array[index];
|
||||||
|
}
|
||||||
|
function range(...args) {
|
||||||
|
let start, stop, step;
|
||||||
|
if (args.length === 1) {
|
||||||
|
start = 0;
|
||||||
|
step = 1;
|
||||||
|
[stop] = args;
|
||||||
|
} else {
|
||||||
|
[start, stop, step = 1] = args;
|
||||||
|
}
|
||||||
|
const arr = [];
|
||||||
|
let current = start;
|
||||||
|
while (current < stop) {
|
||||||
|
arr.push(current);
|
||||||
|
current += step || 1;
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
function move(arr, from, to) {
|
||||||
|
arr.splice(to, 0, arr.splice(from, 1)[0]);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
function clampArrayRange(n, arr) {
|
||||||
|
return clamp(n, 0, arr.length - 1);
|
||||||
|
}
|
||||||
|
function sample(arr, quantity) {
|
||||||
|
return Array.from({ length: quantity }, (_) => arr[Math.round(Math.random() * (arr.length - 1))]);
|
||||||
|
}
|
||||||
|
function shuffle(array) {
|
||||||
|
for (let i = array.length - 1; i > 0; i--) {
|
||||||
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
|
[array[i], array[j]] = [array[j], array[i]];
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
function assert(condition, message) {
|
||||||
|
if (!condition)
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
const toString = (v) => Object.prototype.toString.call(v);
|
||||||
|
function getTypeName(v) {
|
||||||
|
if (v === null)
|
||||||
|
return "null";
|
||||||
|
const type = toString(v).slice(8, -1).toLowerCase();
|
||||||
|
return typeof v === "object" || typeof v === "function" ? type : typeof v;
|
||||||
|
}
|
||||||
|
function noop() {
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDeepEqual(value1, value2) {
|
||||||
|
const type1 = getTypeName(value1);
|
||||||
|
const type2 = getTypeName(value2);
|
||||||
|
if (type1 !== type2)
|
||||||
|
return false;
|
||||||
|
if (type1 === "array") {
|
||||||
|
if (value1.length !== value2.length)
|
||||||
|
return false;
|
||||||
|
return value1.every((item, i) => {
|
||||||
|
return isDeepEqual(item, value2[i]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (type1 === "object") {
|
||||||
|
const keyArr = Object.keys(value1);
|
||||||
|
if (keyArr.length !== Object.keys(value2).length)
|
||||||
|
return false;
|
||||||
|
return keyArr.every((key) => {
|
||||||
|
return isDeepEqual(value1[key], value2[key]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Object.is(value1, value2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function notNullish(v) {
|
||||||
|
return v != null;
|
||||||
|
}
|
||||||
|
function noNull(v) {
|
||||||
|
return v !== null;
|
||||||
|
}
|
||||||
|
function notUndefined(v) {
|
||||||
|
return v !== void 0;
|
||||||
|
}
|
||||||
|
function isTruthy(v) {
|
||||||
|
return Boolean(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isDef = (val) => typeof val !== "undefined";
|
||||||
|
const isBoolean = (val) => typeof val === "boolean";
|
||||||
|
const isFunction = (val) => typeof val === "function";
|
||||||
|
const isNumber = (val) => typeof val === "number";
|
||||||
|
const isString = (val) => typeof val === "string";
|
||||||
|
const isObject = (val) => toString(val) === "[object Object]";
|
||||||
|
const isUndefined = (val) => toString(val) === "[object Undefined]";
|
||||||
|
const isNull = (val) => toString(val) === "[object Null]";
|
||||||
|
const isRegExp = (val) => toString(val) === "[object RegExp]";
|
||||||
|
const isDate = (val) => toString(val) === "[object Date]";
|
||||||
|
const isWindow = (val) => typeof window !== "undefined" && toString(val) === "[object Window]";
|
||||||
|
const isBrowser = typeof window !== "undefined";
|
||||||
|
|
||||||
|
function slash(str) {
|
||||||
|
return str.replace(/\\/g, "/");
|
||||||
|
}
|
||||||
|
function ensurePrefix(prefix, str) {
|
||||||
|
if (!str.startsWith(prefix))
|
||||||
|
return prefix + str;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
function ensureSuffix(suffix, str) {
|
||||||
|
if (!str.endsWith(suffix))
|
||||||
|
return str + suffix;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
function template(str, ...args) {
|
||||||
|
const [firstArg, fallback] = args;
|
||||||
|
if (isObject(firstArg)) {
|
||||||
|
const vars = firstArg;
|
||||||
|
return str.replace(/{([\w\d]+)}/g, (_, key) => vars[key] || ((typeof fallback === "function" ? fallback(key) : fallback) ?? key));
|
||||||
|
} else {
|
||||||
|
return str.replace(/{(\d+)}/g, (_, key) => {
|
||||||
|
const index = Number(key);
|
||||||
|
if (Number.isNaN(index))
|
||||||
|
return key;
|
||||||
|
return args[index];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
|
||||||
|
function randomStr(size = 16, dict = urlAlphabet) {
|
||||||
|
let id = "";
|
||||||
|
let i = size;
|
||||||
|
const len = dict.length;
|
||||||
|
while (i--)
|
||||||
|
id += dict[Math.random() * len | 0];
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
function capitalize(str) {
|
||||||
|
return str[0].toUpperCase() + str.slice(1).toLowerCase();
|
||||||
|
}
|
||||||
|
const _reFullWs = /^\s*$/;
|
||||||
|
function unindent(str) {
|
||||||
|
const lines = (typeof str === "string" ? str : str[0]).split("\n");
|
||||||
|
const whitespaceLines = lines.map((line) => _reFullWs.test(line));
|
||||||
|
const commonIndent = lines.reduce((min, line, idx) => {
|
||||||
|
var _a;
|
||||||
|
if (whitespaceLines[idx])
|
||||||
|
return min;
|
||||||
|
const indent = (_a = line.match(/^\s*/)) == null ? void 0 : _a[0].length;
|
||||||
|
return indent === void 0 ? min : Math.min(min, indent);
|
||||||
|
}, Number.POSITIVE_INFINITY);
|
||||||
|
let emptyLinesHead = 0;
|
||||||
|
while (emptyLinesHead < lines.length && whitespaceLines[emptyLinesHead])
|
||||||
|
emptyLinesHead++;
|
||||||
|
let emptyLinesTail = 0;
|
||||||
|
while (emptyLinesTail < lines.length && whitespaceLines[lines.length - emptyLinesTail - 1])
|
||||||
|
emptyLinesTail++;
|
||||||
|
return lines.slice(emptyLinesHead, lines.length - emptyLinesTail).map((line) => line.slice(commonIndent)).join("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
const timestamp = () => +Date.now();
|
||||||
|
|
||||||
|
function batchInvoke(functions) {
|
||||||
|
functions.forEach((fn) => fn && fn());
|
||||||
|
}
|
||||||
|
function invoke(fn) {
|
||||||
|
return fn();
|
||||||
|
}
|
||||||
|
function tap(value, callback) {
|
||||||
|
callback(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function objectMap(obj, fn) {
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(obj).map(([k, v]) => fn(k, v)).filter(notNullish)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
function isKeyOf(obj, k) {
|
||||||
|
return k in obj;
|
||||||
|
}
|
||||||
|
function objectKeys(obj) {
|
||||||
|
return Object.keys(obj);
|
||||||
|
}
|
||||||
|
function objectEntries(obj) {
|
||||||
|
return Object.entries(obj);
|
||||||
|
}
|
||||||
|
function deepMerge(target, ...sources) {
|
||||||
|
if (!sources.length)
|
||||||
|
return target;
|
||||||
|
const source = sources.shift();
|
||||||
|
if (source === void 0)
|
||||||
|
return target;
|
||||||
|
if (isMergableObject(target) && isMergableObject(source)) {
|
||||||
|
objectKeys(source).forEach((key) => {
|
||||||
|
if (key === "__proto__" || key === "constructor" || key === "prototype")
|
||||||
|
return;
|
||||||
|
if (isMergableObject(source[key])) {
|
||||||
|
if (!target[key])
|
||||||
|
target[key] = {};
|
||||||
|
if (isMergableObject(target[key])) {
|
||||||
|
deepMerge(target[key], source[key]);
|
||||||
|
} else {
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return deepMerge(target, ...sources);
|
||||||
|
}
|
||||||
|
function deepMergeWithArray(target, ...sources) {
|
||||||
|
if (!sources.length)
|
||||||
|
return target;
|
||||||
|
const source = sources.shift();
|
||||||
|
if (source === void 0)
|
||||||
|
return target;
|
||||||
|
if (Array.isArray(target) && Array.isArray(source))
|
||||||
|
target.push(...source);
|
||||||
|
if (isMergableObject(target) && isMergableObject(source)) {
|
||||||
|
objectKeys(source).forEach((key) => {
|
||||||
|
if (key === "__proto__" || key === "constructor" || key === "prototype")
|
||||||
|
return;
|
||||||
|
if (Array.isArray(source[key])) {
|
||||||
|
if (!target[key])
|
||||||
|
target[key] = [];
|
||||||
|
deepMergeWithArray(target[key], source[key]);
|
||||||
|
} else if (isMergableObject(source[key])) {
|
||||||
|
if (!target[key])
|
||||||
|
target[key] = {};
|
||||||
|
deepMergeWithArray(target[key], source[key]);
|
||||||
|
} else {
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return deepMergeWithArray(target, ...sources);
|
||||||
|
}
|
||||||
|
function isMergableObject(item) {
|
||||||
|
return isObject(item) && !Array.isArray(item);
|
||||||
|
}
|
||||||
|
function objectPick(obj, keys, omitUndefined = false) {
|
||||||
|
return keys.reduce((n, k) => {
|
||||||
|
if (k in obj) {
|
||||||
|
if (!omitUndefined || obj[k] !== void 0)
|
||||||
|
n[k] = obj[k];
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
function clearUndefined(obj) {
|
||||||
|
Object.keys(obj).forEach((key) => obj[key] === void 0 ? delete obj[key] : {});
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
function hasOwnProperty(obj, v) {
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
return Object.prototype.hasOwnProperty.call(obj, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createSingletonPromise(fn) {
|
||||||
|
let _promise;
|
||||||
|
function wrapper() {
|
||||||
|
if (!_promise)
|
||||||
|
_promise = fn();
|
||||||
|
return _promise;
|
||||||
|
}
|
||||||
|
wrapper.reset = async () => {
|
||||||
|
const _prev = _promise;
|
||||||
|
_promise = void 0;
|
||||||
|
if (_prev)
|
||||||
|
await _prev;
|
||||||
|
};
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
function sleep(ms, callback) {
|
||||||
|
return new Promise(
|
||||||
|
(resolve) => setTimeout(async () => {
|
||||||
|
await (callback == null ? void 0 : callback());
|
||||||
|
resolve();
|
||||||
|
}, ms)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
function createPromiseLock() {
|
||||||
|
const locks = [];
|
||||||
|
return {
|
||||||
|
async run(fn) {
|
||||||
|
const p = fn();
|
||||||
|
locks.push(p);
|
||||||
|
try {
|
||||||
|
return await p;
|
||||||
|
} finally {
|
||||||
|
remove(locks, p);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async wait() {
|
||||||
|
await Promise.allSettled(locks);
|
||||||
|
},
|
||||||
|
isWaiting() {
|
||||||
|
return Boolean(locks.length);
|
||||||
|
},
|
||||||
|
clear() {
|
||||||
|
locks.length = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function createControlledPromise() {
|
||||||
|
let resolve, reject;
|
||||||
|
const promise = new Promise((_resolve, _reject) => {
|
||||||
|
resolve = _resolve;
|
||||||
|
reject = _reject;
|
||||||
|
});
|
||||||
|
promise.resolve = resolve;
|
||||||
|
promise.reject = reject;
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-disable no-undefined,no-param-reassign,no-shadow */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throttle execution of a function. Especially useful for rate limiting
|
||||||
|
* execution of handlers on events like resize and scroll.
|
||||||
|
*
|
||||||
|
* @param {number} delay - A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher)
|
||||||
|
* are most useful.
|
||||||
|
* @param {Function} callback - A function to be executed after delay milliseconds. The `this` context and all arguments are passed through,
|
||||||
|
* as-is, to `callback` when the throttled-function is executed.
|
||||||
|
* @param {object} [options] - An object to configure options.
|
||||||
|
* @param {boolean} [options.noTrailing] - Optional, defaults to false. If noTrailing is true, callback will only execute every `delay` milliseconds
|
||||||
|
* while the throttled-function is being called. If noTrailing is false or unspecified, callback will be executed
|
||||||
|
* one final time after the last throttled-function call. (After the throttled-function has not been called for
|
||||||
|
* `delay` milliseconds, the internal counter is reset).
|
||||||
|
* @param {boolean} [options.noLeading] - Optional, defaults to false. If noLeading is false, the first throttled-function call will execute callback
|
||||||
|
* immediately. If noLeading is true, the first the callback execution will be skipped. It should be noted that
|
||||||
|
* callback will never executed if both noLeading = true and noTrailing = true.
|
||||||
|
* @param {boolean} [options.debounceMode] - If `debounceMode` is true (at begin), schedule `clear` to execute after `delay` ms. If `debounceMode` is
|
||||||
|
* false (at end), schedule `callback` to execute after `delay` ms.
|
||||||
|
*
|
||||||
|
* @returns {Function} A new, throttled, function.
|
||||||
|
*/
|
||||||
|
function throttle (delay, callback, options) {
|
||||||
|
var _ref = options || {},
|
||||||
|
_ref$noTrailing = _ref.noTrailing,
|
||||||
|
noTrailing = _ref$noTrailing === void 0 ? false : _ref$noTrailing,
|
||||||
|
_ref$noLeading = _ref.noLeading,
|
||||||
|
noLeading = _ref$noLeading === void 0 ? false : _ref$noLeading,
|
||||||
|
_ref$debounceMode = _ref.debounceMode,
|
||||||
|
debounceMode = _ref$debounceMode === void 0 ? undefined : _ref$debounceMode;
|
||||||
|
/*
|
||||||
|
* After wrapper has stopped being called, this timeout ensures that
|
||||||
|
* `callback` is executed at the proper times in `throttle` and `end`
|
||||||
|
* debounce modes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
var timeoutID;
|
||||||
|
var cancelled = false; // Keep track of the last time `callback` was executed.
|
||||||
|
|
||||||
|
var lastExec = 0; // Function to clear existing timeout
|
||||||
|
|
||||||
|
function clearExistingTimeout() {
|
||||||
|
if (timeoutID) {
|
||||||
|
clearTimeout(timeoutID);
|
||||||
|
}
|
||||||
|
} // Function to cancel next exec
|
||||||
|
|
||||||
|
|
||||||
|
function cancel(options) {
|
||||||
|
var _ref2 = options || {},
|
||||||
|
_ref2$upcomingOnly = _ref2.upcomingOnly,
|
||||||
|
upcomingOnly = _ref2$upcomingOnly === void 0 ? false : _ref2$upcomingOnly;
|
||||||
|
|
||||||
|
clearExistingTimeout();
|
||||||
|
cancelled = !upcomingOnly;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* The `wrapper` function encapsulates all of the throttling / debouncing
|
||||||
|
* functionality and when executed will limit the rate at which `callback`
|
||||||
|
* is executed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
function wrapper() {
|
||||||
|
for (var _len = arguments.length, arguments_ = new Array(_len), _key = 0; _key < _len; _key++) {
|
||||||
|
arguments_[_key] = arguments[_key];
|
||||||
|
}
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
var elapsed = Date.now() - lastExec;
|
||||||
|
|
||||||
|
if (cancelled) {
|
||||||
|
return;
|
||||||
|
} // Execute `callback` and update the `lastExec` timestamp.
|
||||||
|
|
||||||
|
|
||||||
|
function exec() {
|
||||||
|
lastExec = Date.now();
|
||||||
|
callback.apply(self, arguments_);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If `debounceMode` is true (at begin) this is used to clear the flag
|
||||||
|
* to allow future `callback` executions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
function clear() {
|
||||||
|
timeoutID = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!noLeading && debounceMode && !timeoutID) {
|
||||||
|
/*
|
||||||
|
* Since `wrapper` is being called for the first time and
|
||||||
|
* `debounceMode` is true (at begin), execute `callback`
|
||||||
|
* and noLeading != true.
|
||||||
|
*/
|
||||||
|
exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
clearExistingTimeout();
|
||||||
|
|
||||||
|
if (debounceMode === undefined && elapsed > delay) {
|
||||||
|
if (noLeading) {
|
||||||
|
/*
|
||||||
|
* In throttle mode with noLeading, if `delay` time has
|
||||||
|
* been exceeded, update `lastExec` and schedule `callback`
|
||||||
|
* to execute after `delay` ms.
|
||||||
|
*/
|
||||||
|
lastExec = Date.now();
|
||||||
|
|
||||||
|
if (!noTrailing) {
|
||||||
|
timeoutID = setTimeout(debounceMode ? clear : exec, delay);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* In throttle mode without noLeading, if `delay` time has been exceeded, execute
|
||||||
|
* `callback`.
|
||||||
|
*/
|
||||||
|
exec();
|
||||||
|
}
|
||||||
|
} else if (noTrailing !== true) {
|
||||||
|
/*
|
||||||
|
* In trailing throttle mode, since `delay` time has not been
|
||||||
|
* exceeded, schedule `callback` to execute `delay` ms after most
|
||||||
|
* recent execution.
|
||||||
|
*
|
||||||
|
* If `debounceMode` is true (at begin), schedule `clear` to execute
|
||||||
|
* after `delay` ms.
|
||||||
|
*
|
||||||
|
* If `debounceMode` is false (at end), schedule `callback` to
|
||||||
|
* execute after `delay` ms.
|
||||||
|
*/
|
||||||
|
timeoutID = setTimeout(debounceMode ? clear : exec, debounceMode === undefined ? delay - elapsed : delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper.cancel = cancel; // Return the wrapper function.
|
||||||
|
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-disable no-undefined */
|
||||||
|
/**
|
||||||
|
* Debounce execution of a function. Debouncing, unlike throttling,
|
||||||
|
* guarantees that a function is only executed a single time, either at the
|
||||||
|
* very beginning of a series of calls, or at the very end.
|
||||||
|
*
|
||||||
|
* @param {number} delay - A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.
|
||||||
|
* @param {Function} callback - A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is,
|
||||||
|
* to `callback` when the debounced-function is executed.
|
||||||
|
* @param {object} [options] - An object to configure options.
|
||||||
|
* @param {boolean} [options.atBegin] - Optional, defaults to false. If atBegin is false or unspecified, callback will only be executed `delay` milliseconds
|
||||||
|
* after the last debounced-function call. If atBegin is true, callback will be executed only at the first debounced-function call.
|
||||||
|
* (After the throttled-function has not been called for `delay` milliseconds, the internal counter is reset).
|
||||||
|
*
|
||||||
|
* @returns {Function} A new, debounced function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function debounce (delay, callback, options) {
|
||||||
|
var _ref = options || {},
|
||||||
|
_ref$atBegin = _ref.atBegin,
|
||||||
|
atBegin = _ref$atBegin === void 0 ? false : _ref$atBegin;
|
||||||
|
|
||||||
|
return throttle(delay, callback, {
|
||||||
|
debounceMode: atBegin !== false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
How it works:
|
||||||
|
`this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Node {
|
||||||
|
value;
|
||||||
|
next;
|
||||||
|
|
||||||
|
constructor(value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Queue {
|
||||||
|
#head;
|
||||||
|
#tail;
|
||||||
|
#size;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
enqueue(value) {
|
||||||
|
const node = new Node(value);
|
||||||
|
|
||||||
|
if (this.#head) {
|
||||||
|
this.#tail.next = node;
|
||||||
|
this.#tail = node;
|
||||||
|
} else {
|
||||||
|
this.#head = node;
|
||||||
|
this.#tail = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dequeue() {
|
||||||
|
const current = this.#head;
|
||||||
|
if (!current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#head = this.#head.next;
|
||||||
|
this.#size--;
|
||||||
|
return current.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.#head = undefined;
|
||||||
|
this.#tail = undefined;
|
||||||
|
this.#size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get size() {
|
||||||
|
return this.#size;
|
||||||
|
}
|
||||||
|
|
||||||
|
* [Symbol.iterator]() {
|
||||||
|
let current = this.#head;
|
||||||
|
|
||||||
|
while (current) {
|
||||||
|
yield current.value;
|
||||||
|
current = current.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const AsyncResource = {
|
||||||
|
bind(fn, _type, thisArg) {
|
||||||
|
return fn.bind(thisArg);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function pLimit(concurrency) {
|
||||||
|
if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {
|
||||||
|
throw new TypeError('Expected `concurrency` to be a number from 1 and up');
|
||||||
|
}
|
||||||
|
|
||||||
|
const queue = new Queue();
|
||||||
|
let activeCount = 0;
|
||||||
|
|
||||||
|
const next = () => {
|
||||||
|
activeCount--;
|
||||||
|
|
||||||
|
if (queue.size > 0) {
|
||||||
|
queue.dequeue()();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const run = async (function_, resolve, arguments_) => {
|
||||||
|
activeCount++;
|
||||||
|
|
||||||
|
const result = (async () => function_(...arguments_))();
|
||||||
|
|
||||||
|
resolve(result);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await result;
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
|
||||||
|
const enqueue = (function_, resolve, arguments_) => {
|
||||||
|
queue.enqueue(
|
||||||
|
AsyncResource.bind(run.bind(undefined, function_, resolve, arguments_)),
|
||||||
|
);
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
// This function needs to wait until the next microtask before comparing
|
||||||
|
// `activeCount` to `concurrency`, because `activeCount` is updated asynchronously
|
||||||
|
// when the run function is dequeued and called. The comparison in the if-statement
|
||||||
|
// needs to happen asynchronously as well to get an up-to-date value for `activeCount`.
|
||||||
|
await Promise.resolve();
|
||||||
|
|
||||||
|
if (activeCount < concurrency && queue.size > 0) {
|
||||||
|
queue.dequeue()();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
|
||||||
|
const generator = (function_, ...arguments_) => new Promise(resolve => {
|
||||||
|
enqueue(function_, resolve, arguments_);
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperties(generator, {
|
||||||
|
activeCount: {
|
||||||
|
get: () => activeCount,
|
||||||
|
},
|
||||||
|
pendingCount: {
|
||||||
|
get: () => queue.size,
|
||||||
|
},
|
||||||
|
clearQueue: {
|
||||||
|
value() {
|
||||||
|
queue.clear();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return generator;
|
||||||
|
}
|
||||||
|
|
||||||
|
const VOID = Symbol("p-void");
|
||||||
|
class PInstance extends Promise {
|
||||||
|
constructor(items = [], options) {
|
||||||
|
super(() => {
|
||||||
|
});
|
||||||
|
this.items = items;
|
||||||
|
this.options = options;
|
||||||
|
this.promises = /* @__PURE__ */ new Set();
|
||||||
|
}
|
||||||
|
get promise() {
|
||||||
|
var _a;
|
||||||
|
let batch;
|
||||||
|
const items = [...Array.from(this.items), ...Array.from(this.promises)];
|
||||||
|
if ((_a = this.options) == null ? void 0 : _a.concurrency) {
|
||||||
|
const limit = pLimit(this.options.concurrency);
|
||||||
|
batch = Promise.all(items.map((p2) => limit(() => p2)));
|
||||||
|
} else {
|
||||||
|
batch = Promise.all(items);
|
||||||
|
}
|
||||||
|
return batch.then((l) => l.filter((i) => i !== VOID));
|
||||||
|
}
|
||||||
|
add(...args) {
|
||||||
|
args.forEach((i) => {
|
||||||
|
this.promises.add(i);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
map(fn) {
|
||||||
|
return new PInstance(
|
||||||
|
Array.from(this.items).map(async (i, idx) => {
|
||||||
|
const v = await i;
|
||||||
|
if (v === VOID)
|
||||||
|
return VOID;
|
||||||
|
return fn(v, idx);
|
||||||
|
}),
|
||||||
|
this.options
|
||||||
|
);
|
||||||
|
}
|
||||||
|
filter(fn) {
|
||||||
|
return new PInstance(
|
||||||
|
Array.from(this.items).map(async (i, idx) => {
|
||||||
|
const v = await i;
|
||||||
|
const r = await fn(v, idx);
|
||||||
|
if (!r)
|
||||||
|
return VOID;
|
||||||
|
return v;
|
||||||
|
}),
|
||||||
|
this.options
|
||||||
|
);
|
||||||
|
}
|
||||||
|
forEach(fn) {
|
||||||
|
return this.map(fn).then();
|
||||||
|
}
|
||||||
|
reduce(fn, initialValue) {
|
||||||
|
return this.promise.then((array) => array.reduce(fn, initialValue));
|
||||||
|
}
|
||||||
|
clear() {
|
||||||
|
this.promises.clear();
|
||||||
|
}
|
||||||
|
then(fn) {
|
||||||
|
const p2 = this.promise;
|
||||||
|
if (fn)
|
||||||
|
return p2.then(fn);
|
||||||
|
else
|
||||||
|
return p2;
|
||||||
|
}
|
||||||
|
catch(fn) {
|
||||||
|
return this.promise.catch(fn);
|
||||||
|
}
|
||||||
|
finally(fn) {
|
||||||
|
return this.promise.finally(fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function p(items, options) {
|
||||||
|
return new PInstance(items, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { assert, at, batchInvoke, capitalize, clamp, clampArrayRange, clearUndefined, createControlledPromise, createPromiseLock, createSingletonPromise, debounce, deepMerge, deepMergeWithArray, ensurePrefix, ensureSuffix, flattenArrayable, getTypeName, hasOwnProperty, invoke, isBoolean, isBrowser, isDate, isDeepEqual, isDef, isFunction, isKeyOf, isNull, isNumber, isObject, isRegExp, isString, isTruthy, isUndefined, isWindow, last, lerp, mergeArrayable, move, noNull, noop, notNullish, notUndefined, objectEntries, objectKeys, objectMap, objectPick, p, partition, randomStr, range, remap, remove, sample, shuffle, slash, sleep, sum, tap, template, throttle, timestamp, toArray, toString, unindent, uniq, uniqueBy };
|
@ -0,0 +1,67 @@
|
|||||||
|
{
|
||||||
|
"name": "@antfu/utils",
|
||||||
|
"type": "module",
|
||||||
|
"version": "0.7.10",
|
||||||
|
"packageManager": "pnpm@9.1.0",
|
||||||
|
"description": "Opinionated collection of common JavaScript / TypeScript utils by @antfu",
|
||||||
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": "https://github.com/sponsors/antfu",
|
||||||
|
"homepage": "https://github.com/antfu/utils#readme",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/antfu/utils.git"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/antfu/utils/issues"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"utils"
|
||||||
|
],
|
||||||
|
"sideEffects": false,
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"import": "./dist/index.mjs",
|
||||||
|
"require": "./dist/index.cjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"main": "dist/index.cjs",
|
||||||
|
"module": "dist/index.mjs",
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"build": "rollup -c",
|
||||||
|
"dev": "nr build --watch",
|
||||||
|
"lint": "eslint .",
|
||||||
|
"lint-fix": "nr lint --fix",
|
||||||
|
"prepublishOnly": "npm run build",
|
||||||
|
"release": "bumpp --commit --push --tag && npm publish",
|
||||||
|
"start": "esno src/index.ts",
|
||||||
|
"typecheck": "tsc --noEmit",
|
||||||
|
"test": "vitest"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@antfu/eslint-config": "^2.16.3",
|
||||||
|
"@antfu/ni": "^0.21.12",
|
||||||
|
"@rollup/plugin-alias": "^5.1.0",
|
||||||
|
"@rollup/plugin-commonjs": "^25.0.7",
|
||||||
|
"@rollup/plugin-json": "^6.1.0",
|
||||||
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||||
|
"@types/node": "^20.12.10",
|
||||||
|
"@types/throttle-debounce": "^5.0.2",
|
||||||
|
"bumpp": "^9.4.1",
|
||||||
|
"eslint": "npm:eslint-ts-patch@8.55.0-1",
|
||||||
|
"eslint-ts-patch": "8.55.0-1",
|
||||||
|
"esno": "^4.7.0",
|
||||||
|
"p-limit": "^5.0.0",
|
||||||
|
"rollup": "^4.17.2",
|
||||||
|
"rollup-plugin-dts": "^6.1.0",
|
||||||
|
"rollup-plugin-esbuild": "^6.1.1",
|
||||||
|
"throttle-debounce": "5.0.0",
|
||||||
|
"typescript": "^5.4.5",
|
||||||
|
"vite": "^5.2.11",
|
||||||
|
"vitest": "^1.6.0"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2015 Rich Harris
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
@ -0,0 +1,424 @@
|
|||||||
|
const comma = ','.charCodeAt(0);
|
||||||
|
const semicolon = ';'.charCodeAt(0);
|
||||||
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||||
|
const intToChar = new Uint8Array(64); // 64 possible chars.
|
||||||
|
const charToInt = new Uint8Array(128); // z is 122 in ASCII
|
||||||
|
for (let i = 0; i < chars.length; i++) {
|
||||||
|
const c = chars.charCodeAt(i);
|
||||||
|
intToChar[i] = c;
|
||||||
|
charToInt[c] = i;
|
||||||
|
}
|
||||||
|
function decodeInteger(reader, relative) {
|
||||||
|
let value = 0;
|
||||||
|
let shift = 0;
|
||||||
|
let integer = 0;
|
||||||
|
do {
|
||||||
|
const c = reader.next();
|
||||||
|
integer = charToInt[c];
|
||||||
|
value |= (integer & 31) << shift;
|
||||||
|
shift += 5;
|
||||||
|
} while (integer & 32);
|
||||||
|
const shouldNegate = value & 1;
|
||||||
|
value >>>= 1;
|
||||||
|
if (shouldNegate) {
|
||||||
|
value = -0x80000000 | -value;
|
||||||
|
}
|
||||||
|
return relative + value;
|
||||||
|
}
|
||||||
|
function encodeInteger(builder, num, relative) {
|
||||||
|
let delta = num - relative;
|
||||||
|
delta = delta < 0 ? (-delta << 1) | 1 : delta << 1;
|
||||||
|
do {
|
||||||
|
let clamped = delta & 0b011111;
|
||||||
|
delta >>>= 5;
|
||||||
|
if (delta > 0)
|
||||||
|
clamped |= 0b100000;
|
||||||
|
builder.write(intToChar[clamped]);
|
||||||
|
} while (delta > 0);
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
function hasMoreVlq(reader, max) {
|
||||||
|
if (reader.pos >= max)
|
||||||
|
return false;
|
||||||
|
return reader.peek() !== comma;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bufLength = 1024 * 16;
|
||||||
|
// Provide a fallback for older environments.
|
||||||
|
const td = typeof TextDecoder !== 'undefined'
|
||||||
|
? /* #__PURE__ */ new TextDecoder()
|
||||||
|
: typeof Buffer !== 'undefined'
|
||||||
|
? {
|
||||||
|
decode(buf) {
|
||||||
|
const out = Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength);
|
||||||
|
return out.toString();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
decode(buf) {
|
||||||
|
let out = '';
|
||||||
|
for (let i = 0; i < buf.length; i++) {
|
||||||
|
out += String.fromCharCode(buf[i]);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
class StringWriter {
|
||||||
|
constructor() {
|
||||||
|
this.pos = 0;
|
||||||
|
this.out = '';
|
||||||
|
this.buffer = new Uint8Array(bufLength);
|
||||||
|
}
|
||||||
|
write(v) {
|
||||||
|
const { buffer } = this;
|
||||||
|
buffer[this.pos++] = v;
|
||||||
|
if (this.pos === bufLength) {
|
||||||
|
this.out += td.decode(buffer);
|
||||||
|
this.pos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flush() {
|
||||||
|
const { buffer, out, pos } = this;
|
||||||
|
return pos > 0 ? out + td.decode(buffer.subarray(0, pos)) : out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class StringReader {
|
||||||
|
constructor(buffer) {
|
||||||
|
this.pos = 0;
|
||||||
|
this.buffer = buffer;
|
||||||
|
}
|
||||||
|
next() {
|
||||||
|
return this.buffer.charCodeAt(this.pos++);
|
||||||
|
}
|
||||||
|
peek() {
|
||||||
|
return this.buffer.charCodeAt(this.pos);
|
||||||
|
}
|
||||||
|
indexOf(char) {
|
||||||
|
const { buffer, pos } = this;
|
||||||
|
const idx = buffer.indexOf(char, pos);
|
||||||
|
return idx === -1 ? buffer.length : idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const EMPTY = [];
|
||||||
|
function decodeOriginalScopes(input) {
|
||||||
|
const { length } = input;
|
||||||
|
const reader = new StringReader(input);
|
||||||
|
const scopes = [];
|
||||||
|
const stack = [];
|
||||||
|
let line = 0;
|
||||||
|
for (; reader.pos < length; reader.pos++) {
|
||||||
|
line = decodeInteger(reader, line);
|
||||||
|
const column = decodeInteger(reader, 0);
|
||||||
|
if (!hasMoreVlq(reader, length)) {
|
||||||
|
const last = stack.pop();
|
||||||
|
last[2] = line;
|
||||||
|
last[3] = column;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const kind = decodeInteger(reader, 0);
|
||||||
|
const fields = decodeInteger(reader, 0);
|
||||||
|
const hasName = fields & 0b0001;
|
||||||
|
const scope = (hasName ? [line, column, 0, 0, kind, decodeInteger(reader, 0)] : [line, column, 0, 0, kind]);
|
||||||
|
let vars = EMPTY;
|
||||||
|
if (hasMoreVlq(reader, length)) {
|
||||||
|
vars = [];
|
||||||
|
do {
|
||||||
|
const varsIndex = decodeInteger(reader, 0);
|
||||||
|
vars.push(varsIndex);
|
||||||
|
} while (hasMoreVlq(reader, length));
|
||||||
|
}
|
||||||
|
scope.vars = vars;
|
||||||
|
scopes.push(scope);
|
||||||
|
stack.push(scope);
|
||||||
|
}
|
||||||
|
return scopes;
|
||||||
|
}
|
||||||
|
function encodeOriginalScopes(scopes) {
|
||||||
|
const writer = new StringWriter();
|
||||||
|
for (let i = 0; i < scopes.length;) {
|
||||||
|
i = _encodeOriginalScopes(scopes, i, writer, [0]);
|
||||||
|
}
|
||||||
|
return writer.flush();
|
||||||
|
}
|
||||||
|
function _encodeOriginalScopes(scopes, index, writer, state) {
|
||||||
|
const scope = scopes[index];
|
||||||
|
const { 0: startLine, 1: startColumn, 2: endLine, 3: endColumn, 4: kind, vars } = scope;
|
||||||
|
if (index > 0)
|
||||||
|
writer.write(comma);
|
||||||
|
state[0] = encodeInteger(writer, startLine, state[0]);
|
||||||
|
encodeInteger(writer, startColumn, 0);
|
||||||
|
encodeInteger(writer, kind, 0);
|
||||||
|
const fields = scope.length === 6 ? 0b0001 : 0;
|
||||||
|
encodeInteger(writer, fields, 0);
|
||||||
|
if (scope.length === 6)
|
||||||
|
encodeInteger(writer, scope[5], 0);
|
||||||
|
for (const v of vars) {
|
||||||
|
encodeInteger(writer, v, 0);
|
||||||
|
}
|
||||||
|
for (index++; index < scopes.length;) {
|
||||||
|
const next = scopes[index];
|
||||||
|
const { 0: l, 1: c } = next;
|
||||||
|
if (l > endLine || (l === endLine && c >= endColumn)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index = _encodeOriginalScopes(scopes, index, writer, state);
|
||||||
|
}
|
||||||
|
writer.write(comma);
|
||||||
|
state[0] = encodeInteger(writer, endLine, state[0]);
|
||||||
|
encodeInteger(writer, endColumn, 0);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
function decodeGeneratedRanges(input) {
|
||||||
|
const { length } = input;
|
||||||
|
const reader = new StringReader(input);
|
||||||
|
const ranges = [];
|
||||||
|
const stack = [];
|
||||||
|
let genLine = 0;
|
||||||
|
let definitionSourcesIndex = 0;
|
||||||
|
let definitionScopeIndex = 0;
|
||||||
|
let callsiteSourcesIndex = 0;
|
||||||
|
let callsiteLine = 0;
|
||||||
|
let callsiteColumn = 0;
|
||||||
|
let bindingLine = 0;
|
||||||
|
let bindingColumn = 0;
|
||||||
|
do {
|
||||||
|
const semi = reader.indexOf(';');
|
||||||
|
let genColumn = 0;
|
||||||
|
for (; reader.pos < semi; reader.pos++) {
|
||||||
|
genColumn = decodeInteger(reader, genColumn);
|
||||||
|
if (!hasMoreVlq(reader, semi)) {
|
||||||
|
const last = stack.pop();
|
||||||
|
last[2] = genLine;
|
||||||
|
last[3] = genColumn;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const fields = decodeInteger(reader, 0);
|
||||||
|
const hasDefinition = fields & 0b0001;
|
||||||
|
const hasCallsite = fields & 0b0010;
|
||||||
|
const hasScope = fields & 0b0100;
|
||||||
|
let callsite = null;
|
||||||
|
let bindings = EMPTY;
|
||||||
|
let range;
|
||||||
|
if (hasDefinition) {
|
||||||
|
const defSourcesIndex = decodeInteger(reader, definitionSourcesIndex);
|
||||||
|
definitionScopeIndex = decodeInteger(reader, definitionSourcesIndex === defSourcesIndex ? definitionScopeIndex : 0);
|
||||||
|
definitionSourcesIndex = defSourcesIndex;
|
||||||
|
range = [genLine, genColumn, 0, 0, defSourcesIndex, definitionScopeIndex];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
range = [genLine, genColumn, 0, 0];
|
||||||
|
}
|
||||||
|
range.isScope = !!hasScope;
|
||||||
|
if (hasCallsite) {
|
||||||
|
const prevCsi = callsiteSourcesIndex;
|
||||||
|
const prevLine = callsiteLine;
|
||||||
|
callsiteSourcesIndex = decodeInteger(reader, callsiteSourcesIndex);
|
||||||
|
const sameSource = prevCsi === callsiteSourcesIndex;
|
||||||
|
callsiteLine = decodeInteger(reader, sameSource ? callsiteLine : 0);
|
||||||
|
callsiteColumn = decodeInteger(reader, sameSource && prevLine === callsiteLine ? callsiteColumn : 0);
|
||||||
|
callsite = [callsiteSourcesIndex, callsiteLine, callsiteColumn];
|
||||||
|
}
|
||||||
|
range.callsite = callsite;
|
||||||
|
if (hasMoreVlq(reader, semi)) {
|
||||||
|
bindings = [];
|
||||||
|
do {
|
||||||
|
bindingLine = genLine;
|
||||||
|
bindingColumn = genColumn;
|
||||||
|
const expressionsCount = decodeInteger(reader, 0);
|
||||||
|
let expressionRanges;
|
||||||
|
if (expressionsCount < -1) {
|
||||||
|
expressionRanges = [[decodeInteger(reader, 0)]];
|
||||||
|
for (let i = -1; i > expressionsCount; i--) {
|
||||||
|
const prevBl = bindingLine;
|
||||||
|
bindingLine = decodeInteger(reader, bindingLine);
|
||||||
|
bindingColumn = decodeInteger(reader, bindingLine === prevBl ? bindingColumn : 0);
|
||||||
|
const expression = decodeInteger(reader, 0);
|
||||||
|
expressionRanges.push([expression, bindingLine, bindingColumn]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
expressionRanges = [[expressionsCount]];
|
||||||
|
}
|
||||||
|
bindings.push(expressionRanges);
|
||||||
|
} while (hasMoreVlq(reader, semi));
|
||||||
|
}
|
||||||
|
range.bindings = bindings;
|
||||||
|
ranges.push(range);
|
||||||
|
stack.push(range);
|
||||||
|
}
|
||||||
|
genLine++;
|
||||||
|
reader.pos = semi + 1;
|
||||||
|
} while (reader.pos < length);
|
||||||
|
return ranges;
|
||||||
|
}
|
||||||
|
function encodeGeneratedRanges(ranges) {
|
||||||
|
if (ranges.length === 0)
|
||||||
|
return '';
|
||||||
|
const writer = new StringWriter();
|
||||||
|
for (let i = 0; i < ranges.length;) {
|
||||||
|
i = _encodeGeneratedRanges(ranges, i, writer, [0, 0, 0, 0, 0, 0, 0]);
|
||||||
|
}
|
||||||
|
return writer.flush();
|
||||||
|
}
|
||||||
|
function _encodeGeneratedRanges(ranges, index, writer, state) {
|
||||||
|
const range = ranges[index];
|
||||||
|
const { 0: startLine, 1: startColumn, 2: endLine, 3: endColumn, isScope, callsite, bindings, } = range;
|
||||||
|
if (state[0] < startLine) {
|
||||||
|
catchupLine(writer, state[0], startLine);
|
||||||
|
state[0] = startLine;
|
||||||
|
state[1] = 0;
|
||||||
|
}
|
||||||
|
else if (index > 0) {
|
||||||
|
writer.write(comma);
|
||||||
|
}
|
||||||
|
state[1] = encodeInteger(writer, range[1], state[1]);
|
||||||
|
const fields = (range.length === 6 ? 0b0001 : 0) | (callsite ? 0b0010 : 0) | (isScope ? 0b0100 : 0);
|
||||||
|
encodeInteger(writer, fields, 0);
|
||||||
|
if (range.length === 6) {
|
||||||
|
const { 4: sourcesIndex, 5: scopesIndex } = range;
|
||||||
|
if (sourcesIndex !== state[2]) {
|
||||||
|
state[3] = 0;
|
||||||
|
}
|
||||||
|
state[2] = encodeInteger(writer, sourcesIndex, state[2]);
|
||||||
|
state[3] = encodeInteger(writer, scopesIndex, state[3]);
|
||||||
|
}
|
||||||
|
if (callsite) {
|
||||||
|
const { 0: sourcesIndex, 1: callLine, 2: callColumn } = range.callsite;
|
||||||
|
if (sourcesIndex !== state[4]) {
|
||||||
|
state[5] = 0;
|
||||||
|
state[6] = 0;
|
||||||
|
}
|
||||||
|
else if (callLine !== state[5]) {
|
||||||
|
state[6] = 0;
|
||||||
|
}
|
||||||
|
state[4] = encodeInteger(writer, sourcesIndex, state[4]);
|
||||||
|
state[5] = encodeInteger(writer, callLine, state[5]);
|
||||||
|
state[6] = encodeInteger(writer, callColumn, state[6]);
|
||||||
|
}
|
||||||
|
if (bindings) {
|
||||||
|
for (const binding of bindings) {
|
||||||
|
if (binding.length > 1)
|
||||||
|
encodeInteger(writer, -binding.length, 0);
|
||||||
|
const expression = binding[0][0];
|
||||||
|
encodeInteger(writer, expression, 0);
|
||||||
|
let bindingStartLine = startLine;
|
||||||
|
let bindingStartColumn = startColumn;
|
||||||
|
for (let i = 1; i < binding.length; i++) {
|
||||||
|
const expRange = binding[i];
|
||||||
|
bindingStartLine = encodeInteger(writer, expRange[1], bindingStartLine);
|
||||||
|
bindingStartColumn = encodeInteger(writer, expRange[2], bindingStartColumn);
|
||||||
|
encodeInteger(writer, expRange[0], 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (index++; index < ranges.length;) {
|
||||||
|
const next = ranges[index];
|
||||||
|
const { 0: l, 1: c } = next;
|
||||||
|
if (l > endLine || (l === endLine && c >= endColumn)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index = _encodeGeneratedRanges(ranges, index, writer, state);
|
||||||
|
}
|
||||||
|
if (state[0] < endLine) {
|
||||||
|
catchupLine(writer, state[0], endLine);
|
||||||
|
state[0] = endLine;
|
||||||
|
state[1] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
writer.write(comma);
|
||||||
|
}
|
||||||
|
state[1] = encodeInteger(writer, endColumn, state[1]);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
function catchupLine(writer, lastLine, line) {
|
||||||
|
do {
|
||||||
|
writer.write(semicolon);
|
||||||
|
} while (++lastLine < line);
|
||||||
|
}
|
||||||
|
|
||||||
|
function decode(mappings) {
|
||||||
|
const { length } = mappings;
|
||||||
|
const reader = new StringReader(mappings);
|
||||||
|
const decoded = [];
|
||||||
|
let genColumn = 0;
|
||||||
|
let sourcesIndex = 0;
|
||||||
|
let sourceLine = 0;
|
||||||
|
let sourceColumn = 0;
|
||||||
|
let namesIndex = 0;
|
||||||
|
do {
|
||||||
|
const semi = reader.indexOf(';');
|
||||||
|
const line = [];
|
||||||
|
let sorted = true;
|
||||||
|
let lastCol = 0;
|
||||||
|
genColumn = 0;
|
||||||
|
while (reader.pos < semi) {
|
||||||
|
let seg;
|
||||||
|
genColumn = decodeInteger(reader, genColumn);
|
||||||
|
if (genColumn < lastCol)
|
||||||
|
sorted = false;
|
||||||
|
lastCol = genColumn;
|
||||||
|
if (hasMoreVlq(reader, semi)) {
|
||||||
|
sourcesIndex = decodeInteger(reader, sourcesIndex);
|
||||||
|
sourceLine = decodeInteger(reader, sourceLine);
|
||||||
|
sourceColumn = decodeInteger(reader, sourceColumn);
|
||||||
|
if (hasMoreVlq(reader, semi)) {
|
||||||
|
namesIndex = decodeInteger(reader, namesIndex);
|
||||||
|
seg = [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
seg = [genColumn, sourcesIndex, sourceLine, sourceColumn];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
seg = [genColumn];
|
||||||
|
}
|
||||||
|
line.push(seg);
|
||||||
|
reader.pos++;
|
||||||
|
}
|
||||||
|
if (!sorted)
|
||||||
|
sort(line);
|
||||||
|
decoded.push(line);
|
||||||
|
reader.pos = semi + 1;
|
||||||
|
} while (reader.pos <= length);
|
||||||
|
return decoded;
|
||||||
|
}
|
||||||
|
function sort(line) {
|
||||||
|
line.sort(sortComparator);
|
||||||
|
}
|
||||||
|
function sortComparator(a, b) {
|
||||||
|
return a[0] - b[0];
|
||||||
|
}
|
||||||
|
function encode(decoded) {
|
||||||
|
const writer = new StringWriter();
|
||||||
|
let sourcesIndex = 0;
|
||||||
|
let sourceLine = 0;
|
||||||
|
let sourceColumn = 0;
|
||||||
|
let namesIndex = 0;
|
||||||
|
for (let i = 0; i < decoded.length; i++) {
|
||||||
|
const line = decoded[i];
|
||||||
|
if (i > 0)
|
||||||
|
writer.write(semicolon);
|
||||||
|
if (line.length === 0)
|
||||||
|
continue;
|
||||||
|
let genColumn = 0;
|
||||||
|
for (let j = 0; j < line.length; j++) {
|
||||||
|
const segment = line[j];
|
||||||
|
if (j > 0)
|
||||||
|
writer.write(comma);
|
||||||
|
genColumn = encodeInteger(writer, segment[0], genColumn);
|
||||||
|
if (segment.length === 1)
|
||||||
|
continue;
|
||||||
|
sourcesIndex = encodeInteger(writer, segment[1], sourcesIndex);
|
||||||
|
sourceLine = encodeInteger(writer, segment[2], sourceLine);
|
||||||
|
sourceColumn = encodeInteger(writer, segment[3], sourceColumn);
|
||||||
|
if (segment.length === 4)
|
||||||
|
continue;
|
||||||
|
namesIndex = encodeInteger(writer, segment[4], namesIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return writer.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
export { decode, decodeGeneratedRanges, decodeOriginalScopes, encode, encodeGeneratedRanges, encodeOriginalScopes };
|
||||||
|
//# sourceMappingURL=sourcemap-codec.mjs.map
|
439
src/健康青年/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.umd.js
generated
vendored
@ -0,0 +1,439 @@
|
|||||||
|
(function (global, factory) {
|
||||||
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
||||||
|
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
||||||
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.sourcemapCodec = {}));
|
||||||
|
})(this, (function (exports) { 'use strict';
|
||||||
|
|
||||||
|
const comma = ','.charCodeAt(0);
|
||||||
|
const semicolon = ';'.charCodeAt(0);
|
||||||
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||||
|
const intToChar = new Uint8Array(64); // 64 possible chars.
|
||||||
|
const charToInt = new Uint8Array(128); // z is 122 in ASCII
|
||||||
|
for (let i = 0; i < chars.length; i++) {
|
||||||
|
const c = chars.charCodeAt(i);
|
||||||
|
intToChar[i] = c;
|
||||||
|
charToInt[c] = i;
|
||||||
|
}
|
||||||
|
function decodeInteger(reader, relative) {
|
||||||
|
let value = 0;
|
||||||
|
let shift = 0;
|
||||||
|
let integer = 0;
|
||||||
|
do {
|
||||||
|
const c = reader.next();
|
||||||
|
integer = charToInt[c];
|
||||||
|
value |= (integer & 31) << shift;
|
||||||
|
shift += 5;
|
||||||
|
} while (integer & 32);
|
||||||
|
const shouldNegate = value & 1;
|
||||||
|
value >>>= 1;
|
||||||
|
if (shouldNegate) {
|
||||||
|
value = -0x80000000 | -value;
|
||||||
|
}
|
||||||
|
return relative + value;
|
||||||
|
}
|
||||||
|
function encodeInteger(builder, num, relative) {
|
||||||
|
let delta = num - relative;
|
||||||
|
delta = delta < 0 ? (-delta << 1) | 1 : delta << 1;
|
||||||
|
do {
|
||||||
|
let clamped = delta & 0b011111;
|
||||||
|
delta >>>= 5;
|
||||||
|
if (delta > 0)
|
||||||
|
clamped |= 0b100000;
|
||||||
|
builder.write(intToChar[clamped]);
|
||||||
|
} while (delta > 0);
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
function hasMoreVlq(reader, max) {
|
||||||
|
if (reader.pos >= max)
|
||||||
|
return false;
|
||||||
|
return reader.peek() !== comma;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bufLength = 1024 * 16;
|
||||||
|
// Provide a fallback for older environments.
|
||||||
|
const td = typeof TextDecoder !== 'undefined'
|
||||||
|
? /* #__PURE__ */ new TextDecoder()
|
||||||
|
: typeof Buffer !== 'undefined'
|
||||||
|
? {
|
||||||
|
decode(buf) {
|
||||||
|
const out = Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength);
|
||||||
|
return out.toString();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
decode(buf) {
|
||||||
|
let out = '';
|
||||||
|
for (let i = 0; i < buf.length; i++) {
|
||||||
|
out += String.fromCharCode(buf[i]);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
class StringWriter {
|
||||||
|
constructor() {
|
||||||
|
this.pos = 0;
|
||||||
|
this.out = '';
|
||||||
|
this.buffer = new Uint8Array(bufLength);
|
||||||
|
}
|
||||||
|
write(v) {
|
||||||
|
const { buffer } = this;
|
||||||
|
buffer[this.pos++] = v;
|
||||||
|
if (this.pos === bufLength) {
|
||||||
|
this.out += td.decode(buffer);
|
||||||
|
this.pos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flush() {
|
||||||
|
const { buffer, out, pos } = this;
|
||||||
|
return pos > 0 ? out + td.decode(buffer.subarray(0, pos)) : out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class StringReader {
|
||||||
|
constructor(buffer) {
|
||||||
|
this.pos = 0;
|
||||||
|
this.buffer = buffer;
|
||||||
|
}
|
||||||
|
next() {
|
||||||
|
return this.buffer.charCodeAt(this.pos++);
|
||||||
|
}
|
||||||
|
peek() {
|
||||||
|
return this.buffer.charCodeAt(this.pos);
|
||||||
|
}
|
||||||
|
indexOf(char) {
|
||||||
|
const { buffer, pos } = this;
|
||||||
|
const idx = buffer.indexOf(char, pos);
|
||||||
|
return idx === -1 ? buffer.length : idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const EMPTY = [];
|
||||||
|
function decodeOriginalScopes(input) {
|
||||||
|
const { length } = input;
|
||||||
|
const reader = new StringReader(input);
|
||||||
|
const scopes = [];
|
||||||
|
const stack = [];
|
||||||
|
let line = 0;
|
||||||
|
for (; reader.pos < length; reader.pos++) {
|
||||||
|
line = decodeInteger(reader, line);
|
||||||
|
const column = decodeInteger(reader, 0);
|
||||||
|
if (!hasMoreVlq(reader, length)) {
|
||||||
|
const last = stack.pop();
|
||||||
|
last[2] = line;
|
||||||
|
last[3] = column;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const kind = decodeInteger(reader, 0);
|
||||||
|
const fields = decodeInteger(reader, 0);
|
||||||
|
const hasName = fields & 0b0001;
|
||||||
|
const scope = (hasName ? [line, column, 0, 0, kind, decodeInteger(reader, 0)] : [line, column, 0, 0, kind]);
|
||||||
|
let vars = EMPTY;
|
||||||
|
if (hasMoreVlq(reader, length)) {
|
||||||
|
vars = [];
|
||||||
|
do {
|
||||||
|
const varsIndex = decodeInteger(reader, 0);
|
||||||
|
vars.push(varsIndex);
|
||||||
|
} while (hasMoreVlq(reader, length));
|
||||||
|
}
|
||||||
|
scope.vars = vars;
|
||||||
|
scopes.push(scope);
|
||||||
|
stack.push(scope);
|
||||||
|
}
|
||||||
|
return scopes;
|
||||||
|
}
|
||||||
|
function encodeOriginalScopes(scopes) {
|
||||||
|
const writer = new StringWriter();
|
||||||
|
for (let i = 0; i < scopes.length;) {
|
||||||
|
i = _encodeOriginalScopes(scopes, i, writer, [0]);
|
||||||
|
}
|
||||||
|
return writer.flush();
|
||||||
|
}
|
||||||
|
function _encodeOriginalScopes(scopes, index, writer, state) {
|
||||||
|
const scope = scopes[index];
|
||||||
|
const { 0: startLine, 1: startColumn, 2: endLine, 3: endColumn, 4: kind, vars } = scope;
|
||||||
|
if (index > 0)
|
||||||
|
writer.write(comma);
|
||||||
|
state[0] = encodeInteger(writer, startLine, state[0]);
|
||||||
|
encodeInteger(writer, startColumn, 0);
|
||||||
|
encodeInteger(writer, kind, 0);
|
||||||
|
const fields = scope.length === 6 ? 0b0001 : 0;
|
||||||
|
encodeInteger(writer, fields, 0);
|
||||||
|
if (scope.length === 6)
|
||||||
|
encodeInteger(writer, scope[5], 0);
|
||||||
|
for (const v of vars) {
|
||||||
|
encodeInteger(writer, v, 0);
|
||||||
|
}
|
||||||
|
for (index++; index < scopes.length;) {
|
||||||
|
const next = scopes[index];
|
||||||
|
const { 0: l, 1: c } = next;
|
||||||
|
if (l > endLine || (l === endLine && c >= endColumn)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index = _encodeOriginalScopes(scopes, index, writer, state);
|
||||||
|
}
|
||||||
|
writer.write(comma);
|
||||||
|
state[0] = encodeInteger(writer, endLine, state[0]);
|
||||||
|
encodeInteger(writer, endColumn, 0);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
function decodeGeneratedRanges(input) {
|
||||||
|
const { length } = input;
|
||||||
|
const reader = new StringReader(input);
|
||||||
|
const ranges = [];
|
||||||
|
const stack = [];
|
||||||
|
let genLine = 0;
|
||||||
|
let definitionSourcesIndex = 0;
|
||||||
|
let definitionScopeIndex = 0;
|
||||||
|
let callsiteSourcesIndex = 0;
|
||||||
|
let callsiteLine = 0;
|
||||||
|
let callsiteColumn = 0;
|
||||||
|
let bindingLine = 0;
|
||||||
|
let bindingColumn = 0;
|
||||||
|
do {
|
||||||
|
const semi = reader.indexOf(';');
|
||||||
|
let genColumn = 0;
|
||||||
|
for (; reader.pos < semi; reader.pos++) {
|
||||||
|
genColumn = decodeInteger(reader, genColumn);
|
||||||
|
if (!hasMoreVlq(reader, semi)) {
|
||||||
|
const last = stack.pop();
|
||||||
|
last[2] = genLine;
|
||||||
|
last[3] = genColumn;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const fields = decodeInteger(reader, 0);
|
||||||
|
const hasDefinition = fields & 0b0001;
|
||||||
|
const hasCallsite = fields & 0b0010;
|
||||||
|
const hasScope = fields & 0b0100;
|
||||||
|
let callsite = null;
|
||||||
|
let bindings = EMPTY;
|
||||||
|
let range;
|
||||||
|
if (hasDefinition) {
|
||||||
|
const defSourcesIndex = decodeInteger(reader, definitionSourcesIndex);
|
||||||
|
definitionScopeIndex = decodeInteger(reader, definitionSourcesIndex === defSourcesIndex ? definitionScopeIndex : 0);
|
||||||
|
definitionSourcesIndex = defSourcesIndex;
|
||||||
|
range = [genLine, genColumn, 0, 0, defSourcesIndex, definitionScopeIndex];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
range = [genLine, genColumn, 0, 0];
|
||||||
|
}
|
||||||
|
range.isScope = !!hasScope;
|
||||||
|
if (hasCallsite) {
|
||||||
|
const prevCsi = callsiteSourcesIndex;
|
||||||
|
const prevLine = callsiteLine;
|
||||||
|
callsiteSourcesIndex = decodeInteger(reader, callsiteSourcesIndex);
|
||||||
|
const sameSource = prevCsi === callsiteSourcesIndex;
|
||||||
|
callsiteLine = decodeInteger(reader, sameSource ? callsiteLine : 0);
|
||||||
|
callsiteColumn = decodeInteger(reader, sameSource && prevLine === callsiteLine ? callsiteColumn : 0);
|
||||||
|
callsite = [callsiteSourcesIndex, callsiteLine, callsiteColumn];
|
||||||
|
}
|
||||||
|
range.callsite = callsite;
|
||||||
|
if (hasMoreVlq(reader, semi)) {
|
||||||
|
bindings = [];
|
||||||
|
do {
|
||||||
|
bindingLine = genLine;
|
||||||
|
bindingColumn = genColumn;
|
||||||
|
const expressionsCount = decodeInteger(reader, 0);
|
||||||
|
let expressionRanges;
|
||||||
|
if (expressionsCount < -1) {
|
||||||
|
expressionRanges = [[decodeInteger(reader, 0)]];
|
||||||
|
for (let i = -1; i > expressionsCount; i--) {
|
||||||
|
const prevBl = bindingLine;
|
||||||
|
bindingLine = decodeInteger(reader, bindingLine);
|
||||||
|
bindingColumn = decodeInteger(reader, bindingLine === prevBl ? bindingColumn : 0);
|
||||||
|
const expression = decodeInteger(reader, 0);
|
||||||
|
expressionRanges.push([expression, bindingLine, bindingColumn]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
expressionRanges = [[expressionsCount]];
|
||||||
|
}
|
||||||
|
bindings.push(expressionRanges);
|
||||||
|
} while (hasMoreVlq(reader, semi));
|
||||||
|
}
|
||||||
|
range.bindings = bindings;
|
||||||
|
ranges.push(range);
|
||||||
|
stack.push(range);
|
||||||
|
}
|
||||||
|
genLine++;
|
||||||
|
reader.pos = semi + 1;
|
||||||
|
} while (reader.pos < length);
|
||||||
|
return ranges;
|
||||||
|
}
|
||||||
|
function encodeGeneratedRanges(ranges) {
|
||||||
|
if (ranges.length === 0)
|
||||||
|
return '';
|
||||||
|
const writer = new StringWriter();
|
||||||
|
for (let i = 0; i < ranges.length;) {
|
||||||
|
i = _encodeGeneratedRanges(ranges, i, writer, [0, 0, 0, 0, 0, 0, 0]);
|
||||||
|
}
|
||||||
|
return writer.flush();
|
||||||
|
}
|
||||||
|
function _encodeGeneratedRanges(ranges, index, writer, state) {
|
||||||
|
const range = ranges[index];
|
||||||
|
const { 0: startLine, 1: startColumn, 2: endLine, 3: endColumn, isScope, callsite, bindings, } = range;
|
||||||
|
if (state[0] < startLine) {
|
||||||
|
catchupLine(writer, state[0], startLine);
|
||||||
|
state[0] = startLine;
|
||||||
|
state[1] = 0;
|
||||||
|
}
|
||||||
|
else if (index > 0) {
|
||||||
|
writer.write(comma);
|
||||||
|
}
|
||||||
|
state[1] = encodeInteger(writer, range[1], state[1]);
|
||||||
|
const fields = (range.length === 6 ? 0b0001 : 0) | (callsite ? 0b0010 : 0) | (isScope ? 0b0100 : 0);
|
||||||
|
encodeInteger(writer, fields, 0);
|
||||||
|
if (range.length === 6) {
|
||||||
|
const { 4: sourcesIndex, 5: scopesIndex } = range;
|
||||||
|
if (sourcesIndex !== state[2]) {
|
||||||
|
state[3] = 0;
|
||||||
|
}
|
||||||
|
state[2] = encodeInteger(writer, sourcesIndex, state[2]);
|
||||||
|
state[3] = encodeInteger(writer, scopesIndex, state[3]);
|
||||||
|
}
|
||||||
|
if (callsite) {
|
||||||
|
const { 0: sourcesIndex, 1: callLine, 2: callColumn } = range.callsite;
|
||||||
|
if (sourcesIndex !== state[4]) {
|
||||||
|
state[5] = 0;
|
||||||
|
state[6] = 0;
|
||||||
|
}
|
||||||
|
else if (callLine !== state[5]) {
|
||||||
|
state[6] = 0;
|
||||||
|
}
|
||||||
|
state[4] = encodeInteger(writer, sourcesIndex, state[4]);
|
||||||
|
state[5] = encodeInteger(writer, callLine, state[5]);
|
||||||
|
state[6] = encodeInteger(writer, callColumn, state[6]);
|
||||||
|
}
|
||||||
|
if (bindings) {
|
||||||
|
for (const binding of bindings) {
|
||||||
|
if (binding.length > 1)
|
||||||
|
encodeInteger(writer, -binding.length, 0);
|
||||||
|
const expression = binding[0][0];
|
||||||
|
encodeInteger(writer, expression, 0);
|
||||||
|
let bindingStartLine = startLine;
|
||||||
|
let bindingStartColumn = startColumn;
|
||||||
|
for (let i = 1; i < binding.length; i++) {
|
||||||
|
const expRange = binding[i];
|
||||||
|
bindingStartLine = encodeInteger(writer, expRange[1], bindingStartLine);
|
||||||
|
bindingStartColumn = encodeInteger(writer, expRange[2], bindingStartColumn);
|
||||||
|
encodeInteger(writer, expRange[0], 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (index++; index < ranges.length;) {
|
||||||
|
const next = ranges[index];
|
||||||
|
const { 0: l, 1: c } = next;
|
||||||
|
if (l > endLine || (l === endLine && c >= endColumn)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index = _encodeGeneratedRanges(ranges, index, writer, state);
|
||||||
|
}
|
||||||
|
if (state[0] < endLine) {
|
||||||
|
catchupLine(writer, state[0], endLine);
|
||||||
|
state[0] = endLine;
|
||||||
|
state[1] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
writer.write(comma);
|
||||||
|
}
|
||||||
|
state[1] = encodeInteger(writer, endColumn, state[1]);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
function catchupLine(writer, lastLine, line) {
|
||||||
|
do {
|
||||||
|
writer.write(semicolon);
|
||||||
|
} while (++lastLine < line);
|
||||||
|
}
|
||||||
|
|
||||||
|
function decode(mappings) {
|
||||||
|
const { length } = mappings;
|
||||||
|
const reader = new StringReader(mappings);
|
||||||
|
const decoded = [];
|
||||||
|
let genColumn = 0;
|
||||||
|
let sourcesIndex = 0;
|
||||||
|
let sourceLine = 0;
|
||||||
|
let sourceColumn = 0;
|
||||||
|
let namesIndex = 0;
|
||||||
|
do {
|
||||||
|
const semi = reader.indexOf(';');
|
||||||
|
const line = [];
|
||||||
|
let sorted = true;
|
||||||
|
let lastCol = 0;
|
||||||
|
genColumn = 0;
|
||||||
|
while (reader.pos < semi) {
|
||||||
|
let seg;
|
||||||
|
genColumn = decodeInteger(reader, genColumn);
|
||||||
|
if (genColumn < lastCol)
|
||||||
|
sorted = false;
|
||||||
|
lastCol = genColumn;
|
||||||
|
if (hasMoreVlq(reader, semi)) {
|
||||||
|
sourcesIndex = decodeInteger(reader, sourcesIndex);
|
||||||
|
sourceLine = decodeInteger(reader, sourceLine);
|
||||||
|
sourceColumn = decodeInteger(reader, sourceColumn);
|
||||||
|
if (hasMoreVlq(reader, semi)) {
|
||||||
|
namesIndex = decodeInteger(reader, namesIndex);
|
||||||
|
seg = [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
seg = [genColumn, sourcesIndex, sourceLine, sourceColumn];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
seg = [genColumn];
|
||||||
|
}
|
||||||
|
line.push(seg);
|
||||||
|
reader.pos++;
|
||||||
|
}
|
||||||
|
if (!sorted)
|
||||||
|
sort(line);
|
||||||
|
decoded.push(line);
|
||||||
|
reader.pos = semi + 1;
|
||||||
|
} while (reader.pos <= length);
|
||||||
|
return decoded;
|
||||||
|
}
|
||||||
|
function sort(line) {
|
||||||
|
line.sort(sortComparator);
|
||||||
|
}
|
||||||
|
function sortComparator(a, b) {
|
||||||
|
return a[0] - b[0];
|
||||||
|
}
|
||||||
|
function encode(decoded) {
|
||||||
|
const writer = new StringWriter();
|
||||||
|
let sourcesIndex = 0;
|
||||||
|
let sourceLine = 0;
|
||||||
|
let sourceColumn = 0;
|
||||||
|
let namesIndex = 0;
|
||||||
|
for (let i = 0; i < decoded.length; i++) {
|
||||||
|
const line = decoded[i];
|
||||||
|
if (i > 0)
|
||||||
|
writer.write(semicolon);
|
||||||
|
if (line.length === 0)
|
||||||
|
continue;
|
||||||
|
let genColumn = 0;
|
||||||
|
for (let j = 0; j < line.length; j++) {
|
||||||
|
const segment = line[j];
|
||||||
|
if (j > 0)
|
||||||
|
writer.write(comma);
|
||||||
|
genColumn = encodeInteger(writer, segment[0], genColumn);
|
||||||
|
if (segment.length === 1)
|
||||||
|
continue;
|
||||||
|
sourcesIndex = encodeInteger(writer, segment[1], sourcesIndex);
|
||||||
|
sourceLine = encodeInteger(writer, segment[2], sourceLine);
|
||||||
|
sourceColumn = encodeInteger(writer, segment[3], sourceColumn);
|
||||||
|
if (segment.length === 4)
|
||||||
|
continue;
|
||||||
|
namesIndex = encodeInteger(writer, segment[4], namesIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return writer.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.decode = decode;
|
||||||
|
exports.decodeGeneratedRanges = decodeGeneratedRanges;
|
||||||
|
exports.decodeOriginalScopes = decodeOriginalScopes;
|
||||||
|
exports.encode = encode;
|
||||||
|
exports.encodeGeneratedRanges = encodeGeneratedRanges;
|
||||||
|
exports.encodeOriginalScopes = encodeOriginalScopes;
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true });
|
||||||
|
|
||||||
|
}));
|
||||||
|
//# sourceMappingURL=sourcemap-codec.umd.js.map
|
1
src/健康青年/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.umd.js.map
generated
vendored
@ -0,0 +1,49 @@
|
|||||||
|
declare type Line = number;
|
||||||
|
declare type Column = number;
|
||||||
|
declare type Kind = number;
|
||||||
|
declare type Name = number;
|
||||||
|
declare type Var = number;
|
||||||
|
declare type SourcesIndex = number;
|
||||||
|
declare type ScopesIndex = number;
|
||||||
|
declare type Mix<A, B, O> = (A & O) | (B & O);
|
||||||
|
export declare type OriginalScope = Mix<[
|
||||||
|
Line,
|
||||||
|
Column,
|
||||||
|
Line,
|
||||||
|
Column,
|
||||||
|
Kind
|
||||||
|
], [
|
||||||
|
Line,
|
||||||
|
Column,
|
||||||
|
Line,
|
||||||
|
Column,
|
||||||
|
Kind,
|
||||||
|
Name
|
||||||
|
], {
|
||||||
|
vars: Var[];
|
||||||
|
}>;
|
||||||
|
export declare type GeneratedRange = Mix<[
|
||||||
|
Line,
|
||||||
|
Column,
|
||||||
|
Line,
|
||||||
|
Column
|
||||||
|
], [
|
||||||
|
Line,
|
||||||
|
Column,
|
||||||
|
Line,
|
||||||
|
Column,
|
||||||
|
SourcesIndex,
|
||||||
|
ScopesIndex
|
||||||
|
], {
|
||||||
|
callsite: CallSite | null;
|
||||||
|
bindings: Binding[];
|
||||||
|
isScope: boolean;
|
||||||
|
}>;
|
||||||
|
export declare type CallSite = [SourcesIndex, Line, Column];
|
||||||
|
declare type Binding = BindingExpressionRange[];
|
||||||
|
export declare type BindingExpressionRange = [Name] | [Name, Line, Column];
|
||||||
|
export declare function decodeOriginalScopes(input: string): OriginalScope[];
|
||||||
|
export declare function encodeOriginalScopes(scopes: OriginalScope[]): string;
|
||||||
|
export declare function decodeGeneratedRanges(input: string): GeneratedRange[];
|
||||||
|
export declare function encodeGeneratedRanges(ranges: GeneratedRange[]): string;
|
||||||
|
export {};
|
8
src/健康青年/node_modules/@jridgewell/sourcemap-codec/dist/types/sourcemap-codec.d.ts
generated
vendored
@ -0,0 +1,8 @@
|
|||||||
|
export { decodeOriginalScopes, encodeOriginalScopes, decodeGeneratedRanges, encodeGeneratedRanges, } from './scopes';
|
||||||
|
export type { OriginalScope, GeneratedRange, CallSite, BindingExpressionRange } from './scopes';
|
||||||
|
export declare type SourceMapSegment = [number] | [number, number, number, number] | [number, number, number, number, number];
|
||||||
|
export declare type SourceMapLine = SourceMapSegment[];
|
||||||
|
export declare type SourceMapMappings = SourceMapLine[];
|
||||||
|
export declare function decode(mappings: string): SourceMapMappings;
|
||||||
|
export declare function encode(decoded: SourceMapMappings): string;
|
||||||
|
export declare function encode(decoded: Readonly<SourceMapMappings>): string;
|
@ -0,0 +1,15 @@
|
|||||||
|
export declare class StringWriter {
|
||||||
|
pos: number;
|
||||||
|
private out;
|
||||||
|
private buffer;
|
||||||
|
write(v: number): void;
|
||||||
|
flush(): string;
|
||||||
|
}
|
||||||
|
export declare class StringReader {
|
||||||
|
pos: number;
|
||||||
|
private buffer;
|
||||||
|
constructor(buffer: string);
|
||||||
|
next(): number;
|
||||||
|
peek(): number;
|
||||||
|
indexOf(char: string): number;
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
import type { StringReader, StringWriter } from './strings';
|
||||||
|
export declare const comma: number;
|
||||||
|
export declare const semicolon: number;
|
||||||
|
export declare function decodeInteger(reader: StringReader, relative: number): number;
|
||||||
|
export declare function encodeInteger(builder: StringWriter, num: number, relative: number): number;
|
||||||
|
export declare function hasMoreVlq(reader: StringReader, max: number): boolean;
|
@ -0,0 +1,75 @@
|
|||||||
|
{
|
||||||
|
"name": "@jridgewell/sourcemap-codec",
|
||||||
|
"version": "1.5.0",
|
||||||
|
"description": "Encode/decode sourcemap mappings",
|
||||||
|
"keywords": [
|
||||||
|
"sourcemap",
|
||||||
|
"vlq"
|
||||||
|
],
|
||||||
|
"main": "dist/sourcemap-codec.umd.js",
|
||||||
|
"module": "dist/sourcemap-codec.mjs",
|
||||||
|
"types": "dist/types/sourcemap-codec.d.ts",
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"exports": {
|
||||||
|
".": [
|
||||||
|
{
|
||||||
|
"types": "./dist/types/sourcemap-codec.d.ts",
|
||||||
|
"browser": "./dist/sourcemap-codec.umd.js",
|
||||||
|
"require": "./dist/sourcemap-codec.umd.js",
|
||||||
|
"import": "./dist/sourcemap-codec.mjs"
|
||||||
|
},
|
||||||
|
"./dist/sourcemap-codec.umd.js"
|
||||||
|
],
|
||||||
|
"./package.json": "./package.json"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"benchmark": "run-s build:rollup benchmark:*",
|
||||||
|
"benchmark:install": "cd benchmark && npm install",
|
||||||
|
"benchmark:only": "node --expose-gc benchmark/index.js",
|
||||||
|
"build": "run-s -n build:*",
|
||||||
|
"build:rollup": "rollup -c rollup.config.js",
|
||||||
|
"build:ts": "tsc --project tsconfig.build.json",
|
||||||
|
"lint": "run-s -n lint:*",
|
||||||
|
"lint:prettier": "npm run test:lint:prettier -- --write",
|
||||||
|
"lint:ts": "npm run test:lint:ts -- --fix",
|
||||||
|
"prebuild": "rm -rf dist",
|
||||||
|
"prepublishOnly": "npm run preversion",
|
||||||
|
"preversion": "run-s test build",
|
||||||
|
"test": "run-s -n test:lint test:only",
|
||||||
|
"test:debug": "mocha --inspect-brk",
|
||||||
|
"test:lint": "run-s -n test:lint:*",
|
||||||
|
"test:lint:prettier": "prettier --check '{src,test}/**/*.ts'",
|
||||||
|
"test:lint:ts": "eslint '{src,test}/**/*.ts'",
|
||||||
|
"test:only": "mocha",
|
||||||
|
"test:coverage": "c8 mocha",
|
||||||
|
"test:watch": "mocha --watch"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/jridgewell/sourcemap-codec.git"
|
||||||
|
},
|
||||||
|
"author": "Rich Harris",
|
||||||
|
"license": "MIT",
|
||||||
|
"devDependencies": {
|
||||||
|
"@rollup/plugin-typescript": "8.3.0",
|
||||||
|
"@types/mocha": "10.0.6",
|
||||||
|
"@types/node": "17.0.15",
|
||||||
|
"@typescript-eslint/eslint-plugin": "5.10.0",
|
||||||
|
"@typescript-eslint/parser": "5.10.0",
|
||||||
|
"benchmark": "2.1.4",
|
||||||
|
"c8": "7.11.2",
|
||||||
|
"eslint": "8.7.0",
|
||||||
|
"eslint-config-prettier": "8.3.0",
|
||||||
|
"mocha": "9.2.0",
|
||||||
|
"npm-run-all": "4.1.5",
|
||||||
|
"prettier": "2.5.1",
|
||||||
|
"rollup": "2.64.0",
|
||||||
|
"source-map": "0.6.1",
|
||||||
|
"source-map-js": "1.0.2",
|
||||||
|
"sourcemap-codec": "1.4.8",
|
||||||
|
"tsx": "4.7.1",
|
||||||
|
"typescript": "4.5.4"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) Denis Malinochkin
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
@ -0,0 +1,171 @@
|
|||||||
|
# @nodelib/fs.scandir
|
||||||
|
|
||||||
|
> List files and directories inside the specified directory.
|
||||||
|
|
||||||
|
## :bulb: Highlights
|
||||||
|
|
||||||
|
The package is aimed at obtaining information about entries in the directory.
|
||||||
|
|
||||||
|
* :moneybag: Returns useful information: `name`, `path`, `dirent` and `stats` (optional).
|
||||||
|
* :gear: On Node.js 10.10+ uses the mechanism without additional calls to determine the entry type. See [`old` and `modern` mode](#old-and-modern-mode).
|
||||||
|
* :link: Can safely work with broken symbolic links.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```console
|
||||||
|
npm install @nodelib/fs.scandir
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import * as fsScandir from '@nodelib/fs.scandir';
|
||||||
|
|
||||||
|
fsScandir.scandir('path', (error, stats) => { /* … */ });
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### .scandir(path, [optionsOrSettings], callback)
|
||||||
|
|
||||||
|
Returns an array of plain objects ([`Entry`](#entry)) with information about entry for provided path with standard callback-style.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
fsScandir.scandir('path', (error, entries) => { /* … */ });
|
||||||
|
fsScandir.scandir('path', {}, (error, entries) => { /* … */ });
|
||||||
|
fsScandir.scandir('path', new fsScandir.Settings(), (error, entries) => { /* … */ });
|
||||||
|
```
|
||||||
|
|
||||||
|
### .scandirSync(path, [optionsOrSettings])
|
||||||
|
|
||||||
|
Returns an array of plain objects ([`Entry`](#entry)) with information about entry for provided path.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const entries = fsScandir.scandirSync('path');
|
||||||
|
const entries = fsScandir.scandirSync('path', {});
|
||||||
|
const entries = fsScandir.scandirSync(('path', new fsScandir.Settings());
|
||||||
|
```
|
||||||
|
|
||||||
|
#### path
|
||||||
|
|
||||||
|
* Required: `true`
|
||||||
|
* Type: `string | Buffer | URL`
|
||||||
|
|
||||||
|
A path to a file. If a URL is provided, it must use the `file:` protocol.
|
||||||
|
|
||||||
|
#### optionsOrSettings
|
||||||
|
|
||||||
|
* Required: `false`
|
||||||
|
* Type: `Options | Settings`
|
||||||
|
* Default: An instance of `Settings` class
|
||||||
|
|
||||||
|
An [`Options`](#options) object or an instance of [`Settings`](#settingsoptions) class.
|
||||||
|
|
||||||
|
> :book: When you pass a plain object, an instance of the `Settings` class will be created automatically. If you plan to call the method frequently, use a pre-created instance of the `Settings` class.
|
||||||
|
|
||||||
|
### Settings([options])
|
||||||
|
|
||||||
|
A class of full settings of the package.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const settings = new fsScandir.Settings({ followSymbolicLinks: false });
|
||||||
|
|
||||||
|
const entries = fsScandir.scandirSync('path', settings);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Entry
|
||||||
|
|
||||||
|
* `name` — The name of the entry (`unknown.txt`).
|
||||||
|
* `path` — The path of the entry relative to call directory (`root/unknown.txt`).
|
||||||
|
* `dirent` — An instance of [`fs.Dirent`](./src/types/index.ts) class. On Node.js below 10.10 will be emulated by [`DirentFromStats`](./src/utils/fs.ts) class.
|
||||||
|
* `stats` (optional) — An instance of `fs.Stats` class.
|
||||||
|
|
||||||
|
For example, the `scandir` call for `tools` directory with one directory inside:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
{
|
||||||
|
dirent: Dirent { name: 'typedoc', /* … */ },
|
||||||
|
name: 'typedoc',
|
||||||
|
path: 'tools/typedoc'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
### stats
|
||||||
|
|
||||||
|
* Type: `boolean`
|
||||||
|
* Default: `false`
|
||||||
|
|
||||||
|
Adds an instance of `fs.Stats` class to the [`Entry`](#entry).
|
||||||
|
|
||||||
|
> :book: Always use `fs.readdir` without the `withFileTypes` option. ??TODO??
|
||||||
|
|
||||||
|
### followSymbolicLinks
|
||||||
|
|
||||||
|
* Type: `boolean`
|
||||||
|
* Default: `false`
|
||||||
|
|
||||||
|
Follow symbolic links or not. Call `fs.stat` on symbolic link if `true`.
|
||||||
|
|
||||||
|
### `throwErrorOnBrokenSymbolicLink`
|
||||||
|
|
||||||
|
* Type: `boolean`
|
||||||
|
* Default: `true`
|
||||||
|
|
||||||
|
Throw an error when symbolic link is broken if `true` or safely use `lstat` call if `false`.
|
||||||
|
|
||||||
|
### `pathSegmentSeparator`
|
||||||
|
|
||||||
|
* Type: `string`
|
||||||
|
* Default: `path.sep`
|
||||||
|
|
||||||
|
By default, this package uses the correct path separator for your OS (`\` on Windows, `/` on Unix-like systems). But you can set this option to any separator character(s) that you want to use instead.
|
||||||
|
|
||||||
|
### `fs`
|
||||||
|
|
||||||
|
* Type: [`FileSystemAdapter`](./src/adapters/fs.ts)
|
||||||
|
* Default: A default FS methods
|
||||||
|
|
||||||
|
By default, the built-in Node.js module (`fs`) is used to work with the file system. You can replace any method with your own.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
interface FileSystemAdapter {
|
||||||
|
lstat?: typeof fs.lstat;
|
||||||
|
stat?: typeof fs.stat;
|
||||||
|
lstatSync?: typeof fs.lstatSync;
|
||||||
|
statSync?: typeof fs.statSync;
|
||||||
|
readdir?: typeof fs.readdir;
|
||||||
|
readdirSync?: typeof fs.readdirSync;
|
||||||
|
}
|
||||||
|
|
||||||
|
const settings = new fsScandir.Settings({
|
||||||
|
fs: { lstat: fakeLstat }
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## `old` and `modern` mode
|
||||||
|
|
||||||
|
This package has two modes that are used depending on the environment and parameters of use.
|
||||||
|
|
||||||
|
### old
|
||||||
|
|
||||||
|
* Node.js below `10.10` or when the `stats` option is enabled
|
||||||
|
|
||||||
|
When working in the old mode, the directory is read first (`fs.readdir`), then the type of entries is determined (`fs.lstat` and/or `fs.stat` for symbolic links).
|
||||||
|
|
||||||
|
### modern
|
||||||
|
|
||||||
|
* Node.js 10.10+ and the `stats` option is disabled
|
||||||
|
|
||||||
|
In the modern mode, reading the directory (`fs.readdir` with the `withFileTypes` option) is combined with obtaining information about its entries. An additional call for symbolic links (`fs.stat`) is still present.
|
||||||
|
|
||||||
|
This mode makes fewer calls to the file system. It's faster.
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
See the [Releases section of our GitHub project](https://github.com/nodelib/nodelib/releases) for changelog for each release version.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This software is released under the terms of the MIT license.
|
@ -0,0 +1,20 @@
|
|||||||
|
import type * as fsStat from '@nodelib/fs.stat';
|
||||||
|
import type { Dirent, ErrnoException } from '../types';
|
||||||
|
export interface ReaddirAsynchronousMethod {
|
||||||
|
(filepath: string, options: {
|
||||||
|
withFileTypes: true;
|
||||||
|
}, callback: (error: ErrnoException | null, files: Dirent[]) => void): void;
|
||||||
|
(filepath: string, callback: (error: ErrnoException | null, files: string[]) => void): void;
|
||||||
|
}
|
||||||
|
export interface ReaddirSynchronousMethod {
|
||||||
|
(filepath: string, options: {
|
||||||
|
withFileTypes: true;
|
||||||
|
}): Dirent[];
|
||||||
|
(filepath: string): string[];
|
||||||
|
}
|
||||||
|
export declare type FileSystemAdapter = fsStat.FileSystemAdapter & {
|
||||||
|
readdir: ReaddirAsynchronousMethod;
|
||||||
|
readdirSync: ReaddirSynchronousMethod;
|
||||||
|
};
|
||||||
|
export declare const FILE_SYSTEM_ADAPTER: FileSystemAdapter;
|
||||||
|
export declare function createFileSystemAdapter(fsMethods?: Partial<FileSystemAdapter>): FileSystemAdapter;
|
@ -0,0 +1,19 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.createFileSystemAdapter = exports.FILE_SYSTEM_ADAPTER = void 0;
|
||||||
|
const fs = require("fs");
|
||||||
|
exports.FILE_SYSTEM_ADAPTER = {
|
||||||
|
lstat: fs.lstat,
|
||||||
|
stat: fs.stat,
|
||||||
|
lstatSync: fs.lstatSync,
|
||||||
|
statSync: fs.statSync,
|
||||||
|
readdir: fs.readdir,
|
||||||
|
readdirSync: fs.readdirSync
|
||||||
|
};
|
||||||
|
function createFileSystemAdapter(fsMethods) {
|
||||||
|
if (fsMethods === undefined) {
|
||||||
|
return exports.FILE_SYSTEM_ADAPTER;
|
||||||
|
}
|
||||||
|
return Object.assign(Object.assign({}, exports.FILE_SYSTEM_ADAPTER), fsMethods);
|
||||||
|
}
|
||||||
|
exports.createFileSystemAdapter = createFileSystemAdapter;
|
@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* IS `true` for Node.js 10.10 and greater.
|
||||||
|
*/
|
||||||
|
export declare const IS_SUPPORT_READDIR_WITH_FILE_TYPES: boolean;
|
@ -0,0 +1,17 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = void 0;
|
||||||
|
const NODE_PROCESS_VERSION_PARTS = process.versions.node.split('.');
|
||||||
|
if (NODE_PROCESS_VERSION_PARTS[0] === undefined || NODE_PROCESS_VERSION_PARTS[1] === undefined) {
|
||||||
|
throw new Error(`Unexpected behavior. The 'process.versions.node' variable has invalid value: ${process.versions.node}`);
|
||||||
|
}
|
||||||
|
const MAJOR_VERSION = Number.parseInt(NODE_PROCESS_VERSION_PARTS[0], 10);
|
||||||
|
const MINOR_VERSION = Number.parseInt(NODE_PROCESS_VERSION_PARTS[1], 10);
|
||||||
|
const SUPPORTED_MAJOR_VERSION = 10;
|
||||||
|
const SUPPORTED_MINOR_VERSION = 10;
|
||||||
|
const IS_MATCHED_BY_MAJOR = MAJOR_VERSION > SUPPORTED_MAJOR_VERSION;
|
||||||
|
const IS_MATCHED_BY_MAJOR_AND_MINOR = MAJOR_VERSION === SUPPORTED_MAJOR_VERSION && MINOR_VERSION >= SUPPORTED_MINOR_VERSION;
|
||||||
|
/**
|
||||||
|
* IS `true` for Node.js 10.10 and greater.
|
||||||
|
*/
|
||||||
|
exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = IS_MATCHED_BY_MAJOR || IS_MATCHED_BY_MAJOR_AND_MINOR;
|
@ -0,0 +1,12 @@
|
|||||||
|
import type { FileSystemAdapter, ReaddirAsynchronousMethod, ReaddirSynchronousMethod } from './adapters/fs';
|
||||||
|
import * as async from './providers/async';
|
||||||
|
import Settings, { Options } from './settings';
|
||||||
|
import type { Dirent, Entry } from './types';
|
||||||
|
declare type AsyncCallback = async.AsyncCallback;
|
||||||
|
declare function scandir(path: string, callback: AsyncCallback): void;
|
||||||
|
declare function scandir(path: string, optionsOrSettings: Options | Settings, callback: AsyncCallback): void;
|
||||||
|
declare namespace scandir {
|
||||||
|
function __promisify__(path: string, optionsOrSettings?: Options | Settings): Promise<Entry[]>;
|
||||||
|
}
|
||||||
|
declare function scandirSync(path: string, optionsOrSettings?: Options | Settings): Entry[];
|
||||||
|
export { scandir, scandirSync, Settings, AsyncCallback, Dirent, Entry, FileSystemAdapter, ReaddirAsynchronousMethod, ReaddirSynchronousMethod, Options };
|
@ -0,0 +1,26 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.Settings = exports.scandirSync = exports.scandir = void 0;
|
||||||
|
const async = require("./providers/async");
|
||||||
|
const sync = require("./providers/sync");
|
||||||
|
const settings_1 = require("./settings");
|
||||||
|
exports.Settings = settings_1.default;
|
||||||
|
function scandir(path, optionsOrSettingsOrCallback, callback) {
|
||||||
|
if (typeof optionsOrSettingsOrCallback === 'function') {
|
||||||
|
async.read(path, getSettings(), optionsOrSettingsOrCallback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
async.read(path, getSettings(optionsOrSettingsOrCallback), callback);
|
||||||
|
}
|
||||||
|
exports.scandir = scandir;
|
||||||
|
function scandirSync(path, optionsOrSettings) {
|
||||||
|
const settings = getSettings(optionsOrSettings);
|
||||||
|
return sync.read(path, settings);
|
||||||
|
}
|
||||||
|
exports.scandirSync = scandirSync;
|
||||||
|
function getSettings(settingsOrOptions = {}) {
|
||||||
|
if (settingsOrOptions instanceof settings_1.default) {
|
||||||
|
return settingsOrOptions;
|
||||||
|
}
|
||||||
|
return new settings_1.default(settingsOrOptions);
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
import type Settings from '../settings';
|
||||||
|
import type { Entry } from '../types';
|
||||||
|
export declare type AsyncCallback = (error: NodeJS.ErrnoException, entries: Entry[]) => void;
|
||||||
|
export declare function read(directory: string, settings: Settings, callback: AsyncCallback): void;
|
||||||
|
export declare function readdirWithFileTypes(directory: string, settings: Settings, callback: AsyncCallback): void;
|
||||||
|
export declare function readdir(directory: string, settings: Settings, callback: AsyncCallback): void;
|
@ -0,0 +1,104 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.readdir = exports.readdirWithFileTypes = exports.read = void 0;
|
||||||
|
const fsStat = require("@nodelib/fs.stat");
|
||||||
|
const rpl = require("run-parallel");
|
||||||
|
const constants_1 = require("../constants");
|
||||||
|
const utils = require("../utils");
|
||||||
|
const common = require("./common");
|
||||||
|
function read(directory, settings, callback) {
|
||||||
|
if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) {
|
||||||
|
readdirWithFileTypes(directory, settings, callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
readdir(directory, settings, callback);
|
||||||
|
}
|
||||||
|
exports.read = read;
|
||||||
|
function readdirWithFileTypes(directory, settings, callback) {
|
||||||
|
settings.fs.readdir(directory, { withFileTypes: true }, (readdirError, dirents) => {
|
||||||
|
if (readdirError !== null) {
|
||||||
|
callFailureCallback(callback, readdirError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const entries = dirents.map((dirent) => ({
|
||||||
|
dirent,
|
||||||
|
name: dirent.name,
|
||||||
|
path: common.joinPathSegments(directory, dirent.name, settings.pathSegmentSeparator)
|
||||||
|
}));
|
||||||
|
if (!settings.followSymbolicLinks) {
|
||||||
|
callSuccessCallback(callback, entries);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tasks = entries.map((entry) => makeRplTaskEntry(entry, settings));
|
||||||
|
rpl(tasks, (rplError, rplEntries) => {
|
||||||
|
if (rplError !== null) {
|
||||||
|
callFailureCallback(callback, rplError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callSuccessCallback(callback, rplEntries);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.readdirWithFileTypes = readdirWithFileTypes;
|
||||||
|
function makeRplTaskEntry(entry, settings) {
|
||||||
|
return (done) => {
|
||||||
|
if (!entry.dirent.isSymbolicLink()) {
|
||||||
|
done(null, entry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
settings.fs.stat(entry.path, (statError, stats) => {
|
||||||
|
if (statError !== null) {
|
||||||
|
if (settings.throwErrorOnBrokenSymbolicLink) {
|
||||||
|
done(statError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
done(null, entry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entry.dirent = utils.fs.createDirentFromStats(entry.name, stats);
|
||||||
|
done(null, entry);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function readdir(directory, settings, callback) {
|
||||||
|
settings.fs.readdir(directory, (readdirError, names) => {
|
||||||
|
if (readdirError !== null) {
|
||||||
|
callFailureCallback(callback, readdirError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tasks = names.map((name) => {
|
||||||
|
const path = common.joinPathSegments(directory, name, settings.pathSegmentSeparator);
|
||||||
|
return (done) => {
|
||||||
|
fsStat.stat(path, settings.fsStatSettings, (error, stats) => {
|
||||||
|
if (error !== null) {
|
||||||
|
done(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const entry = {
|
||||||
|
name,
|
||||||
|
path,
|
||||||
|
dirent: utils.fs.createDirentFromStats(name, stats)
|
||||||
|
};
|
||||||
|
if (settings.stats) {
|
||||||
|
entry.stats = stats;
|
||||||
|
}
|
||||||
|
done(null, entry);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
});
|
||||||
|
rpl(tasks, (rplError, entries) => {
|
||||||
|
if (rplError !== null) {
|
||||||
|
callFailureCallback(callback, rplError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callSuccessCallback(callback, entries);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.readdir = readdir;
|
||||||
|
function callFailureCallback(callback, error) {
|
||||||
|
callback(error);
|
||||||
|
}
|
||||||
|
function callSuccessCallback(callback, result) {
|
||||||
|
callback(null, result);
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
export declare function joinPathSegments(a: string, b: string, separator: string): string;
|
@ -0,0 +1,13 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.joinPathSegments = void 0;
|
||||||
|
function joinPathSegments(a, b, separator) {
|
||||||
|
/**
|
||||||
|
* The correct handling of cases when the first segment is a root (`/`, `C:/`) or UNC path (`//?/C:/`).
|
||||||
|
*/
|
||||||
|
if (a.endsWith(separator)) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
return a + separator + b;
|
||||||
|
}
|
||||||
|
exports.joinPathSegments = joinPathSegments;
|
@ -0,0 +1,5 @@
|
|||||||
|
import type Settings from '../settings';
|
||||||
|
import type { Entry } from '../types';
|
||||||
|
export declare function read(directory: string, settings: Settings): Entry[];
|
||||||
|
export declare function readdirWithFileTypes(directory: string, settings: Settings): Entry[];
|
||||||
|
export declare function readdir(directory: string, settings: Settings): Entry[];
|
@ -0,0 +1,54 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.readdir = exports.readdirWithFileTypes = exports.read = void 0;
|
||||||
|
const fsStat = require("@nodelib/fs.stat");
|
||||||
|
const constants_1 = require("../constants");
|
||||||
|
const utils = require("../utils");
|
||||||
|
const common = require("./common");
|
||||||
|
function read(directory, settings) {
|
||||||
|
if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) {
|
||||||
|
return readdirWithFileTypes(directory, settings);
|
||||||
|
}
|
||||||
|
return readdir(directory, settings);
|
||||||
|
}
|
||||||
|
exports.read = read;
|
||||||
|
function readdirWithFileTypes(directory, settings) {
|
||||||
|
const dirents = settings.fs.readdirSync(directory, { withFileTypes: true });
|
||||||
|
return dirents.map((dirent) => {
|
||||||
|
const entry = {
|
||||||
|
dirent,
|
||||||
|
name: dirent.name,
|
||||||
|
path: common.joinPathSegments(directory, dirent.name, settings.pathSegmentSeparator)
|
||||||
|
};
|
||||||
|
if (entry.dirent.isSymbolicLink() && settings.followSymbolicLinks) {
|
||||||
|
try {
|
||||||
|
const stats = settings.fs.statSync(entry.path);
|
||||||
|
entry.dirent = utils.fs.createDirentFromStats(entry.name, stats);
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
if (settings.throwErrorOnBrokenSymbolicLink) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.readdirWithFileTypes = readdirWithFileTypes;
|
||||||
|
function readdir(directory, settings) {
|
||||||
|
const names = settings.fs.readdirSync(directory);
|
||||||
|
return names.map((name) => {
|
||||||
|
const entryPath = common.joinPathSegments(directory, name, settings.pathSegmentSeparator);
|
||||||
|
const stats = fsStat.statSync(entryPath, settings.fsStatSettings);
|
||||||
|
const entry = {
|
||||||
|
name,
|
||||||
|
path: entryPath,
|
||||||
|
dirent: utils.fs.createDirentFromStats(name, stats)
|
||||||
|
};
|
||||||
|
if (settings.stats) {
|
||||||
|
entry.stats = stats;
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.readdir = readdir;
|
@ -0,0 +1,20 @@
|
|||||||
|
import * as fsStat from '@nodelib/fs.stat';
|
||||||
|
import * as fs from './adapters/fs';
|
||||||
|
export interface Options {
|
||||||
|
followSymbolicLinks?: boolean;
|
||||||
|
fs?: Partial<fs.FileSystemAdapter>;
|
||||||
|
pathSegmentSeparator?: string;
|
||||||
|
stats?: boolean;
|
||||||
|
throwErrorOnBrokenSymbolicLink?: boolean;
|
||||||
|
}
|
||||||
|
export default class Settings {
|
||||||
|
private readonly _options;
|
||||||
|
readonly followSymbolicLinks: boolean;
|
||||||
|
readonly fs: fs.FileSystemAdapter;
|
||||||
|
readonly pathSegmentSeparator: string;
|
||||||
|
readonly stats: boolean;
|
||||||
|
readonly throwErrorOnBrokenSymbolicLink: boolean;
|
||||||
|
readonly fsStatSettings: fsStat.Settings;
|
||||||
|
constructor(_options?: Options);
|
||||||
|
private _getValue;
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const path = require("path");
|
||||||
|
const fsStat = require("@nodelib/fs.stat");
|
||||||
|
const fs = require("./adapters/fs");
|
||||||
|
class Settings {
|
||||||
|
constructor(_options = {}) {
|
||||||
|
this._options = _options;
|
||||||
|
this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, false);
|
||||||
|
this.fs = fs.createFileSystemAdapter(this._options.fs);
|
||||||
|
this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path.sep);
|
||||||
|
this.stats = this._getValue(this._options.stats, false);
|
||||||
|
this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true);
|
||||||
|
this.fsStatSettings = new fsStat.Settings({
|
||||||
|
followSymbolicLink: this.followSymbolicLinks,
|
||||||
|
fs: this.fs,
|
||||||
|
throwErrorOnBrokenSymbolicLink: this.throwErrorOnBrokenSymbolicLink
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_getValue(option, value) {
|
||||||
|
return option !== null && option !== void 0 ? option : value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.default = Settings;
|