jinaga
Version:
Data management for web and mobile applications.
121 lines • 5.21 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GraphDeserializer = void 0;
const hash_1 = require("../fact/hash");
class GraphDeserializer {
constructor(readLine) {
this.readLine = readLine;
this.factReferences = [];
this.publicKeys = [];
}
read(onEnvelopes) {
return __awaiter(this, void 0, void 0, function* () {
let envelopes = [];
let line;
while ((line = yield this.readLine()) !== null) {
if (line.startsWith("PK")) {
const index = parseInt(line.substring(2));
yield this.readPublicKey(index);
}
else {
const type = JSON.parse(line);
envelopes = yield this.readEnvelope(type, envelopes, onEnvelopes);
}
}
if (envelopes.length > 0) {
yield onEnvelopes(envelopes);
}
});
}
readPublicKey(index) {
return __awaiter(this, void 0, void 0, function* () {
if (index !== this.publicKeys.length) {
throw new Error(`Public key index ${index} is out of order`);
}
const publicKey = yield this.parseNextJSONLine();
const emptyLine = yield this.readLine();
if (emptyLine !== "") {
throw new Error(`Expected empty line after public key, but got "${emptyLine}"`);
}
this.publicKeys.push(publicKey);
});
}
readEnvelope(type, envelopes, onEnvelopes) {
return __awaiter(this, void 0, void 0, function* () {
const predecessorIndexes = yield this.parseNextJSONLine();
const fields = yield this.parseNextJSONLine();
const predecessors = this.getPredecessorReferences(predecessorIndexes);
const hash = (0, hash_1.computeHash)(fields, predecessors);
this.factReferences.push({ type, hash });
const fact = { type, hash, predecessors, fields };
const signatures = yield this.readSignatures();
envelopes.push({ fact, signatures });
// Periodically handle a batch of envelopes
if (envelopes.length >= 20) {
yield onEnvelopes(envelopes);
envelopes = [];
}
return envelopes;
});
}
getPredecessorReferences(predecessorIndexes) {
const predecessors = {};
for (const role in predecessorIndexes) {
const index = predecessorIndexes[role];
if (Array.isArray(index)) {
predecessors[role] = index.map(i => {
if (i >= this.factReferences.length) {
throw new Error(`Predecessor reference ${i} is out of range`);
}
return this.factReferences[i];
});
}
else {
if (index >= this.factReferences.length) {
throw new Error(`Predecessor reference ${index} is out of range`);
}
predecessors[role] = this.factReferences[index];
}
}
return predecessors;
}
readSignatures() {
return __awaiter(this, void 0, void 0, function* () {
const signatures = [];
let line;
while ((line = yield this.readLine()) !== null && line !== "") {
if (!line.startsWith("PK")) {
throw new Error(`Expected public key reference, but got "${line}"`);
}
const publicKeyIndex = parseInt(line.substring(2));
if (publicKeyIndex >= this.publicKeys.length) {
throw new Error(`Public key reference ${publicKeyIndex} is out of range`);
}
const publicKey = this.publicKeys[publicKeyIndex];
const signature = yield this.parseNextJSONLine();
signatures.push({ publicKey, signature });
}
return signatures;
});
}
parseNextJSONLine() {
return __awaiter(this, void 0, void 0, function* () {
const line = yield this.readLine();
if (!line) {
throw new Error("Expected JSON line, but got end of file");
}
return JSON.parse(line);
});
}
}
exports.GraphDeserializer = GraphDeserializer;
//# sourceMappingURL=deserializer.js.map