All files / json-patch/op OpStrIns.ts

100% Statements 28/28
100% Branches 9/9
100% Functions 6/6
100% Lines 25/25

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  17x   17x 17x         17x     171x 171x   171x       31x       4x       143x 143x 35x 10x   113x 113x 113x 113x 113x 113x 5x 113x       14x           14x       8x 8x      
import type {CompactStrInsOp, OPCODE_STR_INS} from '../codec/compact/types';
import {AbstractOp} from './AbstractOp';
import type {OperationStrIns} from '../types';
import {find, type Path, formatJsonPointer} from '@jsonjoy.com/json-pointer';
import {OPCODE} from '../constants';
 
/**
 * @category JSON Patch Extended
 */
export class OpStrIns extends AbstractOp<'str_ins'> {
  constructor(
    path: Path,
    public readonly pos: number,
    public readonly str: string,
  ) {
    super(path);
  }
 
  public op() {
    return 'str_ins' as const;
  }
 
  public code() {
    return OPCODE.str_ins;
  }
 
  public apply(doc: unknown) {
    const {val, key, obj} = find(doc, this.path);
    if (typeof val !== 'string') {
      if (val !== undefined) throw new Error('NOT_A_STRING');
      if (this.pos !== 0) throw new Error('POS');
    }
    const str: string = typeof val === 'string' ? val : '';
    const pos = Math.min(this.pos, str.length);
    const before = str.slice(0, pos);
    const after = str.slice(pos);
    const result = before + this.str + after;
    if (obj) (obj as any)[key as any] = result;
    else doc = result;
    return {doc, old: val};
  }
 
  public toJson(parent?: AbstractOp): OperationStrIns {
    const op: OperationStrIns = {
      op: 'str_ins',
      path: formatJsonPointer(this.path),
      pos: this.pos,
      str: this.str,
    };
    return op;
  }
 
  public toCompact(parent: undefined | AbstractOp, verbose: boolean): CompactStrInsOp {
    const opcode: OPCODE_STR_INS = verbose ? 'str_ins' : OPCODE.str_ins;
    return [opcode, this.path, this.pos, this.str];
  }
}