@tucmc/hazel
Version:
Clubs Data Processing Framework
130 lines (129 loc) • 5.65 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FirestoreCollection = void 0;
const fs_1 = __importDefault(require("fs"));
const node_object_hash_1 = require("node-object-hash");
const FieldDelete_1 = require("../../util/data/FieldDelete");
const Collection_1 = require("../../util/database/Collection");
const Colour_1 = require("../../util/debugger/Colour");
const FirestoreDatabase_1 = require("./FirestoreDatabase");
const Mutators_1 = require("./Mutators");
class FirestoreCollection extends Collection_1.Collection {
collectionMutator = Mutators_1.Mutators.DefaultCollectionKeyValueMutator;
initInstance(collectionName) {
return new FirestoreDatabase_1.FirestoreDatabase().getDB().collection(collectionName);
}
async retrieveCollection() {
return this.dbInstance.get();
}
chunkArray(arr, size) {
const myArray = [];
for (let i = 0; i < arr.length; i += size) {
myArray.push(arr.slice(i, i + size));
}
return myArray;
}
async handleChanges(changes) {
const changesChunk = this.chunkArray(changes, 500);
let i = 0;
for (const ca of changesChunk) {
const batch = this.dbInstance.firestore.batch();
ca.forEach((v) => {
let target;
if (!v._docID) {
target = this.dbInstance.doc();
v._docID = target.id;
}
else {
target = this.dbInstance.doc(v._docID);
}
switch (v.type) {
case 'create':
if (v._docID) {
batch.set(target, v.to);
}
else {
batch.create(target, v.to);
}
break;
case 'delete':
batch.delete(target);
break;
case 'update': {
const parsedTo = {};
Object.keys(v.to).forEach((k) => {
const d = v.to[k];
if (d instanceof FieldDelete_1.FieldDelete) {
parsedTo[k] = d.resolve('firestore');
return;
}
parsedTo[k] = d;
});
batch.update(target, parsedTo);
}
}
});
const c = this.debug.loadingInfo(`pushing changes to the database (chunk ${i + 1} of ${changesChunk.length})`);
try {
await batch.commit();
c.succeed();
}
catch (e) {
c.fail();
return changes;
}
i += 1;
}
return changes;
}
async verifyChanges(changes) {
const allDocs = await this.dbInstance.firestore.getAll(...changes.map((d) => this.dbInstance.doc(d._docID)));
const evalResult = changes.map((v) => {
const possibleDbDoc = allDocs.filter((d) => d.id === v._docID);
const dbDoc = possibleDbDoc[0];
if (!dbDoc) {
return null;
}
if (!dbDoc.exists) {
if (v.type === 'delete') {
return { id: v._docID, report: [], reference: '--deleted--' };
}
return {
id: v._docID,
report: [{ present: '--document-not-existed--', expect: v.to }],
reference: '--document-not-existed--'
};
}
const mismatch = [];
Object.keys(v.to).forEach((k) => {
const refVal = v.to[k];
const dbD = dbDoc.get(k);
if (refVal instanceof FieldDelete_1.FieldDelete) {
if (!dbD)
return;
}
const refValHash = (0, node_object_hash_1.hasher)().hash(refVal);
const dbDHash = (0, node_object_hash_1.hasher)().hash(dbD);
if (dbDHash !== refValHash) {
mismatch.push({ key: k, present: dbD, expect: refVal });
}
});
return { id: v._docID, report: mismatch, reference: dbDoc.data() };
});
const total = changes.length;
const missing = evalResult.filter((d) => d === null).length;
const passed = evalResult.filter((d) => d !== null && d.report.length === 0).length;
const failed = evalResult.filter((d) => d !== null && d.report.length > 0);
this.debug.info(`changes verified successfully (total ${total} entities)`);
this.debug.info(`${Colour_1.ConsoleColour.GREEN}passed ${passed}, ${Colour_1.ConsoleColour.RED}failed ${failed.length},${Colour_1.ConsoleColour.RESET} missing ${missing}`);
if (failed.length > 0) {
this.debug.warn(`${failed.length} changes results were found not updated. \nPlease check ${Colour_1.ConsoleColour.BOLD}./review/DEV/.verify_log.json${Colour_1.ConsoleColour.RESET}`);
fs_1.default.writeFileSync(`review/${process.env.RUNTIME_MODE}/.verify_log.json`, JSON.stringify(failed, null, 4));
}
return total === passed;
}
}
exports.FirestoreCollection = FirestoreCollection;