UNPKG

json-joy

Version:

Collection of libraries for building collaborative editing apps.

89 lines (88 loc) 3.01 kB
import { fromBase64 } from '@jsonjoy.com/base64/lib/fromBase64'; import { ts, ClockVector, ServerClockVector, tss } from '../../clock'; import { SESSION } from '../../constants'; import { PatchBuilder } from '../../PatchBuilder'; const decodeId = (time) => typeof time === 'number' ? ts(SESSION.SERVER, time) : ts(time[0], time[1]); /** * Decodes a JSON CRDT patch from a JavaScript POJO into a {@link Patch} instance. * * @param data A JavaScript POJO representing a JSON CRDT patch in "verbose" format. * @returns A decoded {@link Patch} instance. */ export const decode = (data) => { const { id, ops } = data; const clock = typeof id === 'number' ? new ServerClockVector(SESSION.SERVER, id) : new ClockVector(id[0], id[1]); const builder = new PatchBuilder(clock); for (const op of ops) { switch (op.op) { case 'new_con': { if (op.timestamp) { builder.const(decodeId(op.value)); } else { builder.const(op.value); } break; } case 'new_val': { builder.val(); break; } case 'new_obj': { builder.obj(); break; } case 'new_vec': { builder.vec(); break; } case 'new_str': { builder.str(); break; } case 'new_bin': { builder.bin(); break; } case 'new_arr': { builder.arr(); break; } case 'ins_val': { builder.setVal(decodeId(op.obj), decodeId(op.value)); break; } case 'ins_obj': { builder.insObj(decodeId(op.obj), op.value.map(([key, id]) => [key, decodeId(id)])); break; } case 'ins_vec': { builder.insVec(decodeId(op.obj), op.value.map(([key, id]) => [key, decodeId(id)])); break; } case 'ins_str': { builder.insStr(decodeId(op.obj), decodeId(op.after || op.obj), op.value); break; } case 'ins_bin': { builder.insBin(decodeId(op.obj), decodeId(op.after || op.obj), fromBase64(op.value)); break; } case 'ins_arr': { builder.insArr(decodeId(op.obj), decodeId(op.after || op.obj), op.values.map(decodeId)); break; } case 'del': { builder.del(decodeId(op.obj), op.what.map((spans) => tss(...spans))); break; } case 'nop': { builder.nop(op.len || 1); break; } } } const patch = builder.patch; patch.meta = data.meta; return patch; };