es-toolkit 1.31.0 → 1.32.0-dev.1003

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.
Files changed (70) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/_chunk/AbortError-Cg4ZQ1.js +10 -0
  3. package/dist/_chunk/delay-_VMfFa.js +25 -0
  4. package/dist/_chunk/isPlainObject-Xaozpc.js +93 -0
  5. package/dist/_chunk/{isWeakSet-CvIdTA.js → isWeakSet-DoHqUM.js} +42 -71
  6. package/dist/_chunk/{toMerged-DGFrN7.js → toMerged-BQTfB8.js} +39 -8
  7. package/dist/_chunk/{unary-B6qG7C.js → unary-c1NFA5.js} +35 -0
  8. package/dist/array/at.d.mts +1 -1
  9. package/dist/array/at.d.ts +1 -1
  10. package/dist/array/pullAt.d.mts +1 -1
  11. package/dist/array/pullAt.d.ts +1 -1
  12. package/dist/browser.global.js +1 -1
  13. package/dist/browser.global.js.map +1 -1
  14. package/dist/compat/array/find.d.mts +16 -8
  15. package/dist/compat/array/find.d.ts +16 -8
  16. package/dist/compat/array/find.mjs +5 -2
  17. package/dist/compat/array/sortedIndex.d.mts +16 -0
  18. package/dist/compat/array/sortedIndex.d.ts +16 -0
  19. package/dist/compat/array/sortedIndex.mjs +30 -0
  20. package/dist/compat/array/sortedIndexBy.d.mts +19 -0
  21. package/dist/compat/array/sortedIndexBy.d.ts +19 -0
  22. package/dist/compat/array/sortedIndexBy.mjs +56 -0
  23. package/dist/compat/index.d.mts +7 -0
  24. package/dist/compat/index.d.ts +7 -0
  25. package/dist/compat/index.js +145 -43
  26. package/dist/compat/index.mjs +7 -0
  27. package/dist/compat/math/multiply.d.mts +18 -0
  28. package/dist/compat/math/multiply.d.ts +18 -0
  29. package/dist/compat/math/multiply.mjs +21 -0
  30. package/dist/error/index.d.mts +2 -0
  31. package/dist/error/index.d.ts +2 -0
  32. package/dist/error/index.js +15 -0
  33. package/dist/error/index.mjs +2 -0
  34. package/dist/function/index.d.mts +1 -0
  35. package/dist/function/index.d.ts +1 -0
  36. package/dist/function/index.js +2 -1
  37. package/dist/function/index.mjs +1 -0
  38. package/dist/function/retry.d.mts +59 -0
  39. package/dist/function/retry.d.ts +59 -0
  40. package/dist/function/retry.mjs +35 -0
  41. package/dist/index.d.mts +4 -0
  42. package/dist/index.d.ts +4 -0
  43. package/dist/index.js +18 -11
  44. package/dist/index.mjs +4 -0
  45. package/dist/object/cloneDeepWith.mjs +34 -1
  46. package/dist/object/flattenObject.d.mts +10 -2
  47. package/dist/object/flattenObject.d.ts +10 -2
  48. package/dist/object/flattenObject.mjs +6 -6
  49. package/dist/object/index.js +1 -1
  50. package/dist/predicate/index.d.mts +1 -0
  51. package/dist/predicate/index.d.ts +1 -0
  52. package/dist/predicate/index.js +4 -7
  53. package/dist/predicate/index.mjs +1 -0
  54. package/dist/predicate/isPromise.d.mts +20 -0
  55. package/dist/predicate/isPromise.d.ts +20 -0
  56. package/dist/predicate/isPromise.mjs +5 -0
  57. package/dist/promise/index.d.mts +2 -0
  58. package/dist/promise/index.d.ts +2 -0
  59. package/dist/promise/index.js +56 -4
  60. package/dist/promise/index.mjs +2 -0
  61. package/dist/promise/mutex.d.mts +64 -0
  62. package/dist/promise/mutex.d.ts +64 -0
  63. package/dist/promise/mutex.mjs +16 -0
  64. package/dist/promise/semaphore.d.mts +81 -0
  65. package/dist/promise/semaphore.d.ts +81 -0
  66. package/dist/promise/semaphore.mjs +30 -0
  67. package/error.d.ts +1 -0
  68. package/package.json +42 -21
  69. package/dist/_chunk/index-BGZDR9.js +0 -50
  70. package/dist/_chunk/isPlainObject-octpoD.js +0 -32
package/dist/index.js CHANGED
@@ -4,18 +4,21 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
5
  const zipWith = require('./_chunk/zipWith-Bdyzuy.js');
6
6
  const array_index = require('./array/index.js');
7
- const promise_index = require('./_chunk/index-BGZDR9.js');
8
- const unary = require('./_chunk/unary-B6qG7C.js');
7
+ const AbortError = require('./_chunk/AbortError-Cg4ZQ1.js');
8
+ const error_index = require('./error/index.js');
9
+ const unary = require('./_chunk/unary-c1NFA5.js');
9
10
  const function_index = require('./function/index.js');
10
11
  const noop = require('./_chunk/noop-2IwLUk.js');
11
12
  const range = require('./_chunk/range-HnEIT7.js');
12
13
  const randomInt = require('./_chunk/randomInt-CF7bZK.js');
13
14
  const math_index = require('./math/index.js');
14
- const toMerged = require('./_chunk/toMerged-DGFrN7.js');
15
+ const toMerged = require('./_chunk/toMerged-BQTfB8.js');
15
16
  const object_index = require('./object/index.js');
16
- const isWeakSet = require('./_chunk/isWeakSet-CvIdTA.js');
17
+ const isWeakSet = require('./_chunk/isWeakSet-DoHqUM.js');
17
18
  const predicate_index = require('./predicate/index.js');
18
- const isPlainObject = require('./_chunk/isPlainObject-octpoD.js');
19
+ const isPlainObject = require('./_chunk/isPlainObject-Xaozpc.js');
20
+ const delay = require('./_chunk/delay-_VMfFa.js');
21
+ const promise_index = require('./promise/index.js');
19
22
  const upperFirst = require('./_chunk/upperFirst-CorAVn.js');
20
23
  const string_index = require('./string/index.js');
21
24
  const util_index = require('./util/index.js');
@@ -82,11 +85,8 @@ exports.zipWith = zipWith.zipWith;
82
85
  exports.orderBy = array_index.orderBy;
83
86
  exports.sortBy = array_index.sortBy;
84
87
  exports.takeRightWhile = array_index.takeRightWhile;
85
- exports.AbortError = promise_index.AbortError;
86
- exports.TimeoutError = promise_index.TimeoutError;
87
- exports.delay = promise_index.delay;
88
- exports.timeout = promise_index.timeout;
89
- exports.withTimeout = promise_index.withTimeout;
88
+ exports.AbortError = AbortError.AbortError;
89
+ exports.TimeoutError = error_index.TimeoutError;
90
90
  exports.after = unary.after;
91
91
  exports.ary = unary.ary;
92
92
  exports.asyncNoop = unary.asyncNoop;
@@ -100,6 +100,7 @@ exports.once = unary.once;
100
100
  exports.partial = unary.partial;
101
101
  exports.partialRight = unary.partialRight;
102
102
  exports.rest = unary.rest;
103
+ exports.retry = unary.retry;
103
104
  exports.unary = unary.unary;
104
105
  exports.before = function_index.before;
105
106
  exports.curry = function_index.curry;
@@ -151,18 +152,24 @@ exports.isMap = isWeakSet.isMap;
151
152
  exports.isNil = isWeakSet.isNil;
152
153
  exports.isNotNil = isWeakSet.isNotNil;
153
154
  exports.isNull = isWeakSet.isNull;
155
+ exports.isPromise = isWeakSet.isPromise;
154
156
  exports.isRegExp = isWeakSet.isRegExp;
155
157
  exports.isSet = isWeakSet.isSet;
158
+ exports.isSymbol = isWeakSet.isSymbol;
156
159
  exports.isUndefined = isWeakSet.isUndefined;
157
160
  exports.isWeakMap = isWeakSet.isWeakMap;
158
161
  exports.isWeakSet = isWeakSet.isWeakSet;
159
162
  exports.isBoolean = predicate_index.isBoolean;
160
163
  exports.isError = predicate_index.isError;
161
164
  exports.isString = predicate_index.isString;
162
- exports.isSymbol = predicate_index.isSymbol;
163
165
  exports.isPlainObject = isPlainObject.isPlainObject;
164
166
  exports.isPrimitive = isPlainObject.isPrimitive;
165
167
  exports.isTypedArray = isPlainObject.isTypedArray;
168
+ exports.delay = delay.delay;
169
+ exports.Mutex = promise_index.Mutex;
170
+ exports.Semaphore = promise_index.Semaphore;
171
+ exports.timeout = promise_index.timeout;
172
+ exports.withTimeout = promise_index.withTimeout;
166
173
  exports.camelCase = upperFirst.camelCase;
167
174
  exports.capitalize = upperFirst.capitalize;
168
175
  exports.constantCase = upperFirst.constantCase;
package/dist/index.mjs CHANGED
@@ -77,6 +77,7 @@ export { once } from './function/once.mjs';
77
77
  export { partial } from './function/partial.mjs';
78
78
  export { partialRight } from './function/partialRight.mjs';
79
79
  export { rest } from './function/rest.mjs';
80
+ export { retry } from './function/retry.mjs';
80
81
  export { spread } from './function/spread.mjs';
81
82
  export { throttle } from './function/throttle.mjs';
82
83
  export { unary } from './function/unary.mjs';
@@ -126,6 +127,7 @@ export { isNotNil } from './predicate/isNotNil.mjs';
126
127
  export { isNull } from './predicate/isNull.mjs';
127
128
  export { isPlainObject } from './predicate/isPlainObject.mjs';
128
129
  export { isPrimitive } from './predicate/isPrimitive.mjs';
130
+ export { isPromise } from './predicate/isPromise.mjs';
129
131
  export { isRegExp } from './predicate/isRegExp.mjs';
130
132
  export { isSet } from './predicate/isSet.mjs';
131
133
  export { isString } from './predicate/isString.mjs';
@@ -135,6 +137,8 @@ export { isUndefined } from './predicate/isUndefined.mjs';
135
137
  export { isWeakMap } from './predicate/isWeakMap.mjs';
136
138
  export { isWeakSet } from './predicate/isWeakSet.mjs';
137
139
  export { delay } from './promise/delay.mjs';
140
+ export { Mutex } from './promise/mutex.mjs';
141
+ export { Semaphore } from './promise/semaphore.mjs';
138
142
  export { timeout } from './promise/timeout.mjs';
139
143
  export { withTimeout } from './promise/withTimeout.mjs';
140
144
  export { camelCase } from './string/camelCase.mjs';
@@ -1,4 +1,6 @@
1
1
  import { getSymbols } from '../compat/_internal/getSymbols.mjs';
2
+ import { getTag } from '../compat/_internal/getTag.mjs';
3
+ import { uint32ArrayTag, uint16ArrayTag, uint8ClampedArrayTag, uint8ArrayTag, symbolTag, stringTag, setTag, regexpTag, objectTag, numberTag, mapTag, int32ArrayTag, int16ArrayTag, int8ArrayTag, float64ArrayTag, float32ArrayTag, dateTag, booleanTag, dataViewTag, arrayBufferTag, arrayTag, argumentsTag } from '../compat/_internal/tags.mjs';
2
4
  import { isPrimitive } from '../predicate/isPrimitive.mjs';
3
5
  import { isTypedArray } from '../predicate/isTypedArray.mjs';
4
6
 
@@ -99,7 +101,7 @@ function cloneDeepWithImpl(valueToClone, keyToClone, objectToClone, stack = new
99
101
  copyProperties(result, valueToClone, objectToClone, stack, cloneValue);
100
102
  return result;
101
103
  }
102
- if (typeof valueToClone === 'object' && valueToClone !== null) {
104
+ if (typeof valueToClone === 'object' && isCloneableObject(valueToClone)) {
103
105
  const result = Object.create(Object.getPrototypeOf(valueToClone));
104
106
  stack.set(valueToClone, result);
105
107
  copyProperties(result, valueToClone, objectToClone, stack, cloneValue);
@@ -117,5 +119,36 @@ function copyProperties(target, source, objectToClone = target, stack, cloneValu
117
119
  }
118
120
  }
119
121
  }
122
+ function isCloneableObject(object) {
123
+ switch (getTag(object)) {
124
+ case argumentsTag:
125
+ case arrayTag:
126
+ case arrayBufferTag:
127
+ case dataViewTag:
128
+ case booleanTag:
129
+ case dateTag:
130
+ case float32ArrayTag:
131
+ case float64ArrayTag:
132
+ case int8ArrayTag:
133
+ case int16ArrayTag:
134
+ case int32ArrayTag:
135
+ case mapTag:
136
+ case numberTag:
137
+ case objectTag:
138
+ case regexpTag:
139
+ case setTag:
140
+ case stringTag:
141
+ case symbolTag:
142
+ case uint8ArrayTag:
143
+ case uint8ClampedArrayTag:
144
+ case uint16ArrayTag:
145
+ case uint32ArrayTag: {
146
+ return true;
147
+ }
148
+ default: {
149
+ return false;
150
+ }
151
+ }
152
+ }
120
153
 
121
154
  export { cloneDeepWith, cloneDeepWithImpl, copyProperties };
@@ -1,7 +1,15 @@
1
+ interface FlattenObjectOptions {
2
+ /**
3
+ * The delimiter to use between nested keys.
4
+ * @default '.''
5
+ */
6
+ delimiter?: string;
7
+ }
1
8
  /**
2
- * Flattens a nested object into a single level object with dot-separated keys.
9
+ * Flattens a nested object into a single level object with delimiter-separated keys.
3
10
  *
4
11
  * @param {object} object - The object to flatten.
12
+ * @param {string} [options.delimiter='.'] - The delimiter to use between nested keys.
5
13
  * @returns {Record<string, any>} - The flattened object.
6
14
  *
7
15
  * @example
@@ -23,6 +31,6 @@
23
31
  * // 'd.1': 3
24
32
  * // }
25
33
  */
26
- declare function flattenObject(object: object): Record<string, any>;
34
+ declare function flattenObject(object: object, { delimiter }?: FlattenObjectOptions): Record<string, any>;
27
35
 
28
36
  export { flattenObject };
@@ -1,7 +1,15 @@
1
+ interface FlattenObjectOptions {
2
+ /**
3
+ * The delimiter to use between nested keys.
4
+ * @default '.''
5
+ */
6
+ delimiter?: string;
7
+ }
1
8
  /**
2
- * Flattens a nested object into a single level object with dot-separated keys.
9
+ * Flattens a nested object into a single level object with delimiter-separated keys.
3
10
  *
4
11
  * @param {object} object - The object to flatten.
12
+ * @param {string} [options.delimiter='.'] - The delimiter to use between nested keys.
5
13
  * @returns {Record<string, any>} - The flattened object.
6
14
  *
7
15
  * @example
@@ -23,6 +31,6 @@
23
31
  * // 'd.1': 3
24
32
  * // }
25
33
  */
26
- declare function flattenObject(object: object): Record<string, any>;
34
+ declare function flattenObject(object: object, { delimiter }?: FlattenObjectOptions): Record<string, any>;
27
35
 
28
36
  export { flattenObject };
@@ -1,21 +1,21 @@
1
1
  import { isPlainObject } from '../predicate/isPlainObject.mjs';
2
2
 
3
- function flattenObject(object) {
4
- return flattenObjectImpl(object);
3
+ function flattenObject(object, { delimiter = '.' } = {}) {
4
+ return flattenObjectImpl(object, '', delimiter);
5
5
  }
6
- function flattenObjectImpl(object, prefix = '') {
6
+ function flattenObjectImpl(object, prefix = '', delimiter = '.') {
7
7
  const result = {};
8
8
  const keys = Object.keys(object);
9
9
  for (let i = 0; i < keys.length; i++) {
10
10
  const key = keys[i];
11
11
  const value = object[key];
12
- const prefixedKey = prefix ? `${prefix}.${key}` : key;
12
+ const prefixedKey = prefix ? `${prefix}${delimiter}${key}` : key;
13
13
  if (isPlainObject(value) && Object.keys(value).length > 0) {
14
- Object.assign(result, flattenObjectImpl(value, prefixedKey));
14
+ Object.assign(result, flattenObjectImpl(value, prefixedKey, delimiter));
15
15
  continue;
16
16
  }
17
17
  if (Array.isArray(value)) {
18
- Object.assign(result, flattenObjectImpl(value, prefixedKey));
18
+ Object.assign(result, flattenObjectImpl(value, prefixedKey, delimiter));
19
19
  continue;
20
20
  }
21
21
  result[prefixedKey] = value;
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
- const toMerged = require('../_chunk/toMerged-DGFrN7.js');
5
+ const toMerged = require('../_chunk/toMerged-BQTfB8.js');
6
6
 
7
7
  function mergeWith(target, source, merge) {
8
8
  const sourceKeys = Object.keys(source);
@@ -16,6 +16,7 @@ export { isNotNil } from './isNotNil.mjs';
16
16
  export { isNull } from './isNull.mjs';
17
17
  export { isPlainObject } from './isPlainObject.mjs';
18
18
  export { isPrimitive } from './isPrimitive.mjs';
19
+ export { isPromise } from './isPromise.mjs';
19
20
  export { isRegExp } from './isRegExp.mjs';
20
21
  export { isSet } from './isSet.mjs';
21
22
  export { isString } from './isString.mjs';
@@ -16,6 +16,7 @@ export { isNotNil } from './isNotNil.js';
16
16
  export { isNull } from './isNull.js';
17
17
  export { isPlainObject } from './isPlainObject.js';
18
18
  export { isPrimitive } from './isPrimitive.js';
19
+ export { isPromise } from './isPromise.js';
19
20
  export { isRegExp } from './isRegExp.js';
20
21
  export { isSet } from './isSet.js';
21
22
  export { isString } from './isString.js';
@@ -2,8 +2,8 @@
2
2
 
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
- const isWeakSet = require('../_chunk/isWeakSet-CvIdTA.js');
6
- const isPlainObject = require('../_chunk/isPlainObject-octpoD.js');
5
+ const isWeakSet = require('../_chunk/isWeakSet-DoHqUM.js');
6
+ const isPlainObject = require('../_chunk/isPlainObject-Xaozpc.js');
7
7
 
8
8
  function isBoolean(x) {
9
9
  return typeof x === 'boolean';
@@ -17,10 +17,6 @@ function isString(value) {
17
17
  return typeof value === 'string';
18
18
  }
19
19
 
20
- function isSymbol(value) {
21
- return typeof value === 'symbol';
22
- }
23
-
24
20
  exports.isArrayBuffer = isWeakSet.isArrayBuffer;
25
21
  exports.isBlob = isWeakSet.isBlob;
26
22
  exports.isBuffer = isWeakSet.isBuffer;
@@ -37,8 +33,10 @@ exports.isMap = isWeakSet.isMap;
37
33
  exports.isNil = isWeakSet.isNil;
38
34
  exports.isNotNil = isWeakSet.isNotNil;
39
35
  exports.isNull = isWeakSet.isNull;
36
+ exports.isPromise = isWeakSet.isPromise;
40
37
  exports.isRegExp = isWeakSet.isRegExp;
41
38
  exports.isSet = isWeakSet.isSet;
39
+ exports.isSymbol = isWeakSet.isSymbol;
42
40
  exports.isUndefined = isWeakSet.isUndefined;
43
41
  exports.isWeakMap = isWeakSet.isWeakMap;
44
42
  exports.isWeakSet = isWeakSet.isWeakSet;
@@ -48,4 +46,3 @@ exports.isTypedArray = isPlainObject.isTypedArray;
48
46
  exports.isBoolean = isBoolean;
49
47
  exports.isError = isError;
50
48
  exports.isString = isString;
51
- exports.isSymbol = isSymbol;
@@ -16,6 +16,7 @@ export { isNotNil } from './isNotNil.mjs';
16
16
  export { isNull } from './isNull.mjs';
17
17
  export { isPlainObject } from './isPlainObject.mjs';
18
18
  export { isPrimitive } from './isPrimitive.mjs';
19
+ export { isPromise } from './isPromise.mjs';
19
20
  export { isRegExp } from './isRegExp.mjs';
20
21
  export { isSet } from './isSet.mjs';
21
22
  export { isString } from './isString.mjs';
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Checks if a given value is `Promise`.
3
+ *
4
+ * This function can also serve as a type predicate in TypeScript, narrowing the type of the argument to `Promise`.
5
+ *
6
+ * @param {unknown} value The value to check if it is a `Promise`.
7
+ * @returns {value is Promise<any>} Returns `true` if `value` is a `Promise`, else `false`.
8
+ *
9
+ * @example
10
+ * const value1 = new Promise((resolve) => resolve());
11
+ * const value2 = {};
12
+ * const value3 = 123;
13
+ *
14
+ * console.log(isPromise(value1)); // true
15
+ * console.log(isPromise(value2)); // false
16
+ * console.log(isPromise(value3)); // false
17
+ */
18
+ declare function isPromise(value: unknown): value is Promise<any>;
19
+
20
+ export { isPromise };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Checks if a given value is `Promise`.
3
+ *
4
+ * This function can also serve as a type predicate in TypeScript, narrowing the type of the argument to `Promise`.
5
+ *
6
+ * @param {unknown} value The value to check if it is a `Promise`.
7
+ * @returns {value is Promise<any>} Returns `true` if `value` is a `Promise`, else `false`.
8
+ *
9
+ * @example
10
+ * const value1 = new Promise((resolve) => resolve());
11
+ * const value2 = {};
12
+ * const value3 = 123;
13
+ *
14
+ * console.log(isPromise(value1)); // true
15
+ * console.log(isPromise(value2)); // false
16
+ * console.log(isPromise(value3)); // false
17
+ */
18
+ declare function isPromise(value: unknown): value is Promise<any>;
19
+
20
+ export { isPromise };
@@ -0,0 +1,5 @@
1
+ function isPromise(value) {
2
+ return value instanceof Promise;
3
+ }
4
+
5
+ export { isPromise };
@@ -1,3 +1,5 @@
1
1
  export { delay } from './delay.mjs';
2
+ export { Mutex } from './mutex.mjs';
3
+ export { Semaphore } from './semaphore.mjs';
2
4
  export { timeout } from './timeout.mjs';
3
5
  export { withTimeout } from './withTimeout.mjs';
@@ -1,3 +1,5 @@
1
1
  export { delay } from './delay.js';
2
+ export { Mutex } from './mutex.js';
3
+ export { Semaphore } from './semaphore.js';
2
4
  export { timeout } from './timeout.js';
3
5
  export { withTimeout } from './withTimeout.js';
@@ -2,10 +2,62 @@
2
2
 
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
- const promise_index = require('../_chunk/index-BGZDR9.js');
5
+ const delay = require('../_chunk/delay-_VMfFa.js');
6
+ const error_index = require('../error/index.js');
6
7
 
8
+ class Semaphore {
9
+ capacity;
10
+ available;
11
+ deferredTasks = [];
12
+ constructor(capacity) {
13
+ this.capacity = capacity;
14
+ this.available = capacity;
15
+ }
16
+ async acquire() {
17
+ if (this.available > 0) {
18
+ this.available--;
19
+ return;
20
+ }
21
+ return new Promise(resolve => {
22
+ this.deferredTasks.push(resolve);
23
+ });
24
+ }
25
+ release() {
26
+ const deferredTask = this.deferredTasks.shift();
27
+ if (deferredTask != null) {
28
+ deferredTask();
29
+ return;
30
+ }
31
+ if (this.available < this.capacity) {
32
+ this.available++;
33
+ }
34
+ }
35
+ }
7
36
 
37
+ class Mutex {
38
+ semaphore = new Semaphore(1);
39
+ get isLocked() {
40
+ return this.semaphore.available === 0;
41
+ }
42
+ async acquire() {
43
+ return this.semaphore.acquire();
44
+ }
45
+ release() {
46
+ this.semaphore.release();
47
+ }
48
+ }
8
49
 
9
- exports.delay = promise_index.delay;
10
- exports.timeout = promise_index.timeout;
11
- exports.withTimeout = promise_index.withTimeout;
50
+ async function timeout(ms) {
51
+ await delay.delay(ms);
52
+ throw new error_index.TimeoutError();
53
+ }
54
+
55
+ async function withTimeout(run, ms) {
56
+ return Promise.race([run(), timeout(ms)]);
57
+ }
58
+
59
+ exports.delay = delay.delay;
60
+ exports.Mutex = Mutex;
61
+ exports.Semaphore = Semaphore;
62
+ exports.timeout = timeout;
63
+ exports.withTimeout = withTimeout;
@@ -1,3 +1,5 @@
1
1
  export { delay } from './delay.mjs';
2
+ export { Mutex } from './mutex.mjs';
3
+ export { Semaphore } from './semaphore.mjs';
2
4
  export { timeout } from './timeout.mjs';
3
5
  export { withTimeout } from './withTimeout.mjs';
@@ -0,0 +1,64 @@
1
+ /**
2
+ * A Mutex (mutual exclusion lock) for async functions.
3
+ * It allows only one async task to access a critical section at a time.
4
+ *
5
+ * @example
6
+ * const mutex = new Mutex();
7
+ *
8
+ * async function criticalSection() {
9
+ * await mutex.acquire();
10
+ * try {
11
+ * // This code section cannot be executed simultaneously
12
+ * } finally {
13
+ * mutex.release();
14
+ * }
15
+ * }
16
+ *
17
+ * criticalSection();
18
+ * criticalSection(); // This call will wait until the first call releases the mutex.
19
+ */
20
+ declare class Mutex {
21
+ private semaphore;
22
+ /**
23
+ * Checks if the mutex is currently locked.
24
+ * @returns {boolean} True if the mutex is locked, false otherwise.
25
+ *
26
+ * @example
27
+ * const mutex = new Mutex();
28
+ * console.log(mutex.isLocked); // false
29
+ * await mutex.acquire();
30
+ * console.log(mutex.isLocked); // true
31
+ * mutex.release();
32
+ * console.log(mutex.isLocked); // false
33
+ */
34
+ get isLocked(): boolean;
35
+ /**
36
+ * Acquires the mutex, blocking if necessary until it is available.
37
+ * @returns {Promise<void>} A promise that resolves when the mutex is acquired.
38
+ *
39
+ * @example
40
+ * const mutex = new Mutex();
41
+ * await mutex.acquire();
42
+ * try {
43
+ * // This code section cannot be executed simultaneously
44
+ * } finally {
45
+ * mutex.release();
46
+ * }
47
+ */
48
+ acquire(): Promise<void>;
49
+ /**
50
+ * Releases the mutex, allowing another waiting task to proceed.
51
+ *
52
+ * @example
53
+ * const mutex = new Mutex();
54
+ * await mutex.acquire();
55
+ * try {
56
+ * // This code section cannot be executed simultaneously
57
+ * } finally {
58
+ * mutex.release(); // Allows another waiting task to proceed.
59
+ * }
60
+ */
61
+ release(): void;
62
+ }
63
+
64
+ export { Mutex };
@@ -0,0 +1,64 @@
1
+ /**
2
+ * A Mutex (mutual exclusion lock) for async functions.
3
+ * It allows only one async task to access a critical section at a time.
4
+ *
5
+ * @example
6
+ * const mutex = new Mutex();
7
+ *
8
+ * async function criticalSection() {
9
+ * await mutex.acquire();
10
+ * try {
11
+ * // This code section cannot be executed simultaneously
12
+ * } finally {
13
+ * mutex.release();
14
+ * }
15
+ * }
16
+ *
17
+ * criticalSection();
18
+ * criticalSection(); // This call will wait until the first call releases the mutex.
19
+ */
20
+ declare class Mutex {
21
+ private semaphore;
22
+ /**
23
+ * Checks if the mutex is currently locked.
24
+ * @returns {boolean} True if the mutex is locked, false otherwise.
25
+ *
26
+ * @example
27
+ * const mutex = new Mutex();
28
+ * console.log(mutex.isLocked); // false
29
+ * await mutex.acquire();
30
+ * console.log(mutex.isLocked); // true
31
+ * mutex.release();
32
+ * console.log(mutex.isLocked); // false
33
+ */
34
+ get isLocked(): boolean;
35
+ /**
36
+ * Acquires the mutex, blocking if necessary until it is available.
37
+ * @returns {Promise<void>} A promise that resolves when the mutex is acquired.
38
+ *
39
+ * @example
40
+ * const mutex = new Mutex();
41
+ * await mutex.acquire();
42
+ * try {
43
+ * // This code section cannot be executed simultaneously
44
+ * } finally {
45
+ * mutex.release();
46
+ * }
47
+ */
48
+ acquire(): Promise<void>;
49
+ /**
50
+ * Releases the mutex, allowing another waiting task to proceed.
51
+ *
52
+ * @example
53
+ * const mutex = new Mutex();
54
+ * await mutex.acquire();
55
+ * try {
56
+ * // This code section cannot be executed simultaneously
57
+ * } finally {
58
+ * mutex.release(); // Allows another waiting task to proceed.
59
+ * }
60
+ */
61
+ release(): void;
62
+ }
63
+
64
+ export { Mutex };
@@ -0,0 +1,16 @@
1
+ import { Semaphore } from './semaphore.mjs';
2
+
3
+ class Mutex {
4
+ semaphore = new Semaphore(1);
5
+ get isLocked() {
6
+ return this.semaphore.available === 0;
7
+ }
8
+ async acquire() {
9
+ return this.semaphore.acquire();
10
+ }
11
+ release() {
12
+ this.semaphore.release();
13
+ }
14
+ }
15
+
16
+ export { Mutex };
@@ -0,0 +1,81 @@
1
+ /**
2
+ * A counting semaphore for async functions that manages available permits.
3
+ * Semaphores are mainly used to limit the number of concurrent async tasks.
4
+ *
5
+ * Each `acquire` operation takes a permit or waits until one is available.
6
+ * Each `release` operation adds a permit, potentially allowing a waiting task to proceed.
7
+ *
8
+ * The semaphore ensures fairness by maintaining a FIFO (First In, First Out) order for acquirers.
9
+ *
10
+ * @example
11
+ * const sema = new Semaphore(2);
12
+ *
13
+ * async function task() {
14
+ * await sema.acquire();
15
+ * try {
16
+ * // This code can only be executed by two tasks at the same time
17
+ * } finally {
18
+ * sema.release();
19
+ * }
20
+ * }
21
+ *
22
+ * task();
23
+ * task();
24
+ * task(); // This task will wait until one of the previous tasks releases the semaphore.
25
+ */
26
+ declare class Semaphore {
27
+ /**
28
+ * The maximum number of concurrent operations allowed.
29
+ * @type {number}
30
+ */
31
+ capacity: number;
32
+ /**
33
+ * The number of available permits.
34
+ * @type {number}
35
+ */
36
+ available: number;
37
+ private deferredTasks;
38
+ /**
39
+ * Creates an instance of Semaphore.
40
+ * @param {number} capacity - The maximum number of concurrent operations allowed.
41
+ *
42
+ * @example
43
+ * const sema = new Semaphore(3); // Allows up to 3 concurrent operations.
44
+ */
45
+ constructor(capacity: number);
46
+ /**
47
+ * Acquires a semaphore, blocking if necessary until one is available.
48
+ * @returns {Promise<void>} A promise that resolves when the semaphore is acquired.
49
+ *
50
+ * @example
51
+ * const sema = new Semaphore(1);
52
+ *
53
+ * async function criticalSection() {
54
+ * await sema.acquire();
55
+ * try {
56
+ * // This code section cannot be executed simultaneously
57
+ * } finally {
58
+ * sema.release();
59
+ * }
60
+ * }
61
+ */
62
+ acquire(): Promise<void>;
63
+ /**
64
+ * Releases a semaphore, allowing one more operation to proceed.
65
+ *
66
+ * @example
67
+ * const sema = new Semaphore(1);
68
+ *
69
+ * async function task() {
70
+ * await sema.acquire();
71
+ * try {
72
+ * // This code can only be executed by two tasks at the same time
73
+ * } finally {
74
+ * sema.release(); // Allows another waiting task to proceed.
75
+ * }
76
+ * }
77
+ */
78
+ release(): void;
79
+ }
80
+
81
+ export { Semaphore };