foreslash 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -1
- package/LICENSE +1 -1
- package/lib/index.cmn.cjs +244 -9
- package/lib/index.d.ts +173 -3
- package/lib/index.mjs +239 -10
- package/lib/index.umd.js +2094 -1859
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,15 +1,31 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
## Version 0.
|
|
3
|
+
## Version 0.3.0 - 2025-07-01
|
|
4
|
+
|
|
5
|
+
Unstable version
|
|
6
|
+
|
|
7
|
+
- Feat 🥥 Functions added: `capitalize` `deepMerge` `isBlob` and so forth
|
|
8
|
+
- Feat 🥥 Function change: `deepClone` now support `Blob` and `File`
|
|
9
|
+
- Other fixes and improvements
|
|
10
|
+
|
|
11
|
+
不稳定版本
|
|
12
|
+
|
|
13
|
+
- 功能 🥥 添加函数: `capitalize` `deepMerge` `isBlob` 等
|
|
14
|
+
- 功能 🥥 变更函数: `deepClone` 现在支持 `Blob` 和 `File`
|
|
15
|
+
- 其他修复与优化
|
|
16
|
+
|
|
17
|
+
## Version 0.2.4 - 2025-05-29
|
|
4
18
|
|
|
5
19
|
Unstable version
|
|
6
20
|
|
|
7
21
|
- Feat 🥥 Functions added: `retry` `parallel`
|
|
22
|
+
- Change 🥟 Dependencies change: upgrade devDependencies `rollup` `@rollup/plugin-typescript` `rollup-plugin-dts` `vitepress`
|
|
8
23
|
- Other fixes and improvements
|
|
9
24
|
|
|
10
25
|
不稳定版本
|
|
11
26
|
|
|
12
27
|
- 功能 🥥 添加函数: `retry` `parallel`
|
|
28
|
+
- 变更 🥟 依赖变更: 升级开发依赖 `rollup` `@rollup/plugin-typescript` `rollup-plugin-dts` `vitepress`
|
|
13
29
|
- 其他修复与优化
|
|
14
30
|
|
|
15
31
|
## Version 0.2.3 - 2025-03-28
|
package/LICENSE
CHANGED
package/lib/index.cmn.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
Copyright (c) 2024 moushu
|
|
2
|
+
Copyright (c) 2024-2025 moushu
|
|
3
3
|
foreslash is licensed under Mulan PSL v2.
|
|
4
4
|
You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
5
5
|
You may obtain a copy of Mulan PSL v2 at:
|
|
@@ -116,8 +116,8 @@ function getGlobalThis() {
|
|
|
116
116
|
return Function('return this')();
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
const global$
|
|
120
|
-
const ArrayBuffer$1 = global$
|
|
119
|
+
const global$8 = getGlobalThis();
|
|
120
|
+
const ArrayBuffer$1 = global$8.ArrayBuffer;
|
|
121
121
|
function isArrayBuffer(val) {
|
|
122
122
|
return !!ArrayBuffer$1 && val instanceof ArrayBuffer$1;
|
|
123
123
|
}
|
|
@@ -134,6 +134,16 @@ function isBigInt(value) {
|
|
|
134
134
|
return typeof value === 'bigint';
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
+
function isObject(value) {
|
|
138
|
+
return typeof value === 'object' && value !== null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const global$7 = getGlobalThis();
|
|
142
|
+
const Blob = global$7.Blob;
|
|
143
|
+
function isBlob(value) {
|
|
144
|
+
return !!Blob && isObject(value) && getTag(value) === 'Blob';
|
|
145
|
+
}
|
|
146
|
+
|
|
137
147
|
function isBoolean(value) {
|
|
138
148
|
return typeof value === 'boolean';
|
|
139
149
|
}
|
|
@@ -142,10 +152,6 @@ const global$6 = getGlobalThis();
|
|
|
142
152
|
const Buffer = global$6.Buffer;
|
|
143
153
|
const isBuffer = (Buffer && Buffer.isBuffer) || (() => false);
|
|
144
154
|
|
|
145
|
-
function isObject(value) {
|
|
146
|
-
return typeof value === 'object' && value !== null;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
155
|
function isDataView(value) {
|
|
150
156
|
return isObject(value) && getTag(value) === 'DataView';
|
|
151
157
|
}
|
|
@@ -155,9 +161,9 @@ function isDate(value) {
|
|
|
155
161
|
}
|
|
156
162
|
|
|
157
163
|
const global$5 = getGlobalThis();
|
|
158
|
-
const File = global$5.File;
|
|
164
|
+
const File$1 = global$5.File;
|
|
159
165
|
function isFile(value) {
|
|
160
|
-
return !!File && value
|
|
166
|
+
return !!File$1 && isObject(value) && getTag(value) === 'File';
|
|
161
167
|
}
|
|
162
168
|
|
|
163
169
|
const global$4 = getGlobalThis();
|
|
@@ -1251,6 +1257,12 @@ function titleCase(str, options) {
|
|
|
1251
1257
|
: ({ code }) => code.slice(0, 1).toUpperCase() + code.slice(1).toLowerCase());
|
|
1252
1258
|
}
|
|
1253
1259
|
|
|
1260
|
+
function capitalize(str) {
|
|
1261
|
+
if (!str)
|
|
1262
|
+
return str;
|
|
1263
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1254
1266
|
function caseConvert(str, joiner = '', handler) {
|
|
1255
1267
|
const hc = handler ? handler : (token) => token.code;
|
|
1256
1268
|
return _caseConvert(_splitVar(str), joiner, hc);
|
|
@@ -1298,6 +1310,12 @@ function splitWords(str) {
|
|
|
1298
1310
|
return _splitVar(str).map(({ code }) => code);
|
|
1299
1311
|
}
|
|
1300
1312
|
|
|
1313
|
+
function uncapitalize(str) {
|
|
1314
|
+
if (!str)
|
|
1315
|
+
return str;
|
|
1316
|
+
return str.charAt(0).toLowerCase() + str.slice(1);
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1301
1319
|
function compose(...composeFunc) {
|
|
1302
1320
|
if (composeFunc.length === 0) {
|
|
1303
1321
|
throw new Error('Invalid composeFunc parameter: composeFunc is empty');
|
|
@@ -1539,6 +1557,16 @@ function _cloneArrayBuffer(obj, map) {
|
|
|
1539
1557
|
new Uint8Array(res).set(new Uint8Array(obj));
|
|
1540
1558
|
return res;
|
|
1541
1559
|
}
|
|
1560
|
+
function _cloneBlob(obj, map) {
|
|
1561
|
+
const res = obj.slice(0, obj.size, obj.type);
|
|
1562
|
+
map.set(obj, res);
|
|
1563
|
+
return res;
|
|
1564
|
+
}
|
|
1565
|
+
function _cloneFile(obj, map) {
|
|
1566
|
+
const res = new File([obj], obj.name, { type: obj.type, lastModified: obj.lastModified });
|
|
1567
|
+
map.set(obj, res);
|
|
1568
|
+
return res;
|
|
1569
|
+
}
|
|
1542
1570
|
|
|
1543
1571
|
function _deepClone(obj, map, options) {
|
|
1544
1572
|
if (map.has(obj))
|
|
@@ -1583,6 +1611,12 @@ function _deepClone(obj, map, options) {
|
|
|
1583
1611
|
res = new DataView(map.has(obj.buffer) ? map.get(obj.buffer) : _cloneArrayBuffer(obj.buffer, map), obj.byteOffset, obj.byteLength);
|
|
1584
1612
|
map.set(obj, res);
|
|
1585
1613
|
}
|
|
1614
|
+
else if (isFile(obj)) {
|
|
1615
|
+
res = _cloneFile(obj, map);
|
|
1616
|
+
}
|
|
1617
|
+
else if (isBlob(obj)) {
|
|
1618
|
+
res = _cloneBlob(obj, map);
|
|
1619
|
+
}
|
|
1586
1620
|
else if (isWrapperObject(obj)) {
|
|
1587
1621
|
res = Object(obj.valueOf());
|
|
1588
1622
|
map.set(obj, res);
|
|
@@ -1617,6 +1651,201 @@ function deepClone(obj, options, map) {
|
|
|
1617
1651
|
return res;
|
|
1618
1652
|
}
|
|
1619
1653
|
|
|
1654
|
+
const $$Empty = Object.freeze({ '@@merge/placeholder': true });
|
|
1655
|
+
function getMergeStrategy(targetType, sourceType, strategy) {
|
|
1656
|
+
return (strategy[`${sourceType}2${targetType}`] ||
|
|
1657
|
+
strategy[`${sourceType}2Any`] ||
|
|
1658
|
+
strategy[`Any2${targetType}`] ||
|
|
1659
|
+
strategy[`Any2Any`] ||
|
|
1660
|
+
'override');
|
|
1661
|
+
}
|
|
1662
|
+
function getBaseMargeType(obj) {
|
|
1663
|
+
if (isMergeEmptyPlaceholder(obj))
|
|
1664
|
+
return 'Empty';
|
|
1665
|
+
const _tag = getTag(obj);
|
|
1666
|
+
if (/Function/.test(_tag))
|
|
1667
|
+
return 'Function';
|
|
1668
|
+
if (/Iterator/.test(_tag))
|
|
1669
|
+
return 'Iterator';
|
|
1670
|
+
if (/(?:8|16|32|64)Array/.test(_tag))
|
|
1671
|
+
return 'TypedArray';
|
|
1672
|
+
if (/Error/.test(_tag))
|
|
1673
|
+
return 'Error';
|
|
1674
|
+
return _tag;
|
|
1675
|
+
}
|
|
1676
|
+
function isMergeEmptyPlaceholder(arg) {
|
|
1677
|
+
return typeof arg === 'object' && Boolean(arg) && arg['@@merge/placeholder'] === true;
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
function _deepMergeBase(target, source, option, map, path, cloner) {
|
|
1681
|
+
const targetType = getBaseMargeType(target);
|
|
1682
|
+
const sourceType = getBaseMargeType(source);
|
|
1683
|
+
const strategy = getMergeStrategy(targetType, sourceType, option.typeStrategy);
|
|
1684
|
+
if (isFunction(strategy)) {
|
|
1685
|
+
const merger = _curryMore(_deepMergeBase)(_, _, option, map, _, cloner);
|
|
1686
|
+
const mergeRes = strategy({
|
|
1687
|
+
target,
|
|
1688
|
+
source,
|
|
1689
|
+
cloner,
|
|
1690
|
+
merger,
|
|
1691
|
+
path,
|
|
1692
|
+
typeStrategy: option.typeStrategy,
|
|
1693
|
+
unhandledValue: $$Empty,
|
|
1694
|
+
map,
|
|
1695
|
+
});
|
|
1696
|
+
if (!isMergeEmptyPlaceholder(mergeRes))
|
|
1697
|
+
return mergeRes;
|
|
1698
|
+
}
|
|
1699
|
+
if (strategy === 'keep') {
|
|
1700
|
+
if (isMergeEmptyPlaceholder(target))
|
|
1701
|
+
return $$Empty;
|
|
1702
|
+
return cloner(target);
|
|
1703
|
+
}
|
|
1704
|
+
else if (strategy === 'override') {
|
|
1705
|
+
return cloner(source);
|
|
1706
|
+
}
|
|
1707
|
+
else {
|
|
1708
|
+
return cloner(source);
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
const defaultMergeStrategy = {
|
|
1712
|
+
Any2Any: 'override',
|
|
1713
|
+
Any2Empty: 'override',
|
|
1714
|
+
Any2Null: 'override',
|
|
1715
|
+
Any2Undefined: 'override',
|
|
1716
|
+
Null2Any: 'keep',
|
|
1717
|
+
Undefined2Any: 'keep',
|
|
1718
|
+
Null2Empty: 'override',
|
|
1719
|
+
Undefined2Empty: 'override',
|
|
1720
|
+
Number2Any: 'keep',
|
|
1721
|
+
Number2Number: 'override',
|
|
1722
|
+
String2Any: 'keep',
|
|
1723
|
+
String2String: 'override',
|
|
1724
|
+
Boolean2Any: 'keep',
|
|
1725
|
+
Boolean2Boolean: 'override',
|
|
1726
|
+
Symbol2Any: 'keep',
|
|
1727
|
+
Symbol2Symbol: 'override',
|
|
1728
|
+
BigInt2Any: 'keep',
|
|
1729
|
+
BigInt2BigInt: 'override',
|
|
1730
|
+
Number2Empty: 'override',
|
|
1731
|
+
String2Empty: 'override',
|
|
1732
|
+
Boolean2Empty: 'override',
|
|
1733
|
+
Symbol2Empty: 'override',
|
|
1734
|
+
BigInt2Empty: 'override',
|
|
1735
|
+
Number2Null: 'override',
|
|
1736
|
+
String2Null: 'override',
|
|
1737
|
+
Boolean2Null: 'override',
|
|
1738
|
+
Symbol2Null: 'override',
|
|
1739
|
+
BigInt2Null: 'override',
|
|
1740
|
+
Number2Undefined: 'override',
|
|
1741
|
+
String2Undefined: 'override',
|
|
1742
|
+
Boolean2Undefined: 'override',
|
|
1743
|
+
Symbol2Undefined: 'override',
|
|
1744
|
+
BigInt2Undefined: 'override',
|
|
1745
|
+
Object2Object: (({ target, source, cloner, path, merger }) => {
|
|
1746
|
+
const res = cloner(target);
|
|
1747
|
+
Reflect.ownKeys(source).forEach((key) => {
|
|
1748
|
+
const newPath = [...path, key];
|
|
1749
|
+
if (key in res) {
|
|
1750
|
+
res[key] = merger(res[key], source[key], newPath);
|
|
1751
|
+
}
|
|
1752
|
+
else {
|
|
1753
|
+
const mergeRes = merger($$Empty, source[key], newPath);
|
|
1754
|
+
if (!isMergeEmptyPlaceholder(mergeRes))
|
|
1755
|
+
res[key] = mergeRes;
|
|
1756
|
+
}
|
|
1757
|
+
});
|
|
1758
|
+
return res;
|
|
1759
|
+
}),
|
|
1760
|
+
Object2FormData: (({ target, source, cloner, path, merger }) => {
|
|
1761
|
+
const res = cloner(target);
|
|
1762
|
+
Reflect.ownKeys(source).forEach((key) => {
|
|
1763
|
+
if (isSymbol(key))
|
|
1764
|
+
return;
|
|
1765
|
+
const newPath = [...path, key];
|
|
1766
|
+
if (res.has(key)) {
|
|
1767
|
+
res.set(key, merger(res.get(key), source[key], newPath));
|
|
1768
|
+
}
|
|
1769
|
+
else {
|
|
1770
|
+
const mergeRes = merger($$Empty, source[key], newPath);
|
|
1771
|
+
if (!isMergeEmptyPlaceholder(mergeRes))
|
|
1772
|
+
res.set(key, mergeRes);
|
|
1773
|
+
}
|
|
1774
|
+
});
|
|
1775
|
+
return res;
|
|
1776
|
+
}),
|
|
1777
|
+
FormData2Object: (({ target, source, cloner, path, merger }) => {
|
|
1778
|
+
const res = cloner(target);
|
|
1779
|
+
source.forEach((val, key) => {
|
|
1780
|
+
const newPath = [...path, key];
|
|
1781
|
+
if (key in res) {
|
|
1782
|
+
res[key] = merger(res[key], val, newPath);
|
|
1783
|
+
}
|
|
1784
|
+
else {
|
|
1785
|
+
const mergeRes = merger($$Empty, val, newPath);
|
|
1786
|
+
if (!isMergeEmptyPlaceholder(mergeRes))
|
|
1787
|
+
res[key] = mergeRes;
|
|
1788
|
+
}
|
|
1789
|
+
});
|
|
1790
|
+
return res;
|
|
1791
|
+
}),
|
|
1792
|
+
FormData2FormData: (({ target, source, cloner, path, merger }) => {
|
|
1793
|
+
const res = cloner(target);
|
|
1794
|
+
source.forEach((val, key) => {
|
|
1795
|
+
const newPath = [...path, key];
|
|
1796
|
+
if (res.has(key)) {
|
|
1797
|
+
res.set(key, merger(res.get(key), val, newPath));
|
|
1798
|
+
}
|
|
1799
|
+
else {
|
|
1800
|
+
const mergeRes = merger($$Empty, val, newPath);
|
|
1801
|
+
if (!isMergeEmptyPlaceholder(mergeRes))
|
|
1802
|
+
res.set(key, mergeRes);
|
|
1803
|
+
}
|
|
1804
|
+
});
|
|
1805
|
+
return res;
|
|
1806
|
+
}),
|
|
1807
|
+
Set2Set: (({ target, source, cloner }) => {
|
|
1808
|
+
const res = cloner(target);
|
|
1809
|
+
for (const item of source)
|
|
1810
|
+
res.add(cloner(item));
|
|
1811
|
+
return res;
|
|
1812
|
+
}),
|
|
1813
|
+
Map2Map: (({ target, source, cloner }) => {
|
|
1814
|
+
const res = cloner(target);
|
|
1815
|
+
for (const [key, val] of source)
|
|
1816
|
+
res.set(cloner(key), cloner(val));
|
|
1817
|
+
return res;
|
|
1818
|
+
}),
|
|
1819
|
+
Array2Array: (({ target, source, cloner }) => {
|
|
1820
|
+
const res = cloner(target);
|
|
1821
|
+
for (const item of source)
|
|
1822
|
+
res.push(cloner(item));
|
|
1823
|
+
return res;
|
|
1824
|
+
}),
|
|
1825
|
+
Set2Array: (({ target, source, cloner }) => {
|
|
1826
|
+
const res = cloner(target);
|
|
1827
|
+
for (const item of source)
|
|
1828
|
+
res.push(cloner(item));
|
|
1829
|
+
return res;
|
|
1830
|
+
}),
|
|
1831
|
+
Array2Set: (({ target, source, cloner }) => {
|
|
1832
|
+
const res = cloner(target);
|
|
1833
|
+
for (const item of source)
|
|
1834
|
+
res.add(cloner(item));
|
|
1835
|
+
return res;
|
|
1836
|
+
}),
|
|
1837
|
+
};
|
|
1838
|
+
|
|
1839
|
+
function deepMerge(target, source, option) {
|
|
1840
|
+
const typeStrategy = Object.assign(Object.assign({}, defaultMergeStrategy), ((option === null || option === void 0 ? void 0 : option.typeStrategy) || {}));
|
|
1841
|
+
const cloneOptions = Object.assign({ cloneSymbol: true, clonePrototype: false, cloneDescriptor: false, customCloner: [] }, ((option === null || option === void 0 ? void 0 : option.cloneOptions) || {}));
|
|
1842
|
+
const map = new Map();
|
|
1843
|
+
const cloner = _curryMore(_deepClone)(_, map, cloneOptions);
|
|
1844
|
+
const res = _deepMergeBase(target, source, { typeStrategy, cloneOptions }, map, [], cloner);
|
|
1845
|
+
map.clear();
|
|
1846
|
+
return res;
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1620
1849
|
function _fastClone(obj, map) {
|
|
1621
1850
|
if (map.has(obj))
|
|
1622
1851
|
return map.get(obj);
|
|
@@ -1774,10 +2003,12 @@ function throttle(fn, delay, options) {
|
|
|
1774
2003
|
return _throttle(fn, delay, Object.assign({ trailing: false, leading: true }, options));
|
|
1775
2004
|
}
|
|
1776
2005
|
|
|
2006
|
+
exports.$$Empty = $$Empty;
|
|
1777
2007
|
exports._ = _;
|
|
1778
2008
|
exports.acceptableFileName = acceptableFileName;
|
|
1779
2009
|
exports.acceptableFileType = acceptableFileType;
|
|
1780
2010
|
exports.camelCase = camelCase;
|
|
2011
|
+
exports.capitalize = capitalize;
|
|
1781
2012
|
exports.caseCamel = caseCamel;
|
|
1782
2013
|
exports.caseConvert = caseConvert;
|
|
1783
2014
|
exports.caseKebab = caseKebab;
|
|
@@ -1788,6 +2019,7 @@ exports.compose = compose;
|
|
|
1788
2019
|
exports.curry = _curryMore;
|
|
1789
2020
|
exports.debounce = debounce;
|
|
1790
2021
|
exports.deepClone = deepClone;
|
|
2022
|
+
exports.deepMerge = deepMerge;
|
|
1791
2023
|
exports.defer = defer;
|
|
1792
2024
|
exports.fastClone = fastClone;
|
|
1793
2025
|
exports.getAcceptableExtByMIME = getAcceptableExtByMIME;
|
|
@@ -1800,6 +2032,7 @@ exports.isArrayLike = isArrayLike;
|
|
|
1800
2032
|
exports.isBigInt = isBigInt;
|
|
1801
2033
|
exports.isBigInt64Array = isBigInt64Array;
|
|
1802
2034
|
exports.isBigUint64Array = isBigUint64Array;
|
|
2035
|
+
exports.isBlob = isBlob;
|
|
1803
2036
|
exports.isBoolean = isBoolean;
|
|
1804
2037
|
exports.isBuffer = isBuffer;
|
|
1805
2038
|
exports.isDataView = isDataView;
|
|
@@ -1816,6 +2049,7 @@ exports.isInt8Array = isInt8Array;
|
|
|
1816
2049
|
exports.isInteger = isInteger;
|
|
1817
2050
|
exports.isIterable = isIterable;
|
|
1818
2051
|
exports.isMap = isMap;
|
|
2052
|
+
exports.isMergeEmptyPlaceholder = isMergeEmptyPlaceholder;
|
|
1819
2053
|
exports.isNil = isNil;
|
|
1820
2054
|
exports.isNull = isNull;
|
|
1821
2055
|
exports.isNumber = isNumber;
|
|
@@ -1868,6 +2102,7 @@ exports.throttle = throttle;
|
|
|
1868
2102
|
exports.titleCase = titleCase;
|
|
1869
2103
|
exports.tryit = tryit;
|
|
1870
2104
|
exports.ulid = ulid;
|
|
2105
|
+
exports.uncapitalize = uncapitalize;
|
|
1871
2106
|
exports.uuidNil = uuidNil;
|
|
1872
2107
|
exports.uuidV4 = uuidV4;
|
|
1873
2108
|
exports.withResolvers = withResolvers;
|
package/lib/index.d.ts
CHANGED
|
@@ -169,7 +169,7 @@ type RetryOption = {
|
|
|
169
169
|
* ```js
|
|
170
170
|
* // 基本用法, 默认重试 3 次, 每次失败后会立即重新调用
|
|
171
171
|
* const res = await retry(() => fetch(url, params))
|
|
172
|
-
* // 重试 10 次
|
|
172
|
+
* // 重试 10 次, 最多会调用传入的函数 10 次
|
|
173
173
|
* const res = await retry(() => fetch(url, params), { times: 10 })
|
|
174
174
|
* // 延迟模式, 每次失败后会等待 1 秒再重新调用
|
|
175
175
|
* const res = await retry(() => fetch(url, params), { delay: 1000 })
|
|
@@ -308,6 +308,19 @@ declare function isArrayLike(value: unknown): value is ArrayLike<any>;
|
|
|
308
308
|
*/
|
|
309
309
|
declare function isBigInt(value: unknown): value is bigint;
|
|
310
310
|
|
|
311
|
+
/**
|
|
312
|
+
* 类型守卫,判断给定的值是否为 `Blob` 对象
|
|
313
|
+
* @param value 要判断的值
|
|
314
|
+
* @example
|
|
315
|
+
* ```js
|
|
316
|
+
* isBlob(new Blob()) // true
|
|
317
|
+
* isBlob(new ArrayBuffer(8)) // false
|
|
318
|
+
* isBlob([1, 2, 3]) // false
|
|
319
|
+
* ```
|
|
320
|
+
* @version 0.3.0
|
|
321
|
+
*/
|
|
322
|
+
declare function isBlob(value: any): value is Blob;
|
|
323
|
+
|
|
311
324
|
/**
|
|
312
325
|
* 类型守卫,判断给定的值是否为布尔类型
|
|
313
326
|
* @param value 要判断的值
|
|
@@ -1153,6 +1166,18 @@ declare function titleCase(str: string, options?: {
|
|
|
1153
1166
|
keepNumber?: boolean;
|
|
1154
1167
|
}): string;
|
|
1155
1168
|
|
|
1169
|
+
/**
|
|
1170
|
+
* 将字符串的首字母大写
|
|
1171
|
+
* @param str 字符串
|
|
1172
|
+
* @returns 首字母大写后的字符串
|
|
1173
|
+
* @example
|
|
1174
|
+
* ```js
|
|
1175
|
+
* capitalize('hello world') // 'Hello world'
|
|
1176
|
+
* ```
|
|
1177
|
+
* @version 0.3.0
|
|
1178
|
+
*/
|
|
1179
|
+
declare function capitalize(str: string): string;
|
|
1180
|
+
|
|
1156
1181
|
type VarCase = {
|
|
1157
1182
|
code: string;
|
|
1158
1183
|
/** 是否为全大写 */
|
|
@@ -1253,6 +1278,18 @@ declare function caseSnake(str: string, keepLetterCase?: boolean, keepNumber?: b
|
|
|
1253
1278
|
*/
|
|
1254
1279
|
declare function splitWords(str: string): string[];
|
|
1255
1280
|
|
|
1281
|
+
/**
|
|
1282
|
+
* 将字符串的首字母小写
|
|
1283
|
+
* @param str 字符串
|
|
1284
|
+
* @returns 首字母小写后的字符串
|
|
1285
|
+
* @example
|
|
1286
|
+
* ```js
|
|
1287
|
+
* uncapitalize('Hello world') // 'hello world'
|
|
1288
|
+
* ```
|
|
1289
|
+
* @version 0.3.0
|
|
1290
|
+
*/
|
|
1291
|
+
declare function uncapitalize(str: string): string;
|
|
1292
|
+
|
|
1256
1293
|
/**
|
|
1257
1294
|
* 调用`Object.prototype.toString`获取对象类型名称
|
|
1258
1295
|
* @param value 要判断的类型
|
|
@@ -1490,6 +1527,130 @@ type CloneOptions = {
|
|
|
1490
1527
|
*/
|
|
1491
1528
|
declare function deepClone<T>(obj: T, options?: Partial<CloneOptions>, map?: Map<any, any>): T;
|
|
1492
1529
|
|
|
1530
|
+
/**
|
|
1531
|
+
* 合并策略, 可以是 `'keep'` `'override'` `'merge'` 或者一个方法
|
|
1532
|
+
* - `'keep'` 表示保留原值
|
|
1533
|
+
* - `'override'` 表示覆盖为新值
|
|
1534
|
+
* - 如果是自定义合并方法, 那么你的方法接收的第一个参数是需要合并的值以及其路径
|
|
1535
|
+
* - `{ target: 原值; source: 新值; path: 路径数组; unhandledValue: 如果无法处理则返回这个 }`
|
|
1536
|
+
*/
|
|
1537
|
+
type MergeStrategy = 'keep' | 'override' | MergeStrategyFunction;
|
|
1538
|
+
type MergeStrategyFunction<T = any, S = any, Res = any> = (param: {
|
|
1539
|
+
target: T;
|
|
1540
|
+
source: S;
|
|
1541
|
+
path: (string | symbol)[];
|
|
1542
|
+
unhandledValue: any;
|
|
1543
|
+
map: Map<any, any>;
|
|
1544
|
+
typeStrategy: MergeTypeStrategy;
|
|
1545
|
+
/** 深拷贝, 直接传值即可, 参数已经预设好了 */
|
|
1546
|
+
cloner: <T>(obj: T) => T;
|
|
1547
|
+
/** 深合并, 直接传值即可, 参数已经预设好了 */
|
|
1548
|
+
merger: (target: any, source: any, path: (string | symbol)[]) => any;
|
|
1549
|
+
}) => Res;
|
|
1550
|
+
/** 所有内部识别的值类型 */
|
|
1551
|
+
type BaseMargeType = 'Number' | 'String' | 'Boolean' | 'Symbol' | 'BigInt' | 'Null' | 'Undefined' | 'Object' | 'Array' | 'Set' | 'Map' | 'FormData' | 'Date' | 'RegExp' | 'Promise' | 'Function' | 'Generator' | 'Iterator' | 'ArrayBuffer' | 'Buffer' | 'DataView' | 'Blob' | 'File' | 'TypedArray' | 'WeakSet' | 'WeakMap' | 'WeakRef' | 'Error';
|
|
1552
|
+
/** 来源对象上的值类型, 不会有 `'Empty'` */
|
|
1553
|
+
type SourceMergeType = BaseMargeType | 'Any';
|
|
1554
|
+
/** 目标对象上的值类型, 如果某个字段目标上没有而来源上有, 那么就为 `"Empty"` */
|
|
1555
|
+
type TargetMergeType = BaseMargeType | 'Empty' | 'Any';
|
|
1556
|
+
/** 合并类型, 其中来源对象上不会有 `'Empty'` */
|
|
1557
|
+
type MergeType = `${SourceMergeType}2${TargetMergeType}`;
|
|
1558
|
+
/** 根据目标对象类型和来源对象类型获取合并策略 */
|
|
1559
|
+
type MergeTypeStrategy = {
|
|
1560
|
+
[mergeType in MergeType]?: MergeStrategy;
|
|
1561
|
+
};
|
|
1562
|
+
type MergeEmptyPlaceholder = A.x & {
|
|
1563
|
+
'@@merge/placeholder': true;
|
|
1564
|
+
};
|
|
1565
|
+
/** `deepMerge` 深合并的空值占位符 */
|
|
1566
|
+
declare const $$Empty: Readonly<{
|
|
1567
|
+
'@@merge/placeholder': true;
|
|
1568
|
+
}>;
|
|
1569
|
+
/**
|
|
1570
|
+
* 判断给定的参数是否为 `deepMerge` 深合并的空值占位符
|
|
1571
|
+
* @param arg 需要判定的参数
|
|
1572
|
+
* @returns 是否为空值占位符
|
|
1573
|
+
*/
|
|
1574
|
+
declare function isMergeEmptyPlaceholder(arg: any): arg is MergeEmptyPlaceholder;
|
|
1575
|
+
|
|
1576
|
+
/** `deepMerge` 深合并方法的配置参数 */
|
|
1577
|
+
type MergeOption = {
|
|
1578
|
+
/** 针对不同的类型设置不同的合并方法 */
|
|
1579
|
+
typeStrategy?: Partial<MergeTypeStrategy>;
|
|
1580
|
+
/** `deepMerge` 内部使用 `deepClone` 拷贝对象之类的值 */
|
|
1581
|
+
cloneOptions?: CloneOptions;
|
|
1582
|
+
};
|
|
1583
|
+
|
|
1584
|
+
/**
|
|
1585
|
+
* 深合并, 作为基底的对象称为目标对象(target), 往之合并内容的对象称为来源对象(source)
|
|
1586
|
+
* - 不能处理循环引用等特殊场景
|
|
1587
|
+
* - 满足基本的合并功能, 以下行为是其默认行为
|
|
1588
|
+
* - 普通对象、FormData 这类对象会递归合并
|
|
1589
|
+
* - 数组会以拼接的方式合并
|
|
1590
|
+
* - `{ a: [1, 2] }` 和 `{ a: [3, 4] }` 会合并为 `{ a: [1, 2, 3, 4] }`
|
|
1591
|
+
* - Set、Map 会直接合并, 其中 Map 合并时来源对象会覆盖目标对象相同 Key 的值
|
|
1592
|
+
* - Set 和 Map 视为不同类型, 会用来源对象的值覆盖
|
|
1593
|
+
* - Set 和数组会互相合并
|
|
1594
|
+
* - `{ a: [1, 2] }` 和 `{ a: Set([3, 4]) }` 会合并为 `{ a: [1, 2, 3, 4] }`
|
|
1595
|
+
* - `{ a: Set([1, 2]) }` 和 `{ a: [3, 4] }` 会合并为 `{ a: Set([1, 2, 3, 4]) }`
|
|
1596
|
+
* - 来源对象的基本类型值不会覆盖对象
|
|
1597
|
+
* - 来源对象的空值(null、undefined)不会覆盖其他类型的值
|
|
1598
|
+
* - 来源对象的非空值会覆盖目标对象的空值(目标对象不存在某个键时也视为空值)
|
|
1599
|
+
* - 其他情况: 不同类型、原始类型、其他不能合并/拼接的值会以来源对象的为准作覆盖
|
|
1600
|
+
* - 可以根据类型配置不同的策略, 策略可以是 `"keep"` `"override"` 或者一个方法
|
|
1601
|
+
* - `"keep"` 保留目标对象的值
|
|
1602
|
+
* - `"override"` 保留来源对象的值
|
|
1603
|
+
* - 传入方法:
|
|
1604
|
+
* - 类型 `(param: { target: any; source: any; path: (string | symbol)[]; unhandledValue: any; map: Map<any, any> }) => any`
|
|
1605
|
+
* - `target` 当前目标对象上这个位置的值
|
|
1606
|
+
* - `source` 当前来源对象上这个位置的值
|
|
1607
|
+
* - `path` 当前处理的值在对象上的位置
|
|
1608
|
+
* - `map` 用于处理循环引用等情况的 Map 对象
|
|
1609
|
+
* - `unhandledValue` 将这个值返回, 可以跳过处理, 交给兜底逻辑
|
|
1610
|
+
* - 返回值: 合并后的对象
|
|
1611
|
+
* - 合并类型: 一个字符串 `${来源对象值类型}2${目标对象值类型}`, 常见类型见下
|
|
1612
|
+
* - 基本类型 `"Number"` `"String"` `"Boolean"` `"Symbol"` `"BigInt"` `"Null"` `"Undefined"`
|
|
1613
|
+
* - 常见对象 `"Object"` `"Array"` `"Set"` `"Map"` `"FormData"` `"Date"` `"RegExp"` `"Promise"`
|
|
1614
|
+
* - 函数 `"Function"`
|
|
1615
|
+
* - 这些均视为函数 `"AsyncFunction"` `"GeneratorFunction"`, 不能拿来用
|
|
1616
|
+
* - 生成器函数运行后得到生成器 `"Generator"`
|
|
1617
|
+
* - 迭代器 `"Iterator"`
|
|
1618
|
+
* - 这些均视为迭代器, 不能拿来用
|
|
1619
|
+
* - `"String Iterator"` `"Array Iterator"` `"RegExp String Iterator"`
|
|
1620
|
+
* - `"Map Iterator"` `"Set Iterator"` `"Segmenter String Iterator"`
|
|
1621
|
+
* - `"Iterator Helper"`
|
|
1622
|
+
* - 二进制流&文件 `"ArrayBuffer"` `"Buffer"` `"DataView"` `"Blob"` `"File"`
|
|
1623
|
+
* - 类型数组 `"TypedArray"`
|
|
1624
|
+
* - 这些均视为类型数组, 不能拿来用
|
|
1625
|
+
* - `"Int8Array"` `"Int16Array"` `"Int32Array"`
|
|
1626
|
+
* - `"Uint8Array"` `"Uint8ClampedArray"` `"Uint16Array"` `"Uint32Array"`
|
|
1627
|
+
* - `"Float32Array"` `"Float64Array"`
|
|
1628
|
+
* - `"BigInt64Array"` `"BigUint64Array"`
|
|
1629
|
+
* - 弱引用 `"WeakSet"` `"WeakMap"` `"WeakRef"`
|
|
1630
|
+
* - 报错信息 `"Error"`
|
|
1631
|
+
* - 任意类型的错误视为报错信息
|
|
1632
|
+
* - 其他类型 `"Any"` 表示所有类型(用于兜底), 空类型 `"Empty"` 表示目标对象上没有这个键
|
|
1633
|
+
* - `"Empty"` 不会出现在来源对象上, 因此只会有 `"Any2Empty"`, 而不会有 `"Empty2Any"`
|
|
1634
|
+
* - 策略优先级是:
|
|
1635
|
+
* - 精确指定优先级最高: 如 `"Object2Object"` 优先于 `"Object2Any"`
|
|
1636
|
+
* - 来源对象精确指定优先级高: 如 `"Object2Any"` 优先于 `"Any2Object"`
|
|
1637
|
+
* - 空类型 `"Empty"` 视为精确指定
|
|
1638
|
+
* @param target 目标对象
|
|
1639
|
+
* @param source 来源对象, 往目标对象合并内容
|
|
1640
|
+
* @param option 配置
|
|
1641
|
+
* - `option.typeStrategy`: 针对不同的类型设置不同的合并方法
|
|
1642
|
+
* - `option.cloneOptions`: `deepMerge` 内部使用 `deepClone` 拷贝对象之类的值
|
|
1643
|
+
* @example
|
|
1644
|
+
* ```js
|
|
1645
|
+
* const obj1 = { arr: [1, 2], obj: { a: [1], b: { c: 2 } }, p: '1' }
|
|
1646
|
+
* const obj2 = { arr: [3], obj: { a: [2], b: { c: 4, d: 3 } }, p: '2' }
|
|
1647
|
+
* const obj3 = deepMerge(obj1, obj2)
|
|
1648
|
+
* obj3 // { arr: [1, 2, 3], obj: { a: [1, 2], b: { c: 4, d: 3 } }, p: '2' }
|
|
1649
|
+
* ```
|
|
1650
|
+
* @version 0.3.0
|
|
1651
|
+
*/
|
|
1652
|
+
declare function deepMerge<Target, Source, Result = Target & Source>(target: Target, source: Source, option?: MergeOption): Result;
|
|
1653
|
+
|
|
1493
1654
|
/**
|
|
1494
1655
|
* 快速深拷贝
|
|
1495
1656
|
* - 功能较为齐全, 相对 `deepClone` 而言运行更快
|
|
@@ -1549,7 +1710,15 @@ declare function isEmpty(value: unknown): boolean;
|
|
|
1549
1710
|
* - `getKey` 自定义 key 的生成规则, 默认使用内部方法生成 key
|
|
1550
1711
|
* - `ttl` 缓存的过期时间, 单位毫秒, 为 0 表示不过期, 默认不过期
|
|
1551
1712
|
* - `count` 缓存最大使用次数, 为 0 表示不限次数, 默认不限次数
|
|
1552
|
-
* @returns
|
|
1713
|
+
* @returns 记忆化的函数, 输入相同参数再次调用时会直接返回之前的结果而不会调用原函数
|
|
1714
|
+
* @example
|
|
1715
|
+
* ```js
|
|
1716
|
+
* // 计算斐波那契数列
|
|
1717
|
+
* const fib = memo(function (n) {
|
|
1718
|
+
* if (n < 2) return n
|
|
1719
|
+
* return fib(n - 1) + fib(n - 2)
|
|
1720
|
+
* })
|
|
1721
|
+
* ```
|
|
1553
1722
|
*/
|
|
1554
1723
|
declare function memo<TArgs extends any[], TRes>(fn: (...args: TArgs) => TRes, options?: {
|
|
1555
1724
|
getKey?: (...args: TArgs) => string | number;
|
|
@@ -1737,4 +1906,5 @@ declare function throttle<T extends any[]>(fn: (...args: T) => any, delay: numbe
|
|
|
1737
1906
|
reset: () => void;
|
|
1738
1907
|
};
|
|
1739
1908
|
|
|
1740
|
-
export {
|
|
1909
|
+
export { $$Empty, _, acceptableFileName, acceptableFileType, camelCase, capitalize, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, clamp, compose, _curryMore as curry, debounce, deepClone, deepMerge, defer, fastClone, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getTag, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBlob, isBoolean, isBuffer, isDataView, isDate, isEmpty, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, isMergeEmptyPlaceholder, isNil, isNull, isNumber, isObject, isPlaceholder, isPrimitive, isPromise, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isUint16Array, isUint32Array, isUint8Array, isUint8ClampedArray, isUndefined, isWeakMap, isWeakSet, isWrapperBigInt, isWrapperBoolean, isWrapperNumber, isWrapperObject, isWrapperString, isWrapperSymbol, kebabCase, memo, noop, not, parallel, pascalCase, pass, passWith, pipe, randomBase32String, randomChoice, randomHexString, randomInt, randomIntFloor, randomString, range, remove, retry, shuffle, sleep, snakeCase, splitWords, throttle, titleCase, tryit, ulid, uncapitalize, uuidNil, uuidV4, withResolvers };
|
|
1910
|
+
export type { BaseMargeType, CloneOptions, CustomCloner, MergeOption, MergeStrategy, MergeStrategyFunction, MergeType, MergeTypeStrategy, RangeOptions, SourceMergeType, TargetMergeType, TypedArray };
|