@ezez/utils 3.0.0 → 4.1.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.
Files changed (468) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/cap.js.map +1 -1
  3. package/dist/coalesce.d.ts.map +1 -1
  4. package/dist/coalesce.js.map +1 -1
  5. package/dist/compareArrays.d.ts.map +1 -1
  6. package/dist/compareProps.d.ts.map +1 -1
  7. package/dist/compareProps.js.map +1 -1
  8. package/dist/deserialize.d.ts.map +1 -1
  9. package/dist/deserialize.js.map +1 -1
  10. package/dist/ensureArray.d.ts.map +1 -1
  11. package/dist/ensureArray.js.map +1 -1
  12. package/dist/ensureDate.js.map +1 -1
  13. package/dist/ensureError.js.map +1 -1
  14. package/dist/ensurePrefix.js.map +1 -1
  15. package/dist/ensureSuffix.js.map +1 -1
  16. package/dist/ensureTimestamp.js.map +1 -1
  17. package/dist/escapeRegExp.d.ts.map +1 -1
  18. package/dist/escapeRegExp.js +1 -1
  19. package/dist/escapeRegExp.js.map +1 -1
  20. package/dist/formatDate.js +1 -1
  21. package/dist/formatDate.js.map +1 -1
  22. package/dist/get.js.map +1 -1
  23. package/dist/getMultiple.d.ts.map +1 -1
  24. package/dist/getMultiple.js.map +1 -1
  25. package/dist/index.d.ts +4 -0
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +4 -0
  28. package/dist/index.js.map +1 -1
  29. package/dist/insertSeparator.d.ts.map +1 -1
  30. package/dist/insertSeparator.js.map +1 -1
  31. package/dist/isEmpty.js.map +1 -1
  32. package/dist/isNumericString.js +1 -1
  33. package/dist/isNumericString.js.map +1 -1
  34. package/dist/last.d.ts.map +1 -1
  35. package/dist/later.d.ts.map +1 -1
  36. package/dist/mapAsync.d.ts.map +1 -1
  37. package/dist/mapAsync.js.map +1 -1
  38. package/dist/mapValues.d.ts.map +1 -1
  39. package/dist/mapValues.js.map +1 -1
  40. package/dist/match.d.ts.map +1 -1
  41. package/dist/match.js.map +1 -1
  42. package/dist/memoize.d.ts +3 -0
  43. package/dist/memoize.d.ts.map +1 -0
  44. package/dist/memoize.js +19 -0
  45. package/dist/memoize.js.map +1 -0
  46. package/dist/merge.d.ts +11 -7
  47. package/dist/merge.d.ts.map +1 -1
  48. package/dist/merge.js.map +1 -1
  49. package/dist/mostFrequent.d.ts.map +1 -1
  50. package/dist/mostFrequent.js.map +1 -1
  51. package/dist/occurrences.js.map +1 -1
  52. package/dist/omit.d.ts +1 -1
  53. package/dist/omit.d.ts.map +1 -1
  54. package/dist/omit.js.map +1 -1
  55. package/dist/pick.d.ts.map +1 -1
  56. package/dist/pick.js.map +1 -1
  57. package/dist/pull.d.ts.map +1 -1
  58. package/dist/pull.js.map +1 -1
  59. package/dist/remove.d.ts.map +1 -1
  60. package/dist/remove.js +1 -1
  61. package/dist/remove.js.map +1 -1
  62. package/dist/removeCommonProperties.d.ts.map +1 -1
  63. package/dist/removeCommonProperties.js +3 -1
  64. package/dist/removeCommonProperties.js.map +1 -1
  65. package/dist/replace.js +1 -1
  66. package/dist/replace.js.map +1 -1
  67. package/dist/replaceDeep.d.ts +5 -1
  68. package/dist/replaceDeep.d.ts.map +1 -1
  69. package/dist/replaceDeep.js +3 -20
  70. package/dist/replaceDeep.js.map +1 -1
  71. package/dist/replaceDeepByFn.d.ts +7 -0
  72. package/dist/replaceDeepByFn.d.ts.map +1 -0
  73. package/dist/replaceDeepByFn.js +47 -0
  74. package/dist/replaceDeepByFn.js.map +1 -0
  75. package/dist/safe.js.map +1 -1
  76. package/dist/sample.d.ts +3 -1
  77. package/dist/sample.d.ts.map +1 -1
  78. package/dist/sample.js.map +1 -1
  79. package/dist/samples.d.ts.map +1 -1
  80. package/dist/samples.js.map +1 -1
  81. package/dist/seq.d.ts.map +1 -1
  82. package/dist/seq.js +1 -1
  83. package/dist/seq.js.map +1 -1
  84. package/dist/serialize.d.ts.map +1 -1
  85. package/dist/serialize.js +56 -18
  86. package/dist/serialize.js.map +1 -1
  87. package/dist/set.js.map +1 -1
  88. package/dist/setImmutable.js.map +1 -1
  89. package/dist/shuffle.d.ts.map +1 -1
  90. package/dist/sortBy.d.ts.map +1 -1
  91. package/dist/sortBy.js.map +1 -1
  92. package/dist/sortProps.d.ts.map +1 -1
  93. package/dist/sortProps.js.map +1 -1
  94. package/dist/stripPrefix.js.map +1 -1
  95. package/dist/stripSuffix.js.map +1 -1
  96. package/dist/throttle.d.ts.map +1 -1
  97. package/dist/throttle.js.map +1 -1
  98. package/dist/toggle.d.ts.map +1 -1
  99. package/dist/toggle.js.map +1 -1
  100. package/dist/trim.d.ts +3 -0
  101. package/dist/trim.d.ts.map +1 -0
  102. package/dist/trim.js +10 -0
  103. package/dist/trim.js.map +1 -0
  104. package/dist/trimEnd.d.ts +3 -0
  105. package/dist/trimEnd.d.ts.map +1 -0
  106. package/dist/trimEnd.js +12 -0
  107. package/dist/trimEnd.js.map +1 -0
  108. package/dist/trimStart.d.ts +3 -0
  109. package/dist/trimStart.d.ts.map +1 -0
  110. package/dist/trimStart.js +12 -0
  111. package/dist/trimStart.js.map +1 -0
  112. package/dist/truthy.d.ts +1 -1
  113. package/dist/truthy.d.ts.map +1 -1
  114. package/dist/unique.d.ts.map +1 -1
  115. package/dist/utils/utils.d.ts +6 -0
  116. package/dist/utils/utils.d.ts.map +1 -0
  117. package/dist/utils/utils.js +10 -0
  118. package/dist/utils/utils.js.map +1 -0
  119. package/dist/waitFor.d.ts.map +1 -1
  120. package/dist/waitFor.js +1 -1
  121. package/dist/waitFor.js.map +1 -1
  122. package/dist/waitSync.js.map +1 -1
  123. package/docs/assets/icons.js +15 -0
  124. package/docs/assets/icons.svg +1 -0
  125. package/docs/assets/main.js +4 -3
  126. package/docs/assets/navigation.js +1 -0
  127. package/docs/assets/search.js +1 -1
  128. package/docs/assets/style.css +544 -394
  129. package/docs/documents/CHANGELOG.html +337 -0
  130. package/docs/functions/index.cap.html +5 -0
  131. package/docs/functions/index.capitalize.html +13 -0
  132. package/docs/functions/index.coalesce.html +16 -0
  133. package/docs/functions/index.compareArrays.html +8 -0
  134. package/docs/functions/index.compareProps.html +11 -0
  135. package/docs/functions/index.deserialize.html +6 -0
  136. package/docs/functions/index.ensureArray.html +3 -0
  137. package/docs/functions/index.ensureDate.html +10 -0
  138. package/docs/functions/index.ensureError.html +14 -0
  139. package/docs/functions/index.ensurePrefix.html +10 -0
  140. package/docs/functions/index.ensureSuffix.html +10 -0
  141. package/docs/functions/index.ensureTimestamp.html +10 -0
  142. package/docs/functions/index.escapeRegExp.html +7 -0
  143. package/docs/functions/index.formatDate.html +6 -0
  144. package/docs/functions/index.get.html +26 -0
  145. package/docs/functions/index.getMultiple.html +16 -0
  146. package/docs/functions/index.insertSeparator.html +7 -0
  147. package/docs/functions/index.isEmpty.html +33 -0
  148. package/docs/functions/index.isNumericString.html +5 -0
  149. package/docs/functions/index.isPlainObject.html +18 -0
  150. package/docs/functions/index.last.html +15 -0
  151. package/docs/functions/index.later-1.html +6 -0
  152. package/docs/functions/index.mapAsync.html +8 -0
  153. package/docs/functions/index.mapValues.html +14 -0
  154. package/docs/functions/index.match.html +4 -0
  155. package/docs/functions/index.memoize.html +8 -0
  156. package/docs/functions/index.merge.html +13 -0
  157. package/docs/functions/index.mostFrequent.html +2 -0
  158. package/docs/functions/index.noop.html +2 -0
  159. package/docs/functions/index.occurrences.html +14 -0
  160. package/docs/functions/index.omit.html +18 -0
  161. package/docs/functions/index.pick.html +13 -0
  162. package/docs/functions/index.pull.html +2 -0
  163. package/docs/functions/index.remove.html +2 -0
  164. package/docs/functions/index.removeCommonProperties.html +18 -0
  165. package/docs/functions/index.replace.html +10 -0
  166. package/docs/functions/index.replaceDeep.html +15 -0
  167. package/docs/functions/index.rethrow.html +2 -0
  168. package/docs/functions/index.round.html +7 -0
  169. package/docs/functions/index.safe.html +7 -0
  170. package/docs/functions/index.sample.html +6 -0
  171. package/docs/functions/index.samples.html +7 -0
  172. package/docs/functions/index.scale.html +5 -0
  173. package/docs/functions/index.seq.html +17 -0
  174. package/docs/functions/index.seqEarlyBreak.html +12 -0
  175. package/docs/functions/index.serialize.html +14 -0
  176. package/docs/functions/index.set.html +26 -0
  177. package/docs/functions/index.setImmutable.html +25 -0
  178. package/docs/functions/index.shuffle.html +3 -0
  179. package/docs/functions/index.sortBy.html +6 -0
  180. package/docs/functions/index.sortProps.html +10 -0
  181. package/docs/functions/index.stripPrefix.html +4 -0
  182. package/docs/functions/index.stripSuffix.html +4 -0
  183. package/docs/functions/index.throttle.html +14 -0
  184. package/docs/functions/index.toggle.html +5 -0
  185. package/docs/functions/index.trim.html +8 -0
  186. package/docs/functions/index.trimEnd.html +8 -0
  187. package/docs/functions/index.trimStart.html +8 -0
  188. package/docs/functions/index.truthy.html +7 -0
  189. package/docs/functions/index.unique.html +6 -0
  190. package/docs/functions/index.wait.html +3 -0
  191. package/docs/functions/index.waitFor.html +10 -0
  192. package/docs/functions/index.waitSync.html +3 -0
  193. package/docs/index.html +18 -204
  194. package/docs/interfaces/index.ComparePropsOptions.html +5 -0
  195. package/docs/interfaces/index.GetMultipleSource.html +3 -0
  196. package/docs/interfaces/index.GetSource.html +3 -0
  197. package/docs/interfaces/index.IsNumericStringOptions.html +5 -0
  198. package/docs/interfaces/index.OccurencesOptions.html +3 -0
  199. package/docs/interfaces/index.SetImmutableSource.html +3 -0
  200. package/docs/interfaces/index.SetSource.html +3 -0
  201. package/docs/interfaces/index.ThrottleOptions.html +5 -0
  202. package/docs/interfaces/index.ThrottledFunctionExtras.html +5 -0
  203. package/docs/modules/index.html +86 -0
  204. package/docs/types/index.CustomDeserializers.html +1 -0
  205. package/docs/types/index.CustomSerializers.html +1 -0
  206. package/docs/types/index.Later.html +4 -0
  207. package/docs/types/index.MapValuesFn.html +14 -0
  208. package/docs/types/index.MatchCallback.html +1 -0
  209. package/docs/types/index.MergeTwo.html +3 -0
  210. package/docs/types/index.SeqEarlyBreaker.html +4 -0
  211. package/docs/types/index.SeqFn.html +3 -0
  212. package/docs/types/index.SeqFunctions.html +4 -0
  213. package/docs/types/index.SetImmutablePath.html +4 -0
  214. package/docs/types/index.ThrottledFunction.html +1 -0
  215. package/docs/variables/index.mapValuesUNSET.html +2 -0
  216. package/docs/variables/index.mergeUNSET.html +4 -0
  217. package/esm/cap.js.map +1 -1
  218. package/esm/coalesce.d.ts.map +1 -1
  219. package/esm/coalesce.js.map +1 -1
  220. package/esm/compareArrays.d.ts.map +1 -1
  221. package/esm/compareProps.d.ts.map +1 -1
  222. package/esm/compareProps.js.map +1 -1
  223. package/esm/deserialize.d.ts.map +1 -1
  224. package/esm/deserialize.js.map +1 -1
  225. package/esm/ensureArray.d.ts.map +1 -1
  226. package/esm/ensureArray.js.map +1 -1
  227. package/esm/ensureDate.js.map +1 -1
  228. package/esm/ensureError.js.map +1 -1
  229. package/esm/ensurePrefix.js.map +1 -1
  230. package/esm/ensureSuffix.js.map +1 -1
  231. package/esm/ensureTimestamp.js.map +1 -1
  232. package/esm/escapeRegExp.d.ts.map +1 -1
  233. package/esm/escapeRegExp.js +1 -1
  234. package/esm/escapeRegExp.js.map +1 -1
  235. package/esm/formatDate.js +1 -1
  236. package/esm/formatDate.js.map +1 -1
  237. package/esm/get.js.map +1 -1
  238. package/esm/getMultiple.d.ts.map +1 -1
  239. package/esm/getMultiple.js.map +1 -1
  240. package/esm/index.d.ts +4 -0
  241. package/esm/index.d.ts.map +1 -1
  242. package/esm/index.js +4 -0
  243. package/esm/index.js.map +1 -1
  244. package/esm/insertSeparator.d.ts.map +1 -1
  245. package/esm/insertSeparator.js.map +1 -1
  246. package/esm/isEmpty.js.map +1 -1
  247. package/esm/isNumericString.js +1 -1
  248. package/esm/isNumericString.js.map +1 -1
  249. package/esm/last.d.ts.map +1 -1
  250. package/esm/later.d.ts.map +1 -1
  251. package/esm/mapAsync.d.ts.map +1 -1
  252. package/esm/mapAsync.js.map +1 -1
  253. package/esm/mapValues.d.ts.map +1 -1
  254. package/esm/mapValues.js.map +1 -1
  255. package/esm/match.d.ts.map +1 -1
  256. package/esm/match.js.map +1 -1
  257. package/esm/memoize.d.ts +3 -0
  258. package/esm/memoize.d.ts.map +1 -0
  259. package/esm/memoize.js +16 -0
  260. package/esm/memoize.js.map +1 -0
  261. package/esm/merge.d.ts +11 -7
  262. package/esm/merge.d.ts.map +1 -1
  263. package/esm/merge.js.map +1 -1
  264. package/esm/mostFrequent.d.ts.map +1 -1
  265. package/esm/mostFrequent.js.map +1 -1
  266. package/esm/occurrences.js.map +1 -1
  267. package/esm/omit.d.ts +1 -1
  268. package/esm/omit.d.ts.map +1 -1
  269. package/esm/omit.js.map +1 -1
  270. package/esm/pick.d.ts.map +1 -1
  271. package/esm/pick.js.map +1 -1
  272. package/esm/pull.d.ts.map +1 -1
  273. package/esm/pull.js.map +1 -1
  274. package/esm/remove.d.ts.map +1 -1
  275. package/esm/remove.js +1 -1
  276. package/esm/remove.js.map +1 -1
  277. package/esm/removeCommonProperties.d.ts.map +1 -1
  278. package/esm/removeCommonProperties.js +3 -1
  279. package/esm/removeCommonProperties.js.map +1 -1
  280. package/esm/replace.js +1 -1
  281. package/esm/replace.js.map +1 -1
  282. package/esm/replaceDeep.d.ts +5 -1
  283. package/esm/replaceDeep.d.ts.map +1 -1
  284. package/esm/replaceDeep.js +3 -20
  285. package/esm/replaceDeep.js.map +1 -1
  286. package/esm/replaceDeepByFn.d.ts +7 -0
  287. package/esm/replaceDeepByFn.d.ts.map +1 -0
  288. package/esm/replaceDeepByFn.js +44 -0
  289. package/esm/replaceDeepByFn.js.map +1 -0
  290. package/esm/safe.js.map +1 -1
  291. package/esm/sample.d.ts +3 -1
  292. package/esm/sample.d.ts.map +1 -1
  293. package/esm/sample.js.map +1 -1
  294. package/esm/samples.d.ts.map +1 -1
  295. package/esm/samples.js.map +1 -1
  296. package/esm/seq.d.ts.map +1 -1
  297. package/esm/seq.js +1 -1
  298. package/esm/seq.js.map +1 -1
  299. package/esm/serialize.d.ts.map +1 -1
  300. package/esm/serialize.js +56 -18
  301. package/esm/serialize.js.map +1 -1
  302. package/esm/set.js.map +1 -1
  303. package/esm/setImmutable.js.map +1 -1
  304. package/esm/shuffle.d.ts.map +1 -1
  305. package/esm/sortBy.d.ts.map +1 -1
  306. package/esm/sortBy.js.map +1 -1
  307. package/esm/sortProps.d.ts.map +1 -1
  308. package/esm/sortProps.js.map +1 -1
  309. package/esm/stripPrefix.js.map +1 -1
  310. package/esm/stripSuffix.js.map +1 -1
  311. package/esm/throttle.d.ts.map +1 -1
  312. package/esm/throttle.js.map +1 -1
  313. package/esm/toggle.d.ts.map +1 -1
  314. package/esm/toggle.js.map +1 -1
  315. package/esm/trim.d.ts +3 -0
  316. package/esm/trim.d.ts.map +1 -0
  317. package/esm/trim.js +7 -0
  318. package/esm/trim.js.map +1 -0
  319. package/esm/trimEnd.d.ts +3 -0
  320. package/esm/trimEnd.d.ts.map +1 -0
  321. package/esm/trimEnd.js +9 -0
  322. package/esm/trimEnd.js.map +1 -0
  323. package/esm/trimStart.d.ts +3 -0
  324. package/esm/trimStart.d.ts.map +1 -0
  325. package/esm/trimStart.js +9 -0
  326. package/esm/trimStart.js.map +1 -0
  327. package/esm/truthy.d.ts +1 -1
  328. package/esm/truthy.d.ts.map +1 -1
  329. package/esm/unique.d.ts.map +1 -1
  330. package/esm/utils/utils.d.ts +6 -0
  331. package/esm/utils/utils.d.ts.map +1 -0
  332. package/esm/utils/utils.js +7 -0
  333. package/esm/utils/utils.js.map +1 -0
  334. package/esm/waitFor.d.ts.map +1 -1
  335. package/esm/waitFor.js +1 -1
  336. package/esm/waitFor.js.map +1 -1
  337. package/esm/waitSync.js.map +1 -1
  338. package/package.json +10 -17
  339. package/pnpm-lock.yaml +661 -386
  340. package/src/compareProps.ts +9 -2
  341. package/src/deserialize.spec.ts +13 -0
  342. package/src/escapeRegExp.spec.ts +5 -3
  343. package/src/escapeRegExp.ts +3 -2
  344. package/src/formatDate.ts +2 -2
  345. package/src/get.spec.ts +1 -0
  346. package/src/getMultiple.ts +1 -0
  347. package/src/index.ts +4 -0
  348. package/src/isNumericString.ts +3 -3
  349. package/src/memoize.spec.ts +90 -0
  350. package/src/memoize.ts +35 -0
  351. package/src/merge.ts +30 -8
  352. package/src/mostFrequent.ts +1 -0
  353. package/src/omit.ts +8 -2
  354. package/src/pick.ts +1 -1
  355. package/src/remove.ts +1 -1
  356. package/src/removeCommonProperties.ts +4 -2
  357. package/src/replace.ts +1 -1
  358. package/src/replaceDeep.spec.ts +91 -0
  359. package/src/replaceDeep.ts +22 -27
  360. package/src/replaceDeepByFn.spec.ts +162 -0
  361. package/src/replaceDeepByFn.ts +93 -0
  362. package/src/rethrow.ts +1 -1
  363. package/src/sample.spec.ts +1 -0
  364. package/src/sample.ts +18 -2
  365. package/src/samples.ts +1 -1
  366. package/src/seq.spec.ts +6 -3
  367. package/src/seq.ts +1 -1
  368. package/src/serialize.spec.ts +43 -0
  369. package/src/serialize.ts +66 -19
  370. package/src/set.ts +1 -1
  371. package/src/setImmutable.ts +1 -1
  372. package/src/sortBy.ts +1 -1
  373. package/src/throttle.ts +1 -1
  374. package/src/trim.spec.ts +22 -0
  375. package/src/trim.ts +23 -0
  376. package/src/trimEnd.spec.ts +20 -0
  377. package/src/trimEnd.ts +22 -0
  378. package/src/trimStart.spec.ts +20 -0
  379. package/src/trimStart.ts +22 -0
  380. package/src/utils/utils.ts +11 -0
  381. package/src/waitFor.spec.ts +7 -2
  382. package/src/waitFor.ts +1 -1
  383. package/typedoc.cjs +2 -4
  384. package/docs/assets/pages.css +0 -14
  385. package/docs/functions/cap.html +0 -149
  386. package/docs/functions/capitalize.html +0 -154
  387. package/docs/functions/coalesce.html +0 -159
  388. package/docs/functions/compareArrays.html +0 -162
  389. package/docs/functions/compareProps.html +0 -161
  390. package/docs/functions/deserialize.html +0 -153
  391. package/docs/functions/ensureArray.html +0 -147
  392. package/docs/functions/ensureDate.html +0 -149
  393. package/docs/functions/ensureError.html +0 -153
  394. package/docs/functions/ensurePrefix.html +0 -151
  395. package/docs/functions/ensureSuffix.html +0 -151
  396. package/docs/functions/ensureTimestamp.html +0 -149
  397. package/docs/functions/escapeRegExp.html +0 -145
  398. package/docs/functions/formatDate.html +0 -147
  399. package/docs/functions/get.html +0 -171
  400. package/docs/functions/getMultiple.html +0 -162
  401. package/docs/functions/insertSeparator.html +0 -156
  402. package/docs/functions/isEmpty.html +0 -172
  403. package/docs/functions/isNumericString.html +0 -146
  404. package/docs/functions/isPlainObject.html +0 -156
  405. package/docs/functions/last.html +0 -159
  406. package/docs/functions/later-1.html +0 -144
  407. package/docs/functions/mapAsync.html +0 -177
  408. package/docs/functions/mapValues.html +0 -163
  409. package/docs/functions/match.html +0 -155
  410. package/docs/functions/merge.html +0 -497
  411. package/docs/functions/mostFrequent.html +0 -144
  412. package/docs/functions/noop.html +0 -134
  413. package/docs/functions/occurrences.html +0 -158
  414. package/docs/functions/omit.html +0 -162
  415. package/docs/functions/pick.html +0 -162
  416. package/docs/functions/pull.html +0 -146
  417. package/docs/functions/remove.html +0 -162
  418. package/docs/functions/removeCommonProperties.html +0 -161
  419. package/docs/functions/replace.html +0 -151
  420. package/docs/functions/replaceDeep.html +0 -158
  421. package/docs/functions/rethrow.html +0 -139
  422. package/docs/functions/round.html +0 -148
  423. package/docs/functions/safe.html +0 -189
  424. package/docs/functions/sample.html +0 -146
  425. package/docs/functions/samples.html +0 -156
  426. package/docs/functions/scale.html +0 -150
  427. package/docs/functions/seq.html +0 -161
  428. package/docs/functions/seqEarlyBreak.html +0 -159
  429. package/docs/functions/serialize.html +0 -158
  430. package/docs/functions/set.html +0 -171
  431. package/docs/functions/setImmutable.html +0 -170
  432. package/docs/functions/shuffle.html +0 -146
  433. package/docs/functions/sortBy.html +0 -168
  434. package/docs/functions/sortProps.html +0 -156
  435. package/docs/functions/stripPrefix.html +0 -145
  436. package/docs/functions/stripSuffix.html +0 -145
  437. package/docs/functions/throttle.html +0 -164
  438. package/docs/functions/toggle.html +0 -151
  439. package/docs/functions/truthy.html +0 -151
  440. package/docs/functions/unique.html +0 -149
  441. package/docs/functions/wait.html +0 -142
  442. package/docs/functions/waitFor.html +0 -161
  443. package/docs/functions/waitSync.html +0 -142
  444. package/docs/interfaces/ComparePropsOptions.html +0 -70
  445. package/docs/interfaces/GetMultipleSource.html +0 -139
  446. package/docs/interfaces/GetSource.html +0 -139
  447. package/docs/interfaces/IsNumericStringOptions.html +0 -91
  448. package/docs/interfaces/OccurencesOptions.html +0 -72
  449. package/docs/interfaces/SetImmutableSource.html +0 -139
  450. package/docs/interfaces/SetSource.html +0 -139
  451. package/docs/interfaces/ThrottleOptions.html +0 -81
  452. package/docs/interfaces/ThrottledFunctionExtras.html +0 -97
  453. package/docs/modules.html +0 -217
  454. package/docs/pages/CHANGELOG.html +0 -924
  455. package/docs/pages/Introduction.html +0 -127
  456. package/docs/types/CustomDeserializers.html +0 -156
  457. package/docs/types/CustomSerializers.html +0 -156
  458. package/docs/types/Later.html +0 -170
  459. package/docs/types/MapValuesFn.html +0 -167
  460. package/docs/types/MatchCallback.html +0 -146
  461. package/docs/types/SeqEarlyBreaker.html +0 -147
  462. package/docs/types/SeqFn.html +0 -145
  463. package/docs/types/SeqFunctions.html +0 -138
  464. package/docs/types/SetImmutablePath.html +0 -132
  465. package/docs/types/ThrottledFunction.html +0 -146
  466. package/docs/variables/mapValuesUNSET.html +0 -134
  467. package/docs/variables/mergeUNSET.html +0 -136
  468. package/tutorials/Introduction.md +0 -1
@@ -0,0 +1,162 @@
1
+ import { replaceDeepByFn } from "./replaceDeepByFn";
2
+
3
+ class MyClass {
4
+ public value: number;
5
+
6
+ public constructor(value: number) {
7
+ this.value = value;
8
+ }
9
+ }
10
+
11
+ describe("replaceDeepByFn", () => {
12
+ it("should replace given value in a deep object", () => {
13
+ const source = [
14
+ 99,
15
+ 100,
16
+ {
17
+ favouriteBook: {
18
+ title: "The Ring of The Lord",
19
+ price: 100,
20
+ },
21
+ otherBooks: [
22
+ {
23
+ title: "Parry Hotter",
24
+ price: 50,
25
+ tag: "100",
26
+ },
27
+ {
28
+ title: "The Hobbyte 100",
29
+ price: [100],
30
+ },
31
+ ],
32
+ },
33
+ ];
34
+
35
+ must(replaceDeepByFn(source, v => v === 100, () => 200)).eql([
36
+ 99,
37
+ 200,
38
+ {
39
+ favouriteBook: {
40
+ title: "The Ring of The Lord",
41
+ price: 200,
42
+ },
43
+ otherBooks: [
44
+ {
45
+ title: "Parry Hotter",
46
+ price: 50,
47
+ tag: "100",
48
+ },
49
+ {
50
+ title: "The Hobbyte 100",
51
+ price: [200],
52
+ },
53
+ ],
54
+ },
55
+ ]);
56
+ });
57
+
58
+ it("should leave primitives as-is unless they equal to the search value", () => {
59
+ must(replaceDeepByFn(100, v => v === 200, () => 300)).equal(100);
60
+ must(replaceDeepByFn(200, v => v === 200, () => 300)).equal(300);
61
+ must(replaceDeepByFn("100", v => v === 200, () => 300)).equal("100");
62
+ // ESLINT BUG: (see replaceDeep.spec.ts)
63
+ // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
64
+ must(replaceDeepByFn(undefined, v => v === 200, () => 300)).equal(undefined);
65
+ must(replaceDeepByFn(null, v => v === 200, () => 300)).equal(null);
66
+ must(replaceDeepByFn(true, v => v === 200, () => 300)).equal(true);
67
+ must(replaceDeepByFn(666n, v => v === 200, () => 300)).equal(666n);
68
+ });
69
+
70
+ it("should work with nans", async () => {
71
+ must(replaceDeepByFn({
72
+ a: NaN,
73
+ b: 123,
74
+ }, v => Number.isNaN(v), () => 300)).eql({
75
+ a: 300,
76
+ b: 123,
77
+ });
78
+ });
79
+
80
+ it("should allow to replace nils", async () => {
81
+ must(replaceDeepByFn(null, v => v === null, () => 300)).equal(300);
82
+ // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
83
+ must(replaceDeepByFn(undefined, v => v === undefined, () => 300)).equal(300);
84
+ });
85
+
86
+ it("does not mutate the original object", () => {
87
+ const source = {
88
+ a: 1,
89
+ b: {
90
+ c: 2,
91
+ },
92
+ };
93
+ const result = replaceDeepByFn(source, v => v === 2, () => 3);
94
+ must(result).not.equal(source);
95
+ must(result.b).not.equal(source.b);
96
+ must(result).eql({
97
+ a: 1,
98
+ b: {
99
+ c: 3,
100
+ },
101
+ });
102
+ });
103
+
104
+ it("does not mutate original array", async () => {
105
+ const source = [1, 2, 3, [2, 3]];
106
+ const result = replaceDeepByFn(source, v => v === 2, () => 4);
107
+ must(result).not.equal(source);
108
+ must(result[3]).not.equal(source[3]);
109
+ must(result).eql([1, 4, 3, [4, 3]]);
110
+ });
111
+
112
+ it("mutates the original object when enabled", () => {
113
+ const source = {
114
+ a: 1,
115
+ b: {
116
+ c: 2,
117
+ },
118
+ };
119
+ const result = replaceDeepByFn(source, v => v === 2, () => 3, { mutate: true });
120
+ must(result).equal(source);
121
+ must(result.b).equal(source.b);
122
+ must(result).eql({
123
+ a: 1,
124
+ b: {
125
+ c: 3,
126
+ },
127
+ });
128
+ });
129
+
130
+ it("mutates original array when enabled", async () => {
131
+ const source = [1, 2, 3, [2, 3]];
132
+ const result = replaceDeepByFn(source, v => v === 2, () => 4, { mutate: true });
133
+ must(result).equal(source);
134
+ must(result[3]).equal(source[3]);
135
+ must(result).eql([1, 4, 3, [4, 3]]);
136
+ });
137
+
138
+ it("does not get into instances by default", async () => {
139
+ const source = new MyClass(100);
140
+ const result = replaceDeepByFn(source, v => v === 100, () => 200);
141
+ must(result).equal(source);
142
+ must(source.value).equal(100);
143
+ });
144
+
145
+ it("gets into instances when allowed", async () => {
146
+ const source = new MyClass(100);
147
+ const result = replaceDeepByFn(source, v => v === 100, () => 200, {
148
+ replaceInstancesProps: true,
149
+ mutate: true,
150
+ });
151
+ must(result).equal(source);
152
+ must(source.value).equal(200);
153
+ });
154
+
155
+ it("requires `mutate` option if `replaceInstancesProps` is defined", async () => {
156
+ const source = new MyClass(100);
157
+ must(() => replaceDeepByFn(source, v => v === 100, () => 200, {
158
+ replaceInstancesProps: true,
159
+ mutate: false,
160
+ })).throw("`replaceInstancesProps` option requires `mutate` to be enabled");
161
+ });
162
+ });
@@ -0,0 +1,93 @@
1
+ import { isPlainObject } from "./isPlainObject";
2
+
3
+ type Options = {
4
+ /**
5
+ * If true, the source objects and arrays will be mutated. Default is false.
6
+ */
7
+ mutate?: boolean;
8
+ /**
9
+ * If true, the function will go into instances for replacement. Otherwise, it will only replace properties of plain
10
+ * objects. Default is false.
11
+ * Warning: This option requires `mutate` to be enabled, because we can't clone instances.
12
+ */
13
+ replaceInstancesProps?: boolean;
14
+ };
15
+
16
+ /**
17
+ * Replaces all occurrences of `search` with `value` in `source` object/array. You do comparison by yourself by providing a callback function.
18
+ *
19
+ * Warnings:
20
+ * - By default, it does not mutate the `source`/deep objects/arrays, but it can be enabled with `mutate` option.
21
+ * - By default, it does not go into instances for replacement, only plain objects.
22
+ * - If your instances are cross-referenced, you may end up in an infinite loop.
23
+ *
24
+ * TypeScript users: This is way too dynamic to type properly, therefore, typing assumes the most basic form of
25
+ * replacement where search and value are of the same type. If that's not the case for you - you'll have to typecast.
26
+ *
27
+ * @param source - source object/array/value
28
+ * @param search - value to search for
29
+ * @param replaceWith - value to replace with
30
+ * @param options - optional options
31
+ */
32
+ const replaceDeepByFn = <T>( // eslint-disable-line max-statements
33
+ source: T, search: (value: unknown) => boolean, replaceWith: (value: unknown) => unknown, options?: Options,
34
+ ): T => {
35
+ if (options?.replaceInstancesProps && !options.mutate) {
36
+ throw new Error("`replaceInstancesProps` option requires `mutate` to be enabled");
37
+ }
38
+
39
+ const searchResult = search(source);
40
+
41
+ if (typeof searchResult !== "boolean") {
42
+ throw new Error("search function must return a boolean");
43
+ }
44
+
45
+ if (searchResult) {
46
+ return replaceWith(source) as T;
47
+ }
48
+
49
+ if (source == null) {
50
+ return source;
51
+ }
52
+
53
+ if (typeof source === "object") {
54
+ if (Array.isArray(source)) {
55
+ if (options?.mutate) {
56
+ for (let i = 0; i < source.length; i++) {
57
+ // eslint-disable-next-line no-param-reassign,@typescript-eslint/no-unsafe-assignment
58
+ source[i] = replaceDeepByFn(source[i], search, replaceWith, options);
59
+ }
60
+ return source;
61
+ }
62
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
63
+ return source.map((item) => replaceDeepByFn(item, search, replaceWith, options)) as unknown as T;
64
+ }
65
+
66
+ if (options?.mutate) {
67
+ if (isPlainObject(source) || options.replaceInstancesProps) {
68
+ for (const key of Object.keys(source)) {
69
+ // eslint-disable-next-line no-param-reassign
70
+ (source as Record<string, unknown>)[key] = replaceDeepByFn(
71
+ (source as Record<string, unknown>)[key], search, replaceWith, options,
72
+ );
73
+ }
74
+ }
75
+
76
+ return source;
77
+ }
78
+
79
+ if (isPlainObject(source)) {
80
+ return Object.keys(source).reduce<Record<string, unknown>>((acc, key) => {
81
+ // eslint-disable-next-line no-param-reassign
82
+ acc[key] = replaceDeepByFn((source as Record<string, unknown>)[key], search, replaceWith, options);
83
+ return acc;
84
+ }, {}) as T;
85
+ }
86
+ }
87
+
88
+ return source;
89
+ };
90
+
91
+ export {
92
+ replaceDeepByFn,
93
+ };
package/src/rethrow.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * @param {*} e
4
4
  */
5
5
  const rethrow = (e: unknown) => {
6
- // eslint-disable-next-line @typescript-eslint/no-throw-literal
6
+ // eslint-disable-next-line @typescript-eslint/only-throw-error
7
7
  throw e;
8
8
  };
9
9
 
@@ -25,6 +25,7 @@ describe("sample", () => {
25
25
 
26
26
  it("should work with 0 items array", async () => {
27
27
  const array: never[] = [];
28
+ // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
28
29
  const item = sample(array);
29
30
  must(item).equal(undefined);
30
31
  });
package/src/sample.ts CHANGED
@@ -1,9 +1,25 @@
1
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2
+ type IsTuple<T> = T extends readonly [infer A, ...(infer B)] ? true : false;
3
+ type MaybeTupleReturn<T> = IsTuple<T> extends true
4
+ ? (T extends readonly (infer U)[] ? U : never)
5
+ : (T extends (infer U)[] ? U | undefined : never);
6
+
1
7
  /**
2
8
  * Picks a random element from an array.
3
9
  * @param array - source array
10
+ *
11
+ * @example
12
+ * sample([1, 2, 3]); // 2 (type: number | undefined)
13
+ * sample(["a", "b", "c"]); // "c" (type: string | undefined)
14
+ * sample([]); // undefined (type: undefined)
15
+ *
16
+ * const a = [1, 2, 3] as const;
17
+ * sample(a); // 2 (type: 1 | 2 | 3)
18
+ *
19
+ * sample([1, 1, 1] as [number, number, number]); // 1 (type: number)
4
20
  */
5
- const sample = <T>(array: T[]): T => {
6
- return array[Math.floor(Math.random() * array.length)]!;
21
+ const sample = <X, T extends readonly X[]>(array: T): MaybeTupleReturn<T> => {
22
+ return array[Math.floor(Math.random() * array.length)] as MaybeTupleReturn<T>;
7
23
  };
8
24
 
9
25
  export {
package/src/samples.ts CHANGED
@@ -8,7 +8,7 @@
8
8
  * @param elementsToPick - number of elements to pick
9
9
  * @param allowShuffle - if true, it will shuffle the values if elementsToPick is greater or equal to array length instead of returning the original array
10
10
  */
11
- const samples = <T>(array: T[], elementsToPick: number, allowShuffle = false): T[] => { // eslint-disable-line max-statements,max-len
11
+ const samples = <T>(array: T[], elementsToPick: number, allowShuffle = false): T[] => { // eslint-disable-line max-statements
12
12
  if (elementsToPick < 0) {
13
13
  throw new Error("elementsToPick must be a positive number");
14
14
  }
package/src/seq.spec.ts CHANGED
@@ -119,17 +119,20 @@ describe("seq", () => {
119
119
  const list = [
120
120
  () => {
121
121
  firstCalled = true;
122
- // eslint-disable-next-line prefer-promise-reject-errors
122
+
123
+ // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
123
124
  return Promise.reject(1);
124
125
  },
125
126
  () => {
126
127
  secondCalled = true;
127
- // eslint-disable-next-line prefer-promise-reject-errors
128
+
129
+ // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
128
130
  return Promise.reject(2);
129
131
  },
130
132
  () => {
131
133
  thirdCalled = true;
132
- // eslint-disable-next-line prefer-promise-reject-errors
134
+
135
+ // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
133
136
  return Promise.reject(3);
134
137
  },
135
138
  ];
package/src/seq.ts CHANGED
@@ -38,7 +38,7 @@ const run = <T>(list: Fn<T>[], earlyBreaker?: EarlyBreaker): Promise<T> => {
38
38
  const errors: Error[] = [];
39
39
 
40
40
  const doTry = function(error?: Error) {
41
- if (error !== undefined && earlyBreaker && earlyBreaker(error)) {
41
+ if (error !== undefined && earlyBreaker?.(error)) {
42
42
  reject(error);
43
43
  return;
44
44
  }
@@ -9,6 +9,7 @@ interface Test {
9
9
  class Person {
10
10
  public name: string;
11
11
 
12
+ // eslint-disable-next-line @typescript-eslint/no-shadow
12
13
  public constructor(name: string) {
13
14
  this.name = name;
14
15
  }
@@ -80,4 +81,46 @@ describe("serialize", () => {
80
81
 
81
82
  must(serialize(a)).equal(serialize(b));
82
83
  });
84
+
85
+ it("allows serializing dates and other objects containing .toJSON", async () => {
86
+ const date = new Date(1714390008941);
87
+ must(serialize(date, {
88
+ D: (value) => {
89
+ if (value instanceof Date) {
90
+ return String(value.getTime());
91
+ }
92
+ return null;
93
+ },
94
+ })).equal(`"D:1714390008941"`);
95
+ });
96
+
97
+ it("should avoid excessive calls to custom serializers", async () => {
98
+ const customSerializers: CustomSerializers = {
99
+ p: (value) => {
100
+ // console.log("Called with", typeof value, value);
101
+ if (value instanceof Person) {
102
+ return value.name;
103
+ }
104
+ return null;
105
+ },
106
+ };
107
+
108
+ const p1 = new Person("John");
109
+ const spy = jest.spyOn(customSerializers, "p");
110
+
111
+ serialize({
112
+ a: [p1],
113
+ b: 1,
114
+ c: {
115
+ d: true,
116
+ e: p1,
117
+ },
118
+ }, customSerializers);
119
+ expect(spy).toHaveBeenCalledTimes(4);
120
+ });
121
+
122
+ it("should not crash on unknown instances but serialize as plain object", async () => {
123
+ const p1 = new Person("John");
124
+ must(serialize(p1)).equal(`{"name":"s:John"}`);
125
+ });
83
126
  });
package/src/serialize.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  import { sortProps } from "./sortProps.js";
2
+ import { replaceDeepByFn } from "./replaceDeepByFn.js";
3
+ import { isPlainObject } from "./isPlainObject.js";
4
+ import { DataWrapper } from "./utils/utils.js";
2
5
 
3
6
  type CustomSerializers = {
4
7
  [key: string]: (data: unknown) => (string | null);
@@ -32,7 +35,33 @@ type Options = {
32
35
  * @param customSerializers - an object with custom serializers
33
36
  * @param options - options
34
37
  */
35
- const serialize = (data: unknown, customSerializers?: CustomSerializers, options?: Options) => { // eslint-disable-line max-lines-per-function,max-len
38
+ const serialize = (data: unknown, customSerializers?: CustomSerializers, options?: Options) => { // eslint-disable-line max-lines-per-function
39
+ const sourceData = Object.keys(customSerializers ?? {}).length
40
+ ? replaceDeepByFn(
41
+ data,
42
+ value => {
43
+ if (["string", "number", "bigint", "undefined", "boolean"].includes(typeof value)) {
44
+ return false;
45
+ }
46
+ if (value === null || Array.isArray(value)) {
47
+ return false;
48
+ }
49
+ if (isPlainObject(value)) {
50
+ return false;
51
+ }
52
+
53
+ const serializerKeys = Object.keys(customSerializers ?? {});
54
+ for (const key of serializerKeys) {
55
+ const serialized = customSerializers![key]!(value);
56
+ if (typeof serialized === "string") {
57
+ return true;
58
+ }
59
+ }
60
+ return false;
61
+ },
62
+ value => new DataWrapper(value),
63
+ )
64
+ : data;
36
65
  const replacer = (_key: string, value: unknown) => { // eslint-disable-line max-statements
37
66
  if (typeof value === "string") {
38
67
  return `s:${value}`;
@@ -52,12 +81,22 @@ const serialize = (data: unknown, customSerializers?: CustomSerializers, options
52
81
  if (value === null) {
53
82
  return "l:";
54
83
  }
84
+ if (Array.isArray(value)) {
85
+ return value as unknown[];
86
+ }
87
+ if (isPlainObject(value)) {
88
+ return value;
89
+ }
55
90
  const serializerKeys = Object.keys(customSerializers ?? {});
56
91
  for (const key of serializerKeys) {
57
- const serialized = customSerializers![key]!(value);
92
+ const serialized = customSerializers![key]!(value instanceof DataWrapper ? value.data : value);
58
93
  if (typeof serialized === "string") {
59
94
  return `${key}:${serialized}`;
60
95
  }
96
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
97
+ if (serialized !== null) {
98
+ throw new Error(`Custom serializer for key ${key} returned a non-string value: ${String(serialized)}`);
99
+ }
61
100
  }
62
101
  if (typeof value === "object") {
63
102
  return value;
@@ -67,35 +106,43 @@ const serialize = (data: unknown, customSerializers?: CustomSerializers, options
67
106
  };
68
107
 
69
108
  if (
70
- data == null
71
- || typeof data === "string"
72
- || typeof data === "number"
73
- || typeof data === "bigint"
74
- || typeof data === "undefined"
75
- || typeof data === "boolean"
76
- || Array.isArray(data)
109
+ sourceData == null
110
+ || typeof sourceData === "string"
111
+ || typeof sourceData === "number"
112
+ || typeof sourceData === "bigint"
113
+ || typeof sourceData === "undefined"
114
+ || typeof sourceData === "boolean"
115
+ || Array.isArray(sourceData)
77
116
  ) {
78
- return JSON.stringify(data, replacer);
117
+ return JSON.stringify(sourceData, replacer);
79
118
  }
80
119
 
81
- const serializerKeysGlobal = Object.keys(customSerializers ?? {});
82
- for (const key of serializerKeysGlobal) {
83
- const serialized = customSerializers![key]!(data);
84
- if (typeof serialized === "string") {
85
- return `"${key}:${serialized}"`;
120
+ if (!isPlainObject(sourceData)) {
121
+ const serializerKeysGlobal = Object.keys(customSerializers ?? {});
122
+ for (const key of serializerKeysGlobal) {
123
+ const serialized = customSerializers![key]!(
124
+ sourceData instanceof DataWrapper ? sourceData.data : sourceData,
125
+ );
126
+ if (typeof serialized === "string") {
127
+ return `"${key}:${serialized}"`;
128
+ }
129
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
130
+ if (serialized !== null) {
131
+ throw new Error(`Custom serializer for key ${key} returned a non-string value: ${String(serialized)}`);
132
+ }
86
133
  }
87
134
  }
88
135
 
89
- if (typeof data === "object") {
136
+ if (typeof sourceData === "object") {
90
137
  return JSON.stringify(
91
138
  options?.sortProps === false
92
- ? data
93
- : sortProps(data as Record<string, unknown>),
139
+ ? sourceData
140
+ : sortProps(sourceData as Record<string, unknown>),
94
141
  replacer,
95
142
  );
96
143
  }
97
144
 
98
- throw new Error(`Unsupported data type: ${typeof data}`);
145
+ throw new Error(`Unsupported data type: ${typeof sourceData}`);
99
146
  };
100
147
 
101
148
  export type { CustomSerializers };
package/src/set.ts CHANGED
@@ -30,7 +30,7 @@ const isObject = (value: unknown) => (typeof value === "object" || typeof value
30
30
  * { "items": { "0": value }}
31
31
  * @returns {Object} - given object or new object if source was primitive
32
32
  */
33
- const set = (source: Source, path: string | string[], value: unknown): Source | unknown => { // eslint-disable-line @typescript-eslint/no-redundant-type-constituents,max-len
33
+ const set = (source: Source, path: string | string[], value: unknown): Source | unknown => { // eslint-disable-line @typescript-eslint/no-redundant-type-constituents
34
34
  const pathParts = typeof path === "string" ? path.split(".") : path;
35
35
  const len = pathParts.length;
36
36
 
@@ -67,7 +67,7 @@ const getPathParts = (path: Path) => {
67
67
  * { "items": { "0": value }}
68
68
  * @returns {Object} - given object or new object if source was primitive
69
69
  */
70
- const setImmutable = (source: Source, path: Path, value: unknown): Source | unknown => { // eslint-disable-line max-statements, max-len, @typescript-eslint/no-redundant-type-constituents
70
+ const setImmutable = (source: Source, path: Path, value: unknown): Source | unknown => { // eslint-disable-line max-statements, @typescript-eslint/no-redundant-type-constituents
71
71
  const pathParts = getPathParts(path);
72
72
  const isValidPath = hasOnlyValidPathParts(pathParts);
73
73
  if (!isValidPath) {
package/src/sortBy.ts CHANGED
@@ -10,7 +10,7 @@ const sortBy = <T>(propertyName: keyof T, asc = true, defaultValue: unknown = nu
10
10
  return 0;
11
11
  }
12
12
  // @ts-expect-error We don't care about types here, it's for runtime pure JS too
13
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
13
+
14
14
  if ((a[propertyName] ?? defaultValue) > (b[propertyName] ?? defaultValue)) {
15
15
  // eslint-disable-next-line @typescript-eslint/no-magic-numbers
16
16
  return asc ? 1 : -1;
package/src/throttle.ts CHANGED
@@ -46,7 +46,7 @@ type CanReturnUndefined<F extends (...args: any[]) => any> = (...args: Parameter
46
46
  * @param {number | number[]} time - throttle time as number or array of numbers (min 1 element)
47
47
  * @param {Opts} options
48
48
  */
49
- const throttle = <RT, F extends (...args: any[]) => RT>( // eslint-disable-line max-lines-per-function, @typescript-eslint/no-explicit-any, max-len
49
+ const throttle = <RT, F extends (...args: any[]) => RT>( // eslint-disable-line max-lines-per-function, @typescript-eslint/no-explicit-any
50
50
  fn: F, time: number | [number, ...number[]] = 0, options?: Opts,
51
51
  ): CanReturnUndefined<F> & Extras => {
52
52
  const opts: Required<Opts> = {
@@ -0,0 +1,22 @@
1
+ import { trim } from "./trim";
2
+
3
+ describe("trim", () => {
4
+ it("should trim single character from both sides of the string", async () => {
5
+ must(trim("aaacataaa", "a")).equal("cat");
6
+ must(trim("abacteria", "a")).equal("bacteri");
7
+ must(trim("abc", "a")).equal("bc");
8
+ must(trim("abc", "c")).equal("ab");
9
+ must(trim("aajjja", "a")).equal("jjj");
10
+ });
11
+
12
+ it("should trim multiple characters as a whole", async () => {
13
+ must(trim("abopopab", "ab")).equal("opop");
14
+ must(trim("atitleb", "ab")).equal("atitleb");
15
+ must(trim("abtitleab", "ab")).equal("title");
16
+ });
17
+
18
+ it("can trim into empty string", async () => {
19
+ must(trim("abc", "abc")).equal("");
20
+ must(trim("a", "a")).equal("");
21
+ });
22
+ });
package/src/trim.ts ADDED
@@ -0,0 +1,23 @@
1
+ import { trimStart } from "./trimStart.js";
2
+ import { trimEnd } from "./trimEnd.js";
3
+
4
+ /**
5
+ * Removes given characters from both sides of the string.
6
+ * If you want to remove from one side of the string see {@link trimStart} and {@link trimEnd}.
7
+ *
8
+ * @param source - Source string.
9
+ * @param characters - Characters to remove, taken as a whole.
10
+ *
11
+ * @example
12
+ * trim("abcb", "ab"); // "cb"
13
+ * trim("!aaa!", "!"); // "aaa"
14
+ * trim("!aaa!!!", "!"); // "aaa"
15
+ * trim("!aaa!!!", "!!!"); // "!aaa"
16
+ */
17
+ const trim = (source: string, characters: string) => {
18
+ return trimStart(trimEnd(source, characters), characters);
19
+ };
20
+
21
+ export {
22
+ trim,
23
+ };
@@ -0,0 +1,20 @@
1
+ import { trimEnd } from "./trimEnd";
2
+
3
+ describe("trimEnd", () => {
4
+ it("should trim single character from the end of the string", async () => {
5
+ must(trimEnd("abc?", "?")).equal("abc");
6
+ must(trimEnd("a? b?c???", "?")).equal("a? b?c");
7
+ });
8
+
9
+ it("should trim multiple characters as a whole", async () => {
10
+ must(trimEnd("abc", "bc")).equal("a");
11
+
12
+ must(trimEnd("abcc", "bc")).equal("abcc");
13
+ must(trimEnd("abcb", "bc")).equal("abcb");
14
+ });
15
+
16
+ it("can trim into empty string", async () => {
17
+ must(trimEnd("abc", "abc")).equal("");
18
+ must(trimEnd("a", "a")).equal("");
19
+ });
20
+ });
package/src/trimEnd.ts ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Removes given characters from the end of the string.
3
+ * See also: {@link trim} and {@link trimStart}.
4
+ *
5
+ * @param source - Source string.
6
+ * @param characters - Characters to remove, taken as a whole.
7
+ *
8
+ * @example
9
+ * trimEnd("abcxzyz", "yz"); // "abcxz"
10
+ * trimEnd("!aaa!!", "!"); // "!aaa"
11
+ */
12
+ const trimEnd = (source: string, characters: string) => {
13
+ let s = source;
14
+ while (s.endsWith(characters)) {
15
+ s = s.slice(0, -characters.length);
16
+ }
17
+ return s;
18
+ };
19
+
20
+ export {
21
+ trimEnd,
22
+ };