UNPKG

json-joy

Version:

Collection of libraries for building collaborative editing apps.

182 lines (181 loc) 5.12 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Encoder = void 0; const tslib_1 = require("tslib"); const nodes = tslib_1.__importStar(require("../../../nodes")); const toBase64_1 = require("@jsonjoy.com/base64/lib/toBase64"); const constants_1 = require("../../../../json-crdt-patch/constants"); const clock_1 = require("../../../../json-crdt-patch/clock"); class Encoder { encode(model) { this.model = model; const clock = model.clock; const isServerClock = clock.sid === constants_1.SESSION.SERVER; return { time: isServerClock ? clock.time : this.cClock(model.clock), root: this.cVal(model.root), }; } cClock(clock) { const data = []; const sessionId = clock.sid; const localTs = clock.peers.get(sessionId); if (!localTs) data.push([sessionId, clock.time]); for (const c of clock.peers.values()) data.push([c.sid, c.time]); return data; } cTs(ts) { return ts.sid === constants_1.SESSION.SERVER ? ts.time : [ts.sid, ts.time]; } cNode(node) { if (node instanceof nodes.ObjNode) return this.cObj(node); else if (node instanceof nodes.ArrNode) return this.cArr(node); else if (node instanceof nodes.StrNode) return this.cStr(node); else if (node instanceof nodes.ValNode) return this.cVal(node); else if (node instanceof nodes.ConNode) return this.cCon(node); else if (node instanceof nodes.BinNode) return this.cBin(node); else if (node instanceof nodes.VecNode) return this.cVec(node); throw new Error('UNKNOWN_NODE'); } cObj(obj) { const map = {}; obj.nodes((node, key) => { map[key] = this.cNode(node); }); return { type: 'obj', id: this.cTs(obj.id), map, }; } cVec(obj) { const map = []; const elements = obj.elements; const length = elements.length; const index = this.model.index; for (let i = 0; i < length; i++) { const element = elements[i]; if (element === undefined) map.push(null); else map.push(this.cNode(index.get(element))); } return { type: 'vec', id: this.cTs(obj.id), map, }; } cArr(obj) { const chunks = []; const iterator = obj.iterator(); let chunk; while ((chunk = iterator())) chunks.push(this.cArrChunk(chunk)); return { type: 'arr', id: this.cTs(obj.id), chunks, }; } cArrChunk(chunk) { if (chunk.del) { const tombstone = { id: this.cTs(chunk.id), span: chunk.span, }; return tombstone; } const index = this.model.index; const res = { id: this.cTs(chunk.id), value: chunk.data.map((n) => this.cNode(index.get(n))), }; return res; } cStr(obj) { const chunks = []; const iterator = obj.iterator(); let chunk; while ((chunk = iterator())) chunks.push(this.cStrChunk(chunk)); return { type: 'str', id: this.cTs(obj.id), chunks, }; } cStrChunk(chunk) { if (chunk.del) { const tombstone = { id: this.cTs(chunk.id), span: chunk.span, }; return tombstone; } const res = { id: this.cTs(chunk.id), value: chunk.data, }; return res; } cBin(obj) { const chunks = []; const iterator = obj.iterator(); let chunk; while ((chunk = iterator())) chunks.push(this.cBinChunk(chunk)); return { type: 'bin', id: this.cTs(obj.id), chunks, }; } cBinChunk(chunk) { if (chunk.del) { const tombstone = { id: this.cTs(chunk.id), span: chunk.span, }; return tombstone; } const res = { id: this.cTs(chunk.id), value: (0, toBase64_1.toBase64)(chunk.data), }; return res; } cVal(obj) { return { type: 'val', id: this.cTs(obj.id), value: this.cNode(obj.node()), }; } cCon(obj) { const node = { type: 'con', id: this.cTs(obj.id), }; const val = obj.val; if (val instanceof clock_1.Timestamp) { node.timestamp = true; node.value = this.cTs(val); } else { if (val !== undefined) node.value = val; } return node; } } exports.Encoder = Encoder;