* Rebuild `value` replacing every eligible string leaf with `handle(leaf)`. * Used for both collection (handle records and returns the input) and * substitution (handle returns the masked value), so traversal order and * eligibility are guaranteed identical across the two passes.
(value: unknown, handle: (s: string) => string)
| 82 | * eligibility are guaranteed identical across the two passes. |
| 83 | */ |
| 84 | function transformStrings(value: unknown, handle: (s: string) => string): unknown { |
| 85 | if (typeof value === 'string') { |
| 86 | return isEligibleString(value) ? handle(value) : value |
| 87 | } |
| 88 | // Treat offloaded large-value refs as opaque: masking their internal `key`/`id` |
| 89 | // strings would corrupt the reference. Their content is handled separately |
| 90 | // (hydrate → mask → re-store) before this runs. |
| 91 | if (isLargeValueRef(value) || isLargeArrayManifest(value)) { |
| 92 | return value |
| 93 | } |
| 94 | if (Array.isArray(value)) { |
| 95 | return value.map((item) => transformStrings(item, handle)) |
| 96 | } |
| 97 | if (value !== null && typeof value === 'object') { |
| 98 | const out: Record<string, unknown> = {} |
| 99 | for (const [key, v] of Object.entries(value)) { |
| 100 | out[key] = transformStrings(v, handle) |
| 101 | } |
| 102 | return out |
| 103 | } |
| 104 | return value |
| 105 | } |
| 106 | |
| 107 | /** |
| 108 | * Redact a trace span: only its content fields ({@link SPAN_CONTENT_FIELDS}) and |
no test coverage detected