foreslash 0.2.0 → 0.2.1

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/lib/index.cmn.cjs CHANGED
@@ -12,6 +12,12 @@ See the Mulan PSL v2 for more details.
12
12
  'use strict';
13
13
 
14
14
  function range(start, end, stepOrOptions) {
15
+ if (!isFinite(start))
16
+ throw new Error('start must be finite');
17
+ if (end == null)
18
+ return range(0, start);
19
+ if (!isFinite(end))
20
+ throw new Error('end must be finite');
15
21
  let step = 1;
16
22
  let getter = null;
17
23
  if (typeof stepOrOptions === 'number') {
@@ -30,8 +36,6 @@ function range(start, end, stepOrOptions) {
30
36
  throw new Error('step must be finite');
31
37
  if (step === 0)
32
38
  throw new Error('step must not be 0');
33
- if (!isFinite(start) || !isFinite(end))
34
- throw new Error('start and end must be finite');
35
39
  if ((start > end && step > 0) || (start < end && step < 0))
36
40
  step = -step;
37
41
  const res = [];
@@ -1356,7 +1360,7 @@ function _deepClone(obj, map, options) {
1356
1360
  map.set(obj, res);
1357
1361
  }
1358
1362
  else if (obj instanceof DataView) {
1359
- res = new DataView(_cloneArrayBuffer(obj.buffer, map), obj.byteOffset, obj.byteLength);
1363
+ res = new DataView(map.has(obj.buffer) ? map.get(obj.buffer) : _cloneArrayBuffer(obj.buffer, map), obj.byteOffset, obj.byteLength);
1360
1364
  map.set(obj, res);
1361
1365
  }
1362
1366
  else if (isWrapperObject(obj)) {
@@ -1452,8 +1456,63 @@ function isEmpty(value) {
1452
1456
  return isNaN(value.getTime());
1453
1457
  if (isSet(value) || isMap(value))
1454
1458
  return !value.size;
1455
- return !Object.getOwnPropertyNames(value).length;
1459
+ for (const key in value) {
1460
+ if (Object.prototype.hasOwnProperty.call(value, key))
1461
+ return false;
1462
+ }
1463
+ return true;
1464
+ }
1465
+ }
1466
+
1467
+ function _getKey(args) {
1468
+ function toString(item) {
1469
+ if (isBigInt(item))
1470
+ return String(item) + 'n';
1471
+ if (isRegExp(item))
1472
+ return 'RegExp' + String(item);
1473
+ if (isDate(item))
1474
+ return 'Date' + item.toISOString();
1475
+ try {
1476
+ return JSON.stringify(item);
1477
+ }
1478
+ catch (e) {
1479
+ return String(item);
1480
+ }
1481
+ }
1482
+ let res = 'ForeSlashMemoKey:[';
1483
+ for (let i = 0; i < args.length; i++) {
1484
+ res += toString(args[i]) + ',';
1456
1485
  }
1486
+ return res + ']';
1487
+ }
1488
+ function memo(fn, options) {
1489
+ const map = new Map();
1490
+ const getKey = (options === null || options === void 0 ? void 0 : options.getKey) ? options.getKey : _getKey;
1491
+ const setTtl = (options === null || options === void 0 ? void 0 : options.ttl) ? options.ttl : 0;
1492
+ const setCount = (options === null || options === void 0 ? void 0 : options.count) ? options.count : 0;
1493
+ return function (...args) {
1494
+ const key = getKey(args);
1495
+ if (map.has(key)) {
1496
+ const item = map.get(key);
1497
+ const { res, ttl, count } = item;
1498
+ const isValidCache = ttl >= Date.now() && count > 0;
1499
+ item.count -= 1;
1500
+ if (item.count <= 0)
1501
+ map.delete(key);
1502
+ if (ttl < Date.now())
1503
+ map.delete(key);
1504
+ if (isValidCache)
1505
+ return res;
1506
+ }
1507
+ const res = fn.apply(this, args);
1508
+ const memoItem = { res, ttl: Infinity, count: Infinity };
1509
+ if (setCount > 0)
1510
+ memoItem.count = setCount;
1511
+ if (setTtl > 0)
1512
+ memoItem.ttl = Date.now() + setTtl;
1513
+ map.set(key, memoItem);
1514
+ return res;
1515
+ };
1457
1516
  }
1458
1517
 
1459
1518
  function not(value) {
@@ -1554,6 +1613,7 @@ exports.isWrapperObject = isWrapperObject;
1554
1613
  exports.isWrapperString = isWrapperString;
1555
1614
  exports.isWrapperSymbol = isWrapperSymbol;
1556
1615
  exports.kebabCase = kebabCase;
1616
+ exports.memo = memo;
1557
1617
  exports.noop = noop;
1558
1618
  exports.not = not;
1559
1619
  exports.pascalCase = pascalCase;
package/lib/index.d.ts CHANGED
@@ -17,6 +17,17 @@ type RangeOptions<T> = {
17
17
  * @version 0.2.0
18
18
  */
19
19
  declare function range(start: number, end: number): number[];
20
+ /**
21
+ * 根据目标值生成一个数组, 步长默认为 1
22
+ * @param target 目标值
23
+ * @example
24
+ * ```js
25
+ * range(10) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
26
+ * range(-10) // [0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10]
27
+ * ```
28
+ * @version 0.2.1
29
+ */
30
+ declare function range(target: number): number[];
20
31
  /**
21
32
  * 根据起止值生成一个数组, 步长默认为 1
22
33
  * @param start 开始值
@@ -1358,6 +1369,22 @@ declare function fastClone<T>(obj: T, map?: Map<any, any>): T;
1358
1369
  */
1359
1370
  declare function isEmpty(value: unknown): boolean;
1360
1371
 
1372
+ /**
1373
+ * 将一个函数记忆化, 多次调用如果参数相同, 则直接返回缓存的结果, 而不会反复执行函数
1374
+ * - 每次运行时会将当前参数处理为 `key`, 相同 `key` 的函数调用将返回相同的结果
1375
+ * @param fn 要缓存的函数
1376
+ * @param options 缓存选项
1377
+ * - `getKey` 自定义 key 的生成规则, 默认使用内部方法生成 key
1378
+ * - `ttl` 缓存的过期时间, 单位毫秒, 为 0 表示不过期, 默认不过期
1379
+ * - `count` 缓存最大使用次数, 为 0 表示不限次数, 默认不限次数
1380
+ * @returns
1381
+ */
1382
+ declare function memo<TArgs extends any[], TRes>(fn: (...args: TArgs) => TRes, options?: {
1383
+ getKey?: (...args: TArgs) => string | number;
1384
+ ttl?: number;
1385
+ count?: number;
1386
+ }): (this: any, ...args: TArgs) => TRes;
1387
+
1361
1388
  /**
1362
1389
  * 不做任何操作,返回 `void` ,一般用于函数式编程
1363
1390
  * @example
@@ -1525,4 +1552,4 @@ declare function pipe<PipeArgs extends any[], PipeResult, Mid1, Mid2, Mid3, Mid4
1525
1552
  declare function pipe<PipeArgs extends any[], PipeResult, Mid1, Mid2, Mid3, Mid4, Mid5, Mid6, Mid7>(...pipeFunc: PipeFuncList8<PipeArgs, PipeResult, Mid1, Mid2, Mid3, Mid4, Mid5, Mid6, Mid7>): (...args: PipeArgs) => PipeResult;
1526
1553
  declare function pipe<PipeArgs extends any[], PipeResult, Mid1, Mid2, Mid3, Mid4, Mid5, Mid6, Mid7>(...pipeFunc: PipeFuncListMore<PipeArgs, PipeResult, Mid1, Mid2, Mid3, Mid4, Mid5, Mid6, Mid7>): (...args: PipeArgs) => PipeResult;
1527
1554
 
1528
- export { type CloneOptions, type CustomCloner, type RangeOptions, type TypedArray, _, acceptableFileName, acceptableFileType, camelCase, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, compose, _curryMore as curry, deepClone, fastClone, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getTag, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBoolean, isBuffer, isDataView, isDate, isEmpty, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, 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, noop, not, pascalCase, pass, passWith, pipe, randomBase32String, randomChoice, randomHexString, randomInt, randomIntFloor, randomString, range, shuffle, sleep, snakeCase, splitWords, titleCase, tryit, ulid, uuidNil, uuidV4, withResolvers };
1555
+ export { type CloneOptions, type CustomCloner, type RangeOptions, type TypedArray, _, acceptableFileName, acceptableFileType, camelCase, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, compose, _curryMore as curry, deepClone, fastClone, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getTag, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBoolean, isBuffer, isDataView, isDate, isEmpty, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, 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, pascalCase, pass, passWith, pipe, randomBase32String, randomChoice, randomHexString, randomInt, randomIntFloor, randomString, range, shuffle, sleep, snakeCase, splitWords, titleCase, tryit, ulid, uuidNil, uuidV4, withResolvers };
package/lib/index.mjs CHANGED
@@ -10,6 +10,12 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10
10
  See the Mulan PSL v2 for more details.
11
11
  */
12
12
  function range(start, end, stepOrOptions) {
13
+ if (!isFinite(start))
14
+ throw new Error('start must be finite');
15
+ if (end == null)
16
+ return range(0, start);
17
+ if (!isFinite(end))
18
+ throw new Error('end must be finite');
13
19
  let step = 1;
14
20
  let getter = null;
15
21
  if (typeof stepOrOptions === 'number') {
@@ -28,8 +34,6 @@ function range(start, end, stepOrOptions) {
28
34
  throw new Error('step must be finite');
29
35
  if (step === 0)
30
36
  throw new Error('step must not be 0');
31
- if (!isFinite(start) || !isFinite(end))
32
- throw new Error('start and end must be finite');
33
37
  if ((start > end && step > 0) || (start < end && step < 0))
34
38
  step = -step;
35
39
  const res = [];
@@ -1354,7 +1358,7 @@ function _deepClone(obj, map, options) {
1354
1358
  map.set(obj, res);
1355
1359
  }
1356
1360
  else if (obj instanceof DataView) {
1357
- res = new DataView(_cloneArrayBuffer(obj.buffer, map), obj.byteOffset, obj.byteLength);
1361
+ res = new DataView(map.has(obj.buffer) ? map.get(obj.buffer) : _cloneArrayBuffer(obj.buffer, map), obj.byteOffset, obj.byteLength);
1358
1362
  map.set(obj, res);
1359
1363
  }
1360
1364
  else if (isWrapperObject(obj)) {
@@ -1450,8 +1454,63 @@ function isEmpty(value) {
1450
1454
  return isNaN(value.getTime());
1451
1455
  if (isSet(value) || isMap(value))
1452
1456
  return !value.size;
1453
- return !Object.getOwnPropertyNames(value).length;
1457
+ for (const key in value) {
1458
+ if (Object.prototype.hasOwnProperty.call(value, key))
1459
+ return false;
1460
+ }
1461
+ return true;
1462
+ }
1463
+ }
1464
+
1465
+ function _getKey(args) {
1466
+ function toString(item) {
1467
+ if (isBigInt(item))
1468
+ return String(item) + 'n';
1469
+ if (isRegExp(item))
1470
+ return 'RegExp' + String(item);
1471
+ if (isDate(item))
1472
+ return 'Date' + item.toISOString();
1473
+ try {
1474
+ return JSON.stringify(item);
1475
+ }
1476
+ catch (e) {
1477
+ return String(item);
1478
+ }
1479
+ }
1480
+ let res = 'ForeSlashMemoKey:[';
1481
+ for (let i = 0; i < args.length; i++) {
1482
+ res += toString(args[i]) + ',';
1454
1483
  }
1484
+ return res + ']';
1485
+ }
1486
+ function memo(fn, options) {
1487
+ const map = new Map();
1488
+ const getKey = (options === null || options === void 0 ? void 0 : options.getKey) ? options.getKey : _getKey;
1489
+ const setTtl = (options === null || options === void 0 ? void 0 : options.ttl) ? options.ttl : 0;
1490
+ const setCount = (options === null || options === void 0 ? void 0 : options.count) ? options.count : 0;
1491
+ return function (...args) {
1492
+ const key = getKey(args);
1493
+ if (map.has(key)) {
1494
+ const item = map.get(key);
1495
+ const { res, ttl, count } = item;
1496
+ const isValidCache = ttl >= Date.now() && count > 0;
1497
+ item.count -= 1;
1498
+ if (item.count <= 0)
1499
+ map.delete(key);
1500
+ if (ttl < Date.now())
1501
+ map.delete(key);
1502
+ if (isValidCache)
1503
+ return res;
1504
+ }
1505
+ const res = fn.apply(this, args);
1506
+ const memoItem = { res, ttl: Infinity, count: Infinity };
1507
+ if (setCount > 0)
1508
+ memoItem.count = setCount;
1509
+ if (setTtl > 0)
1510
+ memoItem.ttl = Date.now() + setTtl;
1511
+ map.set(key, memoItem);
1512
+ return res;
1513
+ };
1455
1514
  }
1456
1515
 
1457
1516
  function not(value) {
@@ -1486,4 +1545,4 @@ function pipe(...pipeFunc) {
1486
1545
  };
1487
1546
  }
1488
1547
 
1489
- export { _, acceptableFileName, acceptableFileType, camelCase, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, compose, _curryMore as curry, deepClone, fastClone, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getTag, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBoolean, isBuffer, isDataView, isDate, isEmpty, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, 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, noop, not, pascalCase, pass, passWith, pipe, randomBase32String, randomChoice, randomHexString, randomInt, randomIntFloor, randomString, range, shuffle, sleep, snakeCase, splitWords, titleCase, tryit, ulid, uuidNil, uuidV4, withResolvers };
1548
+ export { _, acceptableFileName, acceptableFileType, camelCase, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, compose, _curryMore as curry, deepClone, fastClone, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getTag, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBoolean, isBuffer, isDataView, isDate, isEmpty, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, 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, pascalCase, pass, passWith, pipe, randomBase32String, randomChoice, randomHexString, randomInt, randomIntFloor, randomString, range, shuffle, sleep, snakeCase, splitWords, titleCase, tryit, ulid, uuidNil, uuidV4, withResolvers };
package/lib/index.umd.js CHANGED
@@ -16,6 +16,12 @@ See the Mulan PSL v2 for more details.
16
16
  })(this, (function (exports) { 'use strict';
17
17
 
18
18
  function range(start, end, stepOrOptions) {
19
+ if (!isFinite(start))
20
+ throw new Error('start must be finite');
21
+ if (end == null)
22
+ return range(0, start);
23
+ if (!isFinite(end))
24
+ throw new Error('end must be finite');
19
25
  let step = 1;
20
26
  let getter = null;
21
27
  if (typeof stepOrOptions === 'number') {
@@ -34,8 +40,6 @@ See the Mulan PSL v2 for more details.
34
40
  throw new Error('step must be finite');
35
41
  if (step === 0)
36
42
  throw new Error('step must not be 0');
37
- if (!isFinite(start) || !isFinite(end))
38
- throw new Error('start and end must be finite');
39
43
  if ((start > end && step > 0) || (start < end && step < 0))
40
44
  step = -step;
41
45
  const res = [];
@@ -1360,7 +1364,7 @@ See the Mulan PSL v2 for more details.
1360
1364
  map.set(obj, res);
1361
1365
  }
1362
1366
  else if (obj instanceof DataView) {
1363
- res = new DataView(_cloneArrayBuffer(obj.buffer, map), obj.byteOffset, obj.byteLength);
1367
+ res = new DataView(map.has(obj.buffer) ? map.get(obj.buffer) : _cloneArrayBuffer(obj.buffer, map), obj.byteOffset, obj.byteLength);
1364
1368
  map.set(obj, res);
1365
1369
  }
1366
1370
  else if (isWrapperObject(obj)) {
@@ -1456,8 +1460,63 @@ See the Mulan PSL v2 for more details.
1456
1460
  return isNaN(value.getTime());
1457
1461
  if (isSet(value) || isMap(value))
1458
1462
  return !value.size;
1459
- return !Object.getOwnPropertyNames(value).length;
1463
+ for (const key in value) {
1464
+ if (Object.prototype.hasOwnProperty.call(value, key))
1465
+ return false;
1466
+ }
1467
+ return true;
1468
+ }
1469
+ }
1470
+
1471
+ function _getKey(args) {
1472
+ function toString(item) {
1473
+ if (isBigInt(item))
1474
+ return String(item) + 'n';
1475
+ if (isRegExp(item))
1476
+ return 'RegExp' + String(item);
1477
+ if (isDate(item))
1478
+ return 'Date' + item.toISOString();
1479
+ try {
1480
+ return JSON.stringify(item);
1481
+ }
1482
+ catch (e) {
1483
+ return String(item);
1484
+ }
1485
+ }
1486
+ let res = 'ForeSlashMemoKey:[';
1487
+ for (let i = 0; i < args.length; i++) {
1488
+ res += toString(args[i]) + ',';
1460
1489
  }
1490
+ return res + ']';
1491
+ }
1492
+ function memo(fn, options) {
1493
+ const map = new Map();
1494
+ const getKey = (options === null || options === void 0 ? void 0 : options.getKey) ? options.getKey : _getKey;
1495
+ const setTtl = (options === null || options === void 0 ? void 0 : options.ttl) ? options.ttl : 0;
1496
+ const setCount = (options === null || options === void 0 ? void 0 : options.count) ? options.count : 0;
1497
+ return function (...args) {
1498
+ const key = getKey(args);
1499
+ if (map.has(key)) {
1500
+ const item = map.get(key);
1501
+ const { res, ttl, count } = item;
1502
+ const isValidCache = ttl >= Date.now() && count > 0;
1503
+ item.count -= 1;
1504
+ if (item.count <= 0)
1505
+ map.delete(key);
1506
+ if (ttl < Date.now())
1507
+ map.delete(key);
1508
+ if (isValidCache)
1509
+ return res;
1510
+ }
1511
+ const res = fn.apply(this, args);
1512
+ const memoItem = { res, ttl: Infinity, count: Infinity };
1513
+ if (setCount > 0)
1514
+ memoItem.count = setCount;
1515
+ if (setTtl > 0)
1516
+ memoItem.ttl = Date.now() + setTtl;
1517
+ map.set(key, memoItem);
1518
+ return res;
1519
+ };
1461
1520
  }
1462
1521
 
1463
1522
  function not(value) {
@@ -1558,6 +1617,7 @@ See the Mulan PSL v2 for more details.
1558
1617
  exports.isWrapperString = isWrapperString;
1559
1618
  exports.isWrapperSymbol = isWrapperSymbol;
1560
1619
  exports.kebabCase = kebabCase;
1620
+ exports.memo = memo;
1561
1621
  exports.noop = noop;
1562
1622
  exports.not = not;
1563
1623
  exports.pascalCase = pascalCase;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foreslash",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Foreslash is a Javascript utilities lib which contains plenty of practical functions.",
5
5
  "author": "moushu",
6
6
  "license": "Mulan PSL v2",
@@ -21,7 +21,7 @@
21
21
  ".": {
22
22
  "import": "./lib/index.mjs",
23
23
  "require": "./lib/index.cmn.cjs",
24
- "types": "./types/index.d.ts"
24
+ "types": "./lib/index.d.ts"
25
25
  },
26
26
  "./umd": "./lib/index.umd.js"
27
27
  },