All files / utils desensitize.ts

100% Statements 21/21
95.65% Branches 22/23
100% Functions 2/2
100% Lines 19/19

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 67 68 69 70 71 72 73 74 75 76 77 78                                                                  13x 13x 95x   13x 13x                         14x 13x 13x 7x 4x   3x 1x   2x 1x   1x 1x     6x 5x             1x    
export enum DesensitizeStrategy {
  CHINESE_NAME = 'CHINESE_NAME',
  CHINESE_ID_CARD_NUMBER = 'CHINESE_ID_CARD_NUMBER',
  CHINESE_MOBILE_PHONE_NUMBER = 'CHINESE_MOBILE_PHONE_NUMBER',
  EMAIL = 'EMAIL',
}
 
export interface DesensitizeOptions {
  /**
   * 脱敏策略
   */
  strategy?: DesensitizeStrategy
  /**
   * 脱敏替换字符
   *
   * @default '*'
   */
  replacer?: string
  /**
   * 前置保留字符数
   *
   * @default 0
   */
  preKeep?: number
  /**
   * 后置保留字符数
   *
   * @default 0
   */
  postKeep?: number
}
 
function replace(text: string, start: number, end: number, replacer: string) {
  let res = text.substring(0, start)
  for (let i = start; i < end; i++) {
    res += replacer
  }
  res += text.substring(end)
  return res
}
 
/**
 * 文本脱敏。
 *
 * @param text 待脱敏的文本
 * @param options 脱敏选项
 */
export function desensitize(
  text: string,
  options: DesensitizeOptions = {},
): string {
  if (!text) return text
  const replacer = options?.replacer ?? '*'
  if (options.strategy) {
    if (options.strategy === DesensitizeStrategy.CHINESE_NAME) {
      return replace(text, 1, text.length, replacer)
    }
    if (options.strategy === DesensitizeStrategy.CHINESE_ID_CARD_NUMBER) {
      return replace(text, 1, text.length - 2, replacer)
    }
    if (options.strategy === DesensitizeStrategy.CHINESE_MOBILE_PHONE_NUMBER) {
      return replace(text, 3, text.length - 4, replacer)
    }
    if (options.strategy === DesensitizeStrategy.EMAIL) {
      return replace(text, 1, text.indexOf('@'), replacer)
    }
  }
  if (options.preKeep != null || options.postKeep != null) {
    return replace(
      text,
      options.preKeep ?? 0,
      text.length - (options.postKeep ?? 0),
      replacer,
    )
  }
  return replace(text, 0, text.length, replacer)
}