All files / src/utils get-options-cache-key.ts

80.76% Statements 21/26
83.33% Branches 20/24
85.71% Functions 6/7
84% Lines 21/25

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66      92x       92x 46x       46x 46x   12x 58x   46x   46x     46x       556x 469x     87x 1x     86x 52x     34x 34x                   139x       139x                 52x    
import { GetOptions } from '@fingerprint/agent'
 
function sortObjectKeys(value: unknown, seen = new Set<object>()): unknown {
  Iif (Array.isArray(value)) {
    return value.map((item) => sortObjectKeys(item, seen))
  }
 
  if (value !== null && typeof value === 'object') {
    Iif (seen.has(value)) {
      throw new TypeError('Cannot serialize a circular value')
    }
 
    seen.add(value)
    const sortedValue = Object.fromEntries(
      Object.entries(value)
        .sort(([leftKey], [rightKey]) => (leftKey < rightKey ? -1 : leftKey > rightKey ? 1 : 0))
        .map(([key, item]) => [key, sortObjectKeys(item, seen)])
    )
    seen.delete(value)
 
    return sortedValue
  }
 
  return value
}
 
function serializeCacheValue(value: unknown): string {
  if (value === undefined) {
    return 'undefined:'
  }
 
  if (value === null) {
    return 'null:'
  }
 
  if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
    return `${typeof value}:${String(value)}`
  }
 
  try {
    return `json:${JSON.stringify(sortObjectKeys(value))}`
  } catch {
    return `unserializable:${typeof value}`
  }
}
 
/**
 * Stable (cache) key for `GetOptions` object used for request deduplication and semantic equality.
 */
export function getOptionsCacheKey(options?: GetOptions): string {
  Iif (!options) {
    return ''
  }
 
  return JSON.stringify([
    serializeCacheValue(options.tag),
    serializeCacheValue(options.tags),
    serializeCacheValue(options.linkedId),
    serializeCacheValue(options.timeout),
  ])
}
 
export function areGetOptionsEqual(a: GetOptions, b: GetOptions): boolean {
  return getOptionsCacheKey(a) === getOptionsCacheKey(b)
}