All files / src/utils serialization.ts

100% Statements 62/62
100% Branches 23/23
100% Functions 2/2
100% Lines 62/62

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 631x 1x 2x 6x 1x 1x 5x 2x 2x 1x 1x 1x 1x 1x 1x 1x 1x 32x 32x 4x 4x 28x 32x 2x 2x 26x 32x 4x 4x 22x 32x 7x 7x 15x 32x 2x 2x 32x 2x 2x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 25x 2x 2x 2x 23x 11x 32x 4x 4x 4x 32x  
 
export const serialize = (obj: Record<string, any>): string => {
  return JSON.stringify(obj, (_, value) => {
      if (typeof value === 'function') {
          return `__FUNCTION__${value.toString()}`
      }
      return value
  })
}
 
/**
 * Deserialize a serialized string.
 * 
 * @param {string | null} arg 
 * @returns {R}
 */
export const deserialize = <R>(arg?: string | null): R => {
    // is the argument null or undefined?
    if (arg === null || arg === undefined) {
      return arg as R
    }
    // is the string "undefined"?
    if (arg === 'undefined') {
      return undefined as R
    }
    // is the string empty?
    if (arg === '') {
      return arg as R
    }
    // is the string a number?
    if (!isNaN(Number(arg))) {
      return parseFloat(arg) as R
    }
    // is the string a boolean?
    if (arg === 'true') {
      return true as R
    }
    if (arg === 'false') {
      return false as R
    }
    // is the string JSON?
    try {
      const potentiallyParsableJson = arg
      // wrap all strings wrapped in single quotes with double quotes
      .replace(/'([^']+)'/g, '"$1"')
      // wrap all unquoted keys in double quotes
      .replace(/([{,]\s*)([a-zA-Z0-9_]+?)\s*:/g, '$1"$2":')
      // remove all trailing commas
      .replace(/,\s*}/g, '}').replace(/,\s*]/g, ']')
 
      return JSON.parse(potentiallyParsableJson, (_, value) => {
        if (typeof value === 'string' && value.startsWith('__FUNCTION__')) {
          const functionBody = value.substring(12)
          return new Function(`return ${functionBody}`)()
        }
        return value
      })
    } catch (e) {
      // We've run out of options, just return the string
      return arg as R
    }    
}