@ls-stack/utils 3.24.1 → 3.26.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 +82 -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-FXRZ4RQU.js +257 -0
  25. package/lib/{chunk-JAPKLFIK.js → chunk-QLD7KG5I.js} +34 -20
  26. package/lib/filterObjectOrArrayKeys.cjs +292 -0
  27. package/lib/filterObjectOrArrayKeys.d.cts +44 -0
  28. package/lib/filterObjectOrArrayKeys.d.ts +44 -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 +290 -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
@@ -13,6 +13,14 @@ type RunCmdOptions = {
13
13
  noCiColorForce?: boolean;
14
14
  };
15
15
  /**
16
+ * @param label
17
+ * @param command
18
+ * @param root0
19
+ * @param root0.mock
20
+ * @param root0.silent
21
+ * @param root0.throwOnError
22
+ * @param root0.cwd
23
+ * @param root0.noCiColorForce
16
24
  * @deprecated This utility has been moved to @ls-stack/node-utils. Please update your imports:
17
25
  * ```
18
26
  * // Old (deprecated)
@@ -24,6 +32,9 @@ type RunCmdOptions = {
24
32
  */
25
33
  declare function runCmd(label: string | null, command: string | string[], { mock, silent, throwOnError, cwd, noCiColorForce, }?: RunCmdOptions): Promise<CmdResult>;
26
34
  /**
35
+ * @param label
36
+ * @param cmd
37
+ * @param onResult
27
38
  * @deprecated This utility has been moved to @ls-stack/node-utils. Please update your imports:
28
39
  * ```
29
40
  * // Old (deprecated)
@@ -35,6 +46,10 @@ declare function runCmd(label: string | null, command: string | string[], { mock
35
46
  */
36
47
  declare function concurrentCmd(label: string, cmd: string | string[], onResult: (result: CmdResult) => void): Promise<() => void>;
37
48
  /**
49
+ * @param label
50
+ * @param command
51
+ * @param root0
52
+ * @param root0.silent
38
53
  * @deprecated This utility has been moved to @ls-stack/node-utils. Please update your imports:
39
54
  * ```
40
55
  * // Old (deprecated)
@@ -48,6 +63,7 @@ declare function runCmdUnwrap(label: string | null, command: string | string[],
48
63
  silent?: boolean | 'timeOnly';
49
64
  }): Promise<string>;
50
65
  /**
66
+ * @param command
51
67
  * @deprecated This utility has been moved to @ls-stack/node-utils. Please update your imports:
52
68
  * ```
53
69
  * // Old (deprecated)
@@ -59,6 +75,7 @@ declare function runCmdUnwrap(label: string | null, command: string | string[],
59
75
  */
60
76
  declare function runCmdSilent(command: string | string[]): Promise<CmdResult>;
61
77
  /**
78
+ * @param command
62
79
  * @deprecated This utility has been moved to @ls-stack/node-utils. Please update your imports:
63
80
  * ```
64
81
  * // Old (deprecated)
@@ -1,6 +1,12 @@
1
- /** JSON.stringify can throw if the value is circular or contains functions, this function catches those errors and returns undefined */
1
+ /**
2
+ * JSON.stringify can throw if the value is circular or contains functions, this function catches those errors and returns undefined
3
+ * @param value
4
+ */
2
5
  declare function safeJsonStringify(value: unknown): string | undefined;
3
- /** JSON.parse can throw if the value is not valid JSON, this function catches those errors and returns undefined */
6
+ /**
7
+ * JSON.parse can throw if the value is not valid JSON, this function catches those errors and returns undefined
8
+ * @param value
9
+ */
4
10
  declare function safeJsonParse(value: string): unknown;
5
11
 
6
12
  export { safeJsonParse, safeJsonStringify };
package/lib/safeJson.d.ts CHANGED
@@ -1,6 +1,12 @@
1
- /** JSON.stringify can throw if the value is circular or contains functions, this function catches those errors and returns undefined */
1
+ /**
2
+ * JSON.stringify can throw if the value is circular or contains functions, this function catches those errors and returns undefined
3
+ * @param value
4
+ */
2
5
  declare function safeJsonStringify(value: unknown): string | undefined;
3
- /** JSON.parse can throw if the value is not valid JSON, this function catches those errors and returns undefined */
6
+ /**
7
+ * JSON.parse can throw if the value is not valid JSON, this function catches those errors and returns undefined
8
+ * @param value
9
+ */
4
10
  declare function safeJsonParse(value: string): unknown;
5
11
 
6
12
  export { safeJsonParse, safeJsonStringify };
@@ -8,12 +8,14 @@ type EmptyObject = Record<string, never>;
8
8
  /**
9
9
  * Cast a value to `any` type. Use this when you have legit usage of `any` casting.
10
10
  *
11
+ * @param value
11
12
  * @template V (optional) - When used enforces that the casted value is assignable to the type V, use it for safer casts
12
13
  */
13
14
  declare function __LEGIT_ANY_CAST__<V = unknown>(value: V): __LEGIT_ANY__;
14
15
  /**
15
16
  * Cast a value to a specific type T. Use this when you have legit usage of type assertion.
16
17
  *
18
+ * @param value
17
19
  * @template T - The type to cast to
18
20
  * @template V (optional) - When used enforces that the casted value is assignable to the type V, use it for safer casts
19
21
  */
@@ -21,6 +23,7 @@ declare function __LEGIT_CAST__<T, V = unknown>(value: V): T;
21
23
  /**
22
24
  * Refine a value to a specific type T. Use this when you have legit usage of type assertion.
23
25
  *
26
+ * @param value
24
27
  * @template T - The type to cast to
25
28
  * @template V (optional) - When used enforces that the casted value is assignable to the type V, use it for safer casts
26
29
  */
@@ -8,12 +8,14 @@ type EmptyObject = Record<string, never>;
8
8
  /**
9
9
  * Cast a value to `any` type. Use this when you have legit usage of `any` casting.
10
10
  *
11
+ * @param value
11
12
  * @template V (optional) - When used enforces that the casted value is assignable to the type V, use it for safer casts
12
13
  */
13
14
  declare function __LEGIT_ANY_CAST__<V = unknown>(value: V): __LEGIT_ANY__;
14
15
  /**
15
16
  * Cast a value to a specific type T. Use this when you have legit usage of type assertion.
16
17
  *
18
+ * @param value
17
19
  * @template T - The type to cast to
18
20
  * @template V (optional) - When used enforces that the casted value is assignable to the type V, use it for safer casts
19
21
  */
@@ -21,6 +23,7 @@ declare function __LEGIT_CAST__<T, V = unknown>(value: V): T;
21
23
  /**
22
24
  * Refine a value to a specific type T. Use this when you have legit usage of type assertion.
23
25
  *
26
+ * @param value
24
27
  * @template T - The type to cast to
25
28
  * @template V (optional) - When used enforces that the casted value is assignable to the type V, use it for safer casts
26
29
  */
@@ -2,6 +2,7 @@ type Arg = string | false | undefined | null;
2
2
  /**
3
3
  * A util to create more legible conditional concatenated strings
4
4
  *
5
+ * @param args
5
6
  * @example
6
7
  * joinStrings('a', 'b', 'c') // 'abc'
7
8
  * joinStrings('a', false, 'c') // 'ac'
@@ -2,6 +2,7 @@ type Arg = string | false | undefined | null;
2
2
  /**
3
3
  * A util to create more legible conditional concatenated strings
4
4
  *
5
+ * @param args
5
6
  * @example
6
7
  * joinStrings('a', 'b', 'c') // 'abc'
7
8
  * joinStrings('a', false, 'c') // 'ac'
package/lib/testUtils.cjs CHANGED
@@ -131,6 +131,256 @@ 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
+ const filterPatterns = filterPatternsRaw.map(parsePattern);
146
+ const rejectPatterns = rejectPatternsRaw.map(parsePattern);
147
+ function matchPath(path, pattern) {
148
+ function rec(pi, pti) {
149
+ if (pti >= pattern.length) return pi === path.length;
150
+ const pt = pattern[pti];
151
+ if (pt.type === "WILDCARD_ANY") {
152
+ if (rec(pi, pti + 1)) return true;
153
+ if (pi < path.length) return rec(pi + 1, pti);
154
+ return false;
155
+ }
156
+ if (pt.type === "WILDCARD_ONE") {
157
+ let j = pi;
158
+ let sawKey = false;
159
+ while (j < path.length) {
160
+ if (path[j].type === "KEY") sawKey = true;
161
+ if (sawKey && rec(j, pti + 1)) return true;
162
+ j += 1;
163
+ }
164
+ return false;
165
+ }
166
+ if (pi >= path.length) return false;
167
+ const ct = path[pi];
168
+ switch (pt.type) {
169
+ case "KEY":
170
+ if (ct.type === "KEY" && ct.name === pt.name)
171
+ return rec(pi + 1, pti + 1);
172
+ if (ct.type === "INDEX") return rec(pi + 1, pti);
173
+ return false;
174
+ case "MULTI_KEY":
175
+ if (ct.type === "KEY" && pt.names.includes(ct.name))
176
+ return rec(pi + 1, pti + 1);
177
+ if (ct.type === "INDEX") return rec(pi + 1, pti);
178
+ return false;
179
+ case "INDEX":
180
+ if (ct.type === "INDEX" && ct.index === pt.index)
181
+ return rec(pi + 1, pti + 1);
182
+ return false;
183
+ case "INDEX_ANY":
184
+ if (ct.type === "INDEX") return rec(pi + 1, pti + 1);
185
+ return false;
186
+ case "INDEX_RANGE":
187
+ if (ct.type === "INDEX") {
188
+ const okLower = ct.index >= pt.start;
189
+ const okUpper = pt.end === null ? true : ct.index <= pt.end;
190
+ if (okLower && okUpper) return rec(pi + 1, pti + 1);
191
+ }
192
+ return false;
193
+ }
194
+ }
195
+ return rec(0, 0);
196
+ }
197
+ const matchesAnyFilter = (path) => filterPatterns.some((p) => matchPath(path, p));
198
+ const matchesAnyReject = (path) => rejectPatterns.some((p) => matchPath(path, p));
199
+ const build = (value, path, allowedByFilter, stack2, isRoot, parentIsArray) => {
200
+ if (Array.isArray(value)) {
201
+ if (stack2.has(value)) {
202
+ throw new TypeError("Circular references are not supported");
203
+ }
204
+ stack2.add(value);
205
+ const out = [];
206
+ const includeAllChildren = allowedByFilter || !hasFilters;
207
+ for (let index = 0; index < value.length; index += 1) {
208
+ const childPath = path.concat({ type: "INDEX", index });
209
+ if (hasRejects && matchesAnyReject(childPath)) continue;
210
+ const child = value[index];
211
+ const directInclude = hasFilters ? matchesAnyFilter(childPath) : true;
212
+ const childAllowed = includeAllChildren || directInclude;
213
+ if (isPlainObject(child) || Array.isArray(child)) {
214
+ const builtChild = build(
215
+ child,
216
+ childPath,
217
+ childAllowed,
218
+ stack2,
219
+ false,
220
+ true
221
+ );
222
+ if (builtChild !== void 0) {
223
+ out.push(builtChild);
224
+ }
225
+ } else {
226
+ if (childAllowed) {
227
+ out.push(child);
228
+ }
229
+ }
230
+ }
231
+ stack2.delete(value);
232
+ const filteredOut = rejectEmptyObjectsInArray ? out.filter(
233
+ (item) => !(isPlainObject(item) && Object.keys(item).length === 0)
234
+ ) : out;
235
+ if (filteredOut.length === 0 && !allowedByFilter && !isRoot)
236
+ return void 0;
237
+ return filteredOut;
238
+ }
239
+ if (isPlainObject(value)) {
240
+ if (stack2.has(value)) {
241
+ throw new TypeError("Circular references are not supported");
242
+ }
243
+ stack2.add(value);
244
+ const result = {};
245
+ const includeAllChildren = allowedByFilter || !hasFilters;
246
+ for (const key of Object.keys(value)) {
247
+ const childPath = path.concat({ type: "KEY", name: key });
248
+ if (hasRejects && matchesAnyReject(childPath)) continue;
249
+ const val = value[key];
250
+ const directInclude = hasFilters ? matchesAnyFilter(childPath) : true;
251
+ const childAllowed = includeAllChildren || directInclude;
252
+ if (isPlainObject(val) || Array.isArray(val)) {
253
+ const builtChild = build(
254
+ val,
255
+ childPath,
256
+ childAllowed,
257
+ stack2,
258
+ false,
259
+ false
260
+ );
261
+ if (builtChild === void 0) {
262
+ continue;
263
+ }
264
+ if (Array.isArray(builtChild) && builtChild.length === 0 && !childAllowed) {
265
+ continue;
266
+ }
267
+ if (isPlainObject(builtChild) && Object.keys(builtChild).length === 0 && !childAllowed) {
268
+ continue;
269
+ }
270
+ result[key] = builtChild;
271
+ } else {
272
+ if (childAllowed) {
273
+ result[key] = val;
274
+ }
275
+ }
276
+ }
277
+ stack2.delete(value);
278
+ if (Object.keys(result).length === 0 && !allowedByFilter && !isRoot) {
279
+ if (parentIsArray && !rejectEmptyObjectsInArray) {
280
+ return {};
281
+ }
282
+ return void 0;
283
+ }
284
+ return result;
285
+ }
286
+ return allowedByFilter || !hasFilters ? value : void 0;
287
+ };
288
+ const startPath = [];
289
+ const initialAllowed = !hasFilters;
290
+ const stack = /* @__PURE__ */ new WeakSet();
291
+ const built = build(
292
+ objOrArray,
293
+ startPath,
294
+ initialAllowed,
295
+ stack,
296
+ true,
297
+ false
298
+ );
299
+ if (built === void 0) return Array.isArray(objOrArray) ? [] : {};
300
+ return built;
301
+ }
302
+ function parsePattern(pattern) {
303
+ const tokens = [];
304
+ let i = 0;
305
+ const n = pattern.length;
306
+ const pushKey = (name) => {
307
+ if (name.length === 0) return;
308
+ tokens.push({ type: "KEY", name });
309
+ };
310
+ while (i < n) {
311
+ const ch = pattern[i];
312
+ if (ch === ".") {
313
+ i += 1;
314
+ continue;
315
+ }
316
+ if (ch === "[") {
317
+ const end = pattern.indexOf("]", i + 1);
318
+ const inside = end === -1 ? pattern.slice(i + 1) : pattern.slice(i + 1, end);
319
+ if (inside === "*") {
320
+ tokens.push({ type: "INDEX_ANY" });
321
+ } else if (inside.includes("-")) {
322
+ const parts = inside.split("-");
323
+ const startStr = parts[0] ?? "";
324
+ const endStr = parts[1] ?? "";
325
+ const start = parseInt(startStr, 10);
326
+ const endNum = endStr === "*" ? null : parseInt(endStr, 10);
327
+ tokens.push({
328
+ type: "INDEX_RANGE",
329
+ start,
330
+ end: endNum === null || Number.isFinite(endNum) ? endNum : null
331
+ });
332
+ } else if (inside.length > 0) {
333
+ const idx = parseInt(inside, 10);
334
+ tokens.push({ type: "INDEX", index: idx });
335
+ }
336
+ i = end === -1 ? n : end + 1;
337
+ continue;
338
+ }
339
+ if (ch === "(") {
340
+ const end = pattern.indexOf(")", i + 1);
341
+ const inside = end === -1 ? pattern.slice(i + 1) : pattern.slice(i + 1, end);
342
+ if (inside.includes("|") && inside.trim().length > 0) {
343
+ const names = inside.split("|").filter((name) => name.length > 0);
344
+ if (names.length > 0) {
345
+ tokens.push({ type: "MULTI_KEY", names });
346
+ }
347
+ }
348
+ i = end === -1 ? n : end + 1;
349
+ continue;
350
+ }
351
+ if (ch === "*") {
352
+ if (pattern[i + 1] === "*") {
353
+ tokens.push({ type: "WILDCARD_ANY" });
354
+ i += 2;
355
+ let j2 = i;
356
+ while (j2 < n) {
357
+ const c = pattern[j2];
358
+ if (c === "." || c === "[") break;
359
+ j2 += 1;
360
+ }
361
+ if (j2 > i) {
362
+ pushKey(pattern.slice(i, j2));
363
+ i = j2;
364
+ }
365
+ continue;
366
+ } else {
367
+ tokens.push({ type: "WILDCARD_ONE" });
368
+ i += 1;
369
+ continue;
370
+ }
371
+ }
372
+ let j = i;
373
+ while (j < n) {
374
+ const c = pattern[j];
375
+ if (c === "." || c === "[") break;
376
+ j += 1;
377
+ }
378
+ pushKey(pattern.slice(i, j));
379
+ i = j;
380
+ }
381
+ return tokens;
382
+ }
383
+
134
384
  // src/mathUtils.ts
135
385
  function clampMin(value, min) {
136
386
  return value < min ? min : value;
@@ -197,12 +447,12 @@ function yamlStringify(obj, {
197
447
  addRootObjSpaces = "beforeAndAfter"
198
448
  } = {}) {
199
449
  if (isObject(obj) || Array.isArray(obj) || typeof obj === "function") {
200
- return `${stringifyValue(obj, "", maxLineLength, !!showUndefined, maxDepth, 0, collapseObjects, addRootObjSpaces)}
450
+ return `${stringifyValue(obj, "", maxLineLength, !!showUndefined, maxDepth, 0, collapseObjects, addRootObjSpaces, false)}
201
451
  `;
202
452
  }
203
453
  return JSON.stringify(obj) || "undefined";
204
454
  }
205
- function stringifyValue(value, indent, maxLineLength, showUndefined, maxDepth, depth, collapseObjects, addObjSpaces) {
455
+ function stringifyValue(value, indent, maxLineLength, showUndefined, maxDepth, depth, collapseObjects, addObjSpaces, isArrayItem) {
206
456
  let result = "";
207
457
  const childIndent = `${indent} `;
208
458
  if (isPlainObject(value)) {
@@ -221,7 +471,8 @@ function stringifyValue(value, indent, maxLineLength, showUndefined, maxDepth, d
221
471
  return typeof val === "number" || typeof val === "boolean" || val === null || val === void 0;
222
472
  }
223
473
  );
224
- if (isSimpleObject && entries.length > 0) {
474
+ const shouldCollapse = isArrayItem ? entries.length > 1 : entries.length > 0;
475
+ if (isSimpleObject && shouldCollapse) {
225
476
  let line = "{ ";
226
477
  line += entries.map(([key, val]) => {
227
478
  let valueStr;
@@ -268,20 +519,29 @@ function stringifyValue(value, indent, maxLineLength, showUndefined, maxDepth, d
268
519
  maxDepth,
269
520
  depth + 1,
270
521
  collapseObjects,
271
- addObjSpaces
522
+ addObjSpaces,
523
+ false
272
524
  );
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
- }));
525
+ const willBeCollapsed = isObject(objVal) && (Object.keys(objVal).length === 0 || collapseObjects && depth + 1 > 0 && (() => {
526
+ const filteredEntries = Object.entries(objVal).filter(([, val]) => val !== void 0 || showUndefined);
527
+ const shouldCollapseThis = isArrayItem ? filteredEntries.length > 1 : filteredEntries.length > 0;
528
+ return shouldCollapseThis && filteredEntries.every(([, val]) => {
529
+ if (typeof val === "string") {
530
+ return !val.includes("'") && !val.includes('"') && !val.includes("\\");
531
+ }
532
+ return typeof val === "number" || typeof val === "boolean" || val === null || val === void 0;
533
+ });
534
+ })());
535
+ const prevWasCollapsed = prevValue && isObject(prevValue) && (Object.keys(prevValue).length === 0 || collapseObjects && depth + 1 > 0 && (() => {
536
+ const filteredEntries = Object.entries(prevValue).filter(([, val]) => val !== void 0 || showUndefined);
537
+ const shouldCollapseThis = isArrayItem ? filteredEntries.length > 1 : filteredEntries.length > 0;
538
+ return shouldCollapseThis && filteredEntries.every(([, val]) => {
539
+ if (typeof val === "string") {
540
+ return !val.includes("'") && !val.includes('"') && !val.includes("\\");
541
+ }
542
+ return typeof val === "number" || typeof val === "boolean" || val === null || val === void 0;
543
+ });
544
+ })());
285
545
  if (!afterSpaceWasAdded && indent === "" && isObject(objVal) && !willBeCollapsed && prevValue && !prevWasCollapsed && (addObjSpaces === "before" || addObjSpaces === "beforeAndAfter")) {
286
546
  result += "\n";
287
547
  }
@@ -344,7 +604,8 @@ function stringifyValue(value, indent, maxLineLength, showUndefined, maxDepth, d
344
604
  maxDepth,
345
605
  depth + 1,
346
606
  collapseObjects,
347
- addObjSpaces
607
+ addObjSpaces,
608
+ true
348
609
  );
349
610
  }).join(", ");
350
611
  line += "]";
@@ -368,7 +629,8 @@ function stringifyValue(value, indent, maxLineLength, showUndefined, maxDepth, d
368
629
  maxDepth,
369
630
  depth + 1,
370
631
  collapseObjects,
371
- addObjSpaces
632
+ addObjSpaces,
633
+ true
372
634
  );
373
635
  arrayString = arrayString.trimStart();
374
636
  result += arrayString;
@@ -381,7 +643,8 @@ function stringifyValue(value, indent, maxLineLength, showUndefined, maxDepth, d
381
643
  maxDepth,
382
644
  depth + 1,
383
645
  collapseObjects,
384
- addObjSpaces
646
+ addObjSpaces,
647
+ true
385
648
  );
386
649
  }
387
650
  result += "\n";
@@ -435,7 +698,8 @@ ${indent}${line}
435
698
  maxDepth,
436
699
  depth + 1,
437
700
  collapseObjects,
438
- addObjSpaces
701
+ addObjSpaces,
702
+ false
439
703
  );
440
704
  }
441
705
  return JSON.stringify(value);
@@ -753,126 +1017,6 @@ function waitController() {
753
1017
  }
754
1018
  };
755
1019
  }
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
1020
  function compactSnapshot(value, {
877
1021
  collapseObjects = true,
878
1022
  maxLineLength = 100,
@@ -884,10 +1028,12 @@ function compactSnapshot(value, {
884
1028
  } = {}) {
885
1029
  let processedValue = value;
886
1030
  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
- });
1031
+ if (isPlainObject(processedValue) || Array.isArray(processedValue)) {
1032
+ processedValue = filterObjectOrArrayKeys(processedValue, {
1033
+ rejectKeys,
1034
+ filterKeys
1035
+ });
1036
+ }
891
1037
  }
892
1038
  processedValue = showBooleansAs ? replaceBooleansWithEmoji(processedValue, showBooleansAs) : processedValue;
893
1039
  return `