encodeBigInt = n => {
  const abs = n < 0n ? -n : n;
  const nDigits = abs.toString().length;
  const lDigits = nDigits.toString().length;
  if (n < 0n) {
    return `n${
      // A "#" for each digit beyond the first
      // in the decimal *count* of decimal digits.
      '#'.repeat(lDigits - 1)
    }${
      // The ten's complement of the count of digits.
      (10 ** lDigits - nDigits).toString().padStart(lDigits, '0')
    }:${
      // The ten's complement of the digits.
      (10n ** BigInt(nDigits) + n).toString().padStart(nDigits, '0')
    }`;
  } else {
    return `p${
      // A "~" for each digit beyond the first
      // in the decimal *count* of decimal digits.
      '~'.repeat(lDigits - 1)
    }${
      // The count of digits.
      nDigits
    }:${
      // The digits.
      n
    }`;
  }
}
Encode a JavaScript bigint using a variant of Elias delta coding, with an
initial component for the length of the digit count as a unary string, a
second component for the decimal digit count, and a third component for the
decimal digits preceded by a gratuitous separating colon.
To ensure that the lexicographic sort order of encoded values matches the
numeric sort order of the corresponding numbers, the characters of the unary
prefix are different for negative values (type "n" followed by any number of
"#"s [which sort before decimal digits]) vs. positive and zero values (type
"p" followed by any number of "~"s [which sort after decimal digits]) and
each decimal digit of the encoding for a negative value is replaced with its
ten's complement (so that negative values of the same scale sort by
*descending* absolute value).

@param {bigint} n
@returns {string}