@ls-stack/utils 3.24.1 → 3.25.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 (56) hide show
  1. package/docs/_media/modules.md +1 -0
  2. package/docs/arrayUtils/-internal-.md +1 -1
  3. package/docs/arrayUtils/README.md +12 -12
  4. package/docs/consoleFmt.md +2 -2
  5. package/docs/exhaustiveMatch/-internal-.md +1 -1
  6. package/docs/exhaustiveMatch/README.md +1 -1
  7. package/docs/filterObjectOrArrayKeys.md +80 -0
  8. package/docs/modules.md +1 -0
  9. package/docs/objUtils.md +7 -7
  10. package/docs/parallelAsyncCalls/-internal-.md +3 -3
  11. package/docs/parallelAsyncCalls/README.md +1 -1
  12. package/docs/retryOnError/README.md +1 -1
  13. package/docs/runShellCmd/README.md +9 -9
  14. package/docs/safeJson.md +2 -2
  15. package/docs/saferTyping.md +7 -7
  16. package/docs/stringUtils/README.md +6 -6
  17. package/docs/testUtils.md +40 -6
  18. package/docs/time.md +1 -1
  19. package/docs/tsResult/README.md +17 -11
  20. package/docs/typingFnUtils/-internal-.md +1 -1
  21. package/docs/typingFnUtils/README.md +8 -10
  22. package/lib/arrayUtils.d.cts +6 -1
  23. package/lib/arrayUtils.d.ts +6 -1
  24. package/lib/{chunk-JAPKLFIK.js → chunk-QLD7KG5I.js} +34 -20
  25. package/lib/chunk-XXYTMSFH.js +240 -0
  26. package/lib/filterObjectOrArrayKeys.cjs +275 -0
  27. package/lib/filterObjectOrArrayKeys.d.cts +42 -0
  28. package/lib/filterObjectOrArrayKeys.d.ts +42 -0
  29. package/lib/filterObjectOrArrayKeys.js +7 -0
  30. package/lib/objUtils.d.cts +4 -1
  31. package/lib/objUtils.d.ts +4 -1
  32. package/lib/parallelAsyncCalls.cjs +4 -1
  33. package/lib/parallelAsyncCalls.d.cts +4 -1
  34. package/lib/parallelAsyncCalls.d.ts +4 -1
  35. package/lib/parallelAsyncCalls.js +4 -1
  36. package/lib/retryOnError.d.cts +2 -0
  37. package/lib/retryOnError.d.ts +2 -0
  38. package/lib/runShellCmd.d.cts +17 -0
  39. package/lib/runShellCmd.d.ts +17 -0
  40. package/lib/safeJson.d.cts +8 -2
  41. package/lib/safeJson.d.ts +8 -2
  42. package/lib/saferTyping.d.cts +3 -0
  43. package/lib/saferTyping.d.ts +3 -0
  44. package/lib/stringUtils.d.cts +1 -0
  45. package/lib/stringUtils.d.ts +1 -0
  46. package/lib/testUtils.cjs +273 -144
  47. package/lib/testUtils.d.cts +40 -12
  48. package/lib/testUtils.d.ts +40 -12
  49. package/lib/testUtils.js +10 -125
  50. package/lib/tsResult.d.cts +31 -7
  51. package/lib/tsResult.d.ts +31 -7
  52. package/lib/typingFnUtils.d.cts +20 -6
  53. package/lib/typingFnUtils.d.ts +20 -6
  54. package/lib/yamlStringify.cjs +34 -20
  55. package/lib/yamlStringify.js +1 -1
  56. package/package.json +5 -1
package/lib/testUtils.cjs CHANGED
@@ -131,6 +131,239 @@ function deepEqual(foo, bar, maxDepth = 20) {
131
131
  return foo !== foo && bar !== bar;
132
132
  }
133
133
 
134
+ // src/filterObjectOrArrayKeys.ts
135
+ function filterObjectOrArrayKeys(objOrArray, {
136
+ filterKeys,
137
+ rejectKeys,
138
+ rejectEmptyObjectsInArray = true
139
+ }) {
140
+ const toArray = (v) => v === void 0 ? [] : Array.isArray(v) ? v : [v];
141
+ const filterPatternsRaw = toArray(filterKeys);
142
+ const rejectPatternsRaw = toArray(rejectKeys);
143
+ const hasFilters = filterPatternsRaw.length > 0;
144
+ const hasRejects = rejectPatternsRaw.length > 0;
145
+ function parsePattern(pattern) {
146
+ const tokens = [];
147
+ let i = 0;
148
+ const n = pattern.length;
149
+ const pushKey = (name) => {
150
+ if (name.length === 0) return;
151
+ tokens.push({ type: "KEY", name });
152
+ };
153
+ while (i < n) {
154
+ const ch = pattern[i];
155
+ if (ch === ".") {
156
+ i += 1;
157
+ continue;
158
+ }
159
+ if (ch === "[") {
160
+ const end = pattern.indexOf("]", i + 1);
161
+ const inside = end === -1 ? pattern.slice(i + 1) : pattern.slice(i + 1, end);
162
+ if (inside === "*") {
163
+ tokens.push({ type: "INDEX_ANY" });
164
+ } else if (inside.includes("-")) {
165
+ const parts = inside.split("-");
166
+ const startStr = parts[0] ?? "";
167
+ const endStr = parts[1] ?? "";
168
+ const start = parseInt(startStr, 10);
169
+ const endNum = endStr === "*" ? null : parseInt(endStr, 10);
170
+ tokens.push({
171
+ type: "INDEX_RANGE",
172
+ start,
173
+ end: endNum === null || Number.isFinite(endNum) ? endNum : null
174
+ });
175
+ } else if (inside.length > 0) {
176
+ const idx = parseInt(inside, 10);
177
+ tokens.push({ type: "INDEX", index: idx });
178
+ }
179
+ i = end === -1 ? n : end + 1;
180
+ continue;
181
+ }
182
+ if (ch === "*") {
183
+ if (pattern[i + 1] === "*") {
184
+ tokens.push({ type: "WILDCARD_ANY" });
185
+ i += 2;
186
+ let j2 = i;
187
+ while (j2 < n) {
188
+ const c = pattern[j2];
189
+ if (c === "." || c === "[") break;
190
+ j2 += 1;
191
+ }
192
+ if (j2 > i) {
193
+ pushKey(pattern.slice(i, j2));
194
+ i = j2;
195
+ }
196
+ continue;
197
+ } else {
198
+ tokens.push({ type: "WILDCARD_ONE" });
199
+ i += 1;
200
+ continue;
201
+ }
202
+ }
203
+ let j = i;
204
+ while (j < n) {
205
+ const c = pattern[j];
206
+ if (c === "." || c === "[") break;
207
+ j += 1;
208
+ }
209
+ pushKey(pattern.slice(i, j));
210
+ i = j;
211
+ }
212
+ return tokens;
213
+ }
214
+ const filterPatterns = filterPatternsRaw.map(parsePattern);
215
+ const rejectPatterns = rejectPatternsRaw.map(parsePattern);
216
+ function matchPath(path, pattern) {
217
+ function rec(pi, pti) {
218
+ if (pti >= pattern.length) return pi === path.length;
219
+ const pt = pattern[pti];
220
+ if (pt.type === "WILDCARD_ANY") {
221
+ if (rec(pi, pti + 1)) return true;
222
+ if (pi < path.length) return rec(pi + 1, pti);
223
+ return false;
224
+ }
225
+ if (pt.type === "WILDCARD_ONE") {
226
+ let j = pi;
227
+ let sawKey = false;
228
+ while (j < path.length) {
229
+ if (path[j].type === "KEY") sawKey = true;
230
+ if (sawKey && rec(j, pti + 1)) return true;
231
+ j += 1;
232
+ }
233
+ return false;
234
+ }
235
+ if (pi >= path.length) return false;
236
+ const ct = path[pi];
237
+ switch (pt.type) {
238
+ case "KEY":
239
+ if (ct.type === "KEY" && ct.name === pt.name)
240
+ return rec(pi + 1, pti + 1);
241
+ if (ct.type === "INDEX") return rec(pi + 1, pti);
242
+ return false;
243
+ case "INDEX":
244
+ if (ct.type === "INDEX" && ct.index === pt.index)
245
+ return rec(pi + 1, pti + 1);
246
+ return false;
247
+ case "INDEX_ANY":
248
+ if (ct.type === "INDEX") return rec(pi + 1, pti + 1);
249
+ return false;
250
+ case "INDEX_RANGE":
251
+ if (ct.type === "INDEX") {
252
+ const okLower = ct.index >= pt.start;
253
+ const okUpper = pt.end === null ? true : ct.index <= pt.end;
254
+ if (okLower && okUpper) return rec(pi + 1, pti + 1);
255
+ }
256
+ return false;
257
+ }
258
+ }
259
+ return rec(0, 0);
260
+ }
261
+ const matchesAnyFilter = (path) => filterPatterns.some((p) => matchPath(path, p));
262
+ const matchesAnyReject = (path) => rejectPatterns.some((p) => matchPath(path, p));
263
+ const build = (value, path, allowedByFilter, stack2, isRoot, parentIsArray) => {
264
+ if (Array.isArray(value)) {
265
+ if (stack2.has(value)) {
266
+ throw new TypeError("Circular references are not supported");
267
+ }
268
+ stack2.add(value);
269
+ const out = [];
270
+ const includeAllChildren = allowedByFilter || !hasFilters;
271
+ for (let index = 0; index < value.length; index += 1) {
272
+ const childPath = path.concat({ type: "INDEX", index });
273
+ if (hasRejects && matchesAnyReject(childPath)) continue;
274
+ const child = value[index];
275
+ const directInclude = hasFilters ? matchesAnyFilter(childPath) : true;
276
+ const childAllowed = includeAllChildren || directInclude;
277
+ if (isPlainObject(child) || Array.isArray(child)) {
278
+ const builtChild = build(
279
+ child,
280
+ childPath,
281
+ childAllowed,
282
+ stack2,
283
+ false,
284
+ true
285
+ );
286
+ if (builtChild !== void 0) {
287
+ out.push(builtChild);
288
+ }
289
+ } else {
290
+ if (childAllowed) {
291
+ out.push(child);
292
+ }
293
+ }
294
+ }
295
+ stack2.delete(value);
296
+ const filteredOut = rejectEmptyObjectsInArray ? out.filter(
297
+ (item) => !(isPlainObject(item) && Object.keys(item).length === 0)
298
+ ) : out;
299
+ if (filteredOut.length === 0 && !allowedByFilter && !isRoot)
300
+ return void 0;
301
+ return filteredOut;
302
+ }
303
+ if (isPlainObject(value)) {
304
+ if (stack2.has(value)) {
305
+ throw new TypeError("Circular references are not supported");
306
+ }
307
+ stack2.add(value);
308
+ const result = {};
309
+ const includeAllChildren = allowedByFilter || !hasFilters;
310
+ for (const key of Object.keys(value)) {
311
+ const childPath = path.concat({ type: "KEY", name: key });
312
+ if (hasRejects && matchesAnyReject(childPath)) continue;
313
+ const val = value[key];
314
+ const directInclude = hasFilters ? matchesAnyFilter(childPath) : true;
315
+ const childAllowed = includeAllChildren || directInclude;
316
+ if (isPlainObject(val) || Array.isArray(val)) {
317
+ const builtChild = build(
318
+ val,
319
+ childPath,
320
+ childAllowed,
321
+ stack2,
322
+ false,
323
+ false
324
+ );
325
+ if (builtChild === void 0) {
326
+ continue;
327
+ }
328
+ if (Array.isArray(builtChild) && builtChild.length === 0 && !childAllowed) {
329
+ continue;
330
+ }
331
+ if (isPlainObject(builtChild) && Object.keys(builtChild).length === 0 && !childAllowed) {
332
+ continue;
333
+ }
334
+ result[key] = builtChild;
335
+ } else {
336
+ if (childAllowed) {
337
+ result[key] = val;
338
+ }
339
+ }
340
+ }
341
+ stack2.delete(value);
342
+ if (Object.keys(result).length === 0 && !allowedByFilter && !isRoot) {
343
+ if (parentIsArray && !rejectEmptyObjectsInArray) {
344
+ return {};
345
+ }
346
+ return void 0;
347
+ }
348
+ return result;
349
+ }
350
+ return allowedByFilter || !hasFilters ? value : void 0;
351
+ };
352
+ const startPath = [];
353
+ const initialAllowed = !hasFilters;
354
+ const stack = /* @__PURE__ */ new WeakSet();
355
+ const built = build(
356
+ objOrArray,
357
+ startPath,
358
+ initialAllowed,
359
+ stack,
360
+ true,
361
+ false
362
+ );
363
+ if (built === void 0) return Array.isArray(objOrArray) ? [] : {};
364
+ return built;
365
+ }
366
+
134
367
  // src/mathUtils.ts
135
368
  function clampMin(value, min) {
136
369
  return value < min ? min : value;
@@ -197,12 +430,12 @@ function yamlStringify(obj, {
197
430
  addRootObjSpaces = "beforeAndAfter"
198
431
  } = {}) {
199
432
  if (isObject(obj) || Array.isArray(obj) || typeof obj === "function") {
200
- return `${stringifyValue(obj, "", maxLineLength, !!showUndefined, maxDepth, 0, collapseObjects, addRootObjSpaces)}
433
+ return `${stringifyValue(obj, "", maxLineLength, !!showUndefined, maxDepth, 0, collapseObjects, addRootObjSpaces, false)}
201
434
  `;
202
435
  }
203
436
  return JSON.stringify(obj) || "undefined";
204
437
  }
205
- function stringifyValue(value, indent, maxLineLength, showUndefined, maxDepth, depth, collapseObjects, addObjSpaces) {
438
+ function stringifyValue(value, indent, maxLineLength, showUndefined, maxDepth, depth, collapseObjects, addObjSpaces, isArrayItem) {
206
439
  let result = "";
207
440
  const childIndent = `${indent} `;
208
441
  if (isPlainObject(value)) {
@@ -221,7 +454,8 @@ function stringifyValue(value, indent, maxLineLength, showUndefined, maxDepth, d
221
454
  return typeof val === "number" || typeof val === "boolean" || val === null || val === void 0;
222
455
  }
223
456
  );
224
- if (isSimpleObject && entries.length > 0) {
457
+ const shouldCollapse = isArrayItem ? entries.length > 1 : entries.length > 0;
458
+ if (isSimpleObject && shouldCollapse) {
225
459
  let line = "{ ";
226
460
  line += entries.map(([key, val]) => {
227
461
  let valueStr;
@@ -268,20 +502,29 @@ function stringifyValue(value, indent, maxLineLength, showUndefined, maxDepth, d
268
502
  maxDepth,
269
503
  depth + 1,
270
504
  collapseObjects,
271
- addObjSpaces
505
+ addObjSpaces,
506
+ false
272
507
  );
273
- const willBeCollapsed = isObject(objVal) && (Object.keys(objVal).length === 0 || collapseObjects && depth + 1 > 0 && Object.entries(objVal).filter(([, val]) => val !== void 0 || showUndefined).every(([, val]) => {
274
- if (typeof val === "string") {
275
- return !val.includes("'") && !val.includes('"') && !val.includes("\\");
276
- }
277
- return typeof val === "number" || typeof val === "boolean" || val === null || val === void 0;
278
- }));
279
- const prevWasCollapsed = prevValue && isObject(prevValue) && (Object.keys(prevValue).length === 0 || collapseObjects && depth + 1 > 0 && Object.entries(prevValue).filter(([, val]) => val !== void 0 || showUndefined).every(([, val]) => {
280
- if (typeof val === "string") {
281
- return !val.includes("'") && !val.includes('"') && !val.includes("\\");
282
- }
283
- return typeof val === "number" || typeof val === "boolean" || val === null || val === void 0;
284
- }));
508
+ const willBeCollapsed = isObject(objVal) && (Object.keys(objVal).length === 0 || collapseObjects && depth + 1 > 0 && (() => {
509
+ const filteredEntries = Object.entries(objVal).filter(([, val]) => val !== void 0 || showUndefined);
510
+ const shouldCollapseThis = isArrayItem ? filteredEntries.length > 1 : filteredEntries.length > 0;
511
+ return shouldCollapseThis && filteredEntries.every(([, val]) => {
512
+ if (typeof val === "string") {
513
+ return !val.includes("'") && !val.includes('"') && !val.includes("\\");
514
+ }
515
+ return typeof val === "number" || typeof val === "boolean" || val === null || val === void 0;
516
+ });
517
+ })());
518
+ const prevWasCollapsed = prevValue && isObject(prevValue) && (Object.keys(prevValue).length === 0 || collapseObjects && depth + 1 > 0 && (() => {
519
+ const filteredEntries = Object.entries(prevValue).filter(([, val]) => val !== void 0 || showUndefined);
520
+ const shouldCollapseThis = isArrayItem ? filteredEntries.length > 1 : filteredEntries.length > 0;
521
+ return shouldCollapseThis && filteredEntries.every(([, val]) => {
522
+ if (typeof val === "string") {
523
+ return !val.includes("'") && !val.includes('"') && !val.includes("\\");
524
+ }
525
+ return typeof val === "number" || typeof val === "boolean" || val === null || val === void 0;
526
+ });
527
+ })());
285
528
  if (!afterSpaceWasAdded && indent === "" && isObject(objVal) && !willBeCollapsed && prevValue && !prevWasCollapsed && (addObjSpaces === "before" || addObjSpaces === "beforeAndAfter")) {
286
529
  result += "\n";
287
530
  }
@@ -344,7 +587,8 @@ function stringifyValue(value, indent, maxLineLength, showUndefined, maxDepth, d
344
587
  maxDepth,
345
588
  depth + 1,
346
589
  collapseObjects,
347
- addObjSpaces
590
+ addObjSpaces,
591
+ true
348
592
  );
349
593
  }).join(", ");
350
594
  line += "]";
@@ -368,7 +612,8 @@ function stringifyValue(value, indent, maxLineLength, showUndefined, maxDepth, d
368
612
  maxDepth,
369
613
  depth + 1,
370
614
  collapseObjects,
371
- addObjSpaces
615
+ addObjSpaces,
616
+ true
372
617
  );
373
618
  arrayString = arrayString.trimStart();
374
619
  result += arrayString;
@@ -381,7 +626,8 @@ function stringifyValue(value, indent, maxLineLength, showUndefined, maxDepth, d
381
626
  maxDepth,
382
627
  depth + 1,
383
628
  collapseObjects,
384
- addObjSpaces
629
+ addObjSpaces,
630
+ true
385
631
  );
386
632
  }
387
633
  result += "\n";
@@ -435,7 +681,8 @@ ${indent}${line}
435
681
  maxDepth,
436
682
  depth + 1,
437
683
  collapseObjects,
438
- addObjSpaces
684
+ addObjSpaces,
685
+ false
439
686
  );
440
687
  }
441
688
  return JSON.stringify(value);
@@ -753,126 +1000,6 @@ function waitController() {
753
1000
  }
754
1001
  };
755
1002
  }
756
- function matchesKeyPattern(fullPath, key, pattern, currentPath) {
757
- if (fullPath === pattern) {
758
- return true;
759
- }
760
- if (pattern.startsWith("*.")) {
761
- const propName = pattern.slice(2);
762
- return currentPath !== "" && key === propName;
763
- }
764
- if (pattern.startsWith("*") && !pattern.startsWith("*.")) {
765
- const propName = pattern.slice(1);
766
- return key === propName;
767
- }
768
- if (!pattern.includes("*")) {
769
- return currentPath === "" && key === pattern;
770
- }
771
- return false;
772
- }
773
- function isParentOfPattern(path, pattern) {
774
- if (pattern.includes("*")) {
775
- const patternParts = pattern.split(".");
776
- const pathParts = path.split(".");
777
- if (pathParts.length >= patternParts.length) {
778
- return false;
779
- }
780
- for (let i = 0; i < pathParts.length; i++) {
781
- const pathPart = pathParts[i];
782
- const patternPart = patternParts[i];
783
- if (patternPart === "*") {
784
- continue;
785
- }
786
- if (pathPart !== patternPart) {
787
- return false;
788
- }
789
- }
790
- return true;
791
- } else {
792
- return pattern.startsWith(`${path}.`);
793
- }
794
- }
795
- function applyKeyFiltering(value, { rejectKeys, filterKeys }, currentPath = "", visited = /* @__PURE__ */ new Set()) {
796
- if (!isPlainObject(value) && !Array.isArray(value)) {
797
- return value;
798
- }
799
- if (Array.isArray(value)) {
800
- if (visited.has(value)) {
801
- throw new Error(
802
- "Circular reference detected in array during key filtering"
803
- );
804
- }
805
- visited.add(value);
806
- try {
807
- return value.map(
808
- (item, index) => applyKeyFiltering(
809
- item,
810
- { rejectKeys, filterKeys },
811
- currentPath ? `${currentPath}[${index}]` : `[${index}]`,
812
- visited
813
- )
814
- );
815
- } finally {
816
- visited.delete(value);
817
- }
818
- }
819
- if (isPlainObject(value)) {
820
- if (visited.has(value)) {
821
- throw new Error(
822
- "Circular reference detected in object during key filtering"
823
- );
824
- }
825
- visited.add(value);
826
- try {
827
- const result = {};
828
- for (const [key, itemValue] of Object.entries(value)) {
829
- const fullPath = currentPath ? `${currentPath}.${key}` : key;
830
- if (rejectKeys?.some(
831
- (rejectPath) => matchesKeyPattern(fullPath, key, rejectPath, currentPath)
832
- )) {
833
- continue;
834
- }
835
- if (filterKeys) {
836
- const exactMatch = filterKeys.some(
837
- (filterPath) => matchesKeyPattern(fullPath, key, filterPath, currentPath)
838
- );
839
- const isParent = filterKeys.some(
840
- (filterPath) => isParentOfPattern(fullPath, filterPath)
841
- );
842
- if (!exactMatch && !isParent) {
843
- continue;
844
- }
845
- if (exactMatch) {
846
- result[key] = applyKeyFiltering(
847
- itemValue,
848
- { rejectKeys },
849
- fullPath,
850
- visited
851
- );
852
- } else {
853
- result[key] = applyKeyFiltering(
854
- itemValue,
855
- { rejectKeys, filterKeys },
856
- fullPath,
857
- visited
858
- );
859
- }
860
- } else {
861
- result[key] = applyKeyFiltering(
862
- itemValue,
863
- { rejectKeys, filterKeys },
864
- fullPath,
865
- visited
866
- );
867
- }
868
- }
869
- return result;
870
- } finally {
871
- visited.delete(value);
872
- }
873
- }
874
- return value;
875
- }
876
1003
  function compactSnapshot(value, {
877
1004
  collapseObjects = true,
878
1005
  maxLineLength = 100,
@@ -884,10 +1011,12 @@ function compactSnapshot(value, {
884
1011
  } = {}) {
885
1012
  let processedValue = value;
886
1013
  if (rejectKeys || filterKeys) {
887
- processedValue = applyKeyFiltering(processedValue, {
888
- rejectKeys: Array.isArray(rejectKeys) ? rejectKeys : rejectKeys ? [rejectKeys] : void 0,
889
- filterKeys: Array.isArray(filterKeys) ? filterKeys : filterKeys ? [filterKeys] : void 0
890
- });
1014
+ if (isPlainObject(processedValue) || Array.isArray(processedValue)) {
1015
+ processedValue = filterObjectOrArrayKeys(processedValue, {
1016
+ rejectKeys,
1017
+ filterKeys
1018
+ });
1019
+ }
891
1020
  }
892
1021
  processedValue = showBooleansAs ? replaceBooleansWithEmoji(processedValue, showBooleansAs) : processedValue;
893
1022
  return `
@@ -41,6 +41,46 @@ declare function waitController(): {
41
41
  stopWaiting: () => void;
42
42
  stopWaitingAfter: (ms: number) => void;
43
43
  };
44
+ /**
45
+ * Produces a more compact and readable snapshot of a value using yaml.
46
+ * By default booleans are shown as `✅` and `❌`, use `showBooleansAs` to disable/configure this.
47
+ *
48
+ * Filtering patterns in `rejectKeys` and `filterKeys`:
49
+ * - `'prop'` - Only root-level properties named 'prop'
50
+ * - `'**prop'` - Any property named exactly 'prop' at any level (root or nested)
51
+ * - `'*.prop'` - Any nested property named 'prop' at second level (excludes root-level matches)
52
+ * - `'test.*.prop'` - Any property named 'prop' at second level of 'test'
53
+ * - `'test.*.test.**prop'` - Any property named 'prop' inside of 'test.*.test'
54
+ * - `'prop.nested'` - Exact nested property paths like `obj.prop.nested`
55
+ * - `'prop.**nested'` - All nested properties inside root `prop` with name `nested`
56
+ * - `'prop[0]'` - The first item of the `prop` array
57
+ * - `'prop[*]'` - All items of the `prop` array
58
+ * - `'prop[0].nested'` - `nested` prop of the first item of the `prop` array
59
+ * - `'prop[*].nested'` - `nested` prop of all items of the `prop` array
60
+ * - `'prop[*]**nested'` - all `nested` props of all items of the `prop` array
61
+ * - `'prop[0-2]'` - The first three items of the `prop` array
62
+ * - `'prop[4-*]'` - All items of the `prop` array from the fourth index to the end
63
+ * - `'prop[0-2].nested.**prop'` - Combining multiple nested patterns is supported
64
+ * - Root array:
65
+ * - `'[0]'` - The first item of the root array
66
+ * - `'[*]'` - All items of the array
67
+ * - `'[0].nested'` - `nested` prop of the first item of the array
68
+ * - `'[*].nested'` - `nested` prop of all items of the array
69
+ * - `'[*]**nested'` - all `nested` props of all items of the array
70
+ * - `'[0-2]'` - The first three items of the array
71
+ * - `'[4-*]'` - All items of the array from the fourth index to the end
72
+ *
73
+ * @param value - The value to snapshot.
74
+ * @param options - The options for the snapshot.
75
+ * @param options.collapseObjects - Whether to collapse objects into a single line.
76
+ * @param options.maxLineLength - The maximum length of a line.
77
+ * @param options.showUndefined - Whether to show undefined values.
78
+ * @param options.showBooleansAs - Whether to show booleans as text, by default true is `✅` and false is `❌`
79
+ * @param options.rejectKeys - The keys to reject.
80
+ * @param options.filterKeys - The keys to filter.
81
+ * @param options.ignoreProps - The props to ignore.
82
+ * @returns The compact snapshot of the value.
83
+ */
44
84
  declare function compactSnapshot(value: unknown, { collapseObjects, maxLineLength, showUndefined, showBooleansAs, rejectKeys, filterKeys, ...options }?: YamlStringifyOptions & {
45
85
  showBooleansAs?: boolean | {
46
86
  props?: Record<string, {
@@ -54,12 +94,6 @@ declare function compactSnapshot(value: unknown, { collapseObjects, maxLineLengt
54
94
  /**
55
95
  * Reject (exclude) keys from the snapshot using pattern matching.
56
96
  *
57
- * **Pattern Syntax:**
58
- * - `'prop'` - Only root-level properties named 'prop'
59
- * - `'prop.nested'` - Exact nested property paths like `obj.prop.nested`
60
- * - `'*prop'` - Any property named exactly 'prop' at any level (root or nested)
61
- * - `'*.prop'` - Any nested property named 'prop' (excludes root-level matches)
62
- *
63
97
  * **Examples:**
64
98
  * ```typescript
65
99
  * // Reject root-level 'secret' only
@@ -79,12 +113,6 @@ declare function compactSnapshot(value: unknown, { collapseObjects, maxLineLengt
79
113
  /**
80
114
  * Filter (include only) keys that match the specified patterns.
81
115
  *
82
- * **Pattern Syntax:** (same as rejectKeys)
83
- * - `'prop'` - Only root-level properties named 'prop'
84
- * - `'prop.nested'` - Exact nested property paths like `obj.prop.nested`
85
- * - `'*prop'` - Any property named exactly 'prop' at any level (root or nested)
86
- * - `'*.prop'` - Any nested property named 'prop' (excludes root-level matches)
87
- *
88
116
  * **Examples:**
89
117
  * ```typescript
90
118
  * // Include only root-level 'user'
@@ -41,6 +41,46 @@ declare function waitController(): {
41
41
  stopWaiting: () => void;
42
42
  stopWaitingAfter: (ms: number) => void;
43
43
  };
44
+ /**
45
+ * Produces a more compact and readable snapshot of a value using yaml.
46
+ * By default booleans are shown as `✅` and `❌`, use `showBooleansAs` to disable/configure this.
47
+ *
48
+ * Filtering patterns in `rejectKeys` and `filterKeys`:
49
+ * - `'prop'` - Only root-level properties named 'prop'
50
+ * - `'**prop'` - Any property named exactly 'prop' at any level (root or nested)
51
+ * - `'*.prop'` - Any nested property named 'prop' at second level (excludes root-level matches)
52
+ * - `'test.*.prop'` - Any property named 'prop' at second level of 'test'
53
+ * - `'test.*.test.**prop'` - Any property named 'prop' inside of 'test.*.test'
54
+ * - `'prop.nested'` - Exact nested property paths like `obj.prop.nested`
55
+ * - `'prop.**nested'` - All nested properties inside root `prop` with name `nested`
56
+ * - `'prop[0]'` - The first item of the `prop` array
57
+ * - `'prop[*]'` - All items of the `prop` array
58
+ * - `'prop[0].nested'` - `nested` prop of the first item of the `prop` array
59
+ * - `'prop[*].nested'` - `nested` prop of all items of the `prop` array
60
+ * - `'prop[*]**nested'` - all `nested` props of all items of the `prop` array
61
+ * - `'prop[0-2]'` - The first three items of the `prop` array
62
+ * - `'prop[4-*]'` - All items of the `prop` array from the fourth index to the end
63
+ * - `'prop[0-2].nested.**prop'` - Combining multiple nested patterns is supported
64
+ * - Root array:
65
+ * - `'[0]'` - The first item of the root array
66
+ * - `'[*]'` - All items of the array
67
+ * - `'[0].nested'` - `nested` prop of the first item of the array
68
+ * - `'[*].nested'` - `nested` prop of all items of the array
69
+ * - `'[*]**nested'` - all `nested` props of all items of the array
70
+ * - `'[0-2]'` - The first three items of the array
71
+ * - `'[4-*]'` - All items of the array from the fourth index to the end
72
+ *
73
+ * @param value - The value to snapshot.
74
+ * @param options - The options for the snapshot.
75
+ * @param options.collapseObjects - Whether to collapse objects into a single line.
76
+ * @param options.maxLineLength - The maximum length of a line.
77
+ * @param options.showUndefined - Whether to show undefined values.
78
+ * @param options.showBooleansAs - Whether to show booleans as text, by default true is `✅` and false is `❌`
79
+ * @param options.rejectKeys - The keys to reject.
80
+ * @param options.filterKeys - The keys to filter.
81
+ * @param options.ignoreProps - The props to ignore.
82
+ * @returns The compact snapshot of the value.
83
+ */
44
84
  declare function compactSnapshot(value: unknown, { collapseObjects, maxLineLength, showUndefined, showBooleansAs, rejectKeys, filterKeys, ...options }?: YamlStringifyOptions & {
45
85
  showBooleansAs?: boolean | {
46
86
  props?: Record<string, {
@@ -54,12 +94,6 @@ declare function compactSnapshot(value: unknown, { collapseObjects, maxLineLengt
54
94
  /**
55
95
  * Reject (exclude) keys from the snapshot using pattern matching.
56
96
  *
57
- * **Pattern Syntax:**
58
- * - `'prop'` - Only root-level properties named 'prop'
59
- * - `'prop.nested'` - Exact nested property paths like `obj.prop.nested`
60
- * - `'*prop'` - Any property named exactly 'prop' at any level (root or nested)
61
- * - `'*.prop'` - Any nested property named 'prop' (excludes root-level matches)
62
- *
63
97
  * **Examples:**
64
98
  * ```typescript
65
99
  * // Reject root-level 'secret' only
@@ -79,12 +113,6 @@ declare function compactSnapshot(value: unknown, { collapseObjects, maxLineLengt
79
113
  /**
80
114
  * Filter (include only) keys that match the specified patterns.
81
115
  *
82
- * **Pattern Syntax:** (same as rejectKeys)
83
- * - `'prop'` - Only root-level properties named 'prop'
84
- * - `'prop.nested'` - Exact nested property paths like `obj.prop.nested`
85
- * - `'*prop'` - Any property named exactly 'prop' at any level (root or nested)
86
- * - `'*.prop'` - Any nested property named 'prop' (excludes root-level matches)
87
- *
88
116
  * **Examples:**
89
117
  * ```typescript
90
118
  * // Include only root-level 'user'