@gzl10/ts-helpers 4.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/CHANGELOG.md +320 -0
  2. package/README.md +233 -0
  3. package/USAGE-GUIDE.md +800 -0
  4. package/dist/browser/async.js +15 -0
  5. package/dist/browser/async.js.map +1 -0
  6. package/dist/browser/chunk-4O7ZPIJN.js +383 -0
  7. package/dist/browser/chunk-4O7ZPIJN.js.map +1 -0
  8. package/dist/browser/chunk-75XNTC34.js +60 -0
  9. package/dist/browser/chunk-75XNTC34.js.map +1 -0
  10. package/dist/browser/chunk-C3D7YZVE.js +299 -0
  11. package/dist/browser/chunk-C3D7YZVE.js.map +1 -0
  12. package/dist/browser/chunk-CZL6C2EI.js +452 -0
  13. package/dist/browser/chunk-CZL6C2EI.js.map +1 -0
  14. package/dist/browser/chunk-D4FZFIVA.js +240 -0
  15. package/dist/browser/chunk-D4FZFIVA.js.map +1 -0
  16. package/dist/browser/chunk-IL7NG7IC.js +72 -0
  17. package/dist/browser/chunk-IL7NG7IC.js.map +1 -0
  18. package/dist/browser/chunk-NSBPE2FW.js +17 -0
  19. package/dist/browser/chunk-NSBPE2FW.js.map +1 -0
  20. package/dist/browser/chunk-SLQVNPTH.js +27 -0
  21. package/dist/browser/chunk-SLQVNPTH.js.map +1 -0
  22. package/dist/browser/chunk-WG7ILCUB.js +195 -0
  23. package/dist/browser/chunk-WG7ILCUB.js.map +1 -0
  24. package/dist/browser/chunk-WJA4JDMZ.js +278 -0
  25. package/dist/browser/chunk-WJA4JDMZ.js.map +1 -0
  26. package/dist/browser/chunk-ZFVYLUTT.js +65 -0
  27. package/dist/browser/chunk-ZFVYLUTT.js.map +1 -0
  28. package/dist/browser/chunk-ZYTSVMTI.js +263 -0
  29. package/dist/browser/chunk-ZYTSVMTI.js.map +1 -0
  30. package/dist/browser/dates.js +78 -0
  31. package/dist/browser/dates.js.map +1 -0
  32. package/dist/browser/environment-detection.js +21 -0
  33. package/dist/browser/environment-detection.js.map +1 -0
  34. package/dist/browser/environment.js +34 -0
  35. package/dist/browser/environment.js.map +1 -0
  36. package/dist/browser/errors.js +18 -0
  37. package/dist/browser/errors.js.map +1 -0
  38. package/dist/browser/index.js +412 -0
  39. package/dist/browser/index.js.map +1 -0
  40. package/dist/browser/math.js +51 -0
  41. package/dist/browser/math.js.map +1 -0
  42. package/dist/browser/number.js +10 -0
  43. package/dist/browser/number.js.map +1 -0
  44. package/dist/browser/objects.js +31 -0
  45. package/dist/browser/objects.js.map +1 -0
  46. package/dist/browser/strings.js +80 -0
  47. package/dist/browser/strings.js.map +1 -0
  48. package/dist/browser/validation-core.js +54 -0
  49. package/dist/browser/validation-core.js.map +1 -0
  50. package/dist/browser/validation-crypto.js +28 -0
  51. package/dist/browser/validation-crypto.js.map +1 -0
  52. package/dist/browser/validators.js +98 -0
  53. package/dist/browser/validators.js.map +1 -0
  54. package/dist/cjs/async.js +86 -0
  55. package/dist/cjs/async.js.map +1 -0
  56. package/dist/cjs/dates.js +285 -0
  57. package/dist/cjs/dates.js.map +1 -0
  58. package/dist/cjs/environment-detection.js +84 -0
  59. package/dist/cjs/environment-detection.js.map +1 -0
  60. package/dist/cjs/environment.js +261 -0
  61. package/dist/cjs/environment.js.map +1 -0
  62. package/dist/cjs/errors.js +80 -0
  63. package/dist/cjs/errors.js.map +1 -0
  64. package/dist/cjs/index.js +2035 -0
  65. package/dist/cjs/index.js.map +1 -0
  66. package/dist/cjs/math.js +388 -0
  67. package/dist/cjs/math.js.map +1 -0
  68. package/dist/cjs/number.js +37 -0
  69. package/dist/cjs/number.js.map +1 -0
  70. package/dist/cjs/objects.js +249 -0
  71. package/dist/cjs/objects.js.map +1 -0
  72. package/dist/cjs/strings.js +253 -0
  73. package/dist/cjs/strings.js.map +1 -0
  74. package/dist/cjs/validation.js +450 -0
  75. package/dist/cjs/validation.js.map +1 -0
  76. package/dist/esm/async.js +15 -0
  77. package/dist/esm/async.js.map +1 -0
  78. package/dist/esm/chunk-4O7ZPIJN.js +383 -0
  79. package/dist/esm/chunk-4O7ZPIJN.js.map +1 -0
  80. package/dist/esm/chunk-75XNTC34.js +60 -0
  81. package/dist/esm/chunk-75XNTC34.js.map +1 -0
  82. package/dist/esm/chunk-BDOBKBKA.js +72 -0
  83. package/dist/esm/chunk-BDOBKBKA.js.map +1 -0
  84. package/dist/esm/chunk-C3D7YZVE.js +299 -0
  85. package/dist/esm/chunk-C3D7YZVE.js.map +1 -0
  86. package/dist/esm/chunk-CZL6C2EI.js +452 -0
  87. package/dist/esm/chunk-CZL6C2EI.js.map +1 -0
  88. package/dist/esm/chunk-EBLSTOEC.js +263 -0
  89. package/dist/esm/chunk-EBLSTOEC.js.map +1 -0
  90. package/dist/esm/chunk-NSBPE2FW.js +17 -0
  91. package/dist/esm/chunk-NSBPE2FW.js.map +1 -0
  92. package/dist/esm/chunk-SLQVNPTH.js +27 -0
  93. package/dist/esm/chunk-SLQVNPTH.js.map +1 -0
  94. package/dist/esm/chunk-WG7ILCUB.js +195 -0
  95. package/dist/esm/chunk-WG7ILCUB.js.map +1 -0
  96. package/dist/esm/chunk-WJA4JDMZ.js +278 -0
  97. package/dist/esm/chunk-WJA4JDMZ.js.map +1 -0
  98. package/dist/esm/chunk-ZFVYLUTT.js +65 -0
  99. package/dist/esm/chunk-ZFVYLUTT.js.map +1 -0
  100. package/dist/esm/dates.js +78 -0
  101. package/dist/esm/dates.js.map +1 -0
  102. package/dist/esm/environment-detection.js +21 -0
  103. package/dist/esm/environment-detection.js.map +1 -0
  104. package/dist/esm/environment.js +34 -0
  105. package/dist/esm/environment.js.map +1 -0
  106. package/dist/esm/errors.js +18 -0
  107. package/dist/esm/errors.js.map +1 -0
  108. package/dist/esm/index.js +380 -0
  109. package/dist/esm/index.js.map +1 -0
  110. package/dist/esm/math.js +51 -0
  111. package/dist/esm/math.js.map +1 -0
  112. package/dist/esm/number.js +10 -0
  113. package/dist/esm/number.js.map +1 -0
  114. package/dist/esm/objects.js +31 -0
  115. package/dist/esm/objects.js.map +1 -0
  116. package/dist/esm/strings.js +80 -0
  117. package/dist/esm/strings.js.map +1 -0
  118. package/dist/esm/validation.js +54 -0
  119. package/dist/esm/validation.js.map +1 -0
  120. package/dist/node/async.js +93 -0
  121. package/dist/node/async.js.map +1 -0
  122. package/dist/node/csv.js +102 -0
  123. package/dist/node/csv.js.map +1 -0
  124. package/dist/node/data.js +880 -0
  125. package/dist/node/data.js.map +1 -0
  126. package/dist/node/dates.js +324 -0
  127. package/dist/node/dates.js.map +1 -0
  128. package/dist/node/environment.js +278 -0
  129. package/dist/node/environment.js.map +1 -0
  130. package/dist/node/errors.js +89 -0
  131. package/dist/node/errors.js.map +1 -0
  132. package/dist/node/index.js +3151 -0
  133. package/dist/node/index.js.map +1 -0
  134. package/dist/node/json.js +107 -0
  135. package/dist/node/json.js.map +1 -0
  136. package/dist/node/math.js +413 -0
  137. package/dist/node/math.js.map +1 -0
  138. package/dist/node/number.js +42 -0
  139. package/dist/node/number.js.map +1 -0
  140. package/dist/node/objects.js +264 -0
  141. package/dist/node/objects.js.map +1 -0
  142. package/dist/node/strings.js +293 -0
  143. package/dist/node/strings.js.map +1 -0
  144. package/dist/node/tree.js +89 -0
  145. package/dist/node/tree.js.map +1 -0
  146. package/dist/node/validation-core.js +477 -0
  147. package/dist/node/validation-core.js.map +1 -0
  148. package/dist/node/validation-crypto.js +179 -0
  149. package/dist/node/validation-crypto.js.map +1 -0
  150. package/dist/node/validation.js +677 -0
  151. package/dist/node/validation.js.map +1 -0
  152. package/dist/node/validators.js +123 -0
  153. package/dist/node/validators.js.map +1 -0
  154. package/dist/node-esm/async.js +15 -0
  155. package/dist/node-esm/async.js.map +1 -0
  156. package/dist/node-esm/chunk-3YOF7NPT.js +299 -0
  157. package/dist/node-esm/chunk-3YOF7NPT.js.map +1 -0
  158. package/dist/node-esm/chunk-64TBXJQS.js +263 -0
  159. package/dist/node-esm/chunk-64TBXJQS.js.map +1 -0
  160. package/dist/node-esm/chunk-75XNTC34.js +60 -0
  161. package/dist/node-esm/chunk-75XNTC34.js.map +1 -0
  162. package/dist/node-esm/chunk-C4PKXIPB.js +278 -0
  163. package/dist/node-esm/chunk-C4PKXIPB.js.map +1 -0
  164. package/dist/node-esm/chunk-CMDFZME3.js +452 -0
  165. package/dist/node-esm/chunk-CMDFZME3.js.map +1 -0
  166. package/dist/node-esm/chunk-DZZPUYMP.js +74 -0
  167. package/dist/node-esm/chunk-DZZPUYMP.js.map +1 -0
  168. package/dist/node-esm/chunk-HTSEHRHI.js +195 -0
  169. package/dist/node-esm/chunk-HTSEHRHI.js.map +1 -0
  170. package/dist/node-esm/chunk-JCAUVOPH.js +27 -0
  171. package/dist/node-esm/chunk-JCAUVOPH.js.map +1 -0
  172. package/dist/node-esm/chunk-KBHE3K2F.js +505 -0
  173. package/dist/node-esm/chunk-KBHE3K2F.js.map +1 -0
  174. package/dist/node-esm/chunk-LYTET5NX.js +65 -0
  175. package/dist/node-esm/chunk-LYTET5NX.js.map +1 -0
  176. package/dist/node-esm/chunk-PZ5AY32C.js +10 -0
  177. package/dist/node-esm/chunk-PZ5AY32C.js.map +1 -0
  178. package/dist/node-esm/chunk-UKGXL2QO.js +383 -0
  179. package/dist/node-esm/chunk-UKGXL2QO.js.map +1 -0
  180. package/dist/node-esm/chunk-XAEYT23H.js +164 -0
  181. package/dist/node-esm/chunk-XAEYT23H.js.map +1 -0
  182. package/dist/node-esm/csv.js +63 -0
  183. package/dist/node-esm/csv.js.map +1 -0
  184. package/dist/node-esm/data.js +32 -0
  185. package/dist/node-esm/data.js.map +1 -0
  186. package/dist/node-esm/dates.js +78 -0
  187. package/dist/node-esm/dates.js.map +1 -0
  188. package/dist/node-esm/environment.js +34 -0
  189. package/dist/node-esm/environment.js.map +1 -0
  190. package/dist/node-esm/errors.js +18 -0
  191. package/dist/node-esm/errors.js.map +1 -0
  192. package/dist/node-esm/index.js +426 -0
  193. package/dist/node-esm/index.js.map +1 -0
  194. package/dist/node-esm/json.js +68 -0
  195. package/dist/node-esm/json.js.map +1 -0
  196. package/dist/node-esm/math.js +51 -0
  197. package/dist/node-esm/math.js.map +1 -0
  198. package/dist/node-esm/number.js +10 -0
  199. package/dist/node-esm/number.js.map +1 -0
  200. package/dist/node-esm/objects.js +31 -0
  201. package/dist/node-esm/objects.js.map +1 -0
  202. package/dist/node-esm/strings.js +80 -0
  203. package/dist/node-esm/strings.js.map +1 -0
  204. package/dist/node-esm/tree.js +8 -0
  205. package/dist/node-esm/tree.js.map +1 -0
  206. package/dist/node-esm/validation-core.js +54 -0
  207. package/dist/node-esm/validation-core.js.map +1 -0
  208. package/dist/node-esm/validation-crypto.js +26 -0
  209. package/dist/node-esm/validation-crypto.js.map +1 -0
  210. package/dist/node-esm/validation.js +606 -0
  211. package/dist/node-esm/validation.js.map +1 -0
  212. package/dist/node-esm/validators.js +98 -0
  213. package/dist/node-esm/validators.js.map +1 -0
  214. package/dist/types/async-C8gvbSG-.d.ts +453 -0
  215. package/dist/types/async.d.ts +1 -0
  216. package/dist/types/csv.d.ts +226 -0
  217. package/dist/types/data.d.ts +1561 -0
  218. package/dist/types/dates-hTiE0Z11.d.ts +298 -0
  219. package/dist/types/dates.d.ts +1 -0
  220. package/dist/types/environment-B8eLS7KT.d.ts +420 -0
  221. package/dist/types/environment-detection.d.ts +102 -0
  222. package/dist/types/environment.d.ts +1 -0
  223. package/dist/types/errors.d.ts +147 -0
  224. package/dist/types/index.d.ts +211 -0
  225. package/dist/types/json.d.ts +284 -0
  226. package/dist/types/math-BQ9Lwdp7.d.ts +2060 -0
  227. package/dist/types/math.d.ts +1 -0
  228. package/dist/types/number-CYnQfLWj.d.ts +44 -0
  229. package/dist/types/number.d.ts +1 -0
  230. package/dist/types/objects-BohS8GCS.d.ts +1185 -0
  231. package/dist/types/objects.d.ts +1 -0
  232. package/dist/types/strings-CiqRPYLL.d.ts +1349 -0
  233. package/dist/types/strings.d.ts +1 -0
  234. package/dist/types/tree.d.ts +284 -0
  235. package/dist/types/validation-core-DfHF8rCG.d.ts +238 -0
  236. package/dist/types/validation-crypto-browser.d.ts +56 -0
  237. package/dist/types/validation-crypto-node.d.ts +31 -0
  238. package/dist/types/validation.d.ts +1 -0
  239. package/dist/types/validators.d.ts +216 -0
  240. package/package.json +253 -0
@@ -0,0 +1,195 @@
1
+ import {
2
+ areDatesEqualWithTolerance,
3
+ isDateTime,
4
+ toDate
5
+ } from "./chunk-3YOF7NPT.js";
6
+ import {
7
+ __export
8
+ } from "./chunk-PZ5AY32C.js";
9
+
10
+ // src/objects.ts
11
+ var objects_exports = {};
12
+ __export(objects_exports, {
13
+ calculateDifferences: () => calculateDifferences,
14
+ comparator: () => comparator,
15
+ deepEqual: () => deepEqual,
16
+ deleteArrayElementsBy: () => deleteArrayElementsBy,
17
+ formatToReadableString: () => formatToReadableString,
18
+ generateCrcHash: () => generateCrcHash,
19
+ getDeepValue: () => getDeepValue,
20
+ getShallowProperties: () => getShallowProperties,
21
+ hasSameType: () => hasSameType,
22
+ setDeepValue: () => setDeepValue,
23
+ updateArrayElementById: () => updateArrayElementById,
24
+ updateArrayElementsBy: () => updateArrayElementsBy
25
+ });
26
+ import crc32 from "crc/crc32";
27
+ import * as lodash from "lodash";
28
+ import fastEqual from "fast-deep-equal";
29
+ var {
30
+ isArray,
31
+ isArrayBuffer,
32
+ isBoolean,
33
+ isBuffer,
34
+ isEqual,
35
+ isNil,
36
+ isNumber,
37
+ isObject,
38
+ isPlainObject,
39
+ isString,
40
+ isTypedArray,
41
+ transform
42
+ } = lodash;
43
+ var nativeFilter = (array, predicate) => {
44
+ return array.filter((item) => {
45
+ return Object.keys(predicate).every((key) => item[key] === predicate[key]);
46
+ });
47
+ };
48
+ var nativeAssign = (target, source) => {
49
+ return Object.assign(target, source);
50
+ };
51
+ var nativePick = (object, keys) => {
52
+ const result = {};
53
+ keys.forEach((key) => {
54
+ if (key in object) {
55
+ result[key] = object[key];
56
+ }
57
+ });
58
+ return result;
59
+ };
60
+ var nativeRemove = (array, predicate) => {
61
+ const removed = [];
62
+ for (let i = array.length - 1; i >= 0; i--) {
63
+ if (predicate(array[i])) {
64
+ removed.unshift(array.splice(i, 1)[0]);
65
+ }
66
+ }
67
+ return removed;
68
+ };
69
+ var comparator = (data1, data2) => isEqual(data1, data2);
70
+ var deepEqual = (data1, data2) => fastEqual(data1, data2);
71
+ var formatToReadableString = (data) => JSON.stringify(data).replace(/[{}"]/g, "").replace(/,/g, ", ");
72
+ var getShallowProperties = (obj) => {
73
+ if (!obj) return {};
74
+ const topLevelProps = {};
75
+ for (const prop in obj) {
76
+ if (Object.hasOwnProperty.call(obj, prop)) {
77
+ const value = obj[prop];
78
+ const type = typeof value;
79
+ if (type !== "object" && type !== "function" || value === null) {
80
+ topLevelProps[prop] = value;
81
+ }
82
+ }
83
+ }
84
+ return topLevelProps;
85
+ };
86
+ var calculateDifferences = (oldObj, newObj) => {
87
+ return transform(
88
+ newObj,
89
+ (result, value, key) => {
90
+ const oldValue = oldObj[key];
91
+ if (isDateTime(value) && isDateTime(oldValue)) {
92
+ if (!areDatesEqualWithTolerance(toDate(value), toDate(oldValue))) {
93
+ result[key] = value;
94
+ }
95
+ } else if (!isEqual(value, oldValue)) {
96
+ result[key] = value;
97
+ }
98
+ },
99
+ {}
100
+ );
101
+ };
102
+ var generateCrcHash = (str) => {
103
+ if (isNil(str)) return crc32("-").toString(16);
104
+ if (isString(str)) return crc32(str).toString(16);
105
+ if (isBuffer(str)) return crc32(str).toString(16);
106
+ if (isArrayBuffer(str)) return crc32(str).toString(16);
107
+ if (isBoolean(str)) return crc32(str ? "true" : "false").toString(16);
108
+ if (isNumber(str)) return crc32(str.toString()).toString(16);
109
+ if (isArray(str) || isObject(str)) return generateCrcHash(JSON.stringify(str));
110
+ return crc32(str || "").toString(16);
111
+ };
112
+ var hasSameType = (sourceTarget, destinationTarget) => {
113
+ if (isArray(sourceTarget) && isArray(destinationTarget)) return true;
114
+ if (isArray(sourceTarget) !== isArray(destinationTarget)) return false;
115
+ if (isTypedArray(sourceTarget) && isTypedArray(destinationTarget)) {
116
+ if (Object.prototype.toString.call(sourceTarget) === Object.prototype.toString.call(destinationTarget))
117
+ return true;
118
+ else return false;
119
+ }
120
+ if (isTypedArray(sourceTarget) !== isTypedArray(destinationTarget)) return false;
121
+ if (isPlainObject(sourceTarget) && isPlainObject(destinationTarget)) return true;
122
+ if (isPlainObject(sourceTarget) !== isPlainObject(destinationTarget)) return false;
123
+ return typeof sourceTarget === typeof destinationTarget;
124
+ };
125
+ var updateArrayElementsBy = (data, objUpd, objSearch) => {
126
+ nativeFilter(data, objSearch).forEach((element) => nativeAssign(element, objUpd));
127
+ return data;
128
+ };
129
+ var updateArrayElementById = (data, objUpd, idField) => {
130
+ const index = data.findIndex((x) => x[idField] === objUpd[idField]);
131
+ if (index !== -1) data.splice(index, 1, objUpd);
132
+ };
133
+ var deleteArrayElementsBy = (data, objSearch) => {
134
+ nativeRemove(data, (x) => deepEqual(nativePick(x, Object.keys(objSearch)), objSearch));
135
+ return data;
136
+ };
137
+ function setDeepValue(obj, path, value) {
138
+ if (!obj || typeof obj !== "object") {
139
+ throw new TypeError("setDeepValue: target must be an object");
140
+ }
141
+ if (!path || typeof path !== "string") {
142
+ throw new TypeError("setDeepValue: path must be a non-empty string");
143
+ }
144
+ const keys = path.split(".");
145
+ let current = obj;
146
+ for (let i = 0; i < keys.length - 1; i++) {
147
+ const key = keys[i];
148
+ const nextKey = keys[i + 1];
149
+ const isNextArray = /^\d+$/.test(nextKey);
150
+ if (!(key in current) || typeof current[key] !== "object") {
151
+ current[key] = isNextArray ? [] : {};
152
+ }
153
+ current = current[key];
154
+ }
155
+ const lastKey = keys[keys.length - 1];
156
+ current[lastKey] = value;
157
+ return obj;
158
+ }
159
+ function getDeepValue(obj, path, defaultValue) {
160
+ if (!obj || typeof obj !== "object") {
161
+ return defaultValue;
162
+ }
163
+ if (!path || typeof path !== "string") {
164
+ return defaultValue;
165
+ }
166
+ const keys = path.split(".");
167
+ let current = obj;
168
+ for (const key of keys) {
169
+ if (current === null || current === void 0 || typeof current !== "object") {
170
+ return defaultValue;
171
+ }
172
+ if (!(key in current)) {
173
+ return defaultValue;
174
+ }
175
+ current = current[key];
176
+ }
177
+ return current !== void 0 ? current : defaultValue;
178
+ }
179
+
180
+ export {
181
+ comparator,
182
+ deepEqual,
183
+ formatToReadableString,
184
+ getShallowProperties,
185
+ calculateDifferences,
186
+ generateCrcHash,
187
+ hasSameType,
188
+ updateArrayElementsBy,
189
+ updateArrayElementById,
190
+ deleteArrayElementsBy,
191
+ setDeepValue,
192
+ getDeepValue,
193
+ objects_exports
194
+ };
195
+ //# sourceMappingURL=chunk-HTSEHRHI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/objects.ts"],"sourcesContent":["/**\n * Object manipulation and comparison utilities\n * Consolidated from primitives/object and array modules\n */\n\nimport crc32 from 'crc/crc32'\nimport * as lodash from 'lodash'\nconst {\n isArray,\n isArrayBuffer,\n isBoolean,\n isBuffer,\n isEqual,\n isNil,\n isNumber,\n isObject,\n isPlainObject,\n isString,\n isTypedArray,\n transform,\n} = lodash\nimport fastEqual from 'fast-deep-equal'\nimport { areDatesEqualWithTolerance, isDateTime, toDate } from './dates'\n\n// Native implementations to replace lodash functions\nconst nativeFilter = <T>(array: T[], predicate: Partial<T>): T[] => {\n return array.filter(item => {\n return Object.keys(predicate).every(key => item[key as keyof T] === predicate[key as keyof T])\n })\n}\n\nconst nativeAssign = <T extends object>(target: T, source: Partial<T>): T => {\n return Object.assign(target, source)\n}\n\nconst nativePick = <T extends object, K extends keyof T>(object: T, keys: K[]): Pick<T, K> => {\n const result = {} as Pick<T, K>\n keys.forEach(key => {\n if (key in object) {\n result[key] = object[key]\n }\n })\n return result\n}\n\nconst nativeRemove = <T>(array: T[], predicate: (item: T) => boolean): T[] => {\n const removed: T[] = []\n for (let i = array.length - 1; i >= 0; i--) {\n if (predicate(array[i])) {\n removed.unshift(array.splice(i, 1)[0])\n }\n }\n return removed\n}\n\n/**\n * Compares two objects utilizing lodash deep comparison\n * @deprecated Use `deepEqual` instead for consistency\n * @param data1 First object to compare\n * @param data2 Second object to compare\n * @returns True if objects are deeply equal, false otherwise\n */\nexport const comparator = (data1: any, data2: any) => isEqual(data1, data2)\n\n/**\n * Performs fast deep comparison between two values\n *\n * Compares values recursively including nested objects, arrays, dates, RegExp, and primitives.\n * Uses fast-deep-equal library for optimal performance (~5-10x faster than JSON.stringify).\n *\n * Comparison rules:\n * - Primitives: strict equality (===)\n * - Objects: recursive key-value comparison\n * - Arrays: length + element-by-element comparison\n * - Dates: compares timestamps\n * - RegExp: compares source and flags\n * - null/undefined: strict equality\n *\n * Use cases: Testing, change detection, cache invalidation, data validation\n *\n * @param data1 - First value to compare (any type)\n * @param data2 - Second value to compare (any type)\n * @returns True if values are deeply equal, false otherwise\n *\n * @example\n * ```typescript\n * // Primitive values\n * deepEqual(42, 42) // true\n * deepEqual('hello', 'hello') // true\n * deepEqual(null, null) // true\n * deepEqual(42, '42') // false (different types)\n *\n * // Objects\n * deepEqual({ a: 1, b: 2 }, { a: 1, b: 2 }) // true\n * deepEqual({ a: 1, b: 2 }, { b: 2, a: 1 }) // true (order doesn't matter)\n * deepEqual({ a: 1 }, { a: 1, b: undefined }) // false\n *\n * // Arrays\n * deepEqual([1, 2, 3], [1, 2, 3]) // true\n * deepEqual([1, 2, 3], [3, 2, 1]) // false (order matters)\n *\n * // Nested structures\n * deepEqual(\n * { user: { name: 'Alice', tags: ['admin'] } },\n * { user: { name: 'Alice', tags: ['admin'] } }\n * ) // true\n *\n * // Dates\n * deepEqual(new Date('2024-01-01'), new Date('2024-01-01')) // true\n * deepEqual(new Date('2024-01-01'), new Date('2024-01-02')) // false\n *\n * // RegExp\n * deepEqual(/test/gi, /test/gi) // true\n * deepEqual(/test/g, /test/i) // false\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Detect if form data changed\n * const originalData = {\n * name: 'John Doe',\n * email: 'john@example.com',\n * preferences: { theme: 'dark', notifications: true }\n * }\n *\n * const currentData = {\n * name: 'John Doe',\n * email: 'john.doe@example.com', // Changed!\n * preferences: { theme: 'dark', notifications: true }\n * }\n *\n * const hasChanges = !deepEqual(originalData, currentData)\n * if (hasChanges) {\n * console.log('⚠️ You have unsaved changes')\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Cache invalidation\n * const cache = new Map<string, { params: any; result: any }>()\n *\n * function cachedApiCall(params: any) {\n * const cacheKey = 'api-call'\n * const cached = cache.get(cacheKey)\n *\n * // Check if cached params match current params\n * if (cached && deepEqual(cached.params, params)) {\n * console.log('✅ Cache hit')\n * return cached.result\n * }\n *\n * console.log('❌ Cache miss - fetching')\n * const result = fetchData(params)\n * cache.set(cacheKey, { params, result })\n * return result\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: React shouldComponentUpdate optimization\n * class UserProfile extends React.Component {\n * shouldComponentUpdate(nextProps: any) {\n * // Only re-render if props actually changed\n * return !deepEqual(this.props, nextProps)\n * }\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Testing\n * import { deepEqual } from '@g10/ts-helpers'\n *\n * test('API returns expected user structure', async () => {\n * const response = await api.getUser(123)\n *\n * const expected = {\n * id: 123,\n * name: 'Alice',\n * roles: ['user', 'admin'],\n * metadata: { lastLogin: expect.any(Date) }\n * }\n *\n * // Deep comparison ignoring date instance\n * expect(deepEqual(\n * { ...response, metadata: { ...response.metadata, lastLogin: null } },\n * { ...expected, metadata: { ...expected.metadata, lastLogin: null } }\n * )).toBe(true)\n * })\n * ```\n *\n * @see {@link calculateDifferences} for finding specific differences between objects\n * @see {@link comparator} for lodash-based comparison (deprecated)\n * @see {@link https://github.com/epoberezkin/fast-deep-equal fast-deep-equal library}\n */\nexport const deepEqual = (data1: any, data2: any) => fastEqual(data1, data2)\n\n/**\n * Converts an object to a human-readable string representation\n *\n * Transforms JSON object to clean, readable text by removing braces, quotes, and\n * adding spacing. Useful for logging, debugging, UI displays, and error messages.\n *\n * Transformation:\n * 1. Stringify object to JSON\n * 2. Remove braces `{}` and quotes `\"`\n * 3. Replace commas with comma+space for readability\n *\n * @param data - Object to format (must be JSON-serializable)\n * @returns Human-readable string representation\n *\n * @example\n * ```typescript\n * // Simple object\n * formatToReadableString({ name: 'Alice', age: 25 })\n * // 'name: Alice, age: 25'\n *\n * // Multiple properties\n * formatToReadableString({ id: 1, status: 'active', verified: true })\n * // 'id: 1, status: active, verified: true'\n *\n * // Nested objects (flattened)\n * formatToReadableString({ user: { name: 'Bob' }, role: 'admin' })\n * // 'user: name: Bob, role: admin'\n *\n * // Empty object\n * formatToReadableString({})\n * // ''\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Log request parameters\n * function logApiRequest(endpoint: string, params: any) {\n * const paramsStr = formatToReadableString(params)\n * console.log(`API Request: ${endpoint} | Params: ${paramsStr}`)\n * }\n *\n * logApiRequest('/users', { page: 1, limit: 20, role: 'admin' })\n * // API Request: /users | Params: page: 1, limit: 20, role: admin\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Display validation errors\n * const errors = { email: 'Invalid format', password: 'Too short' }\n * const message = `Validation failed: ${formatToReadableString(errors)}`\n * console.log(message)\n * // Validation failed: email: Invalid format, password: Too short\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Format metadata for display\n * const metadata = {\n * author: 'John Doe',\n * created: '2024-01-01',\n * tags: ['javascript', 'typescript']\n * }\n *\n * const metadataDisplay = formatToReadableString(metadata)\n * // 'author: John Doe, created: 2024-01-01, tags: javascript, typescript'\n * ```\n *\n * @see {@link JSON.stringify} for full JSON serialization\n */\nexport const formatToReadableString = (data: { [key: string]: any }): string =>\n JSON.stringify(data).replace(/[{}\"]/g, '').replace(/,/g, ', ')\n\n/**\n * Extracts only top-level primitive properties from an object\n *\n * Filters out nested objects, arrays, and functions, returning only primitive values\n * (string, number, boolean, null, undefined, symbol). Useful for serialization,\n * API payloads, and database operations.\n *\n * Included types: string, number, boolean, null, undefined, symbol\n * Excluded types: object, array, function\n *\n * @param obj - Object from which to extract properties (null/undefined returns {})\n * @returns New object containing only primitive top-level properties\n *\n * @example\n * ```typescript\n * // Mixed types object\n * const user = {\n * id: 123,\n * name: 'Alice',\n * email: 'alice@example.com',\n * age: 25,\n * active: true,\n * metadata: { lastLogin: '2024-01-01' }, // Excluded (object)\n * roles: ['admin', 'user'], // Excluded (array)\n * save: () => {} // Excluded (function)\n * }\n *\n * getShallowProperties(user)\n * // { id: 123, name: 'Alice', email: 'alice@example.com', age: 25, active: true }\n *\n * // Only primitives\n * const config = { host: 'localhost', port: 5432, ssl: false }\n * getShallowProperties(config)\n * // { host: 'localhost', port: 5432, ssl: false } (unchanged)\n *\n * // Null/undefined values preserved\n * const partial = { a: 1, b: null, c: undefined, d: { nested: true } }\n * getShallowProperties(partial)\n * // { a: 1, b: null, c: undefined }\n *\n * // Empty/null input\n * getShallowProperties({}) // {}\n * getShallowProperties(null) // {}\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Prepare data for SQL insert (exclude nested objects)\n * const formData = {\n * firstName: 'John',\n * lastName: 'Doe',\n * email: 'john@example.com',\n * age: 30,\n * address: { street: '123 Main St', city: 'NYC' }, // Excluded\n * preferences: { theme: 'dark' } // Excluded\n * }\n *\n * const insertData = getShallowProperties(formData)\n * // { firstName: 'John', lastName: 'Doe', email: 'john@example.com', age: 30 }\n *\n * // Now safe to insert into flat database table\n * await db.insert('users', insertData)\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Extract searchable fields for indexing\n * const product = {\n * sku: 'ABC123',\n * name: 'Widget',\n * price: 29.99,\n * inStock: true,\n * category: { id: 1, name: 'Electronics' }, // Excluded\n * reviews: [{ rating: 5 }], // Excluded\n * images: ['img1.jpg', 'img2.jpg'] // Excluded\n * }\n *\n * const searchableFields = getShallowProperties(product)\n * // { sku: 'ABC123', name: 'Widget', price: 29.99, inStock: true }\n *\n * // Index only primitive fields for search\n * searchIndex.add(product.sku, searchableFields)\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Extract flat properties for CSV export\n * const users = [\n * {\n * id: 1,\n * name: 'Alice',\n * email: 'alice@example.com',\n * profile: { bio: 'Developer' },\n * tags: ['admin']\n * },\n * {\n * id: 2,\n * name: 'Bob',\n * email: 'bob@example.com',\n * profile: { bio: 'Designer' },\n * tags: ['user']\n * }\n * ]\n *\n * const csvData = users.map(getShallowProperties)\n * // [\n * // { id: 1, name: 'Alice', email: 'alice@example.com' },\n * // { id: 2, name: 'Bob', email: 'bob@example.com' }\n * // ]\n * // Now safe to convert to CSV\n * ```\n *\n * @see {@link calculateDifferences} for comparing objects\n * @see {@link deepEqual} for deep comparison including nested objects\n */\nexport const getShallowProperties = (obj: any): any => {\n if (!obj) return {}\n const topLevelProps: any = {}\n for (const prop in obj) {\n if (Object.hasOwnProperty.call(obj, prop)) {\n const value = obj[prop]\n const type = typeof value\n // Include primitives: string, number, boolean, undefined, symbol, and null\n if ((type !== 'object' && type !== 'function') || value === null) {\n topLevelProps[prop] = value\n }\n }\n }\n return topLevelProps\n}\n\n/**\n * Calculates differences between two objects\n *\n * Compares two objects and returns only the properties that differ. Useful for\n * change tracking, audit logs, delta updates, and optimistic UI updates.\n *\n * Special features:\n * - Date comparison: Compares dates ignoring milliseconds (tolerance-based)\n * - Shallow comparison: Only checks top-level properties\n * - One-way diff: Returns changed properties from newObj (not deletions)\n *\n * @param oldObj - Original object to compare against (baseline)\n * @param newObj - New object to compare (current state)\n * @returns Object containing only properties that changed in newObj\n *\n * @example\n * ```typescript\n * // Simple property changes\n * const old = { name: 'Alice', age: 25, city: 'NYC' }\n * const updated = { name: 'Alice', age: 26, city: 'NYC' }\n *\n * calculateDifferences(old, updated)\n * // { age: 26 } - only changed property\n *\n * // Multiple changes\n * const old2 = { a: 1, b: 2, c: 3 }\n * const new2 = { a: 1, b: 999, c: 3 }\n * calculateDifferences(old2, new2)\n * // { b: 999 }\n *\n * // No changes\n * const old3 = { x: 10 }\n * const new3 = { x: 10 }\n * calculateDifferences(old3, new3)\n * // {} - empty object\n *\n * // Date comparison (ignores milliseconds)\n * const oldDate = { timestamp: new Date('2024-01-01T10:00:00.123Z') }\n * const newDate = { timestamp: new Date('2024-01-01T10:00:00.456Z') }\n * calculateDifferences(oldDate, newDate)\n * // {} - dates considered equal (same second)\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Track form changes for audit log\n * const originalUser = {\n * name: 'John Doe',\n * email: 'john@example.com',\n * role: 'user',\n * lastLogin: new Date('2024-01-01')\n * }\n *\n * const updatedUser = {\n * name: 'John Doe',\n * email: 'john.doe@company.com', // Changed\n * role: 'admin', // Changed\n * lastLogin: new Date('2024-01-01')\n * }\n *\n * const changes = calculateDifferences(originalUser, updatedUser)\n * console.log('User changes:', changes)\n * // { email: 'john.doe@company.com', role: 'admin' }\n *\n * // Save to audit log\n * auditLog.push({\n * userId: user.id,\n * timestamp: new Date(),\n * changes: changes\n * })\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Optimistic UI updates (send only changed fields)\n * function updateUserProfile(userId: string, formData: any) {\n * const originalData = getCurrentUserData(userId)\n *\n * // Only send changed fields to API\n * const delta = calculateDifferences(originalData, formData)\n *\n * if (Object.keys(delta).length === 0) {\n * console.log('✅ No changes to save')\n * return\n * }\n *\n * // Send PATCH request with only changed fields\n * return api.patch(`/users/${userId}`, delta)\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Configuration change detection\n * const previousConfig = {\n * database: { host: 'localhost', port: 5432 },\n * cache: { ttl: 3600 },\n * features: { darkMode: true }\n * }\n *\n * const newConfig = {\n * database: { host: 'prod-db.example.com', port: 5432 },\n * cache: { ttl: 7200 },\n * features: { darkMode: true }\n * }\n *\n * const configChanges = calculateDifferences(previousConfig, newConfig)\n * // {\n * // database: { host: 'prod-db.example.com', port: 5432 },\n * // cache: { ttl: 7200 }\n * // }\n *\n * // Note: Returns entire nested object if any property changed\n * if (configChanges.database) {\n * console.log('⚠️ Database configuration changed - restart required')\n * }\n * ```\n *\n * @see {@link deepEqual} for full equality check\n * @see {@link getShallowProperties} for extracting only primitive properties\n */\nexport const calculateDifferences = (oldObj: any, newObj: any): any => {\n return transform(\n newObj,\n (result, value, key) => {\n const oldValue = oldObj[key]\n // If both values are dates, compare them ignoring milliseconds\n if (isDateTime(value) && isDateTime(oldValue)) {\n if (!areDatesEqualWithTolerance(toDate(value), toDate(oldValue))) {\n result[key] = value\n }\n } else if (!isEqual(value, oldValue)) {\n result[key] = value\n }\n },\n {}\n )\n}\n\n/**\n * Generates CRC32 hash from various input types\n *\n * Creates a 32-bit cyclic redundancy check (CRC32) hash as hexadecimal string.\n * Fast, deterministic fingerprinting for data integrity, caching, and change detection.\n *\n * Supported types:\n * - String: Direct hash\n * - Buffer/Uint8Array/ArrayBuffer: Binary hash\n * - Number: Converts to string then hash\n * - Boolean: 'true'/'false' then hash\n * - Object/Array: JSON.stringify then hash\n * - null/undefined: Hash of '-'\n *\n * Use cases: Content fingerprinting, ETags, cache keys, data deduplication\n *\n * ⚠️ NOTE: CRC32 is NOT cryptographically secure. Use for checksums, not security.\n *\n * @param str - Input data of any type (string, Buffer, object, array, primitive)\n * @returns CRC32 hash as hexadecimal string (8 characters)\n *\n * @example\n * ```typescript\n * // String inputs\n * generateCrcHash('hello') // '3610a686'\n * generateCrcHash('Hello') // 'f7d18982' (case-sensitive)\n * generateCrcHash('') // '0'\n *\n * // Numbers\n * generateCrcHash(123) // '884863d2' (hashes '123')\n * generateCrcHash(0) // 'f4dbdf21'\n *\n * // Booleans\n * generateCrcHash(true) // 'cc2c5c10' (hashes 'true')\n * generateCrcHash(false) // 'cc0c5c10' (hashes 'false')\n *\n * // Objects (deterministic)\n * generateCrcHash({ a: 1, b: 2 }) // Same hash for same object\n * generateCrcHash({ b: 2, a: 1 }) // Different hash (key order matters)\n *\n * // Arrays\n * generateCrcHash([1, 2, 3]) // Consistent hash\n *\n * // null/undefined\n * generateCrcHash(null) // '4e08bfb4' (hashes '-')\n * generateCrcHash(undefined) // '4e08bfb4' (hashes '-')\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Generate ETag for HTTP caching\n * function generateETag(content: string): string {\n * const hash = generateCrcHash(content)\n * return `\"${hash}\"`\n * }\n *\n * const html = '<html><body>Hello World</body></html>'\n * const etag = generateETag(html)\n * // \"a3c2f1b8\"\n *\n * // Client sends: If-None-Match: \"a3c2f1b8\"\n * // Server compares ETags, returns 304 Not Modified if match\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Content-based cache key\n * const cache = new Map<string, any>()\n *\n * function cacheApiResponse(params: any, response: any) {\n * const cacheKey = generateCrcHash(JSON.stringify(params))\n * cache.set(cacheKey, response)\n * }\n *\n * function getCachedResponse(params: any) {\n * const cacheKey = generateCrcHash(JSON.stringify(params))\n * return cache.get(cacheKey)\n * }\n *\n * // Same params = same hash = cache hit\n * cacheApiResponse({ userId: 123, page: 1 }, { data: [...] })\n * const cached = getCachedResponse({ userId: 123, page: 1 })\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Detect duplicate content\n * const seen = new Set<string>()\n *\n * function isDuplicate(content: string): boolean {\n * const hash = generateCrcHash(content)\n * if (seen.has(hash)) {\n * return true\n * }\n * seen.add(hash)\n * return false\n * }\n *\n * isDuplicate('Hello') // false (first time)\n * isDuplicate('World') // false\n * isDuplicate('Hello') // true (duplicate!)\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: File versioning/fingerprinting\n * const fileContents = [\n * { path: 'app.js', content: 'console.log(\"v1\")' },\n * { path: 'style.css', content: 'body { color: red; }' }\n * ]\n *\n * const manifest = fileContents.map(file => ({\n * path: file.path,\n * hash: generateCrcHash(file.content),\n * url: `${file.path}?v=${generateCrcHash(file.content)}`\n * }))\n *\n * // [\n * // { path: 'app.js', hash: 'a3c2f1b8', url: 'app.js?v=a3c2f1b8' },\n * // { path: 'style.css', hash: 'b4d3e2c1', url: 'style.css?v=b4d3e2c1' }\n * // ]\n * // Cache-busting URLs change only when content changes\n * ```\n *\n * @see {@link deepEqual} for comparing objects for equality\n * @see {@link https://en.wikipedia.org/wiki/Cyclic_redundancy_check CRC32 Algorithm}\n */\nexport const generateCrcHash = (str: string | Buffer | Uint8Array | any): string => {\n if (isNil(str)) return crc32('-').toString(16)\n if (isString(str)) return crc32(str).toString(16)\n if (isBuffer(str)) return crc32(str).toString(16)\n if (isArrayBuffer(str)) return crc32(str).toString(16)\n if (isBoolean(str)) return crc32(str ? 'true' : 'false').toString(16)\n if (isNumber(str)) return crc32(str.toString()).toString(16)\n if (isArray(str) || isObject(str)) return generateCrcHash(JSON.stringify(str))\n return crc32(str || '').toString(16)\n}\n\n/**\n * Verifies if two variables have the same type\n *\n * Performs strict type comparison with special handling for arrays, typed arrays,\n * plain objects, and primitives. Uses runtime type checking for accurate validation.\n *\n * Type detection hierarchy:\n * 1. Arrays: Standard Array.isArray() check\n * 2. Typed Arrays: Int8Array, Uint8Array, Float32Array, etc. (checks exact typed array class)\n * 3. Plain Objects: Object literals (not class instances or built-in objects)\n * 4. Primitives: typeof comparison (string, number, boolean, undefined, symbol)\n *\n * Special features:\n * - Differentiates between arrays and typed arrays\n * - Typed array class matching (Int8Array ≠ Uint8Array)\n * - Plain object vs class instance detection\n * - null/undefined handling\n *\n * @param sourceTarget - First value to check type\n * @param destinationTarget - Second value to check type\n * @returns True if both values have the same type, false otherwise\n *\n * @example\n * ```typescript\n * // Basic types - Primitives\n * hasSameType('hello', 'world') // true (both string)\n * hasSameType(42, 100) // true (both number)\n * hasSameType(true, false) // true (both boolean)\n * hasSameType('hello', 42) // false (string vs number)\n * hasSameType(null, undefined) // false (different types)\n * ```\n *\n * @example\n * ```typescript\n * // Arrays and objects\n * hasSameType([1, 2, 3], [4, 5]) // true (both arrays)\n * hasSameType({ a: 1 }, { b: 2 }) // true (both plain objects)\n * hasSameType([1, 2], { a: 1 }) // false (array vs object)\n * hasSameType([], {}) // false (array vs object)\n * ```\n *\n * @example\n * ```typescript\n * // Typed arrays - Strict class matching\n * const int8 = new Int8Array([1, 2, 3])\n * const int8_2 = new Int8Array([4, 5])\n * const uint8 = new Uint8Array([1, 2, 3])\n * const float32 = new Float32Array([1.5, 2.5])\n *\n * hasSameType(int8, int8_2) // true (both Int8Array)\n * hasSameType(int8, uint8) // false (Int8Array vs Uint8Array)\n * hasSameType(uint8, float32) // false (Uint8Array vs Float32Array)\n * hasSameType(int8, [1, 2, 3]) // false (typed array vs regular array)\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Type-safe data merging\n * function safeMerge<T>(source: T, updates: any): T | null {\n * if (!hasSameType(source, updates)) {\n * console.error('❌ Type mismatch: cannot merge incompatible types')\n * return null\n * }\n *\n * if (Array.isArray(source)) {\n * return [...source, ...updates] as T\n * }\n *\n * if (typeof source === 'object' && source !== null) {\n * return { ...source, ...updates }\n * }\n *\n * return updates // Replace primitive values\n * }\n *\n * // Valid merges\n * const user = { name: 'John', age: 30 }\n * const updated = safeMerge(user, { age: 31, city: 'NYC' })\n * // { name: 'John', age: 31, city: 'NYC' }\n *\n * // Type mismatch prevented\n * const invalid = safeMerge(user, [1, 2, 3])\n * // null (with error logged)\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: API response validation\n * function validateResponseShape(expected: any, actual: any): boolean {\n * // Check if response has the same structure\n * if (!hasSameType(expected, actual)) {\n * console.error('Invalid response type:', {\n * expected: typeof expected,\n * actual: typeof actual\n * })\n * return false\n * }\n *\n * // Additional validation for objects/arrays\n * if (typeof expected === 'object' && expected !== null) {\n * for (const key of Object.keys(expected)) {\n * if (!hasSameType(expected[key], actual[key])) {\n * console.error(`Type mismatch at key \"${key}\"`)\n * return false\n * }\n * }\n * }\n *\n * return true\n * }\n *\n * const expectedUser = {\n * id: 0,\n * name: '',\n * active: false,\n * tags: [] as string[]\n * }\n *\n * const validResponse = {\n * id: 123,\n * name: 'Alice',\n * active: true,\n * tags: ['admin', 'verified']\n * }\n *\n * validateResponseShape(expectedUser, validResponse) // true\n *\n * const invalidResponse = {\n * id: '123', // ❌ string instead of number\n * name: 'Alice',\n * active: true,\n * tags: ['admin']\n * }\n *\n * validateResponseShape(expectedUser, invalidResponse) // false\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Buffer/TypedArray validation before processing\n * function processImageBuffer(buffer: Uint8Array | Uint8ClampedArray): void {\n * const validBufferTypes = [\n * new Uint8Array(0),\n * new Uint8ClampedArray(0)\n * ]\n *\n * const isValidType = validBufferTypes.some(validType =>\n * hasSameType(buffer, validType)\n * )\n *\n * if (!isValidType) {\n * throw new TypeError('Expected Uint8Array or Uint8ClampedArray for image data')\n * }\n *\n * // Safe to process buffer\n * console.log(`Processing ${buffer.length} bytes of image data`)\n * }\n *\n * // Valid buffers\n * const imageData = new Uint8ClampedArray([255, 0, 0, 255]) // RGBA pixel\n * processImageBuffer(imageData) // ✅ Works\n *\n * // Invalid buffer type\n * const float32Buffer = new Float32Array([1.0, 0.5])\n * processImageBuffer(float32Buffer) // ❌ TypeError\n * ```\n *\n * @example\n * ```typescript\n * // Edge cases\n * hasSameType(null, null) // true (both null)\n * hasSameType(undefined, undefined) // true (both undefined)\n * hasSameType(null, undefined) // false (different types)\n * hasSameType(NaN, NaN) // true (both number)\n * hasSameType(Infinity, -Infinity) // true (both number)\n *\n * // Class instances vs plain objects\n * class User { name = 'John' }\n * const userInstance = new User()\n * const plainUser = { name: 'John' }\n * hasSameType(userInstance, plainUser) // false (class instance vs plain object)\n *\n * // Functions\n * const fn1 = () => {}\n * const fn2 = function() {}\n * hasSameType(fn1, fn2) // true (both functions)\n * ```\n *\n * @see {@link deepEqual} for value comparison (not just type)\n * @see {@link isArray} for array checking\n * @see {@link isPlainObject} for plain object detection\n */\nexport const hasSameType = (sourceTarget: any, destinationTarget: any) => {\n if (isArray(sourceTarget) && isArray(destinationTarget)) return true\n if (isArray(sourceTarget) !== isArray(destinationTarget)) return false\n if (isTypedArray(sourceTarget) && isTypedArray(destinationTarget)) {\n if (\n Object.prototype.toString.call(sourceTarget) ===\n Object.prototype.toString.call(destinationTarget)\n )\n return true\n else return false\n }\n if (isTypedArray(sourceTarget) !== isTypedArray(destinationTarget)) return false\n if (isPlainObject(sourceTarget) && isPlainObject(destinationTarget)) return true\n\n // Check if one is object and the other is not\n if (isPlainObject(sourceTarget) !== isPlainObject(destinationTarget)) return false\n\n return typeof sourceTarget === typeof destinationTarget\n}\n\n/**\n * Updates array elements that match search criteria\n *\n * Finds all elements matching the search criteria and merges update object into them.\n * Mutates the original array. Useful for batch updates on filtered data.\n *\n * Algorithm:\n * 1. Filter array to find elements matching objSearch\n * 2. For each match, merge objUpd properties using Object.assign\n * 3. Return the mutated array\n *\n * @param data - Array to update (will be mutated)\n * @param objUpd - Object with properties to merge into matching elements\n * @param objSearch - Object with search criteria (all properties must match)\n * @returns The mutated array with updated elements\n *\n * @example\n * ```typescript\n * // Update all users with role 'user' to 'member'\n * const users = [\n * { id: 1, name: 'Alice', role: 'user', active: true },\n * { id: 2, name: 'Bob', role: 'admin', active: true },\n * { id: 3, name: 'Charlie', role: 'user', active: false }\n * ]\n *\n * updateArrayElementsBy(users, { role: 'member' }, { role: 'user' })\n * // users is now:\n * // [\n * // { id: 1, name: 'Alice', role: 'member', active: true },\n * // { id: 2, name: 'Bob', role: 'admin', active: true },\n * // { id: 3, name: 'Charlie', role: 'member', active: false }\n * // ]\n *\n * // Update multiple properties\n * const products = [\n * { sku: 'A1', status: 'draft', published: false },\n * { sku: 'A2', status: 'draft', published: false },\n * { sku: 'B1', status: 'active', published: true }\n * ]\n *\n * updateArrayElementsBy(\n * products,\n * { status: 'active', published: true },\n * { status: 'draft' }\n * )\n * // All draft products now active and published\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Bulk activate pending users\n * const pendingUsers = [\n * { email: 'user1@example.com', status: 'pending', verified: false },\n * { email: 'user2@example.com', status: 'pending', verified: false },\n * { email: 'user3@example.com', status: 'active', verified: true }\n * ]\n *\n * // Activate all pending users\n * updateArrayElementsBy(\n * pendingUsers,\n * { status: 'active', verified: true, activatedAt: new Date() },\n * { status: 'pending' }\n * )\n *\n * console.log(pendingUsers.filter(u => u.status === 'active').length)\n * // 3 (all users now active)\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Mark completed tasks as archived\n * const tasks = [\n * { id: 1, title: 'Task 1', completed: true, archived: false },\n * { id: 2, title: 'Task 2', completed: false, archived: false },\n * { id: 3, title: 'Task 3', completed: true, archived: false }\n * ]\n *\n * updateArrayElementsBy(\n * tasks,\n * { archived: true, archivedAt: new Date() },\n * { completed: true }\n * )\n *\n * const archivedCount = tasks.filter(t => t.archived).length\n * console.log(`Archived ${archivedCount} completed tasks`)\n * ```\n *\n * @see {@link updateArrayElementById} for updating single element by ID\n * @see {@link deleteArrayElementsBy} for deleting elements by criteria\n */\nexport const updateArrayElementsBy = (data: any[], objUpd: any, objSearch: any) => {\n nativeFilter(data, objSearch).forEach(element => nativeAssign(element, objUpd))\n return data\n}\n\n/**\n * Updates a single array element by its ID field\n *\n * Finds element by matching ID field value and replaces entire element with new object.\n * Mutates the original array. Use for updating single records by primary key.\n *\n * Algorithm:\n * 1. Find index of element where element[idField] === objUpd[idField]\n * 2. If found, replace entire element with objUpd\n * 3. If not found, array remains unchanged\n *\n * @param data - Array to update (will be mutated)\n * @param objUpd - New object to replace the found element (must contain idField)\n * @param idField - Name of field to use as identifier (default: 'id')\n * @returns void (modifies array in-place)\n *\n * @example\n * ```typescript\n * // Update user by ID\n * const users = [\n * { id: 1, name: 'Alice', email: 'alice@example.com' },\n * { id: 2, name: 'Bob', email: 'bob@example.com' },\n * { id: 3, name: 'Charlie', email: 'charlie@example.com' }\n * ]\n *\n * updateArrayElementById(\n * users,\n * { id: 2, name: 'Robert', email: 'robert@example.com', verified: true },\n * 'id'\n * )\n * // users[1] is now: { id: 2, name: 'Robert', email: 'robert@example.com', verified: true }\n *\n * // ID not found - no change\n * updateArrayElementById(users, { id: 999, name: 'Unknown' }, 'id')\n * // users array unchanged\n *\n * // Custom ID field\n * const products = [\n * { sku: 'ABC123', name: 'Widget', price: 10 },\n * { sku: 'DEF456', name: 'Gadget', price: 20 }\n * ]\n *\n * updateArrayElementById(\n * products,\n * { sku: 'ABC123', name: 'Super Widget', price: 15 },\n * 'sku'\n * )\n * // products[0] is now: { sku: 'ABC123', name: 'Super Widget', price: 15 }\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Update cached user after API response\n * const userCache = [\n * { id: 1, name: 'Alice', role: 'user' },\n * { id: 2, name: 'Bob', role: 'admin' },\n * ]\n *\n * async function updateUser(userId: number, updates: any) {\n * // API call\n * const response = await api.patch(`/users/${userId}`, updates)\n *\n * // Update local cache with full response\n * updateArrayElementById(userCache, response.data, 'id')\n *\n * console.log('✅ Cache updated')\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Replace product in shopping cart\n * const cart = [\n * { productId: 'P1', name: 'Laptop', qty: 1, price: 1000 },\n * { productId: 'P2', name: 'Mouse', qty: 2, price: 25 }\n * ]\n *\n * function updateCartItem(updatedItem: any) {\n * updateArrayElementById(cart, updatedItem, 'productId')\n * recalculateTotal()\n * }\n *\n * // User changes laptop quantity\n * updateCartItem({ productId: 'P1', name: 'Laptop', qty: 2, price: 1000 })\n * ```\n *\n * @see {@link updateArrayElementsBy} for updating multiple elements by criteria\n * @see {@link deleteArrayElementsBy} for deleting elements\n */\nexport const updateArrayElementById = (data: any[], objUpd: any, idField: string) => {\n const index = data.findIndex(x => x[idField] === objUpd[idField])\n if (index !== -1) data.splice(index, 1, objUpd)\n}\n\n/**\n * Removes array elements that match search criteria\n *\n * Filters out elements matching all properties in the search object.\n * Mutates the original array. Useful for batch deletions based on criteria.\n *\n * Algorithm:\n * 1. Pick properties from each element matching objSearch keys\n * 2. Deep compare picked properties with objSearch\n * 3. Remove element if all properties match\n * 4. Return the mutated array\n *\n * @param data - Array to modify (will be mutated)\n * @param objSearch - Object with search criteria (all properties must match for deletion)\n * @returns The mutated array with matching elements removed\n *\n * @example\n * ```typescript\n * // Delete users with role 'guest'\n * const users = [\n * { id: 1, name: 'Alice', role: 'admin' },\n * { id: 2, name: 'Bob', role: 'guest' },\n * { id: 3, name: 'Charlie', role: 'guest' },\n * { id: 4, name: 'Dave', role: 'user' }\n * ]\n *\n * deleteArrayElementsBy(users, { role: 'guest' })\n * // users is now: [\n * // { id: 1, name: 'Alice', role: 'admin' },\n * // { id: 4, name: 'Dave', role: 'user' }\n * // ]\n *\n * // Multiple criteria (AND condition)\n * const tasks = [\n * { id: 1, status: 'done', archived: true },\n * { id: 2, status: 'done', archived: false },\n * { id: 3, status: 'pending', archived: false }\n * ]\n *\n * deleteArrayElementsBy(tasks, { status: 'done', archived: true })\n * // Removes only tasks that are BOTH done AND archived\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Clean up expired sessions\n * const sessions = [\n * { sessionId: 'abc', userId: 1, expired: false },\n * { sessionId: 'def', userId: 2, expired: true },\n * { sessionId: 'ghi', userId: 3, expired: true },\n * { sessionId: 'jkl', userId: 4, expired: false }\n * ]\n *\n * // Remove all expired sessions\n * deleteArrayElementsBy(sessions, { expired: true })\n *\n * console.log(`Active sessions: ${sessions.length}`)\n * // Active sessions: 2\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Remove cancelled orders from pending list\n * const orders = [\n * { orderId: 'O1', status: 'pending', cancelled: false },\n * { orderId: 'O2', status: 'pending', cancelled: true },\n * { orderId: 'O3', status: 'shipped', cancelled: false },\n * { orderId: 'O4', status: 'pending', cancelled: true }\n * ]\n *\n * // Clean up cancelled pending orders\n * deleteArrayElementsBy(orders, { status: 'pending', cancelled: true })\n *\n * // orders now only has valid pending and shipped orders\n * console.log(orders.length) // 2\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Clear failed upload queue\n * const uploadQueue = [\n * { fileId: 'F1', status: 'uploading', retries: 0 },\n * { fileId: 'F2', status: 'failed', retries: 3 },\n * { fileId: 'F3', status: 'failed', retries: 3 },\n * { fileId: 'F4', status: 'completed', retries: 0 }\n * ]\n *\n * // Remove permanently failed uploads (max retries reached)\n * deleteArrayElementsBy(uploadQueue, { status: 'failed', retries: 3 })\n *\n * console.log(`Remaining in queue: ${uploadQueue.length}`)\n * // Remaining in queue: 2 (uploading + completed)\n * ```\n *\n * @see {@link updateArrayElementsBy} for updating elements by criteria\n * @see {@link updateArrayElementById} for updating single element by ID\n */\nexport const deleteArrayElementsBy = (data: any[], objSearch: any) => {\n nativeRemove(data, x => deepEqual(nativePick(x, Object.keys(objSearch) as any), objSearch))\n return data\n}\n\n/**\n * Sets a value at a deep path in an object using dot notation\n *\n * Creates intermediate objects/arrays as needed. Supports nested paths\n * and array indices. Mutates the original object.\n *\n * @param obj - Object to modify (will be mutated)\n * @param path - Dot-notation path (e.g., 'database.connection.timeout')\n * @param value - Value to set at the path\n * @returns The modified object (same reference as input)\n *\n * @example\n * ```typescript\n * // Simple nested path\n * const config = {}\n * setDeepValue(config, 'database.host', 'localhost')\n * // config = { database: { host: 'localhost' } }\n *\n * // Multi-level nesting\n * const obj = {}\n * setDeepValue(obj, 'app.server.port', 3000)\n * // obj = { app: { server: { port: 3000 } } }\n *\n * // Array indices\n * const data = { users: [] }\n * setDeepValue(data, 'users.0.name', 'Alice')\n * // data = { users: [{ name: 'Alice' }] }\n *\n * // Overwriting existing values\n * const settings = { database: { host: 'old' } }\n * setDeepValue(settings, 'database.host', 'new')\n * // settings = { database: { host: 'new' } }\n *\n * // Complex paths\n * const complex = {}\n * setDeepValue(complex, 'features.authentication.oauth.providers.0', 'google')\n * // complex = { features: { authentication: { oauth: { providers: ['google'] } } } }\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Dynamic configuration\n * const config = {}\n * const envVars = {\n * 'DATABASE_HOST': 'localhost',\n * 'DATABASE_PORT': '5432',\n * 'CACHE_TTL': '3600'\n * }\n *\n * // Convert flat env vars to nested config\n * setDeepValue(config, 'database.host', envVars.DATABASE_HOST)\n * setDeepValue(config, 'database.port', parseInt(envVars.DATABASE_PORT))\n * setDeepValue(config, 'cache.ttl', parseInt(envVars.CACHE_TTL))\n * // config = {\n * // database: { host: 'localhost', port: 5432 },\n * // cache: { ttl: 3600 }\n * // }\n * ```\n */\nexport function setDeepValue<T = any>(obj: T, path: string, value: any): T {\n if (!obj || typeof obj !== 'object') {\n throw new TypeError('setDeepValue: target must be an object')\n }\n\n if (!path || typeof path !== 'string') {\n throw new TypeError('setDeepValue: path must be a non-empty string')\n }\n\n const keys = path.split('.')\n let current: any = obj\n\n for (let i = 0; i < keys.length - 1; i++) {\n const key = keys[i]\n const nextKey = keys[i + 1]\n\n // Determine if next level should be an array or object\n const isNextArray = /^\\d+$/.test(nextKey)\n\n // Create intermediate level if it doesn't exist\n if (!(key in current) || typeof current[key] !== 'object') {\n current[key] = isNextArray ? [] : {}\n }\n\n current = current[key]\n }\n\n // Set the final value\n const lastKey = keys[keys.length - 1]\n current[lastKey] = value\n\n return obj\n}\n\n/**\n * Gets a value at a deep path in an object using dot notation\n *\n * Safely retrieves values from nested objects/arrays. Returns undefined\n * or a default value if path doesn't exist.\n *\n * @param obj - Object to read from\n * @param path - Dot-notation path (e.g., 'database.connection.timeout')\n * @param defaultValue - Value to return if path doesn't exist (default: undefined)\n * @returns Value at the path, or defaultValue if not found\n *\n * @example\n * ```typescript\n * // Simple nested access\n * const config = { database: { host: 'localhost' } }\n * getDeepValue(config, 'database.host') // 'localhost'\n *\n * // Non-existent path returns undefined\n * getDeepValue(config, 'database.port') // undefined\n *\n * // With default value\n * getDeepValue(config, 'database.port', 5432) // 5432\n *\n * // Array access\n * const data = { users: [{ name: 'Alice' }, { name: 'Bob' }] }\n * getDeepValue(data, 'users.0.name') // 'Alice'\n * getDeepValue(data, 'users.1.name') // 'Bob'\n *\n * // Deep paths\n * const app = { features: { auth: { enabled: true } } }\n * getDeepValue(app, 'features.auth.enabled') // true\n * getDeepValue(app, 'features.payments.enabled', false) // false (default)\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Safe config access\n * const config = {\n * database: { host: 'localhost' },\n * cache: { ttl: 3600 }\n * }\n *\n * const dbHost = getDeepValue(config, 'database.host', '127.0.0.1')\n * const dbPort = getDeepValue(config, 'database.port', 5432)\n * const cacheTtl = getDeepValue(config, 'cache.ttl', 1800)\n * const redisHost = getDeepValue(config, 'redis.host', 'localhost')\n *\n * // All values are safely retrieved with fallbacks\n * ```\n */\nexport function getDeepValue<T = any>(obj: any, path: string, defaultValue?: T): T | undefined {\n if (!obj || typeof obj !== 'object') {\n return defaultValue\n }\n\n if (!path || typeof path !== 'string') {\n return defaultValue\n }\n\n const keys = path.split('.')\n let current = obj\n\n for (const key of keys) {\n if (current === null || current === undefined || typeof current !== 'object') {\n return defaultValue\n }\n\n if (!(key in current)) {\n return defaultValue\n }\n\n current = current[key]\n }\n\n return current !== undefined ? current : defaultValue\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,27 @@
1
+ import {
2
+ __export
3
+ } from "./chunk-PZ5AY32C.js";
4
+
5
+ // src/number.ts
6
+ var number_exports = {};
7
+ __export(number_exports, {
8
+ isNumericValue: () => isNumericValue,
9
+ roundToDecimals: () => roundToDecimals
10
+ });
11
+ function isNumericValue(value) {
12
+ if (value === null || value === void 0) return false;
13
+ if (typeof value === "number") return !isNaN(value) && isFinite(value);
14
+ if (typeof value === "string") return value.trim() !== "" && !isNaN(Number(value));
15
+ return false;
16
+ }
17
+ function roundToDecimals(num, decimals = 2) {
18
+ const factor = Math.pow(10, decimals);
19
+ return num >= 0 ? Math.round(num * factor) / factor : -Math.round(Math.abs(num) * factor) / factor;
20
+ }
21
+
22
+ export {
23
+ isNumericValue,
24
+ roundToDecimals,
25
+ number_exports
26
+ };
27
+ //# sourceMappingURL=chunk-JCAUVOPH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/number.ts"],"sourcesContent":["/**\n * Number utilities\n */\n\n/**\n * Verifica si un valor es numéricamente válido o convertible a número.\n * Acepta números y cadenas que representan números válidos.\n * @param value - El valor a verificar.\n * @returns true si el valor es numéricamente válido, false en caso contrario.\n * @example\n * ```ts\n * isNumericValue(5) // true\n * isNumericValue(\"5\") // true\n * isNumericValue(\"12.34\") // true\n * isNumericValue(\"-42\") // true\n * isNumericValue(\"abc\") // false\n * isNumericValue(\"\") // false\n * isNumericValue(\" \") // false\n * isNumericValue(null) // false\n * isNumericValue(undefined) // false\n * isNumericValue(NaN) // false\n * isNumericValue(Infinity) // false\n * ```\n */\nexport function isNumericValue(value: any): boolean {\n if (value === null || value === undefined) return false\n if (typeof value === 'number') return !isNaN(value) && isFinite(value)\n if (typeof value === 'string') return value.trim() !== '' && !isNaN(Number(value))\n return false\n}\n\n/**\n * Rounds a number to a specified number of decimal places\n * @param num - The number to round\n * @param decimals - Number of decimal places (default: 2)\n * @returns The rounded number\n * @example\n * ```ts\n * roundToDecimals(3.14159, 2) // 3.14\n * roundToDecimals(-2.7182, 3) // -2.718\n * ```\n */\nexport function roundToDecimals(num: number, decimals: number = 2): number {\n const factor = Math.pow(10, decimals)\n // Use sign-aware rounding to handle negative numbers correctly\n return num >= 0 ? Math.round(num * factor) / factor : -Math.round(Math.abs(num) * factor) / factor\n}\n"],"mappings":";;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBO,SAAS,eAAe,OAAqB;AAClD,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO,CAAC,MAAM,KAAK,KAAK,SAAS,KAAK;AACrE,MAAI,OAAO,UAAU,SAAU,QAAO,MAAM,KAAK,MAAM,MAAM,CAAC,MAAM,OAAO,KAAK,CAAC;AACjF,SAAO;AACT;AAaO,SAAS,gBAAgB,KAAa,WAAmB,GAAW;AACzE,QAAM,SAAS,KAAK,IAAI,IAAI,QAAQ;AAEpC,SAAO,OAAO,IAAI,KAAK,MAAM,MAAM,MAAM,IAAI,SAAS,CAAC,KAAK,MAAM,KAAK,IAAI,GAAG,IAAI,MAAM,IAAI;AAC9F;","names":[]}