nhb-toolbox 4.11.6 → 4.11.7-alpha.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 (274) hide show
  1. package/dist/cjs/array/Finder.js +289 -0
  2. package/dist/cjs/array/basics.js +83 -0
  3. package/dist/cjs/array/sort.js +70 -0
  4. package/dist/cjs/array/transform.js +128 -0
  5. package/dist/cjs/array/types.js +2 -0
  6. package/dist/cjs/array/utils.js +81 -0
  7. package/dist/cjs/colors/Color.js +452 -0
  8. package/dist/cjs/colors/constants.js +53 -0
  9. package/dist/cjs/colors/convert.js +324 -0
  10. package/dist/cjs/colors/css-colors.js +162 -0
  11. package/dist/cjs/colors/helpers.js +186 -0
  12. package/dist/cjs/colors/initials.js +61 -0
  13. package/dist/cjs/colors/random.js +42 -0
  14. package/dist/cjs/colors/types.js +2 -0
  15. package/dist/cjs/colors/utils.js +36 -0
  16. package/dist/cjs/date/Chronos.js +1895 -0
  17. package/dist/cjs/date/chronos-fn.js +129 -0
  18. package/dist/cjs/date/constants.js +445 -0
  19. package/dist/cjs/date/greet.js +47 -0
  20. package/dist/cjs/date/guards.js +85 -0
  21. package/dist/cjs/date/types.js +2 -0
  22. package/dist/cjs/date/utils.js +71 -0
  23. package/dist/cjs/dom/query.js +87 -0
  24. package/dist/cjs/dom/storage.js +69 -0
  25. package/dist/cjs/dom/utils.js +78 -0
  26. package/dist/cjs/form/convert.js +239 -0
  27. package/dist/cjs/form/guards.js +102 -0
  28. package/dist/cjs/form/transform.js +93 -0
  29. package/dist/cjs/form/types.js +2 -0
  30. package/dist/cjs/guards/non-primitives.js +168 -0
  31. package/dist/cjs/guards/primitives.js +137 -0
  32. package/dist/cjs/guards/specials.js +122 -0
  33. package/dist/cjs/index.js +386 -0
  34. package/dist/cjs/number/Currency.js +107 -0
  35. package/dist/cjs/number/Unit.js +368 -0
  36. package/dist/cjs/number/basics.js +169 -0
  37. package/dist/cjs/number/constants.js +607 -0
  38. package/dist/cjs/number/convert.js +75 -0
  39. package/dist/cjs/number/fibonacci.js +89 -0
  40. package/dist/cjs/number/guards.js +64 -0
  41. package/dist/cjs/number/helpers.js +71 -0
  42. package/dist/cjs/number/percent.js +92 -0
  43. package/dist/cjs/number/prime.js +38 -0
  44. package/dist/cjs/number/range.js +79 -0
  45. package/dist/cjs/number/types.js +2 -0
  46. package/dist/cjs/number/utilities.js +87 -0
  47. package/dist/cjs/object/basics.js +25 -0
  48. package/dist/cjs/object/convert.js +124 -0
  49. package/dist/cjs/object/objectify.js +246 -0
  50. package/dist/cjs/object/sanitize.js +208 -0
  51. package/dist/cjs/object/types.js +2 -0
  52. package/dist/cjs/string/anagram.js +33 -0
  53. package/dist/cjs/string/basics.js +110 -0
  54. package/dist/cjs/string/constants.js +130 -0
  55. package/dist/cjs/string/convert.js +189 -0
  56. package/dist/cjs/string/guards.js +59 -0
  57. package/dist/cjs/string/types.js +2 -0
  58. package/dist/cjs/string/utilities.js +45 -0
  59. package/dist/cjs/types/index.js +2 -0
  60. package/dist/cjs/utils/Paginator.js +235 -0
  61. package/dist/cjs/utils/index.js +238 -0
  62. package/dist/cjs/utils/types.js +2 -0
  63. package/dist/dts/array/Finder.d.ts +81 -0
  64. package/dist/dts/array/Finder.d.ts.map +1 -0
  65. package/dist/dts/array/basics.d.ts +42 -0
  66. package/dist/dts/array/basics.d.ts.map +1 -0
  67. package/dist/dts/array/sort.d.ts +21 -0
  68. package/dist/dts/array/sort.d.ts.map +1 -0
  69. package/dist/dts/array/transform.d.ts +69 -0
  70. package/dist/dts/array/transform.d.ts.map +1 -0
  71. package/dist/dts/array/types.d.ts +114 -0
  72. package/dist/dts/array/types.d.ts.map +1 -0
  73. package/dist/dts/array/utils.d.ts +14 -0
  74. package/dist/dts/array/utils.d.ts.map +1 -0
  75. package/dist/dts/colors/Color.d.ts +252 -0
  76. package/dist/dts/colors/Color.d.ts.map +1 -0
  77. package/dist/dts/colors/constants.d.ts +6 -0
  78. package/dist/dts/colors/constants.d.ts.map +1 -0
  79. package/dist/dts/colors/convert.d.ts +184 -0
  80. package/dist/dts/colors/convert.d.ts.map +1 -0
  81. package/dist/dts/colors/css-colors.d.ts +160 -0
  82. package/dist/dts/colors/css-colors.d.ts.map +1 -0
  83. package/dist/dts/colors/helpers.d.ts +86 -0
  84. package/dist/dts/colors/helpers.d.ts.map +1 -0
  85. package/dist/dts/colors/initials.d.ts +25 -0
  86. package/dist/dts/colors/initials.d.ts.map +1 -0
  87. package/dist/dts/colors/random.d.ts +19 -0
  88. package/dist/dts/colors/random.d.ts.map +1 -0
  89. package/dist/dts/colors/types.d.ts +128 -0
  90. package/dist/dts/colors/types.d.ts.map +1 -0
  91. package/dist/dts/colors/utils.d.ts +22 -0
  92. package/dist/dts/colors/utils.d.ts.map +1 -0
  93. package/dist/dts/date/Chronos.d.ts +841 -0
  94. package/dist/dts/date/Chronos.d.ts.map +1 -0
  95. package/dist/{chronos.d.ts → dts/date/chronos-fn.d.ts} +3 -5
  96. package/dist/dts/date/chronos-fn.d.ts.map +1 -0
  97. package/dist/dts/date/constants.d.ts +296 -0
  98. package/dist/dts/date/constants.d.ts.map +1 -0
  99. package/dist/dts/date/greet.d.ts +9 -0
  100. package/dist/dts/date/greet.d.ts.map +1 -0
  101. package/dist/dts/date/guards.d.ts +32 -0
  102. package/dist/dts/date/guards.d.ts.map +1 -0
  103. package/dist/dts/date/types.d.ts +358 -0
  104. package/dist/dts/date/types.d.ts.map +1 -0
  105. package/dist/dts/date/utils.d.ts +45 -0
  106. package/dist/dts/date/utils.d.ts.map +1 -0
  107. package/dist/dts/dom/query.d.ts +43 -0
  108. package/dist/dts/dom/query.d.ts.map +1 -0
  109. package/dist/dts/dom/storage.d.ts +41 -0
  110. package/dist/dts/dom/storage.d.ts.map +1 -0
  111. package/dist/dts/dom/utils.d.ts +18 -0
  112. package/dist/dts/dom/utils.d.ts.map +1 -0
  113. package/dist/dts/form/convert.d.ts +12 -0
  114. package/dist/dts/form/convert.d.ts.map +1 -0
  115. package/dist/dts/form/guards.d.ts +55 -0
  116. package/dist/dts/form/guards.d.ts.map +1 -0
  117. package/dist/dts/form/transform.d.ts +19 -0
  118. package/dist/dts/form/transform.d.ts.map +1 -0
  119. package/dist/dts/form/types.d.ts +99 -0
  120. package/dist/dts/form/types.d.ts.map +1 -0
  121. package/dist/dts/guards/non-primitives.d.ts +108 -0
  122. package/dist/dts/guards/non-primitives.d.ts.map +1 -0
  123. package/dist/dts/guards/primitives.d.ts +86 -0
  124. package/dist/dts/guards/primitives.d.ts.map +1 -0
  125. package/dist/dts/guards/specials.d.ts +71 -0
  126. package/dist/dts/guards/specials.d.ts.map +1 -0
  127. package/dist/dts/index.d.ts +61 -0
  128. package/dist/dts/index.d.ts.map +1 -0
  129. package/dist/dts/number/Currency.d.ts +55 -0
  130. package/dist/dts/number/Currency.d.ts.map +1 -0
  131. package/dist/dts/number/Unit.d.ts +203 -0
  132. package/dist/dts/number/Unit.d.ts.map +1 -0
  133. package/dist/dts/number/basics.d.ts +75 -0
  134. package/dist/dts/number/basics.d.ts.map +1 -0
  135. package/dist/dts/number/constants.d.ts +232 -0
  136. package/dist/dts/number/constants.d.ts.map +1 -0
  137. package/dist/dts/number/convert.d.ts +18 -0
  138. package/dist/dts/number/convert.d.ts.map +1 -0
  139. package/dist/dts/number/fibonacci.d.ts +31 -0
  140. package/dist/dts/number/fibonacci.d.ts.map +1 -0
  141. package/dist/dts/number/guards.d.ts +44 -0
  142. package/dist/dts/number/guards.d.ts.map +1 -0
  143. package/dist/dts/number/helpers.d.ts +31 -0
  144. package/dist/dts/number/helpers.d.ts.map +1 -0
  145. package/dist/dts/number/percent.d.ts +17 -0
  146. package/dist/dts/number/percent.d.ts.map +1 -0
  147. package/dist/dts/number/prime.d.ts +16 -0
  148. package/dist/dts/number/prime.d.ts.map +1 -0
  149. package/dist/dts/number/range.d.ts +11 -0
  150. package/dist/dts/number/range.d.ts.map +1 -0
  151. package/dist/dts/number/types.d.ts +133 -0
  152. package/dist/dts/number/types.d.ts.map +1 -0
  153. package/dist/dts/number/utilities.d.ts +52 -0
  154. package/dist/dts/number/utilities.d.ts.map +1 -0
  155. package/dist/dts/object/basics.d.ts +16 -0
  156. package/dist/dts/object/basics.d.ts.map +1 -0
  157. package/dist/dts/object/convert.d.ts +72 -0
  158. package/dist/dts/object/convert.d.ts.map +1 -0
  159. package/dist/dts/object/objectify.d.ts +75 -0
  160. package/dist/dts/object/objectify.d.ts.map +1 -0
  161. package/dist/dts/object/sanitize.d.ts +51 -0
  162. package/dist/dts/object/sanitize.d.ts.map +1 -0
  163. package/dist/dts/object/types.d.ts +75 -0
  164. package/dist/dts/object/types.d.ts.map +1 -0
  165. package/dist/dts/string/anagram.d.ts +8 -0
  166. package/dist/dts/string/anagram.d.ts.map +1 -0
  167. package/dist/dts/string/basics.d.ts +40 -0
  168. package/dist/dts/string/basics.d.ts.map +1 -0
  169. package/dist/dts/string/constants.d.ts +2 -0
  170. package/dist/dts/string/constants.d.ts.map +1 -0
  171. package/dist/dts/string/convert.d.ts +86 -0
  172. package/dist/dts/string/convert.d.ts.map +1 -0
  173. package/dist/dts/string/guards.d.ts +37 -0
  174. package/dist/dts/string/guards.d.ts.map +1 -0
  175. package/dist/dts/string/types.d.ts +45 -0
  176. package/dist/dts/string/types.d.ts.map +1 -0
  177. package/dist/dts/string/utilities.d.ts +21 -0
  178. package/dist/dts/string/utilities.d.ts.map +1 -0
  179. package/dist/dts/types/index.d.ts +72 -0
  180. package/dist/dts/types/index.d.ts.map +1 -0
  181. package/dist/dts/utils/Paginator.d.ts +125 -0
  182. package/dist/dts/utils/Paginator.d.ts.map +1 -0
  183. package/dist/dts/utils/index.d.ts +108 -0
  184. package/dist/dts/utils/index.d.ts.map +1 -0
  185. package/dist/dts/utils/types.d.ts +41 -0
  186. package/dist/dts/utils/types.d.ts.map +1 -0
  187. package/dist/esm/array/Finder.js +289 -0
  188. package/dist/esm/array/basics.js +83 -0
  189. package/dist/esm/array/sort.js +70 -0
  190. package/dist/esm/array/transform.js +128 -0
  191. package/dist/esm/array/types.js +2 -0
  192. package/dist/esm/array/utils.js +81 -0
  193. package/dist/esm/colors/Color.js +452 -0
  194. package/dist/esm/colors/constants.js +53 -0
  195. package/dist/esm/colors/convert.js +324 -0
  196. package/dist/esm/colors/css-colors.js +162 -0
  197. package/dist/esm/colors/helpers.js +186 -0
  198. package/dist/esm/colors/initials.js +61 -0
  199. package/dist/esm/colors/random.js +42 -0
  200. package/dist/esm/colors/types.js +2 -0
  201. package/dist/esm/colors/utils.js +36 -0
  202. package/dist/esm/date/Chronos.js +1895 -0
  203. package/dist/esm/date/chronos-fn.js +129 -0
  204. package/dist/esm/date/constants.js +445 -0
  205. package/dist/esm/date/greet.js +47 -0
  206. package/dist/esm/date/guards.js +85 -0
  207. package/dist/esm/date/types.js +2 -0
  208. package/dist/esm/date/utils.js +71 -0
  209. package/dist/esm/dom/query.js +87 -0
  210. package/dist/esm/dom/storage.js +69 -0
  211. package/dist/esm/dom/utils.js +78 -0
  212. package/dist/esm/form/convert.js +239 -0
  213. package/dist/esm/form/guards.js +102 -0
  214. package/dist/esm/form/transform.js +93 -0
  215. package/dist/esm/form/types.js +2 -0
  216. package/dist/esm/guards/non-primitives.js +168 -0
  217. package/dist/esm/guards/primitives.js +137 -0
  218. package/dist/esm/guards/specials.js +122 -0
  219. package/dist/esm/index.js +386 -0
  220. package/dist/esm/number/Currency.js +107 -0
  221. package/dist/esm/number/Unit.js +368 -0
  222. package/dist/esm/number/basics.js +169 -0
  223. package/dist/esm/number/constants.js +607 -0
  224. package/dist/esm/number/convert.js +75 -0
  225. package/dist/esm/number/fibonacci.js +89 -0
  226. package/dist/esm/number/guards.js +64 -0
  227. package/dist/esm/number/helpers.js +71 -0
  228. package/dist/esm/number/percent.js +92 -0
  229. package/dist/esm/number/prime.js +38 -0
  230. package/dist/esm/number/range.js +79 -0
  231. package/dist/esm/number/types.js +2 -0
  232. package/dist/esm/number/utilities.js +87 -0
  233. package/dist/esm/object/basics.js +25 -0
  234. package/dist/esm/object/convert.js +124 -0
  235. package/dist/esm/object/objectify.js +246 -0
  236. package/dist/esm/object/sanitize.js +208 -0
  237. package/dist/esm/object/types.js +2 -0
  238. package/dist/esm/string/anagram.js +33 -0
  239. package/dist/esm/string/basics.js +110 -0
  240. package/dist/esm/string/constants.js +130 -0
  241. package/dist/esm/string/convert.js +189 -0
  242. package/dist/esm/string/guards.js +59 -0
  243. package/dist/esm/string/types.js +2 -0
  244. package/dist/esm/string/utilities.js +45 -0
  245. package/dist/esm/types/index.js +2 -0
  246. package/dist/esm/utils/Paginator.js +235 -0
  247. package/dist/esm/utils/index.js +238 -0
  248. package/dist/esm/utils/types.js +2 -0
  249. package/package.json +81 -31
  250. package/dist/Chronos-v7ni8eaQ.d.mts +0 -2045
  251. package/dist/Chronos-v7ni8eaQ.d.ts +0 -2045
  252. package/dist/chronos.d.mts +0 -41
  253. package/dist/chronos.js +0 -2374
  254. package/dist/chronos.js.map +0 -1
  255. package/dist/chronos.mjs +0 -2365
  256. package/dist/chronos.mjs.map +0 -1
  257. package/dist/chunk-nhb.js +0 -1116
  258. package/dist/chunk-nhb.js.map +0 -1
  259. package/dist/chunk-nhb.mjs +0 -1032
  260. package/dist/chunk-nhb.mjs.map +0 -1
  261. package/dist/index.d.mts +0 -1932
  262. package/dist/index.d.ts +0 -1932
  263. package/dist/index.js +0 -4235
  264. package/dist/index.js.map +0 -1
  265. package/dist/index.mjs +0 -3594
  266. package/dist/index.mjs.map +0 -1
  267. package/dist/typedefs-BYmqOW77.d.mts +0 -979
  268. package/dist/typedefs-C3luCa9l.d.ts +0 -979
  269. package/dist/typedefs.d.mts +0 -2
  270. package/dist/typedefs.d.ts +0 -2
  271. package/dist/typedefs.js +0 -4
  272. package/dist/typedefs.js.map +0 -1
  273. package/dist/typedefs.mjs +0 -3
  274. package/dist/typedefs.mjs.map +0 -1
@@ -0,0 +1,289 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Finder = void 0;
4
+ /**
5
+ * The `Finder` class performs optimized searching on arrays.
6
+ * It supports binary search, fuzzy search, and smart caching with TTL.
7
+ */
8
+ class Finder {
9
+ static #DEFAULT_TTL = 1000 * 60 * 5;
10
+ #cachedResult = new Map();
11
+ #sortedCache = new Map();
12
+ #ttl;
13
+ #items;
14
+ /**
15
+ * * Creates a new `Finder` instance.
16
+ *
17
+ * @param data The initial array of items or a callback returning them.
18
+ * @param ttl Time-to-live (in milliseconds) for cached search results. Defaults to {@link Finder.#DEFAULT_TTL 5 Minutes}.
19
+ */
20
+ constructor(data, ttl = Finder.#DEFAULT_TTL) {
21
+ this.#ttl = ttl;
22
+ this.#items = typeof data === 'function' ? data() : data;
23
+ }
24
+ /**
25
+ * @instance Clears cache globally or for a specific key.
26
+ * @param key Optional key to clear only a specific cache entry.
27
+ */
28
+ clearCache(key) {
29
+ if (key) {
30
+ this.#cachedResult.delete(key);
31
+ }
32
+ else {
33
+ this.#cachedResult.clear();
34
+ }
35
+ }
36
+ /**
37
+ * @instance Finds all items that match the provided matcher using optional caching or fuzzy logic.
38
+ * @param matcher The value to match against.
39
+ * @param keySelector Property key or selector function.
40
+ * @param options Optional settings for search behavior and source list.
41
+ */
42
+ findAll(matcher, keySelector, options) {
43
+ const { fuzzy = false, needSorting = true, cacheKey = 'finder-cache', forceBinary = false, caseInsensitive = true, data, } = options ?? {};
44
+ const source = typeof data === 'function' ? data() : (data ?? this.#items);
45
+ if (!source?.length)
46
+ return [];
47
+ const rawGetKey = typeof keySelector === 'function' ? keySelector : ((item) => item[keySelector]);
48
+ const getKey = Finder.#createMemoizedKeyGetter(rawGetKey);
49
+ const normalizedMatcher = caseInsensitive && typeof matcher === 'string' ?
50
+ matcher.toLowerCase()
51
+ : matcher;
52
+ if (cacheKey) {
53
+ const entry = this.#cachedResult.get(cacheKey);
54
+ if (entry && Date.now() - entry.timestamp < this.#ttl) {
55
+ return entry.result;
56
+ }
57
+ else {
58
+ this.#cachedResult.delete(cacheKey);
59
+ }
60
+ }
61
+ let results = [];
62
+ if (source.length < 100 && !forceBinary) {
63
+ results = source.filter((item) => {
64
+ const key = getKey(item);
65
+ const value = caseInsensitive && typeof key === 'string' ?
66
+ key.toLowerCase()
67
+ : key;
68
+ return value === normalizedMatcher;
69
+ });
70
+ }
71
+ else {
72
+ const sorted = needSorting ?
73
+ this.#sortAndCache(source, getKey, cacheKey)
74
+ : source;
75
+ const firstMatch = this.binarySearch(sorted, normalizedMatcher, getKey, caseInsensitive);
76
+ if (firstMatch) {
77
+ const baseKey = getKey(firstMatch);
78
+ const base = caseInsensitive && typeof baseKey === 'string' ?
79
+ baseKey.toLowerCase()
80
+ : baseKey;
81
+ results = sorted.filter((item) => {
82
+ const key = getKey(item);
83
+ const value = caseInsensitive && typeof key === 'string' ?
84
+ key.toLowerCase()
85
+ : key;
86
+ return value === base;
87
+ });
88
+ }
89
+ }
90
+ if (!results.length && fuzzy && typeof normalizedMatcher === 'string') {
91
+ results = source.filter((item) => {
92
+ const rawKey = getKey(item);
93
+ const key = caseInsensitive && typeof rawKey === 'string' ?
94
+ rawKey.toLowerCase()
95
+ : String(rawKey);
96
+ return this.#match(key, normalizedMatcher);
97
+ });
98
+ }
99
+ if (cacheKey) {
100
+ this.#cachedResult.set(cacheKey, {
101
+ result: results,
102
+ timestamp: Date.now(),
103
+ });
104
+ }
105
+ return results;
106
+ }
107
+ /**
108
+ * @instance Finds first matching item that matches the provided matcher using optional caching or fuzzy logic.
109
+ * @param matcher The value to match.
110
+ * @param keySelector Property key or selector function.
111
+ * @param options Optional behavior flags and item source.
112
+ */
113
+ findOne(matcher, keySelector, options) {
114
+ const { fuzzy = false, needSorting = true, cacheKey = 'finder-cache', forceBinary = false, caseInsensitive = true, data, } = options ?? {};
115
+ const source = typeof data === 'function' ? data() : (data ?? this.#items);
116
+ if (!source?.length)
117
+ return undefined;
118
+ const rawGetKey = typeof keySelector === 'function' ? keySelector : ((item) => item[keySelector]);
119
+ const getKey = Finder.#createMemoizedKeyGetter(rawGetKey);
120
+ const normalizedMatcher = caseInsensitive && typeof matcher === 'string' ?
121
+ matcher.toLowerCase()
122
+ : matcher;
123
+ if (cacheKey) {
124
+ const entry = this.#cachedResult.get(cacheKey);
125
+ if (entry && Date.now() - entry.timestamp < this.#ttl) {
126
+ return entry.result[0];
127
+ }
128
+ else {
129
+ this.#cachedResult.delete(cacheKey);
130
+ }
131
+ }
132
+ let result;
133
+ if (source?.length < 100 && !forceBinary) {
134
+ result = source?.find((item) => {
135
+ const key = getKey(item);
136
+ const value = caseInsensitive && typeof key === 'string' ?
137
+ key.toLowerCase()
138
+ : key;
139
+ return value === normalizedMatcher;
140
+ });
141
+ }
142
+ else {
143
+ result = this.binarySearch(needSorting ?
144
+ this.#sortAndCache(source, getKey, cacheKey)
145
+ : source, normalizedMatcher, getKey, caseInsensitive);
146
+ }
147
+ if (!result && fuzzy && typeof normalizedMatcher === 'string') {
148
+ return this.fuzzySearch(source, normalizedMatcher, getKey, caseInsensitive);
149
+ }
150
+ if (cacheKey && result) {
151
+ this.#cachedResult.set(cacheKey, {
152
+ result: [result],
153
+ timestamp: Date.now(),
154
+ });
155
+ }
156
+ return result;
157
+ }
158
+ /**
159
+ * @instance Asynchronous variant of `findAll` that accepts a promise-based data supplier.
160
+ * @param supplier Async function resolving the items list.
161
+ * @param matcher The value to match.
162
+ * @param keySelector Property key or selector function.
163
+ * @param options Optional settings for search behavior and cache.
164
+ */
165
+ async findAllAsync(supplier, matcher, keySelector, options) {
166
+ const items = await supplier();
167
+ return this.findAll(matcher, keySelector, { ...options, data: items });
168
+ }
169
+ /**
170
+ * @instance Asynchronous variant of `findOne`.
171
+ * @param supplier Async function resolving the items list.
172
+ * @param matcher The value to match.
173
+ * @param keySelector Property key or selector function.
174
+ * @param options Optional settings for behavior and cache.
175
+ */
176
+ async findOneAsync(supplier, matcher, keySelector, options) {
177
+ const items = await supplier();
178
+ return this.findOne(matcher, keySelector, { ...options, data: items });
179
+ }
180
+ /**
181
+ * @instance Performs a binary search on a sorted array using a custom key selector.
182
+ *
183
+ * @param sorted - The sorted array of items to search.
184
+ * @param matcher - The value to search for.
185
+ * @param keySelector - A function that extracts the comparable key from each item.
186
+ * @param caseInsensitive - Whether to compare string keys ignoring case.
187
+ * @returns The first matching item if found; otherwise, undefined.
188
+ */
189
+ binarySearch(sorted, matcher, keySelector, caseInsensitive) {
190
+ let min = 0, max = sorted?.length - 1;
191
+ while (min <= max) {
192
+ const mid = Math.floor((min + max) / 2);
193
+ const midKey = keySelector(sorted[mid]);
194
+ const key = caseInsensitive && typeof midKey === 'string' ?
195
+ midKey.toLowerCase()
196
+ : midKey;
197
+ if (key === matcher)
198
+ return sorted[mid];
199
+ if (key < matcher)
200
+ min = mid + 1;
201
+ else
202
+ max = mid - 1;
203
+ }
204
+ return undefined;
205
+ }
206
+ /**
207
+ * @instance Performs a fuzzy search on an array by matching characters in sequence.
208
+ *
209
+ * @param array - The array of items to search.
210
+ * @param matcher - The fuzzy search string to match against.
211
+ * @param keySelector - A function that extracts the key to search from each item.
212
+ * @param caseInsensitive - Whether to compare ignoring case for string values.
213
+ * @returns The first fuzzy-matching item if found; otherwise, undefined.
214
+ */
215
+ fuzzySearch(array, matcher, keySelector, caseInsensitive) {
216
+ for (const item of array) {
217
+ const rawKey = keySelector(item);
218
+ const key = caseInsensitive && typeof rawKey === 'string' ?
219
+ rawKey.toLowerCase()
220
+ : String(rawKey);
221
+ if (this.#match(key, matcher))
222
+ return item;
223
+ }
224
+ return undefined;
225
+ }
226
+ /**
227
+ * @private Checks if the characters in the target string appear in order within the source string.
228
+ * @param source Source string to search within.
229
+ * @param target Target string to match against the source string.
230
+ * @returns True if the target string is a fuzzy match within the source string; otherwise, false.
231
+ */
232
+ #match(source, target) {
233
+ let i = 0;
234
+ for (const char of target) {
235
+ i = source?.indexOf(char, i);
236
+ if (i === -1)
237
+ return false;
238
+ i++;
239
+ }
240
+ return true;
241
+ }
242
+ /**
243
+ * @private Sorts an array and caches the result for a specified time-to-live (TTL).
244
+ * @param data Data to sort and cache.
245
+ * @param getKey Key extraction function.
246
+ * @param cacheKey Optional cache key for storing the result.
247
+ * @returns
248
+ */
249
+ #sortAndCache(data, getKey, cacheKey) {
250
+ if (cacheKey) {
251
+ const entry = this.#sortedCache.get(cacheKey);
252
+ if (entry && Date.now() - entry.timestamp < this.#ttl) {
253
+ return entry.result;
254
+ }
255
+ else {
256
+ this.#sortedCache.delete(cacheKey);
257
+ }
258
+ }
259
+ const sorted = [...data].sort((a, b) => {
260
+ const keyA = getKey(a);
261
+ const keyB = getKey(b);
262
+ return (keyA < keyB ? -1
263
+ : keyA > keyB ? 1
264
+ : 0);
265
+ });
266
+ if (cacheKey) {
267
+ this.#sortedCache.set(cacheKey, {
268
+ result: sorted,
269
+ timestamp: Date.now(),
270
+ });
271
+ }
272
+ return sorted;
273
+ }
274
+ /**
275
+ * @static @private Creates a memoized version of a key extractor.
276
+ * @param getKey Original key extraction function
277
+ */
278
+ static #createMemoizedKeyGetter(getKey) {
279
+ const cache = new Map();
280
+ return (item) => {
281
+ if (cache.has(item))
282
+ return cache.get(item);
283
+ const key = getKey(item);
284
+ cache.set(item, key);
285
+ return key;
286
+ };
287
+ }
288
+ }
289
+ exports.Finder = Finder;
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getLastArrayElement = exports.shuffleArray = exports.isInvalidOrEmptyArray = exports.filterArrayOfObjects = exports.flattenArray = void 0;
4
+ /**
5
+ * * Flattens a nested array recursively or wraps any non-array data type in an array.
6
+ *
7
+ * @param input - The input value, which can be a nested array or a non-array value.
8
+ * @returns A fully flattened array of type `Flatten<T>`. If the input is not an array, it wraps it in a single-element array.
9
+ */
10
+ const flattenArray = (input) => {
11
+ if (!Array.isArray(input))
12
+ return [input];
13
+ return input.reduce((acc, item) => {
14
+ // If item is an array, recursively flatten it; otherwise, add it directly.
15
+ return acc.concat(Array.isArray(item) ? (0, exports.flattenArray)(item) : [item]);
16
+ }, []);
17
+ };
18
+ exports.flattenArray = flattenArray;
19
+ /**
20
+ * @deprecated _Please, use `findAll` instance method from `Finder` class for **more advanced filtering and searching.**_
21
+ *
22
+ * * Filters an array of objects based on multiple conditions for specified keys.
23
+ * @param array - The array of objects to filter.
24
+ * @param conditions - An object where keys represent the property names and values represent filter conditions.
25
+ * The conditions can be a function `(value: T[K]) => boolean`.
26
+ * @returns The filtered array of objects.
27
+ * @throws `Error` If the input is not a valid array.
28
+ */
29
+ const filterArrayOfObjects = (array, conditions) => {
30
+ if (!Array.isArray(array)) {
31
+ throw new Error('The provided input is not a valid array!');
32
+ }
33
+ return array?.filter((item) => Object.entries(conditions)?.every(([key, conditionFn]) => {
34
+ if (typeof conditionFn === 'function') {
35
+ return conditionFn(item[key]);
36
+ }
37
+ return true;
38
+ }));
39
+ };
40
+ exports.filterArrayOfObjects = filterArrayOfObjects;
41
+ /**
42
+ * * Checks if a value is an empty array or an array with only empty values.
43
+ *
44
+ * @param value - The value to check.
45
+ * @returns `true` if the value is not an array, an empty array, or an array containing only `null`, `undefined`, empty objects, or empty arrays.
46
+ */
47
+ const isInvalidOrEmptyArray = (value) => {
48
+ if (!Array.isArray(value))
49
+ return true;
50
+ if (value?.length === 0)
51
+ return true;
52
+ return value?.every((item) => item == null ||
53
+ (Array.isArray(item) && item?.length === 0) ||
54
+ (typeof item === 'object' && Object.keys(item || {})?.length === 0));
55
+ };
56
+ exports.isInvalidOrEmptyArray = isInvalidOrEmptyArray;
57
+ /**
58
+ * * Shuffle the elements of an array.
59
+ *
60
+ * @param array Array to shuffle.
61
+ * @returns Shuffled array.
62
+ */
63
+ const shuffleArray = (array) => {
64
+ if ((0, exports.isInvalidOrEmptyArray)(array))
65
+ return array;
66
+ const shuffled = structuredClone(array);
67
+ for (let i = shuffled?.length - 1; i > 0; i--) {
68
+ const j = Math.floor(Math.random() * (i + 1));
69
+ [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
70
+ }
71
+ return shuffled;
72
+ };
73
+ exports.shuffleArray = shuffleArray;
74
+ /**
75
+ * * Get the last element of an array.
76
+ *
77
+ * @param array Array to get the last element from.
78
+ * @returns The last element or `undefined` if the array is empty.
79
+ */
80
+ const getLastArrayElement = (array) => {
81
+ return array?.length > 0 ? array[array?.length - 1] : undefined;
82
+ };
83
+ exports.getLastArrayElement = getLastArrayElement;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sortAnArray = sortAnArray;
4
+ const non_primitives_1 = require("../guards/non-primitives");
5
+ const primitives_1 = require("../guards/primitives");
6
+ const utils_1 = require("./utils");
7
+ /**
8
+ * * Sorts an array of strings, numbers, booleans, or objects based on the provided options.
9
+ *
10
+ * - If the array contains strings, it sorts them alphabetically.
11
+ * - If the array contains numbers, it sorts them numerically.
12
+ * - If the array contains booleans, it sorts them by their boolean value.
13
+ * - If the array contains objects, it sorts them by the specified field in the options `sortByField`.
14
+ *
15
+ * @param array - The array to sort.
16
+ * @param options - Sorting options for objects.
17
+ * @returns The sorted array.
18
+ */
19
+ function sortAnArray(array, options) {
20
+ if (!(0, non_primitives_1.isValidArray)(array))
21
+ return array;
22
+ // Check if the array contains strings
23
+ if ((0, non_primitives_1.isArrayOfType)(array, primitives_1.isString)) {
24
+ return [...array].sort((a, b) => options?.sortOrder === 'desc' ?
25
+ (0, utils_1.naturalSort)(b, a)
26
+ : (0, utils_1.naturalSort)(a, b));
27
+ }
28
+ // Check if the array contains numbers
29
+ if ((0, non_primitives_1.isArrayOfType)(array, primitives_1.isNumber)) {
30
+ return [...array].sort((a, b) => options?.sortOrder === 'desc' ? b - a : a - b);
31
+ }
32
+ // Check if the array contains booleans
33
+ if ((0, non_primitives_1.isArrayOfType)(array, primitives_1.isBoolean)) {
34
+ return [...array].sort((a, b) => options?.sortOrder === 'desc' ?
35
+ Number(b) - Number(a)
36
+ : Number(a) - Number(b));
37
+ }
38
+ // Handle array of objects
39
+ if ((0, non_primitives_1.isArrayOfType)(array, non_primitives_1.isObject) && options && 'sortByField' in options) {
40
+ return [...array].sort((a, b) => {
41
+ const _getKeyValue = (obj, path) => {
42
+ return path
43
+ .split('.')
44
+ .reduce((acc, key) => acc?.[key], obj);
45
+ };
46
+ const keyA = _getKeyValue(a, options?.sortByField);
47
+ const keyB = _getKeyValue(b, options?.sortByField);
48
+ if (keyA == null || keyB == null) {
49
+ return keyA == null ? 1 : -1;
50
+ }
51
+ if (typeof keyA === 'string' && typeof keyB === 'string') {
52
+ return options?.sortOrder === 'desc' ?
53
+ (0, utils_1.naturalSort)(keyB, keyA)
54
+ : (0, utils_1.naturalSort)(keyA, keyB);
55
+ }
56
+ if (typeof keyA === 'number' && typeof keyB === 'number') {
57
+ return options?.sortOrder === 'desc' ?
58
+ keyB - keyA
59
+ : keyA - keyB;
60
+ }
61
+ if (typeof keyA === 'boolean' && typeof keyB === 'boolean') {
62
+ return options?.sortOrder === 'desc' ?
63
+ Number(keyB) - Number(keyA)
64
+ : Number(keyA) - Number(keyB);
65
+ }
66
+ return 0;
67
+ });
68
+ }
69
+ return array;
70
+ }
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createOptionsArray = createOptionsArray;
4
+ exports.removeDuplicatesFromArray = removeDuplicatesFromArray;
5
+ exports.getDuplicates = getDuplicates;
6
+ exports.findMissingElements = findMissingElements;
7
+ exports.splitArray = splitArray;
8
+ exports.rotateArray = rotateArray;
9
+ exports.moveArrayElement = moveArrayElement;
10
+ const primitives_1 = require("../guards/primitives");
11
+ const utils_1 = require("../utils");
12
+ /**
13
+ * * Converts an array of objects into a formatted array of options.
14
+ *
15
+ * @param data - An array of objects to convert into options.
16
+ * @param config - The configuration object to specify the keys for the `value` (firstFieldName) and `label` (secondFieldName) fields and rename as needed.
17
+ * @returns An array of options, where each option has `value` and `label` fields as default or as specified by user in the config options.
18
+ */
19
+ function createOptionsArray(data, config) {
20
+ const { firstFieldKey, secondFieldKey, firstFieldName = 'value', secondFieldName = 'label', retainNumberValue = false, } = config || {};
21
+ if (data && data?.length) {
22
+ return data?.map((datum) => {
23
+ const firstValue = retainNumberValue && (0, primitives_1.isNumber)(datum[firstFieldKey]) ?
24
+ datum[firstFieldKey]
25
+ : String(datum[firstFieldKey] ?? '');
26
+ return {
27
+ [firstFieldName]: firstValue,
28
+ [secondFieldName]: String(datum[secondFieldKey] ?? ''),
29
+ };
30
+ });
31
+ }
32
+ else {
33
+ return [];
34
+ }
35
+ }
36
+ /**
37
+ * * Removes duplicate values from an array, supporting deep comparison for objects and arrays.
38
+ *
39
+ * @param array - The array from which duplicates need to be removed.
40
+ * @returns A new array with duplicates removed.
41
+ */
42
+ function removeDuplicatesFromArray(array) {
43
+ return array?.filter((item, index, self) => index === self?.findIndex((el) => (0, utils_1.isDeepEqual)(el, item)));
44
+ }
45
+ /**
46
+ * * Finds duplicate values in an array, runs deep comparison for objects and arrays.
47
+ *
48
+ * @param array - The array in which to find duplicates.
49
+ * @returns An array containing all duplicate entries (each one only once).
50
+ */
51
+ function getDuplicates(array) {
52
+ const seen = [];
53
+ const duplicates = [];
54
+ for (const item of array) {
55
+ const hasSeen = seen?.find((el) => (0, utils_1.isDeepEqual)(el, item));
56
+ const hasDuplicate = duplicates?.find((el) => (0, utils_1.isDeepEqual)(el, item));
57
+ if (hasSeen && !hasDuplicate) {
58
+ duplicates?.push(item);
59
+ }
60
+ else if (!hasSeen) {
61
+ seen?.push(item);
62
+ }
63
+ }
64
+ return duplicates;
65
+ }
66
+ /**
67
+ * * Finds elements missing from one array compared to another using deep comparison.
68
+ *
69
+ * @param options - Configuration to specify which array to compare and direction of check.
70
+ * @returns An array of missing elements based on the comparison direction.
71
+ */
72
+ /**
73
+ * * Finds elements missing from one array compared to another using deep comparison.
74
+ *
75
+ * @param array1 The first array to compare.
76
+ * @param array2 The second array to compare.
77
+ * @param missingFrom Which direction to compare for missing values:.
78
+ * - `'from-first'` → values in `array1` missing in `array2`.
79
+ * - `'from-second'` → values in `array2` missing in `array1`.
80
+ * @returns An array of missing elements based on the comparison direction.
81
+ */
82
+ function findMissingElements(array1, array2, missingFrom) {
83
+ const source = (missingFrom === 'from-first' ? array1 : array2) ?? [];
84
+ const target = (missingFrom === 'from-first' ? array2 : array1) ?? [];
85
+ return source.filter((s) => !target?.some((t) => (0, utils_1.isDeepEqual)(t, s)));
86
+ }
87
+ /**
88
+ * * Splits an array into chunks of a given size.
89
+ *
90
+ * @param arr The array to split.
91
+ * @param chunkSize The size of each chunk.
92
+ * @returns An array of chunked arrays.
93
+ */
94
+ function splitArray(arr, chunkSize) {
95
+ const result = [];
96
+ for (let i = 0; i < arr?.length; i += chunkSize) {
97
+ result.push(arr.slice(i, i + chunkSize));
98
+ }
99
+ return result;
100
+ }
101
+ /**
102
+ * * Rotates an array left or right by a given number of steps.
103
+ *
104
+ * @param arr The array to rotate.
105
+ * @param steps The number of positions to rotate (positive: right, negative: left).
106
+ * @returns The rotated array.
107
+ */
108
+ function rotateArray(arr, steps) {
109
+ const length = arr?.length;
110
+ if (length === 0)
111
+ return arr;
112
+ const offset = ((steps % length) + length) % length;
113
+ return arr.slice(-offset).concat(arr.slice(0, -offset));
114
+ }
115
+ /**
116
+ * * Moves an element within an array from one index to another.
117
+ *
118
+ * @param arr The array to modify.
119
+ * @param fromIndex The index of the element to move.
120
+ * @param toIndex The new index for the element.
121
+ * @returns A new array with the element moved.
122
+ */
123
+ function moveArrayElement(arr, fromIndex, toIndex) {
124
+ const newArr = [...arr];
125
+ const [item] = newArr.splice(fromIndex, 1);
126
+ newArr.splice(toIndex, 0, item);
127
+ return newArr;
128
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.naturalSort = naturalSort;
4
+ /**
5
+ * * Compare two strings using natural sorting (e.g., "file2" < "file10").
6
+ * Optionally supports case-insensitive and locale-aware string chunk comparisons.
7
+ *
8
+ * @param a - The first string to compare.
9
+ * @param b - The second string to compare.
10
+ * @param options - Optional settings to configure comparison behavior.
11
+ * @param options.caseInsensitive - If true, compares string chunks without case sensitivity. Defaults to `true`.
12
+ * @param options.localeAware - If true, uses localeCompare for string chunk comparisons. Defaults to `false`.
13
+ * @returns A negative number if `a` comes before `b`, a positive number if `a` comes after `b`, or 0 if equal.
14
+ */
15
+ function naturalSort(a, b, options) {
16
+ const { caseInsensitive = true, localeAware = false } = options || {};
17
+ /**
18
+ * * Splits a string into an array of number and non-number chunks.
19
+ * @param str - The string to split.
20
+ * @returns An array of string and number parts.
21
+ */
22
+ const _createChunks = (str) => {
23
+ const chunks = [];
24
+ let current = '';
25
+ let isNumeric = false;
26
+ for (const char of str) {
27
+ const charIsNum = !Number.isNaN(Number(char));
28
+ if (current?.length === 0) {
29
+ current = char;
30
+ isNumeric = charIsNum;
31
+ continue;
32
+ }
33
+ if (charIsNum === isNumeric) {
34
+ current += char;
35
+ }
36
+ else {
37
+ chunks?.push(isNumeric ? Number(current) : current);
38
+ current = char;
39
+ isNumeric = charIsNum;
40
+ }
41
+ }
42
+ if (current?.length > 0) {
43
+ chunks?.push(isNumeric ? Number(current) : current);
44
+ }
45
+ return chunks;
46
+ };
47
+ const aChunks = _createChunks(a);
48
+ const bChunks = _createChunks(b);
49
+ for (let i = 0; i < Math.min(aChunks?.length, bChunks?.length); i++) {
50
+ let aChunk = aChunks[i];
51
+ let bChunk = bChunks[i];
52
+ // Normalize string chunks if case-insensitive
53
+ if (caseInsensitive &&
54
+ typeof aChunk === 'string' &&
55
+ typeof bChunk === 'string') {
56
+ aChunk = aChunk?.toLowerCase();
57
+ bChunk = bChunk?.toLowerCase();
58
+ }
59
+ // Compare types: number vs string
60
+ if (typeof aChunk !== typeof bChunk) {
61
+ return typeof aChunk === 'string' ? 1 : -1;
62
+ }
63
+ // Compare same-type chunks
64
+ if (aChunk !== bChunk) {
65
+ if (typeof aChunk === 'number' && typeof bChunk === 'number') {
66
+ return aChunk - bChunk;
67
+ }
68
+ if (typeof aChunk === 'string' && typeof bChunk === 'string') {
69
+ if (localeAware) {
70
+ const cmp = aChunk.localeCompare(bChunk, undefined, {
71
+ sensitivity: caseInsensitive ? 'accent' : 'variant',
72
+ });
73
+ if (cmp !== 0)
74
+ return cmp;
75
+ }
76
+ return aChunk < bChunk ? -1 : 1;
77
+ }
78
+ }
79
+ }
80
+ return aChunks?.length - bChunks?.length;
81
+ }