UNPKG

@tucmc/hazel

Version:
189 lines (188 loc) 8.09 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SimulatedCollection = void 0; const crypto = __importStar(require("crypto")); const fs_1 = __importDefault(require("fs")); const node_object_hash_1 = require("node-object-hash"); const process = __importStar(require("process")); const DMap_1 = require("../../util/data/DMap"); const FieldDelete_1 = require("../../util/data/FieldDelete"); const LiveDMap_1 = require("../../util/data/LiveDMap"); const ReferableEntity_1 = require("../../util/data/ReferableEntity"); const Collection_1 = require("../../util/database/Collection"); const Colour_1 = require("../../util/debugger/Colour"); const Files_1 = require("../../util/io/Files"); class SimulatedCollection extends Collection_1.Collection { simulatedContent; constructor(name, preset, instructor) { super(name); const MODE = process.env.RUNTIME_MODE; if (MODE === 'PROD') { throw Error(`${Colour_1.ConsoleColour.RED}Simulated collection must not be used on PRODUCTION runtime.${Colour_1.ConsoleColour.RESET}`); } const buildCache = this.loadBuildCache(); if (buildCache) { this.simulatedContent = new DMap_1.DMap(buildCache.content); return; } this.simulatedContent = new DMap_1.DMap(preset); instructor && instructor(this.simulatedContent); this.saveBuildCache(); } async handleChanges(changes) { const object = new DMap_1.DMap(this.simulatedContent.getRecord()); changes.forEach((v) => { if (!v._docID) { v._docID = `simulated-${crypto.randomUUID()}`; } switch (v.type) { case 'create': object.set(v._docID, v.to); break; case 'delete': object.remove(v._docID); break; case 'update': { const parsedTo = {}; const original = object.get(v._docID); if (!original) break; Object.keys(v.to).forEach((k) => { const d = v.to[k]; if (d instanceof FieldDelete_1.FieldDelete) { delete original[k]; return; } parsedTo[k] = d; }); object.set(v._docID, { ...original, ...parsedTo }); } } }); this.debug.info(`${Colour_1.ConsoleColour.BGYELLOW}pushing changes to the database...`); Files_1.Files.writeFile(object.getRecord(), `resource/collection/simulated/${this.name}`); return changes; } initInstance(collectionName) { return null; } retrieveCollection() { return Promise.resolve(new DMap_1.DMap({})); } collectionMutator = (d) => d.getRecord(); async verifyChanges(changes) { const data = this.loadBuildCache(); if (!data) { return false; } const allDocs = new DMap_1.DMap(data.content).map((k, v) => { return { id: k, ...v }; }); const evalResult = changes.map((v) => { const possibleDbDoc = allDocs.filter((d) => d.id === v._docID); const dbDoc = possibleDbDoc[0]; if (!dbDoc) { 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[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 }; }); 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; } loadBuildCache() { return Files_1.Files.readFile(`resource/collection/simulated/${this.name}`); } saveBuildCache() { Files_1.Files.writeFile(this.simulatedContent.getRecord(), `resource/collection/simulated/${this.name}`); } buildRef() { const mutated = this.collectionMutator(this.simulatedContent); const refMap = new DMap_1.DMap(mutated); const nMap = new LiveDMap_1.LiveDMap({}); refMap.iterateSync((k, v) => { let id = k; if (v._docID) { id = v._docID; } const entity = new ReferableEntity_1.ReferableMapEntity(v, id); entity.setSynthesized(false); nMap.set(k, entity); }); return nMap; } async readFromCache(autoFetch = false) { return this.fetch(); } async fetch() { const loader = this.debug.loadingInfo('fetching collection from database.'); loader.succeed(); return this.buildRef(); } async fetchNoRef() { const loader = this.debug.loadingInfo('fetching collection from database.'); loader.succeed(); const mutated = this.collectionMutator(this.simulatedContent); console.log(Object.keys(mutated)); return new DMap_1.DMap(this.clearEntityReference(mutated)); } } exports.SimulatedCollection = SimulatedCollection;