@ezez/utils 4.8.0 → 4.8.2

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 (188) hide show
  1. package/.claude/settings.local.json +14 -0
  2. package/CHANGELOG.md +18 -0
  3. package/CLAUDE.md +137 -0
  4. package/dist/get.d.ts.map +1 -1
  5. package/dist/get.js +1 -1
  6. package/dist/get.js.map +1 -1
  7. package/dist/mostFrequent.d.ts +1 -1
  8. package/dist/mostFrequent.d.ts.map +1 -1
  9. package/dist/mostFrequent.js +2 -5
  10. package/dist/mostFrequent.js.map +1 -1
  11. package/dist/samples.d.ts.map +1 -1
  12. package/dist/samples.js +2 -1
  13. package/dist/samples.js.map +1 -1
  14. package/dist/scale.d.ts.map +1 -1
  15. package/dist/scale.js +3 -0
  16. package/dist/scale.js.map +1 -1
  17. package/dist/serializeToBuffer/unserializeFromBuffer.d.ts.map +1 -1
  18. package/dist/serializeToBuffer/unserializeFromBuffer.js +1 -3
  19. package/dist/serializeToBuffer/unserializeFromBuffer.js.map +1 -1
  20. package/dist/sortByMultiple.d.ts.map +1 -1
  21. package/dist/sortByMultiple.js.map +1 -1
  22. package/dist/throttle.d.ts +3 -3
  23. package/dist/throttle.d.ts.map +1 -1
  24. package/dist/throttle.js +2 -3
  25. package/dist/throttle.js.map +1 -1
  26. package/dist/trimEnd.d.ts.map +1 -1
  27. package/dist/trimEnd.js +3 -0
  28. package/dist/trimEnd.js.map +1 -1
  29. package/dist/trimStart.d.ts.map +1 -1
  30. package/dist/trimStart.js +3 -0
  31. package/dist/trimStart.js.map +1 -1
  32. package/dist/waitFor.d.ts.map +1 -1
  33. package/dist/waitFor.js +19 -11
  34. package/dist/waitFor.js.map +1 -1
  35. package/docs/documents/Changelog.html +72 -54
  36. package/docs/functions/index.assertProps.html +2 -2
  37. package/docs/functions/index.cap.html +2 -2
  38. package/docs/functions/index.capitalize.html +2 -2
  39. package/docs/functions/index.coalesce.html +2 -2
  40. package/docs/functions/index.compareArrays.html +2 -2
  41. package/docs/functions/index.compareProps.html +2 -2
  42. package/docs/functions/index.deserialize.html +2 -2
  43. package/docs/functions/index.ensureArray.html +2 -2
  44. package/docs/functions/index.ensureDate.html +2 -2
  45. package/docs/functions/index.ensureError.html +2 -2
  46. package/docs/functions/index.ensurePrefix.html +2 -2
  47. package/docs/functions/index.ensureSuffix.html +2 -2
  48. package/docs/functions/index.ensureTimestamp.html +2 -2
  49. package/docs/functions/index.escapeRegExp.html +2 -2
  50. package/docs/functions/index.formatDate.html +2 -2
  51. package/docs/functions/index.formatHash.html +2 -2
  52. package/docs/functions/index.get.html +3 -3
  53. package/docs/functions/index.getMultiple.html +2 -2
  54. package/docs/functions/index.hasProps.html +2 -2
  55. package/docs/functions/index.ignore.html +2 -2
  56. package/docs/functions/index.insertSeparator.html +2 -2
  57. package/docs/functions/index.isEmpty.html +2 -2
  58. package/docs/functions/index.isNumericString.html +2 -2
  59. package/docs/functions/index.isPlainObject.html +2 -2
  60. package/docs/functions/index.last.html +2 -2
  61. package/docs/functions/index.later-1.html +2 -2
  62. package/docs/functions/index.mapAsync.html +2 -2
  63. package/docs/functions/index.mapValues.html +2 -2
  64. package/docs/functions/index.match.html +2 -2
  65. package/docs/functions/index.memoize.html +2 -2
  66. package/docs/functions/index.merge.html +2 -2
  67. package/docs/functions/index.mostFrequent.html +2 -2
  68. package/docs/functions/index.noop.html +2 -2
  69. package/docs/functions/index.occurrences.html +2 -2
  70. package/docs/functions/index.omit.html +2 -2
  71. package/docs/functions/index.pick.html +2 -2
  72. package/docs/functions/index.pull.html +2 -2
  73. package/docs/functions/index.race.html +2 -2
  74. package/docs/functions/index.remove.html +2 -2
  75. package/docs/functions/index.removeCommonProperties.html +2 -2
  76. package/docs/functions/index.replace.html +2 -2
  77. package/docs/functions/index.replaceDeep.html +2 -2
  78. package/docs/functions/index.rethrow.html +2 -2
  79. package/docs/functions/index.retry.html +2 -2
  80. package/docs/functions/index.round.html +2 -2
  81. package/docs/functions/index.safe.html +2 -2
  82. package/docs/functions/index.sample.html +2 -2
  83. package/docs/functions/index.samples.html +2 -2
  84. package/docs/functions/index.scale.html +3 -2
  85. package/docs/functions/index.seq.html +2 -2
  86. package/docs/functions/index.seqEarlyBreak.html +2 -2
  87. package/docs/functions/index.serialize.html +2 -2
  88. package/docs/functions/index.serializeToBuffer.html +2 -2
  89. package/docs/functions/index.set.html +2 -2
  90. package/docs/functions/index.setImmutable.html +2 -2
  91. package/docs/functions/index.shuffle.html +2 -2
  92. package/docs/functions/index.sortBy.html +2 -2
  93. package/docs/functions/index.sortByMultiple.html +3 -3
  94. package/docs/functions/index.sortProps.html +2 -2
  95. package/docs/functions/index.stripPrefix.html +2 -2
  96. package/docs/functions/index.stripSuffix.html +2 -2
  97. package/docs/functions/index.throttle.html +3 -3
  98. package/docs/functions/index.toggle.html +2 -2
  99. package/docs/functions/index.trim.html +2 -2
  100. package/docs/functions/index.trimEnd.html +2 -2
  101. package/docs/functions/index.trimStart.html +2 -2
  102. package/docs/functions/index.truthy.html +2 -2
  103. package/docs/functions/index.unique.html +2 -2
  104. package/docs/functions/index.unserializeFromBuffer.html +2 -2
  105. package/docs/functions/index.wait.html +2 -2
  106. package/docs/functions/index.waitFor.html +2 -2
  107. package/docs/functions/index.waitSync.html +2 -2
  108. package/docs/index.html +2 -2
  109. package/docs/interfaces/index.ComparePropsOptions.html +3 -3
  110. package/docs/interfaces/index.GetMultipleSource.html +2 -2
  111. package/docs/interfaces/index.GetSource.html +2 -2
  112. package/docs/interfaces/index.IsNumericStringOptions.html +2 -2
  113. package/docs/interfaces/index.OccurencesOptions.html +2 -2
  114. package/docs/interfaces/index.SetImmutableSource.html +2 -2
  115. package/docs/interfaces/index.SetSource.html +2 -2
  116. package/docs/interfaces/index.ThrottleOptions.html +3 -3
  117. package/docs/interfaces/index.ThrottledFunctionExtras.html +3 -3
  118. package/docs/modules/index.html +1 -1
  119. package/docs/modules.html +1 -1
  120. package/docs/types/index.CustomDeserializers.html +1 -1
  121. package/docs/types/index.CustomSerializers.html +1 -1
  122. package/docs/types/index.Later.html +2 -2
  123. package/docs/types/index.MapValuesFn.html +2 -2
  124. package/docs/types/index.MatchCallback.html +1 -1
  125. package/docs/types/index.MergeTwo.html +2 -2
  126. package/docs/types/index.SeqEarlyBreaker.html +2 -2
  127. package/docs/types/index.SeqFn.html +2 -2
  128. package/docs/types/index.SeqFunctions.html +2 -2
  129. package/docs/types/index.SetImmutablePath.html +2 -2
  130. package/docs/types/index.ThrottledFunction.html +1 -1
  131. package/docs/variables/index.mapValuesUNSET.html +2 -2
  132. package/docs/variables/index.mergeUNSET.html +2 -2
  133. package/esm/get.d.ts.map +1 -1
  134. package/esm/get.js +1 -1
  135. package/esm/get.js.map +1 -1
  136. package/esm/mostFrequent.d.ts +1 -1
  137. package/esm/mostFrequent.d.ts.map +1 -1
  138. package/esm/mostFrequent.js +2 -5
  139. package/esm/mostFrequent.js.map +1 -1
  140. package/esm/samples.d.ts.map +1 -1
  141. package/esm/samples.js +2 -1
  142. package/esm/samples.js.map +1 -1
  143. package/esm/scale.d.ts.map +1 -1
  144. package/esm/scale.js +3 -0
  145. package/esm/scale.js.map +1 -1
  146. package/esm/serializeToBuffer/unserializeFromBuffer.d.ts.map +1 -1
  147. package/esm/serializeToBuffer/unserializeFromBuffer.js +1 -3
  148. package/esm/serializeToBuffer/unserializeFromBuffer.js.map +1 -1
  149. package/esm/sortByMultiple.d.ts.map +1 -1
  150. package/esm/sortByMultiple.js.map +1 -1
  151. package/esm/throttle.d.ts +3 -3
  152. package/esm/throttle.d.ts.map +1 -1
  153. package/esm/throttle.js +2 -3
  154. package/esm/throttle.js.map +1 -1
  155. package/esm/trimEnd.d.ts.map +1 -1
  156. package/esm/trimEnd.js +3 -0
  157. package/esm/trimEnd.js.map +1 -1
  158. package/esm/trimStart.d.ts.map +1 -1
  159. package/esm/trimStart.js +3 -0
  160. package/esm/trimStart.js.map +1 -1
  161. package/esm/waitFor.d.ts.map +1 -1
  162. package/esm/waitFor.js +19 -11
  163. package/esm/waitFor.js.map +1 -1
  164. package/package.json +12 -17
  165. package/pnpm-workspace.yaml +2 -0
  166. package/src/get.ts +1 -1
  167. package/src/mostFrequent.spec.ts +2 -1
  168. package/src/mostFrequent.ts +3 -7
  169. package/src/race.spec.ts +42 -0
  170. package/src/race.ts +0 -2
  171. package/src/retry.spec.ts +87 -0
  172. package/src/retry.ts +0 -2
  173. package/src/samples.spec.ts +9 -0
  174. package/src/samples.ts +4 -1
  175. package/src/scale.spec.ts +18 -0
  176. package/src/scale.ts +4 -0
  177. package/src/serializeToBuffer/unserializeFromBuffer.spec.ts +10 -0
  178. package/src/serializeToBuffer/unserializeFromBuffer.ts +1 -4
  179. package/src/sortByMultiple.ts +1 -0
  180. package/src/throttle.spec.ts +35 -0
  181. package/src/throttle.ts +7 -8
  182. package/src/trimEnd.spec.ts +5 -0
  183. package/src/trimEnd.ts +3 -0
  184. package/src/trimStart.spec.ts +5 -0
  185. package/src/trimStart.ts +3 -0
  186. package/src/waitFor.spec.ts +61 -0
  187. package/src/waitFor.ts +33 -15
  188. package/src/waitSync.ts +2 -2
package/src/waitFor.ts CHANGED
@@ -26,6 +26,18 @@ const defaultOptions: Required<Options> = {
26
26
  maxTries: Infinity,
27
27
  };
28
28
 
29
+ /**
30
+ * Appends the synchronously-captured caller frames onto an error created later (on a timer or
31
+ * microtask), so its stack trace points at whoever called `waitFor` instead of just node internals.
32
+ */
33
+ const graftCallerStack = (error: Error, callSite: Error): void => {
34
+ const callerFrames = callSite.stack?.replace(/^.*\n/u, "");
35
+ if (callerFrames) {
36
+ // eslint-disable-next-line no-param-reassign
37
+ error.stack = error.stack ? `${error.stack}\n${callerFrames}` : callerFrames;
38
+ }
39
+ };
40
+
29
41
  /**
30
42
  * Runs the callback function every specified interval and returns a Promise that resolves when the callback returns
31
43
  * any other value than `null`, `undefined` or `false`.
@@ -39,26 +51,35 @@ const defaultOptions: Required<Options> = {
39
51
  * @param fn - callback function
40
52
  * @param options - options object
41
53
  */
42
- const waitFor = <T>(fn: () => MaybePromise<T>, options: Options = defaultOptions): Promise<T> => {
54
+ const waitFor = <T>(fn: () => MaybePromise<T>, options: Options = defaultOptions): Promise<T> => { // eslint-disable-line max-lines-per-function
55
+ // Captured synchronously on the caller's stack: once execution hops onto a timer or
56
+ // microtask those frames are gone, so we graft them back onto any rejected error (see
57
+ // `graftCallerStack`) to keep production stack traces pointing at the actual caller.
58
+ const callSite = new Error();
59
+
43
60
  return new Promise<T>((resolve, reject) => {
44
61
  let intervalTimer: TTimeout, failTimer: TTimeout;
45
62
 
63
+ const fail = (error: Error): void => {
64
+ graftCallerStack(error, callSite);
65
+ clearTimeout(failTimer);
66
+ clearTimeout(intervalTimer);
67
+ reject(error);
68
+ };
69
+
46
70
  const opts = { ...defaultOptions, ...options };
47
71
  if (typeof opts.maxTries === "number" && opts.maxTries < 1) {
48
- reject(new TypeError("[waitFor] maxTries must be greater than 0"));
72
+ fail(new TypeError("[waitFor] maxTries must be greater than 0"));
49
73
  return;
50
74
  }
51
75
 
52
76
  if (Number.isFinite(opts.timeout)) {
53
77
  failTimer = setTimeout(() => {
54
- reject(new Error("[waitFor] Timeout"));
55
- clearTimeout(intervalTimer);
78
+ fail(new Error("[waitFor] Timeout"));
56
79
  }, opts.timeout);
57
80
  }
58
81
 
59
82
  let tries = 0;
60
-
61
- // eslint-disable-next-line max-statements
62
83
  const tryFn = (async () => {
63
84
  try {
64
85
  tries++;
@@ -71,24 +92,21 @@ const waitFor = <T>(fn: () => MaybePromise<T>, options: Options = defaultOptions
71
92
  }
72
93
  else {
73
94
  if (Number.isFinite(opts.maxTries) && tries >= opts.maxTries) {
74
- clearTimeout(failTimer);
75
- clearTimeout(intervalTimer);
76
- reject(new Error("[waitFor] Max tries reached"));
95
+ fail(new Error("[waitFor] Max tries reached"));
77
96
  return;
78
97
  }
79
98
 
80
99
  intervalTimer = setTimeout(() => {
81
100
  tryFn().catch(noop);
82
- }, options.interval);
101
+ }, opts.interval);
83
102
  }
84
103
  }
85
104
  catch (error: unknown) {
86
- clearTimeout(failTimer);
87
- clearTimeout(intervalTimer);
88
-
89
- const e: Error & { details?: unknown } = new Error("[waitFor] check function threw an error");
105
+ const e: Error & { details?: unknown } = new Error(
106
+ "[waitFor] check function threw an error", { cause: error },
107
+ );
90
108
  e.details = { error };
91
- reject(e);
109
+ fail(e);
92
110
  }
93
111
  });
94
112
  tryFn().catch(noop);
package/src/waitSync.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Synchronously wait for a given time, blocking the event loop [!]
3
- * @param {number} timeMs - time to wait
4
- * @returns {Promise<void>}
3
+ * @param timeMs - time to wait
4
+ * @returns
5
5
  */
6
6
  const waitSync = (timeMs = 0): void => {
7
7
  const s = Date.now();