All files / web/src/lib generateShareId.ts

100% Statements 46/46
100% Branches 8/8
100% Functions 2/2
100% Lines 46/46

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 471x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 123x 123x 123x 123x 123x 123x 123x 864x 864x 864x 123x 123x 123x 1x 1x 1x 1x 1x 30x 27x 27x 30x 180x 3x 3x 180x 24x 24x 24x  
/**
 * Generate a short, URL-safe ID for worksheet shares
 *
 * Uses base62 encoding (0-9, a-z, A-Z) for maximum readability
 * 7 characters = 62^7 = ~3.5 trillion possible IDs
 *
 * Format: abc123X (lowercase, uppercase, numbers)
 * Example: k7mP2qR
 */
 
const BASE62_CHARS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
const ID_LENGTH = 7
 
/**
 * Generate a random base62 string of specified length
 */
export function generateShareId(length: number = ID_LENGTH): string {
  let result = ''
 
  // Use crypto.getRandomValues for cryptographically secure randomness
  const randomBytes = new Uint8Array(length)
  crypto.getRandomValues(randomBytes)
 
  for (let i = 0; i < length; i++) {
    // Map random byte to base62 character
    result += BASE62_CHARS[randomBytes[i] % BASE62_CHARS.length]
  }
 
  return result
}
 
/**
 * Check if a share ID has valid format
 */
export function isValidShareId(id: string): boolean {
  if (id.length !== ID_LENGTH) return false
 
  // Check all characters are in base62 alphabet
  for (let i = 0; i < id.length; i++) {
    if (!BASE62_CHARS.includes(id[i])) {
      return false
    }
  }
 
  return true
}