json-joy
Version:
Collection of libraries for building collaborative editing apps.
182 lines (181 loc) • 5.12 kB
JavaScript
"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;