All files / json-patch/op OpStrDel.ts

96.77% Statements 30/31
91.66% Branches 11/12
100% Functions 7/7
100% Lines 29/29

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  17x   17x 17x         17x     160x 160x 160x   160x       33x       6x       34x       112x 112x 112x 112x 112x 112x 112x 112x 112x 112x 112x 20x 112x       21x 8x             13x                 12x 12x          
import type {CompactStrDelOp, OPCODE_STR_DEL} from '../codec/compact/types';
import {AbstractOp} from './AbstractOp';
import type {OperationStrDel} from '../types';
import {find, type Path, formatJsonPointer} from '@jsonjoy.com/json-pointer';
import {OPCODE} from '../constants';
 
/**
 * @category JSON Patch Extended
 */
export class OpStrDel extends AbstractOp<'str_del'> {
  constructor(
    path: Path,
    public readonly pos: number,
    public readonly str: string | undefined,
    public readonly len: number | undefined,
  ) {
    super(path);
  }
 
  public op() {
    return 'str_del' as const;
  }
 
  public code() {
    return OPCODE.str_del;
  }
 
  public deleteLength(): number {
    return typeof this.str === 'string' ? this.str.length : this.len!;
  }
 
  public apply(doc: unknown) {
    const {val, key, obj} = find(doc, this.path);
    Iif (typeof val !== 'string') throw new Error('NOT_A_STRING');
    const length = val.length;
    const pos = Math.min(this.pos, val.length);
    const start = Math.min(pos, length);
    const deletionLength: number = this.str !== undefined ? this.str.length : this.len!;
    const end = Math.min(pos + deletionLength, length);
    const before = val.slice(0, start);
    const after = val.substr(end);
    const result = before + after;
    if (obj) (obj as any)[key as any] = result;
    else doc = result;
    return {doc, old: val};
  }
 
  public toJson(parent?: AbstractOp): OperationStrDel {
    if (typeof this.str === 'string') {
      return {
        op: 'str_del',
        path: formatJsonPointer(this.path),
        pos: this.pos,
        str: this.str,
      };
    }
    return {
      op: 'str_del',
      path: formatJsonPointer(this.path),
      pos: this.pos,
      len: this.len,
    };
  }
 
  public toCompact(parent: undefined | AbstractOp, verbose: boolean): CompactStrDelOp {
    const opcode: OPCODE_STR_DEL = verbose ? 'str_del' : OPCODE.str_del;
    return typeof this.str === 'string'
      ? [opcode, this.path, this.pos, this.str]
      : ([opcode, this.path, this.pos, 0, this.len] as CompactStrDelOp);
  }
}