@pawells/typescript-common 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +148 -0
  3. package/build/array/array-chunk.d.ts +10 -0
  4. package/build/array/array-chunk.d.ts.map +1 -0
  5. package/build/array/array-chunk.js +19 -0
  6. package/build/array/array-chunk.js.map +1 -0
  7. package/build/array/array-compact.d.ts +18 -0
  8. package/build/array/array-compact.d.ts.map +1 -0
  9. package/build/array/array-compact.js +22 -0
  10. package/build/array/array-compact.js.map +1 -0
  11. package/build/array/array-contains.d.ts +9 -0
  12. package/build/array/array-contains.d.ts.map +1 -0
  13. package/build/array/array-contains.js +13 -0
  14. package/build/array/array-contains.js.map +1 -0
  15. package/build/array/array-count-by.d.ts +21 -0
  16. package/build/array/array-count-by.d.ts.map +1 -0
  17. package/build/array/array-count-by.js +29 -0
  18. package/build/array/array-count-by.js.map +1 -0
  19. package/build/array/array-difference.d.ts +25 -0
  20. package/build/array/array-difference.d.ts.map +1 -0
  21. package/build/array/array-difference.js +34 -0
  22. package/build/array/array-difference.js.map +1 -0
  23. package/build/array/array-element.d.ts +7 -0
  24. package/build/array/array-element.d.ts.map +1 -0
  25. package/build/array/array-element.js +2 -0
  26. package/build/array/array-element.js.map +1 -0
  27. package/build/array/array-filter.d.ts +37 -0
  28. package/build/array/array-filter.d.ts.map +1 -0
  29. package/build/array/array-filter.js +78 -0
  30. package/build/array/array-filter.js.map +1 -0
  31. package/build/array/array-flatten.d.ts +16 -0
  32. package/build/array/array-flatten.d.ts.map +1 -0
  33. package/build/array/array-flatten.js +20 -0
  34. package/build/array/array-flatten.js.map +1 -0
  35. package/build/array/array-group-by.d.ts +13 -0
  36. package/build/array/array-group-by.d.ts.map +1 -0
  37. package/build/array/array-group-by.js +24 -0
  38. package/build/array/array-group-by.js.map +1 -0
  39. package/build/array/array-intersection.d.ts +25 -0
  40. package/build/array/array-intersection.d.ts.map +1 -0
  41. package/build/array/array-intersection.js +39 -0
  42. package/build/array/array-intersection.js.map +1 -0
  43. package/build/array/array-partition.d.ts +19 -0
  44. package/build/array/array-partition.d.ts.map +1 -0
  45. package/build/array/array-partition.js +32 -0
  46. package/build/array/array-partition.js.map +1 -0
  47. package/build/array/array-range.d.ts +18 -0
  48. package/build/array/array-range.d.ts.map +1 -0
  49. package/build/array/array-range.js +30 -0
  50. package/build/array/array-range.js.map +1 -0
  51. package/build/array/array-sample.d.ts +29 -0
  52. package/build/array/array-sample.d.ts.map +1 -0
  53. package/build/array/array-sample.js +19 -0
  54. package/build/array/array-sample.js.map +1 -0
  55. package/build/array/array-shuffle.d.ts +8 -0
  56. package/build/array/array-shuffle.d.ts.map +1 -0
  57. package/build/array/array-shuffle.js +19 -0
  58. package/build/array/array-shuffle.js.map +1 -0
  59. package/build/array/array-sort-by.d.ts +20 -0
  60. package/build/array/array-sort-by.d.ts.map +1 -0
  61. package/build/array/array-sort-by.js +31 -0
  62. package/build/array/array-sort-by.js.map +1 -0
  63. package/build/array/array-zip.d.ts +22 -0
  64. package/build/array/array-zip.d.ts.map +1 -0
  65. package/build/array/array-zip.js +25 -0
  66. package/build/array/array-zip.js.map +1 -0
  67. package/build/array/array.test.d.ts +2 -0
  68. package/build/array/array.test.d.ts.map +1 -0
  69. package/build/array/array.test.js +347 -0
  70. package/build/array/array.test.js.map +1 -0
  71. package/build/array/index.d.ts +27 -0
  72. package/build/array/index.d.ts.map +1 -0
  73. package/build/array/index.js +25 -0
  74. package/build/array/index.js.map +1 -0
  75. package/build/array/types.d.ts +32 -0
  76. package/build/array/types.d.ts.map +1 -0
  77. package/build/array/types.js +2 -0
  78. package/build/array/types.js.map +1 -0
  79. package/build/array/unique.d.ts +8 -0
  80. package/build/array/unique.d.ts.map +1 -0
  81. package/build/array/unique.js +13 -0
  82. package/build/array/unique.js.map +1 -0
  83. package/build/enum/enum-entries.d.ts +11 -0
  84. package/build/enum/enum-entries.d.ts.map +1 -0
  85. package/build/enum/enum-entries.js +14 -0
  86. package/build/enum/enum-entries.js.map +1 -0
  87. package/build/enum/enum-key-by-value.d.ts +13 -0
  88. package/build/enum/enum-key-by-value.d.ts.map +1 -0
  89. package/build/enum/enum-key-by-value.js +21 -0
  90. package/build/enum/enum-key-by-value.js.map +1 -0
  91. package/build/enum/enum-keys.d.ts +10 -0
  92. package/build/enum/enum-keys.d.ts.map +1 -0
  93. package/build/enum/enum-keys.js +14 -0
  94. package/build/enum/enum-keys.js.map +1 -0
  95. package/build/enum/enum-safe-value.d.ts +14 -0
  96. package/build/enum/enum-safe-value.d.ts.map +1 -0
  97. package/build/enum/enum-safe-value.js +16 -0
  98. package/build/enum/enum-safe-value.js.map +1 -0
  99. package/build/enum/enum-values.d.ts +19 -0
  100. package/build/enum/enum-values.d.ts.map +1 -0
  101. package/build/enum/enum-values.js +25 -0
  102. package/build/enum/enum-values.js.map +1 -0
  103. package/build/enum/enum.test.d.ts +2 -0
  104. package/build/enum/enum.test.d.ts.map +1 -0
  105. package/build/enum/enum.test.js +122 -0
  106. package/build/enum/enum.test.js.map +1 -0
  107. package/build/enum/index.d.ts +17 -0
  108. package/build/enum/index.d.ts.map +1 -0
  109. package/build/enum/index.js +17 -0
  110. package/build/enum/index.js.map +1 -0
  111. package/build/enum/types.d.ts +9 -0
  112. package/build/enum/types.d.ts.map +1 -0
  113. package/build/enum/types.js +2 -0
  114. package/build/enum/types.js.map +1 -0
  115. package/build/enum/validate-enum-value.d.ts +13 -0
  116. package/build/enum/validate-enum-value.d.ts.map +1 -0
  117. package/build/enum/validate-enum-value.js +18 -0
  118. package/build/enum/validate-enum-value.js.map +1 -0
  119. package/build/function/compose.d.ts +37 -0
  120. package/build/function/compose.d.ts.map +1 -0
  121. package/build/function/compose.js +7 -0
  122. package/build/function/compose.js.map +1 -0
  123. package/build/function/debounce.d.ts +25 -0
  124. package/build/function/debounce.d.ts.map +1 -0
  125. package/build/function/debounce.js +37 -0
  126. package/build/function/debounce.js.map +1 -0
  127. package/build/function/function.test.d.ts +2 -0
  128. package/build/function/function.test.d.ts.map +1 -0
  129. package/build/function/function.test.js +158 -0
  130. package/build/function/function.test.js.map +1 -0
  131. package/build/function/index.d.ts +17 -0
  132. package/build/function/index.d.ts.map +1 -0
  133. package/build/function/index.js +16 -0
  134. package/build/function/index.js.map +1 -0
  135. package/build/function/memoize.d.ts +23 -0
  136. package/build/function/memoize.d.ts.map +1 -0
  137. package/build/function/memoize.js +34 -0
  138. package/build/function/memoize.js.map +1 -0
  139. package/build/function/once.d.ts +17 -0
  140. package/build/function/once.d.ts.map +1 -0
  141. package/build/function/once.js +27 -0
  142. package/build/function/once.js.map +1 -0
  143. package/build/function/sleep.d.ts +20 -0
  144. package/build/function/sleep.d.ts.map +1 -0
  145. package/build/function/sleep.js +22 -0
  146. package/build/function/sleep.js.map +1 -0
  147. package/build/function/throttle.d.ts +17 -0
  148. package/build/function/throttle.d.ts.map +1 -0
  149. package/build/function/throttle.js +37 -0
  150. package/build/function/throttle.js.map +1 -0
  151. package/build/function/types.d.ts +5 -0
  152. package/build/function/types.d.ts.map +1 -0
  153. package/build/function/types.js +2 -0
  154. package/build/function/types.js.map +1 -0
  155. package/build/index.d.ts +32 -0
  156. package/build/index.d.ts.map +1 -0
  157. package/build/index.js +51 -0
  158. package/build/index.js.map +1 -0
  159. package/build/object/assert-object.d.ts +8 -0
  160. package/build/object/assert-object.d.ts.map +1 -0
  161. package/build/object/assert-object.js +10 -0
  162. package/build/object/assert-object.js.map +1 -0
  163. package/build/object/clone.d.ts +39 -0
  164. package/build/object/clone.d.ts.map +1 -0
  165. package/build/object/clone.js +85 -0
  166. package/build/object/clone.js.map +1 -0
  167. package/build/object/equals.d.ts +44 -0
  168. package/build/object/equals.d.ts.map +1 -0
  169. package/build/object/equals.js +104 -0
  170. package/build/object/equals.js.map +1 -0
  171. package/build/object/filter-cached.d.ts +9 -0
  172. package/build/object/filter-cached.d.ts.map +1 -0
  173. package/build/object/filter-cached.js +108 -0
  174. package/build/object/filter-cached.js.map +1 -0
  175. package/build/object/filter.d.ts +85 -0
  176. package/build/object/filter.d.ts.map +1 -0
  177. package/build/object/filter.js +248 -0
  178. package/build/object/filter.js.map +1 -0
  179. package/build/object/has-circular-reference.d.ts +8 -0
  180. package/build/object/has-circular-reference.d.ts.map +1 -0
  181. package/build/object/has-circular-reference.js +40 -0
  182. package/build/object/has-circular-reference.js.map +1 -0
  183. package/build/object/hash.d.ts +20 -0
  184. package/build/object/hash.d.ts.map +1 -0
  185. package/build/object/hash.js +39 -0
  186. package/build/object/hash.js.map +1 -0
  187. package/build/object/index.d.ts +32 -0
  188. package/build/object/index.d.ts.map +1 -0
  189. package/build/object/index.js +30 -0
  190. package/build/object/index.js.map +1 -0
  191. package/build/object/key-value-pairs.d.ts +21 -0
  192. package/build/object/key-value-pairs.d.ts.map +1 -0
  193. package/build/object/key-value-pairs.js +28 -0
  194. package/build/object/key-value-pairs.js.map +1 -0
  195. package/build/object/map-cached.d.ts +9 -0
  196. package/build/object/map-cached.d.ts.map +1 -0
  197. package/build/object/map-cached.js +97 -0
  198. package/build/object/map-cached.js.map +1 -0
  199. package/build/object/map.d.ts +29 -0
  200. package/build/object/map.d.ts.map +1 -0
  201. package/build/object/map.js +40 -0
  202. package/build/object/map.js.map +1 -0
  203. package/build/object/merge.d.ts +14 -0
  204. package/build/object/merge.d.ts.map +1 -0
  205. package/build/object/merge.js +41 -0
  206. package/build/object/merge.js.map +1 -0
  207. package/build/object/object-diff.d.ts +40 -0
  208. package/build/object/object-diff.d.ts.map +1 -0
  209. package/build/object/object-diff.js +45 -0
  210. package/build/object/object-diff.js.map +1 -0
  211. package/build/object/object-flatten.d.ts +22 -0
  212. package/build/object/object-flatten.d.ts.map +1 -0
  213. package/build/object/object-flatten.js +38 -0
  214. package/build/object/object-flatten.js.map +1 -0
  215. package/build/object/object-invert.d.ts +20 -0
  216. package/build/object/object-invert.d.ts.map +1 -0
  217. package/build/object/object-invert.js +26 -0
  218. package/build/object/object-invert.js.map +1 -0
  219. package/build/object/object.test.d.ts +2 -0
  220. package/build/object/object.test.d.ts.map +1 -0
  221. package/build/object/object.test.js +432 -0
  222. package/build/object/object.test.js.map +1 -0
  223. package/build/object/omit.d.ts +8 -0
  224. package/build/object/omit.d.ts.map +1 -0
  225. package/build/object/omit.js +17 -0
  226. package/build/object/omit.js.map +1 -0
  227. package/build/object/pick.d.ts +50 -0
  228. package/build/object/pick.d.ts.map +1 -0
  229. package/build/object/pick.js +60 -0
  230. package/build/object/pick.js.map +1 -0
  231. package/build/object/property-paths.d.ts +115 -0
  232. package/build/object/property-paths.d.ts.map +1 -0
  233. package/build/object/property-paths.js +170 -0
  234. package/build/object/property-paths.js.map +1 -0
  235. package/build/object/security-utils.d.ts +59 -0
  236. package/build/object/security-utils.d.ts.map +1 -0
  237. package/build/object/security-utils.js +165 -0
  238. package/build/object/security-utils.js.map +1 -0
  239. package/build/object/sort-keys.d.ts +26 -0
  240. package/build/object/sort-keys.d.ts.map +1 -0
  241. package/build/object/sort-keys.js +52 -0
  242. package/build/object/sort-keys.js.map +1 -0
  243. package/build/object/types.d.ts +152 -0
  244. package/build/object/types.d.ts.map +1 -0
  245. package/build/object/types.js +6 -0
  246. package/build/object/types.js.map +1 -0
  247. package/build/string/case-conversion.d.ts +50 -0
  248. package/build/string/case-conversion.d.ts.map +1 -0
  249. package/build/string/case-conversion.js +94 -0
  250. package/build/string/case-conversion.js.map +1 -0
  251. package/build/string/formatting.d.ts +108 -0
  252. package/build/string/formatting.d.ts.map +1 -0
  253. package/build/string/formatting.js +171 -0
  254. package/build/string/formatting.js.map +1 -0
  255. package/build/string/index.d.ts +15 -0
  256. package/build/string/index.d.ts.map +1 -0
  257. package/build/string/index.js +14 -0
  258. package/build/string/index.js.map +1 -0
  259. package/build/string/string.test.d.ts +2 -0
  260. package/build/string/string.test.d.ts.map +1 -0
  261. package/build/string/string.test.js +321 -0
  262. package/build/string/string.test.js.map +1 -0
  263. package/build/string/transformation.d.ts +18 -0
  264. package/build/string/transformation.d.ts.map +1 -0
  265. package/build/string/transformation.js +32 -0
  266. package/build/string/transformation.js.map +1 -0
  267. package/build/string/types.d.ts +44 -0
  268. package/build/string/types.d.ts.map +1 -0
  269. package/build/string/types.js +2 -0
  270. package/build/string/types.js.map +1 -0
  271. package/build/string/validation.d.ts +18 -0
  272. package/build/string/validation.d.ts.map +1 -0
  273. package/build/string/validation.js +26 -0
  274. package/build/string/validation.js.map +1 -0
  275. package/build/time/elapsed-time/constants.d.ts +10 -0
  276. package/build/time/elapsed-time/constants.d.ts.map +1 -0
  277. package/build/time/elapsed-time/constants.js +96 -0
  278. package/build/time/elapsed-time/constants.js.map +1 -0
  279. package/build/time/elapsed-time/elapsed-time.d.ts +412 -0
  280. package/build/time/elapsed-time/elapsed-time.d.ts.map +1 -0
  281. package/build/time/elapsed-time/elapsed-time.js +652 -0
  282. package/build/time/elapsed-time/elapsed-time.js.map +1 -0
  283. package/build/time/elapsed-time/types.d.ts +150 -0
  284. package/build/time/elapsed-time/types.d.ts.map +1 -0
  285. package/build/time/elapsed-time/types.js +2 -0
  286. package/build/time/elapsed-time/types.js.map +1 -0
  287. package/build/time/elapsed-time/utils.d.ts +18 -0
  288. package/build/time/elapsed-time/utils.d.ts.map +1 -0
  289. package/build/time/elapsed-time/utils.js +24 -0
  290. package/build/time/elapsed-time/utils.js.map +1 -0
  291. package/build/time/index.d.ts +18 -0
  292. package/build/time/index.d.ts.map +1 -0
  293. package/build/time/index.js +17 -0
  294. package/build/time/index.js.map +1 -0
  295. package/build/time/stopwatch/entry-types.d.ts +13 -0
  296. package/build/time/stopwatch/entry-types.d.ts.map +1 -0
  297. package/build/time/stopwatch/entry-types.js +2 -0
  298. package/build/time/stopwatch/entry-types.js.map +1 -0
  299. package/build/time/stopwatch/entry.d.ts +80 -0
  300. package/build/time/stopwatch/entry.d.ts.map +1 -0
  301. package/build/time/stopwatch/entry.js +105 -0
  302. package/build/time/stopwatch/entry.js.map +1 -0
  303. package/build/time/stopwatch/stopwatch.d.ts +232 -0
  304. package/build/time/stopwatch/stopwatch.d.ts.map +1 -0
  305. package/build/time/stopwatch/stopwatch.js +315 -0
  306. package/build/time/stopwatch/stopwatch.js.map +1 -0
  307. package/build/time/time.test.d.ts +2 -0
  308. package/build/time/time.test.d.ts.map +1 -0
  309. package/build/time/time.test.js +211 -0
  310. package/build/time/time.test.js.map +1 -0
  311. package/package.json +63 -0
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Performs a deep comparison between two values to determine if they are equivalent.
3
+ * Handles primitives, objects, arrays, dates, regular expressions, and special values like NaN.
4
+ *
5
+ * @param a - First value to compare
6
+ * @param b - Second value to compare
7
+ * @returns True if the values are equivalent, false otherwise
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * // Primitive values
12
+ * ObjectEquals(42, 42); // true
13
+ * ObjectEquals('hello', 'hello'); // true
14
+ * ObjectEquals(true, false); // false
15
+ *
16
+ * // Objects
17
+ * ObjectEquals({ a: 1, b: 2 }, { a: 1, b: 2 }); // true
18
+ * ObjectEquals({ a: 1, b: 2 }, { a: 1, b: 3 }); // false
19
+ *
20
+ * // Nested objects
21
+ * const obj1 = { user: { name: 'John', age: 30 }, active: true };
22
+ * const obj2 = { user: { name: 'John', age: 30 }, active: true };
23
+ * ObjectEquals(obj1, obj2); // true
24
+ *
25
+ * // Arrays
26
+ * ObjectEquals([1, 2, 3], [1, 2, 3]); // true
27
+ * ObjectEquals([1, [2, 3]], [1, [2, 3]]); // true
28
+ *
29
+ * // Date objects
30
+ * const date1 = new Date('2023-01-01');
31
+ * const date2 = new Date('2023-01-01');
32
+ * ObjectEquals(date1, date2); // true
33
+ *
34
+ * // Regular expressions
35
+ * ObjectEquals(/abc/g, /abc/g); // true
36
+ * ObjectEquals(/abc/g, /abc/i); // false
37
+ *
38
+ * // Special cases
39
+ * ObjectEquals(NaN, NaN); // true (unlike === comparison)
40
+ * ObjectEquals(null, undefined); // false
41
+ * ```
42
+ */
43
+ export function ObjectEquals(a, b) {
44
+ // If the values are strictly equal, return true
45
+ if (a === b)
46
+ return true;
47
+ // Handle NaN special case - NaN should equal NaN for assertion purposes
48
+ if (typeof a === 'number' && typeof b === 'number' && isNaN(a) && isNaN(b)) {
49
+ return true;
50
+ }
51
+ // If either value is null, undefined, or not an object, they can't be equivalent
52
+ if (a === null || b === null || a === undefined || b === undefined)
53
+ return false;
54
+ if (typeof a !== typeof b)
55
+ return false;
56
+ if (typeof a !== 'object')
57
+ return false;
58
+ // Handle Date objects
59
+ if (a instanceof Date && b instanceof Date) {
60
+ return a.getTime() === b.getTime();
61
+ }
62
+ // Handle RegExp objects
63
+ if (a instanceof RegExp && b instanceof RegExp) {
64
+ return a.toString() === b.toString();
65
+ }
66
+ // Handle arrays
67
+ if (Array.isArray(a) && Array.isArray(b)) {
68
+ if (a.length !== b.length)
69
+ return false;
70
+ // Compare each element in the arrays
71
+ for (let i = 0; i < a.length; i++) {
72
+ if (!ObjectEquals(a[i], b[i]))
73
+ return false;
74
+ }
75
+ return true;
76
+ }
77
+ // If one is array and the other isn't, they're not equal
78
+ if (Array.isArray(a) !== Array.isArray(b))
79
+ return false;
80
+ // Compare object properties
81
+ const keysA = Object.keys(a);
82
+ const keysB = Object.keys(b);
83
+ if (keysA.length !== keysB.length)
84
+ return false;
85
+ // Also compare symbol properties
86
+ const symbolsA = Object.getOwnPropertySymbols(a);
87
+ const symbolsB = Object.getOwnPropertySymbols(b);
88
+ if (symbolsA.length !== symbolsB.length)
89
+ return false;
90
+ for (const key of keysA) {
91
+ if (!Object.hasOwn(b, key))
92
+ return false;
93
+ if (!ObjectEquals(a[key], b[key]))
94
+ return false;
95
+ }
96
+ for (const symbol of symbolsA) {
97
+ if (!Object.getOwnPropertySymbols(b).includes(symbol))
98
+ return false;
99
+ if (!ObjectEquals(a[symbol], b[symbol]))
100
+ return false;
101
+ }
102
+ return true;
103
+ }
104
+ //# sourceMappingURL=equals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"equals.js","sourceRoot":"","sources":["../../src/object/equals.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { ICachedObjectFilterOptions, TCachedObjectFilterFunction } from './types.js';
2
+ /**
3
+ * Creates a cached version of filter for improved performance when filtering the same objects repeatedly
4
+ *
5
+ * @param options Configuration options for both the cache and the underlying filter
6
+ * @returns A cached version of the filter function
7
+ */
8
+ export declare function ObjectFilterCached<T extends object>(options?: ICachedObjectFilterOptions): TCachedObjectFilterFunction<T>;
9
+ //# sourceMappingURL=filter-cached.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-cached.d.ts","sourceRoot":"","sources":["../../src/object/filter-cached.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,0BAA0B,EAAE,2BAA2B,EAAwB,MAAM,YAAY,CAAC;AAOhH;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,EAAE,OAAO,GAAE,0BAA+B,GAAG,2BAA2B,CAAC,CAAC,CAAC,CAmH7H"}
@@ -0,0 +1,108 @@
1
+ import { ObjectFilter } from './filter.js';
2
+ import { ObjectHash } from './hash.js';
3
+ // Cache configuration constants
4
+ const DEFAULT_MAX_CACHE_SIZE = 1000;
5
+ const CACHE_EVICTION_PERCENTAGE = 0.2; // 20%
6
+ const INITIAL_CACHE_HASH_LENGTH = 16;
7
+ /**
8
+ * Creates a cached version of filter for improved performance when filtering the same objects repeatedly
9
+ *
10
+ * @param options Configuration options for both the cache and the underlying filter
11
+ * @returns A cached version of the filter function
12
+ */
13
+ export function ObjectFilterCached(options = {}) {
14
+ const { maxCacheSize = DEFAULT_MAX_CACHE_SIZE, useDeepEqual = false, caseInsensitiveStrings = false, validatePaths = true, } = options;
15
+ const cache = new Map();
16
+ let totalCachedEntries = 0;
17
+ /**
18
+ * Evicts approximately 20% of entries from the largest per-filter cache bucket
19
+ * when the total number of cached results exceeds `maxCacheSize`.
20
+ *
21
+ * The eviction strategy targets the most-populated bucket to reclaim the most
22
+ * memory in a single pass while preserving results for other active filters.
23
+ */
24
+ const clearOldestEntries = () => {
25
+ if (cache.size === 0)
26
+ return;
27
+ // Find the cache with the most entries
28
+ let largestCache = null;
29
+ let largestCacheKey = '';
30
+ let largestSize = 0;
31
+ for (const [key, objectCache] of cache.entries()) {
32
+ if (objectCache.size > largestSize) {
33
+ largestCache = objectCache;
34
+ largestCacheKey = key;
35
+ largestSize = objectCache.size;
36
+ }
37
+ }
38
+ if (largestCache) {
39
+ // Remove approximately 20% of entries from the largest cache
40
+ const entriesToRemove = Math.ceil(largestSize * CACHE_EVICTION_PERCENTAGE);
41
+ let removed = 0;
42
+ for (const key of largestCache.keys()) {
43
+ largestCache.delete(key);
44
+ removed++;
45
+ if (removed >= entriesToRemove)
46
+ break;
47
+ }
48
+ // If the cache is now empty, remove it completely
49
+ if (largestCache.size === 0) {
50
+ cache.delete(largestCacheKey);
51
+ }
52
+ totalCachedEntries -= removed;
53
+ }
54
+ };
55
+ return (cursor, filter) => {
56
+ // Validate inputs
57
+ if (!cursor || typeof cursor !== 'object') {
58
+ return Promise.resolve(false);
59
+ }
60
+ if (!filter || typeof filter !== 'object') {
61
+ return Promise.resolve(true); // Empty filter matches everything
62
+ }
63
+ // Optimize cache key generation with shorter hash for better performance
64
+ const filterKey = ObjectHash(filter).substring(0, INITIAL_CACHE_HASH_LENGTH);
65
+ // Try to get the object cache for this filter
66
+ let objectCache = cache.get(filterKey);
67
+ if (!objectCache) {
68
+ objectCache = new Map();
69
+ cache.set(filterKey, objectCache);
70
+ }
71
+ // Create optimized hash-based cache key for the object being filtered
72
+ // Use shorter hash for better memory efficiency and performance
73
+ let objectKey;
74
+ try {
75
+ objectKey = ObjectHash(cursor).substring(0, INITIAL_CACHE_HASH_LENGTH);
76
+ }
77
+ catch {
78
+ // If object has circular references, skip caching and compute directly
79
+ const filterOptions = {
80
+ useDeepEqual,
81
+ caseInsensitiveStrings,
82
+ validatePaths,
83
+ };
84
+ return Promise.resolve(ObjectFilter(cursor, filter, filterOptions));
85
+ }
86
+ // Check if we have a cached result
87
+ if (objectCache.has(objectKey)) {
88
+ const cachedResult = objectCache.get(objectKey);
89
+ return Promise.resolve(cachedResult ?? false);
90
+ }
91
+ // Calculate the result
92
+ const filterOptions = {
93
+ useDeepEqual,
94
+ caseInsensitiveStrings,
95
+ validatePaths,
96
+ };
97
+ const result = ObjectFilter(cursor, filter, filterOptions);
98
+ // Cache the result
99
+ objectCache.set(objectKey, result);
100
+ totalCachedEntries++;
101
+ // Ensure the cache size does not exceed the limit
102
+ if (totalCachedEntries > maxCacheSize) {
103
+ clearOldestEntries();
104
+ }
105
+ return Promise.resolve(result);
106
+ };
107
+ }
108
+ //# sourceMappingURL=filter-cached.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-cached.js","sourceRoot":"","sources":["../../src/object/filter-cached.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ import type { IObjectFilterOptions, TPropertyFilter } from './types.js';
2
+ /**
3
+ * Filters an object based on a provided filter using flexible matching criteria.
4
+ * Supports dot notation for nested properties, deep equality comparison, case-insensitive string matching,
5
+ * and array inclusion/subset matching.
6
+ *
7
+ * @template T - The type of object being filtered
8
+ * @param object - The object to filter
9
+ * @param filter - The filter criteria to apply
10
+ * @param options - Optional configuration for filtering behavior
11
+ * @returns True if the object satisfies the filter, false otherwise
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // Basic property matching
16
+ * const user = { name: 'John', age: 30, active: true };
17
+ * ObjectFilter(user, { name: 'John' }); // true
18
+ * ObjectFilter(user, { age: 25 }); // false
19
+ *
20
+ * // Multiple properties (AND logic)
21
+ * ObjectFilter(user, { name: 'John', active: true }); // true
22
+ * ObjectFilter(user, { name: 'John', age: 25 }); // false
23
+ *
24
+ * // Dot notation for nested properties
25
+ * const profile = {
26
+ * user: { name: 'John', details: { age: 30, city: 'NYC' } },
27
+ * meta: { created: '2023-01-01', active: true }
28
+ * };
29
+ * ObjectFilter(profile, { 'user.name': 'John' }); // true
30
+ * ObjectFilter(profile, { 'user.details.city': 'NYC' }); // true
31
+ * ObjectFilter(profile, { 'meta.active': true }); // true
32
+ *
33
+ * // Case-insensitive string matching
34
+ * ObjectFilter(user, { name: 'john' }, { caseInsensitiveStrings: true }); // true
35
+ * ObjectFilter(user, { name: 'JOHN' }, { caseInsensitiveStrings: true }); // true
36
+ *
37
+ * // Array matching - inclusion check
38
+ * const post = { tags: ['javascript', 'typescript', 'node'], category: 'tech' };
39
+ * ObjectFilter(post, { tags: 'javascript' }); // true (string in array)
40
+ * ObjectFilter(post, { tags: 'python' }); // false
41
+ *
42
+ * // Array subset matching
43
+ * ObjectFilter(post, { tags: ['javascript', 'typescript'] }); // true (subset)
44
+ * ObjectFilter(post, { tags: ['javascript', 'python'] }); // false (not subset)
45
+ *
46
+ * // Deep equality for nested objects
47
+ * const order = {
48
+ * items: [{ id: 1, name: 'Book' }, { id: 2, name: 'Pen' }],
49
+ * shipping: { address: { city: 'NYC', zip: '10001' } }
50
+ * };
51
+ * ObjectFilter(order,
52
+ * { shipping: { address: { city: 'NYC' } } },
53
+ * { useDeepEqual: true }
54
+ * ); // true (partial match with deep equality)
55
+ *
56
+ * // Path validation (security)
57
+ * ObjectFilter(profile, { '../malicious': 'value' }, { validatePaths: true }); // false
58
+ * ObjectFilter(profile, { 'user..name': 'John' }, { validatePaths: true }); // false
59
+ * ```
60
+ */
61
+ export declare function ObjectFilter<T>(object: T, filter: Record<string, any>, options?: IObjectFilterOptions): boolean;
62
+ /**
63
+ * Filters an object's properties using a predicate function.
64
+ * Creates a new object containing only the properties for which the predicate returns true.
65
+ *
66
+ * @template T - The type of the source object
67
+ * @param obj - The object to filter
68
+ * @param predicate - A function that takes a property key and value, returning true to include the property
69
+ * @returns A new object with only the filtered properties
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * const obj = { a: 1, b: 2, c: 3, d: 4 };
74
+ * const filtered = FilterObject(obj, (key, value) => value > 2);
75
+ * // Result: { c: 3, d: 4 }
76
+ *
77
+ * // Type-safe filtering
78
+ * interface User { id: number; name: string; age: number; }
79
+ * const user: User = { id: 1, name: 'John', age: 30 };
80
+ * const publicData = FilterObject(user, (key, value) => key !== 'age');
81
+ * // Result: { id: 1, name: 'John' }
82
+ * ```
83
+ */
84
+ export declare function FilterObject<T extends object>(obj: T, predicate: TPropertyFilter<T>): Partial<T>;
85
+ //# sourceMappingURL=filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../src/object/filter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AA2HxE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAgDnH;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAiBhG"}
@@ -0,0 +1,248 @@
1
+ import { ObjectEquals } from './equals.js';
2
+ import { isPropertyPathSafe } from './security-utils.js';
3
+ /**
4
+ * Navigates to a nested property value using dot notation path
5
+ *
6
+ * @param object - The object to navigate
7
+ * @param path - The dot notation path (e.g., 'meta.details.category')
8
+ * @returns The value at the path, or undefined if path doesn't exist
9
+ */
10
+ function objectGetValueByPath(object, path) {
11
+ const pathSegments = path.split('.');
12
+ let current = object;
13
+ for (const segment of pathSegments) {
14
+ current = current?.[segment];
15
+ if (current === undefined || current === null) {
16
+ return undefined;
17
+ }
18
+ }
19
+ return current;
20
+ }
21
+ /**
22
+ * Compares two objects using deep equality logic for ObjectFilter
23
+ *
24
+ * @param objValue - The object value to compare
25
+ * @param filterValue - The filter value to compare against
26
+ * @param caseInsensitiveStrings - Whether to use case-insensitive string comparison
27
+ * @returns True if the values match according to deep equality rules
28
+ */
29
+ function objectDeepComparison(objValue, filterValue, caseInsensitiveStrings = false) {
30
+ // Handle string comparison with case insensitivity option
31
+ if (caseInsensitiveStrings && typeof objValue === 'string' && typeof filterValue === 'string') {
32
+ return objValue.toLowerCase() === filterValue.toLowerCase();
33
+ }
34
+ // Special handling for Date objects
35
+ if (objValue instanceof Date && filterValue instanceof Date) {
36
+ return objValue.getTime() === filterValue.getTime();
37
+ }
38
+ // Handle array cases: if objValue is an array, use array comparison logic
39
+ if (Array.isArray(objValue)) {
40
+ return objectHandleArrayComparison(objValue, filterValue, caseInsensitiveStrings, true);
41
+ }
42
+ // For deeply nested structures, check if filter is a subset of the object
43
+ if (typeof objValue === 'object' && objValue !== null && typeof filterValue === 'object' && filterValue !== null && !Array.isArray(filterValue)) {
44
+ return ObjectFilter(objValue, filterValue, { useDeepEqual: true, caseInsensitiveStrings });
45
+ }
46
+ // Default case: use full object equality
47
+ return ObjectEquals(objValue, filterValue);
48
+ }
49
+ /**
50
+ * Handles array filtering logic with support for string inclusion and subset matching
51
+ *
52
+ * @param objValue - The array value from the object
53
+ * @param filterValue - The filter value to match against
54
+ * @param caseInsensitiveStrings - Whether to use case-insensitive string comparison
55
+ * @param useDeepEqual - Whether to use deep equality for nested objects
56
+ * @returns True if the filter matches the array value
57
+ */
58
+ function objectHandleArrayComparison(objValue, filterValue, caseInsensitiveStrings, useDeepEqual) {
59
+ // If filterValue is a string, check if it exists in the array
60
+ if (typeof filterValue === 'string') {
61
+ if (caseInsensitiveStrings) {
62
+ return objValue.some((item) => typeof item === 'string' && item.toLowerCase() === filterValue.toLowerCase());
63
+ }
64
+ return objValue.includes(filterValue);
65
+ }
66
+ // If filterValue is also an array, check if it's a subset
67
+ if (Array.isArray(filterValue)) {
68
+ return filterValue.every((item) => objValue.some((objItem) => objectCompareValues(objItem, item, caseInsensitiveStrings, useDeepEqual)));
69
+ }
70
+ // For non-string, non-array filter values, check direct inclusion
71
+ return objValue.some((item) => objectCompareValues(item, filterValue, caseInsensitiveStrings, useDeepEqual));
72
+ }
73
+ /**
74
+ * Compare values based on filter criteria
75
+ *
76
+ * @param objValue The object value
77
+ * @param filterValue The filter value to compare against
78
+ * @param caseInsensitiveStrings Whether to do case-insensitive string comparison
79
+ * @param useDeepEqual Whether to use deep equality for nested objects
80
+ * @returns True if values match according to specified criteria
81
+ */
82
+ function objectCompareValues(objValue, filterValue, caseInsensitiveStrings, useDeepEqual = false) {
83
+ // Check if objValue is an array
84
+ if (Array.isArray(objValue)) {
85
+ return objectHandleArrayComparison(objValue, filterValue, caseInsensitiveStrings, useDeepEqual);
86
+ }
87
+ // Handle string comparison with case insensitivity option
88
+ if (caseInsensitiveStrings && typeof objValue === 'string' && typeof filterValue === 'string') {
89
+ return objValue.toLowerCase() === filterValue.toLowerCase();
90
+ }
91
+ // Special handling for NaN
92
+ if (typeof objValue === 'number' && typeof filterValue === 'number' && isNaN(objValue) && isNaN(filterValue)) {
93
+ return true;
94
+ }
95
+ // For object filtering with useDeepEqual, check if filterValue is a subset of objValue
96
+ if (useDeepEqual && typeof objValue === 'object' && objValue !== null && typeof filterValue === 'object' && filterValue !== null && !Array.isArray(filterValue)) {
97
+ return ObjectFilter(objValue, filterValue, { useDeepEqual: true, caseInsensitiveStrings });
98
+ }
99
+ // Use deep equality if requested
100
+ if (useDeepEqual) {
101
+ return ObjectEquals(objValue, filterValue);
102
+ }
103
+ // Default strict equality
104
+ return objValue === filterValue;
105
+ }
106
+ /**
107
+ * Filters an object based on a provided filter using flexible matching criteria.
108
+ * Supports dot notation for nested properties, deep equality comparison, case-insensitive string matching,
109
+ * and array inclusion/subset matching.
110
+ *
111
+ * @template T - The type of object being filtered
112
+ * @param object - The object to filter
113
+ * @param filter - The filter criteria to apply
114
+ * @param options - Optional configuration for filtering behavior
115
+ * @returns True if the object satisfies the filter, false otherwise
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * // Basic property matching
120
+ * const user = { name: 'John', age: 30, active: true };
121
+ * ObjectFilter(user, { name: 'John' }); // true
122
+ * ObjectFilter(user, { age: 25 }); // false
123
+ *
124
+ * // Multiple properties (AND logic)
125
+ * ObjectFilter(user, { name: 'John', active: true }); // true
126
+ * ObjectFilter(user, { name: 'John', age: 25 }); // false
127
+ *
128
+ * // Dot notation for nested properties
129
+ * const profile = {
130
+ * user: { name: 'John', details: { age: 30, city: 'NYC' } },
131
+ * meta: { created: '2023-01-01', active: true }
132
+ * };
133
+ * ObjectFilter(profile, { 'user.name': 'John' }); // true
134
+ * ObjectFilter(profile, { 'user.details.city': 'NYC' }); // true
135
+ * ObjectFilter(profile, { 'meta.active': true }); // true
136
+ *
137
+ * // Case-insensitive string matching
138
+ * ObjectFilter(user, { name: 'john' }, { caseInsensitiveStrings: true }); // true
139
+ * ObjectFilter(user, { name: 'JOHN' }, { caseInsensitiveStrings: true }); // true
140
+ *
141
+ * // Array matching - inclusion check
142
+ * const post = { tags: ['javascript', 'typescript', 'node'], category: 'tech' };
143
+ * ObjectFilter(post, { tags: 'javascript' }); // true (string in array)
144
+ * ObjectFilter(post, { tags: 'python' }); // false
145
+ *
146
+ * // Array subset matching
147
+ * ObjectFilter(post, { tags: ['javascript', 'typescript'] }); // true (subset)
148
+ * ObjectFilter(post, { tags: ['javascript', 'python'] }); // false (not subset)
149
+ *
150
+ * // Deep equality for nested objects
151
+ * const order = {
152
+ * items: [{ id: 1, name: 'Book' }, { id: 2, name: 'Pen' }],
153
+ * shipping: { address: { city: 'NYC', zip: '10001' } }
154
+ * };
155
+ * ObjectFilter(order,
156
+ * { shipping: { address: { city: 'NYC' } } },
157
+ * { useDeepEqual: true }
158
+ * ); // true (partial match with deep equality)
159
+ *
160
+ * // Path validation (security)
161
+ * ObjectFilter(profile, { '../malicious': 'value' }, { validatePaths: true }); // false
162
+ * ObjectFilter(profile, { 'user..name': 'John' }, { validatePaths: true }); // false
163
+ * ```
164
+ */
165
+ export function ObjectFilter(object, filter, options = {}) {
166
+ // Default options
167
+ const { useDeepEqual = false, caseInsensitiveStrings = false, validatePaths = false } = options;
168
+ for (const key in filter) {
169
+ // Skip properties that are not own properties of the filter object
170
+ if (!Object.hasOwn(filter, key))
171
+ continue;
172
+ // Handle dot notation paths
173
+ if (key.includes('.')) {
174
+ if (validatePaths && !isPropertyPathSafe(key)) {
175
+ return false;
176
+ }
177
+ const objValue = objectGetValueByPath(object, key);
178
+ if (objValue === undefined) {
179
+ return false;
180
+ }
181
+ // Compare the values
182
+ const filterValue = filter[key];
183
+ if (useDeepEqual) {
184
+ if (!objectDeepComparison(objValue, filterValue, caseInsensitiveStrings)) {
185
+ return false;
186
+ }
187
+ }
188
+ else if (!objectCompareValues(objValue, filterValue, caseInsensitiveStrings, useDeepEqual)) {
189
+ return false;
190
+ }
191
+ }
192
+ else {
193
+ // Direct property comparison
194
+ const objValue = object[key];
195
+ const filterValue = filter[key];
196
+ if (!(key in object)) {
197
+ return false;
198
+ }
199
+ if (useDeepEqual) {
200
+ if (!objectDeepComparison(objValue, filterValue, caseInsensitiveStrings)) {
201
+ return false;
202
+ }
203
+ }
204
+ else if (!objectCompareValues(objValue, filterValue, caseInsensitiveStrings, useDeepEqual)) {
205
+ return false;
206
+ }
207
+ }
208
+ }
209
+ return true;
210
+ }
211
+ /**
212
+ * Filters an object's properties using a predicate function.
213
+ * Creates a new object containing only the properties for which the predicate returns true.
214
+ *
215
+ * @template T - The type of the source object
216
+ * @param obj - The object to filter
217
+ * @param predicate - A function that takes a property key and value, returning true to include the property
218
+ * @returns A new object with only the filtered properties
219
+ *
220
+ * @example
221
+ * ```typescript
222
+ * const obj = { a: 1, b: 2, c: 3, d: 4 };
223
+ * const filtered = FilterObject(obj, (key, value) => value > 2);
224
+ * // Result: { c: 3, d: 4 }
225
+ *
226
+ * // Type-safe filtering
227
+ * interface User { id: number; name: string; age: number; }
228
+ * const user: User = { id: 1, name: 'John', age: 30 };
229
+ * const publicData = FilterObject(user, (key, value) => key !== 'age');
230
+ * // Result: { id: 1, name: 'John' }
231
+ * ```
232
+ */
233
+ export function FilterObject(obj, predicate) {
234
+ if (!obj || typeof obj !== 'object') {
235
+ return {};
236
+ }
237
+ const result = {};
238
+ for (const key in obj) {
239
+ if (Object.hasOwn(obj, key)) {
240
+ const value = obj[key];
241
+ if (predicate(key, value)) {
242
+ result[key] = value;
243
+ }
244
+ }
245
+ }
246
+ return result;
247
+ }
248
+ //# sourceMappingURL=filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter.js","sourceRoot":"","sources":["../../src/object/filter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Checks whether an object contains circular references
3
+ *
4
+ * @param obj - The object to check for circular references
5
+ * @returns True if the object contains circular references, false otherwise
6
+ */
7
+ export declare function ObjectHasCircularReference(obj: unknown): boolean;
8
+ //# sourceMappingURL=has-circular-reference.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"has-circular-reference.d.ts","sourceRoot":"","sources":["../../src/object/has-circular-reference.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAyChE"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Checks whether an object contains circular references
3
+ *
4
+ * @param obj - The object to check for circular references
5
+ * @returns True if the object contains circular references, false otherwise
6
+ */
7
+ export function ObjectHasCircularReference(obj) {
8
+ const seen = new WeakSet();
9
+ const detectCircular = (value) => {
10
+ // Only check for circular references in non-null objects
11
+ if (value === null || typeof value !== 'object') {
12
+ return false;
13
+ }
14
+ // If we've seen this object before, it's a circular reference
15
+ if (seen.has(value)) {
16
+ return true;
17
+ }
18
+ // Mark this object as seen
19
+ seen.add(value);
20
+ // For arrays, check each element
21
+ if (Array.isArray(value)) {
22
+ for (const item of value) {
23
+ if (detectCircular(item)) {
24
+ return true;
25
+ }
26
+ }
27
+ return false;
28
+ }
29
+ // For objects, check each own enumerable property
30
+ const keys = Object.keys(value);
31
+ for (const key of keys) {
32
+ if (detectCircular(value[key])) {
33
+ return true;
34
+ }
35
+ }
36
+ return false;
37
+ };
38
+ return detectCircular(obj);
39
+ }
40
+ //# sourceMappingURL=has-circular-reference.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"has-circular-reference.js","sourceRoot":"","sources":["../../src/object/has-circular-reference.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CAAC,GAAY;IACtD,MAAM,IAAI,GAAG,IAAI,OAAO,EAAE,CAAC;IAE3B,MAAM,cAAc,GAAG,CAAC,KAAc,EAAW,EAAE;QAClD,yDAAyD;QACzD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACjD,OAAO,KAAK,CAAC;QACd,CAAC;QAED,8DAA8D;QAC9D,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC;QACb,CAAC;QAED,2BAA2B;QAC3B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAEhB,iCAAiC;QACjC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBAC1B,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC1B,OAAO,IAAI,CAAC;gBACb,CAAC;YACF,CAAC;YAED,OAAO,KAAK,CAAC;QACd,CAAC;QAED,kDAAkD;QAClD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAgC,CAAC,CAAC;QAE3D,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACxB,IAAI,cAAc,CAAE,KAAiC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBAC7D,OAAO,IAAI,CAAC;YACb,CAAC;QACF,CAAC;QAED,OAAO,KAAK,CAAC;IACd,CAAC,CAAC;IAEF,OAAO,cAAc,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC"}