UNPKG

popurelate

Version:

Easily populate and filter documents using data from related collections.

284 lines (283 loc) 10.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.deps = void 0; const path_1 = require("../path"); const const_1 = require("./const"); const addDependenciesIf = (each, startIndex, pipelines, finder, dependenceCheckFn) => { for (let i = startIndex; i < pipelines.length; ++i) { const second = pipelines[i]; const isDepended = Array.isArray(dependenceCheckFn) ? dependenceCheckFn.some(fn => fn(second.pipeline)) : dependenceCheckFn(second.pipeline); if (isDepended) { pairDependence(each.id, second.id, finder); } } }; const updateDependency = (pipelines, index, finder) => { const primary = pipelines[index]; if (primary.removable) return; for (let j = index + 1; j < pipelines.length; j++) { const secondary = pipelines[j]; if (secondary.removable) continue; if (isDependedOnMe(primary, secondary)) { pairDependence(primary.id, secondary.id, finder); break; } } }; const updatePredefinedDependency = (wrappedPipeliles, i, finder, helper) => { const is = helper.pipelineIs; const each = wrappedPipeliles[i]; if (is.changingCountOrOrder(each.pipeline)) { addDependenciesIf(each, i + 1, wrappedPipeliles, finder, is.orderAndCountImportant); } if (is.orderAndCountImportant(each.pipeline)) { addDependenciesIf(each, i + 1, wrappedPipeliles, finder, is.changingCountOrOrder); } }; const isDependedOnMe = (primary, secondary) => { const IAmChanging = primary.IAmChangingFields; const dependency = secondary.IAmDependedOnFields; if (!IAmChanging) return false; if (!IAmChanging.isChangingEveryField) { for (const field of IAmChanging.fields) { for (const depField of dependency) { if (path_1.isSubPathOf(field, depField) || path_1.isSubPathOf(depField, field)) { return true; } } } return false; } for (const field of IAmChanging.except) { for (const depField of dependency) { if (!path_1.isSubPathOf(field, depField)) return true; } } return false; }; const pairDependence = (mainId, depenedOnMeId, finder) => { const main = finder[mainId]; if (main) { main.pipelineIdsDepenedOnMe.add(depenedOnMeId); main.removable = false; } const depenedOnMe = finder[depenedOnMeId]; if (depenedOnMe) { depenedOnMe.IAmDependedOnPipelineIds.add(mainId); } }; const releaseDependencies = (pipelines, finder, helper) => { let lastAffectedIndex = -1; const is = helper.pipelineIs; for (let i = 0; i < pipelines.length; ++i) { const each = pipelines[i]; if (isMarkedRemovable(each)) continue; if (is.countLike(each.pipeline)) { const changed = releaseCountlikeDependencies(i, pipelines, finder, helper); if (changed) lastAffectedIndex = i; } if (is.skip(each.pipeline) && each.pipeline.skip === 0) { markRemovable(each.id, finder); lastAffectedIndex = i; } } const index = releaseNonusableSetters(pipelines, finder, helper); lastAffectedIndex = Math.max(lastAffectedIndex, index); if (lastAffectedIndex !== -1) { recalculateDependencies(pipelines, finder, helper); } return lastAffectedIndex; }; const releaseNonusableSetters = (pipelines, finder, helper) => { let lastAffectedIndex = -1; const is = helper.pipelineIs; for (let i = 0; i < pipelines.length; ++i) { const each = pipelines[i]; if (isMarkedRemovable(each) || !each.IAmChangingFields || each.IAmChangingFields.isChangingEveryField) { continue; } if (is.rawPipeline(each.pipeline) || is.changingCountOrOrder(each.pipeline)) { continue; } // console.log("---", "\n", each.pipeline, "\n", "---"); const changingFields = each.IAmChangingFields.fields; const willBeNeglectedFields = getNeglectedFields(i, pipelines, changingFields); if (willBeNeglectedFields.size === changingFields.size) { markRemovable(each.id, finder); lastAffectedIndex = i; } // console.log("\n\n\n\n"); } return lastAffectedIndex; }; const getNeglectedFields = (myIndex, pipelines, changingFieldsOriginal) => { const changingFields = new Set(changingFieldsOriginal); const neglectedFields = new Set(); for (let i = myIndex + 1; i < pipelines.length; ++i) { const secondaryPipeline = pipelines[i]; let recentlyNeglected = new Set(); if (secondaryPipeline.IAmChangingFields) { ({ recentlyNeglected } = getNegligenceInfo(changingFields, secondaryPipeline.IAmChangingFields, neglectedFields)); } for (const field of secondaryPipeline.IAmDependedOnFields) { for (const myField of changingFields) { if (path_1.isSubPathOf(field, myField) || path_1.isSubPathOf(myField, field)) { neglectedFields.delete(myField); changingFields.delete(myField); } } } for (const field of recentlyNeglected) { changingFields.delete(field); } if (changingFields.size === 0) break; } return neglectedFields; }; const getNegligenceInfo = (myChangingFields, secondaryChanging, neglectedFields = new Set()) => { const recentlyNeglected = new Set(); if (secondaryChanging && !secondaryChanging.isChangingEveryField) { for (const field of secondaryChanging.fields) { for (const myField of myChangingFields) { if (path_1.isSubPathOf(field, myField)) { neglectedFields.add(myField); recentlyNeglected.add(myField); } } } } if (secondaryChanging && secondaryChanging.isChangingEveryField) { for (const myField of myChangingFields) { for (const field of secondaryChanging.except) { if (!path_1.isSubPathOf(field, myField)) { neglectedFields.add(myField); recentlyNeglected.add(myField); } } } } return { neglectedFields, recentlyNeglected }; }; const releaseCountlikeDependencies = (myIndex, pipelines, finder, helper) => { let hasAffected = false; const is = helper.pipelineIs; for (let i = myIndex - 1; i >= 0; --i) { const each = pipelines[i]; if (isMarkedRemovable(each)) continue; if (!is.changingDocCount(each.pipeline)) { markRemovable(each.id, finder); hasAffected = true; } else break; } return hasAffected; }; const removeDependency = (from, to, finder) => { const me = finder[from]; if (me) { me.IAmDependedOnPipelineIds.delete(to); } const second = finder[to]; if (second) { second.pipelineIdsDepenedOnMe.delete(from); if (second.pipelineIdsDepenedOnMe.size === 0 && !second.cannotBeRemoved) { second.removable = true; } } }; const markRemovable = (id, finder) => { console.trace("=========remove id=======", id); const me = finder[id]; if (!me) return; for (const from of me.pipelineIdsDepenedOnMe) { removeDependency(from, id, finder); } }; const isMarkedRemovable = (pipeline) => !!pipeline.removable; const addRelations = (wrappedPipeliles, finder, helper) => { for (let i = 0; i < wrappedPipeliles.length; ++i) { updatePredefinedDependency(wrappedPipeliles, i, finder, helper); updateDependency(wrappedPipeliles, i, finder); } }; const resetDependencies = (wrappedPipeliles) => { // requires all pipelines. Don not pass slice of it for (let i = 0; i < wrappedPipeliles.length; ++i) { const each = wrappedPipeliles[i]; const isFinalDocDepened = each.pipelineIdsDepenedOnMe.has(const_1.FINAL_DOC_ID); each.pipelineIdsDepenedOnMe = new Set(); each.IAmDependedOnPipelineIds = new Set(); each.removable = true; if (isFinalDocDepened) { each.removable = false; each.pipelineIdsDepenedOnMe.add(const_1.FINAL_DOC_ID); } } }; const recalculateDependencies = (wrappedPipeliles, finder, helper) => { resetDependencies(wrappedPipeliles); addRelations(wrappedPipeliles, finder, helper); }; const transferDependences = (from, to, finder) => { const fromInfo = finder[from]; if (!fromInfo) return; const toInfo = finder[to]; if (!toInfo) return; for (const pipelineId of fromInfo.IAmDependedOnPipelineIds) { removeDependency(from, pipelineId, finder); pairDependence(pipelineId, to, finder); } for (const pipelineId of fromInfo.pipelineIdsDepenedOnMe) { removeDependency(pipelineId, from, finder); pairDependence(to, pipelineId, finder); } }; const markSameSetters = (pipelines) => { for (let i = 0; i < pipelines.length; ++i) { const first = pipelines[i]; for (let j = i + 1; j < pipelines.length; ++j) { const second = pipelines[j]; if (areChangingSameThings(first.IAmChangingFields, second.IAmChangingFields)) { first.sameSettersWith.add(second.id); second.sameSettersWith.add(first.id); } } } }; const areChangingSameThings = (ch1, ch2) => { if (!ch1 || !ch2) return false; if (!ch1.isChangingEveryField) { const { neglectedFields } = getNegligenceInfo(new Set(ch1.fields), ch2); return neglectedFields.size > 0; } if (!ch2.isChangingEveryField) { const { neglectedFields } = getNegligenceInfo(new Set(ch2.fields), ch1); return neglectedFields.size > 0; } return true; }; exports.deps = { releaseDependencies, addRelations, transferDependences, markSameSetters, recalculateDependencies, };