New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@ag-grid-enterprise/server-side-row-model

Package Overview
Dependencies
Maintainers
3
Versions
76
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ag-grid-enterprise/server-side-row-model - npm Package Compare versions

Comparing version 29.2.0 to 29.3.0

dist/cjs/es5/serverSideRowModel/stores/lazy/multiIndexMap.d.ts

1

dist/cjs/es5/serverSideRowModel/blocks/blockUtils.js

@@ -46,3 +46,2 @@ "use strict";

rowNode.stub = true;
rowNode.__needsRefresh = false;
rowNode.__needsRefreshWhenVisible = false;

@@ -49,0 +48,0 @@ if (rowNode.group) {

@@ -84,2 +84,6 @@ import { IServerSideStore, LoadSuccessParams, NumberSequence, RowBounds, RowNode, RowNodeBlock, ServerSideGroupLevelParams, ServerSideGroupLevelState, ServerSideTransaction, ServerSideTransactionResult, StoreRefreshAfterParams, IRowNode } from "@ag-grid-community/core";

getRowNodesInRange(firstInRange: RowNode, lastInRange: RowNode): RowNode[];
getStoreBounds(): {
topPx: number;
heightPx: number;
};
}

@@ -623,2 +623,8 @@ "use strict";

};
FullStore.prototype.getStoreBounds = function () {
return {
topPx: this.topPx,
heightPx: this.heightPx,
};
};
__decorate([

@@ -625,0 +631,0 @@ core_1.Autowired('ssrmStoreUtils')

@@ -11,2 +11,3 @@ import { BeanStub, RowNode, ServerSideGroupLevelParams } from "@ag-grid-community/core";

private readonly cache;
private checkForLoadQueued;
private loaderTimeout;

@@ -18,9 +19,7 @@ private nextBlockToLoad;

isRowLoading(index: number): boolean;
private doesRowNeedLoaded;
private getBlocksToLoad;
private getNodeRanges;
private getBlockToLoad;
reset(): void;
private executeLoad;
private isBlockInViewport;
private getNextBlockToLoad;
queueLoadCheck(): void;
queueLoadAction(): void;

@@ -27,0 +26,0 @@ private attemptLoad;

@@ -37,6 +37,2 @@ "use strict";

};
var __spread = (this && this.__spread) || function () {
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
return ar;
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -50,2 +46,3 @@ exports.LazyBlockLoader = void 0;

_this.loadingNodes = new Set();
_this.checkForLoadQueued = false;
_this.loaderTimeout = undefined;

@@ -65,52 +62,47 @@ _this.nextBlockToLoad = undefined;

};
LazyBlockLoader.prototype.doesRowNeedLoaded = function (index) {
// block already loading, don't duplicate request
if (this.loadingNodes.has(index)) {
return false;
LazyBlockLoader.prototype.getBlockToLoad = function () {
var _a;
var firstRowInViewport = this.api.getFirstDisplayedRow();
var lastRowInViewport = this.api.getLastDisplayedRow();
// quick look-up for priority rows needing loading in viewport.
for (var i = firstRowInViewport; i <= lastRowInViewport; i++) {
var node = this.cache.getNodeCachedByDisplayIndex(i);
if (!node) {
// if no row details, ignore, as row hasn't been created
// and it's too expensive to work out its location here
continue;
}
var lazyNode = this.cache.getNodes().getBy('node', node);
if (!lazyNode) {
continue;
}
if (this.isRowLoading(lazyNode.index)) {
continue;
}
if (node.__needsRefreshWhenVisible || (node.stub && !node.failedLoad)) {
return this.getBlockStartIndexForIndex(lazyNode.index);
}
}
var node = this.cache.getRowByStoreIndex(index);
if (!node) {
return false;
}
// user has manually refreshed this node
if (node.__needsRefresh) {
return true;
}
var firstRow = this.api.getFirstDisplayedRow();
var lastRow = this.api.getLastDisplayedRow();
var isRowInViewport = node.rowIndex != null && node.rowIndex >= firstRow && node.rowIndex <= lastRow;
// other than refreshing nodes, only ever load nodes in viewport
if (!isRowInViewport) {
return false;
}
// if node is a loading stub, or if it needs reverified, we refresh
return (node.stub && !node.failedLoad) || node.__needsRefreshWhenVisible;
};
LazyBlockLoader.prototype.getBlocksToLoad = function () {
var _this = this;
var indexesToLoad = new Set();
// filter for nodes somewhat reasonably close to viewport, so we don't refresh all data
// sort by distance to viewport, so user is making relevant requests
this.cache.getNodeMapEntries().forEach(function (_a) {
var _b = __read(_a, 2), stringIndex = _b[0], node = _b[1];
var numericIndex = Number(stringIndex);
var blockStart = _this.getBlockStartIndexForIndex(numericIndex);
// if node is a loading stub, or has manually been marked as needsRefresh we refresh
if (_this.doesRowNeedLoaded(numericIndex)) {
indexesToLoad.add(blockStart);
var nodesToRefresh = this.cache.getNodesToRefresh();
var nodeToRefresh = null;
var nodeToRefreshDist = Number.MAX_SAFE_INTEGER;
nodesToRefresh.forEach(function (node) {
if (node.rowIndex == null) {
nodeToRefresh = node;
return;
}
var distToViewportTop = Math.abs(firstRowInViewport - node.rowIndex);
var distToViewportBottom = Math.abs(node.rowIndex - lastRowInViewport);
if (distToViewportTop < nodeToRefreshDist) {
nodeToRefresh = node;
nodeToRefreshDist = distToViewportTop;
}
if (distToViewportBottom < nodeToRefreshDist) {
nodeToRefresh = node;
nodeToRefreshDist = distToViewportBottom;
}
});
return __spread(indexesToLoad);
var lazyIndex = (_a = this.cache.getNodes().getBy('node', nodeToRefresh)) === null || _a === void 0 ? void 0 : _a.index;
return lazyIndex == null ? undefined : this.getBlockStartIndexForIndex(lazyIndex);
};
LazyBlockLoader.prototype.getNodeRanges = function () {
var _this = this;
var ranges = {};
this.getBlocksToLoad().forEach(function (index) {
var rangeSize = core_1._.oneOrGreater(_this.gridOptionsService.getNum('cacheBlockSize')) || LazyBlockLoader.DEFAULT_BLOCK_SIZE;
var translatedIndex = index - (index % rangeSize);
ranges[translatedIndex] = translatedIndex + rangeSize;
});
return ranges;
};
LazyBlockLoader.prototype.reset = function () {

@@ -172,35 +164,23 @@ this.loadingNodes.clear();

};
LazyBlockLoader.prototype.isBlockInViewport = function (blockStart, blockEnd) {
var firstRowInViewport = this.api.getFirstDisplayedRow();
var lastRowInViewport = this.api.getLastDisplayedRow();
var blockContainsViewport = blockStart <= firstRowInViewport && blockEnd >= lastRowInViewport;
var blockEndIsInViewport = blockEnd > firstRowInViewport && blockEnd < lastRowInViewport;
var blockStartIsInViewport = blockStart > firstRowInViewport && blockStart < lastRowInViewport;
return blockContainsViewport || blockEndIsInViewport || blockStartIsInViewport;
LazyBlockLoader.prototype.getNextBlockToLoad = function () {
var result = this.getBlockToLoad();
if (result != null && result < 0) {
this.getBlockToLoad();
}
if (result != null) {
return [String(result), result + this.getBlockSize()];
}
return null;
};
LazyBlockLoader.prototype.getNextBlockToLoad = function () {
LazyBlockLoader.prototype.queueLoadCheck = function () {
var _this = this;
var ranges = this.getNodeRanges();
var toLoad = Object.entries(ranges);
if (toLoad.length === 0) {
return null;
// already going to check next cycle, ignore.
if (this.checkForLoadQueued) {
return;
}
var firstRowInViewport = this.api.getFirstDisplayedRow();
toLoad.sort(function (_a, _b) {
var _c = __read(_a, 2), aStart = _c[0], aEnd = _c[1];
var _d = __read(_b, 2), bStart = _d[0], bEnd = _d[1];
var isAInViewport = _this.isBlockInViewport(Number(aStart), aEnd);
var isBInViewport = _this.isBlockInViewport(Number(bStart), bEnd);
// always prioritise loading blocks in viewport
if (isAInViewport) {
return -1;
}
// always prioritise loading blocks in viewport
if (isBInViewport) {
return 1;
}
// prioritise based on how close to the viewport the block is
return Math.abs(firstRowInViewport - Number(aStart)) - Math.abs(firstRowInViewport - Number(bStart));
this.checkForLoadQueued = true;
window.queueMicrotask(function () {
_this.checkForLoadQueued = false;
_this.queueLoadAction();
});
return toLoad[0];
};

@@ -207,0 +187,0 @@ LazyBlockLoader.prototype.queueLoadAction = function () {

import { BeanStub, LoadSuccessParams, NumberSequence, RowNode, IRowNode, ServerSideGroupLevelParams } from "@ag-grid-community/core";
import { LazyStore } from "./lazyStore";
import { MultiIndexMap } from "./multiIndexMap";
interface LazyStoreNode {
id: string;
index: number;
node: RowNode;
}
export declare class LazyCache extends BeanStub {

@@ -8,11 +14,48 @@ private api;

private nodeManager;
/**
* Indicates whether this is still the live dataset for this store (used for ignoring old requests after purge)
*/
private live;
private nodeIndexMap;
private nodeIds;
/**
* A node map indexed by the node's id, index, and node.
*/
private nodeMap;
/**
* A map of nodes indexed by the display index.
*/
private nodeDisplayIndexMap;
/**
* A set of nodes waiting to be refreshed
*/
private nodesToRefresh;
/**
* A list of display indexes bounds which are not currently present in this store, this can be due to;
* - Row stub hasn't been generated yet
* - Display index belongs to a child store
* - Display index is a detail node
*
* (Note, this is not always up to date, as stub nodes being generated do not refresh this, however
* this is a non issue as stub nodes are only ever default height and occupy 1 display index)
*/
private skippedDisplayIndexes;
/**
* End of store properties
*/
private numberOfRows;
private isLastRowKnown;
/**
* The prefix to use for node ids, this is used to ensure that node ids are unique across stores
*/
private defaultNodeIdPrefix;
/**
* Sibling services - 1-1 relationships.
*/
private store;
private rowLoader;
private storeParams;
/**
* Grid options properties - stored locally for access speed.
*/
private getRowIdFunc?;
private isMasterDetail;
constructor(store: LazyStore, numberOfRows: number, storeParams: ServerSideGroupLevelParams);

@@ -35,3 +78,3 @@ private init;

*/
getRowByStoreIndex(index: number): RowNode<any>;
getRowByStoreIndex(index: number): RowNode<any> | undefined;
/**

@@ -53,8 +96,16 @@ * Given a number of rows, skips through the given sequence & row top reference (using default row height)

setRowCount(rowCount: number, isLastRowIndexKnown?: boolean): void;
getNodeMapEntries(): [string, RowNode][];
getAllNodes(): RowNode[];
getNodes(): MultiIndexMap<LazyStoreNode>;
getNodeCachedByDisplayIndex(displayIndex: number): RowNode | null;
getNodesToRefresh(): Set<RowNode>;
/**
* Get or calculate the display index for this store
* @returns the previous and next loaded row nodes surrounding the given display index
*/
getSurroundingNodesByDisplayIndex(displayIndex: number): {
previousNode: RowNode<any> | undefined;
nextNode: RowNode<any> | undefined;
} | null;
/**
* Get or calculate the display index for a given store index
* @param storeIndex the rows index within this store
* @returns the rows visible display index relative to all stores
* @returns the rows visible display index relative to the grid
*/

@@ -95,2 +146,3 @@ getDisplayIndexFromStoreIndex(storeIndex: number): number | null;

onLoadSuccess(firstRowIndex: number, numberOfRowsExpected: number, response: LoadSuccessParams): void;
fireRefreshFinishedEvent(): void;
isLastRowIndexKnown(): boolean;

@@ -101,8 +153,11 @@ onLoadFailed(firstRowIndex: number, numberOfRowsExpected: number): void;

private fireStoreUpdatedEvent;
private isUsingRowIds;
private getRowId;
private lookupRowNode;
updateRowNodes(updates: any[]): RowNode[];
insertRowNodes(inserts: any[], indexToAdd?: number): RowNode[];
getOrderedNodeMap(): {
[key: number]: LazyStoreNode;
};
clearDisplayIndexes(): void;
removeRowNodes(idsToRemove: string[]): RowNode[];
}
export {};

@@ -45,2 +45,4 @@ "use strict";

var lazyBlockLoader_1 = require("./lazyBlockLoader");
var multiIndexMap_1 = require("./multiIndexMap");
;
var LazyCache = /** @class */ (function (_super) {

@@ -50,3 +52,5 @@ __extends(LazyCache, _super);

var _this = _super.call(this) || this;
// Indicates whether this is still the live dataset for this store (used for ignoring old requests after purge)
/**
* Indicates whether this is still the live dataset for this store (used for ignoring old requests after purge)
*/
_this.live = true;

@@ -60,12 +64,20 @@ _this.store = store;

LazyCache.prototype.init = function () {
this.nodeIndexMap = {};
this.nodeIds = new Set();
// initiate the node map to be indexed at 'index', 'id' and 'node' for quick look-up.
// it's important id isn't first, as stub nodes overwrite each-other, and the first index is
// used for iteration.
this.nodeMap = new multiIndexMap_1.MultiIndexMap('index', 'id', 'node');
this.nodeDisplayIndexMap = new Map();
this.nodesToRefresh = new Set();
this.defaultNodeIdPrefix = this.blockUtils.createNodeIdPrefix(this.store.getParentNode());
this.rowLoader = this.createManagedBean(new lazyBlockLoader_1.LazyBlockLoader(this, this.store.getParentNode(), this.storeParams));
this.getRowIdFunc = this.gridOptionsService.getRowIdFunc();
this.isMasterDetail = this.gridOptionsService.isMasterDetail();
};
LazyCache.prototype.destroyRowNodes = function () {
var _this = this;
this.numberOfRows = 0;
this.blockUtils.destroyRowNodes(this.getAllNodes());
this.nodeIndexMap = {};
this.nodeIds.clear();
this.nodeMap.forEach(function (node) { return _this.blockUtils.destroyRowNode(node.node); });
this.nodeMap.clear();
this.nodeDisplayIndexMap.clear();
this.nodesToRefresh.clear();
this.live = false;

@@ -79,3 +91,3 @@ };

LazyCache.prototype.getRowByDisplayIndex = function (displayIndex) {
var _a;
var _a, _b, _c, _d;
// if index isn't in store, nothing to return

@@ -85,47 +97,54 @@ if (!this.store.isDisplayIndexInStore(displayIndex)) {

}
var nodeAfterStringIndex;
var nodeMapEntries = this.getNodeMapEntries();
for (var i = 0; i < nodeMapEntries.length; i++) {
var _b = __read(nodeMapEntries[i], 2), stringIndex = _b[0], node = _b[1];
// if we find the index, simply return this node
if (node.rowIndex === displayIndex) {
if (node.stub || node.__needsRefreshWhenVisible) {
this.rowLoader.queueLoadAction();
}
return node;
// first try to directly look this node up in the display index map
var node = this.nodeDisplayIndexMap.get(displayIndex);
if (node) {
// if we have the node, check if it needs refreshed when rendered
if (node.stub || node.__needsRefreshWhenVisible) {
this.rowLoader.queueLoadCheck();
}
// then check if current row contains a detail row with the index
var expandedMasterRow = node.master && node.expanded;
var detailNode = node.detailNode;
if (expandedMasterRow && detailNode && detailNode.rowIndex === displayIndex) {
return detailNode;
return node;
}
// next check if this is the first row, if so return a stub node
// this is a performance optimisation, as it is the most common scenario
// and enables the node - 1 check to kick in more often.
if (displayIndex === this.store.getDisplayIndexStart()) {
return this.createStubNode(0, displayIndex);
}
// check if the row immediately prior is available in the store
var contiguouslyPreviousNode = this.nodeDisplayIndexMap.get(displayIndex - 1);
if (contiguouslyPreviousNode) {
// if previous row is master detail, and expanded, this node must be detail
if (this.isMasterDetail && contiguouslyPreviousNode.master && contiguouslyPreviousNode.expanded) {
return contiguouslyPreviousNode.detailNode;
}
// if the index belongs to a child store, recursively search
if ((_a = node.childStore) === null || _a === void 0 ? void 0 : _a.isDisplayIndexInStore(displayIndex)) {
return node.childStore.getRowUsingDisplayIndex(displayIndex);
// if previous row is expanded group, this node will belong to that group.
if (contiguouslyPreviousNode.expanded && ((_a = contiguouslyPreviousNode.childStore) === null || _a === void 0 ? void 0 : _a.isDisplayIndexInStore(displayIndex))) {
return (_b = contiguouslyPreviousNode.childStore) === null || _b === void 0 ? void 0 : _b.getRowUsingDisplayIndex(displayIndex);
}
// if current row index is higher, then the node has been passed
if (node.rowIndex > displayIndex) {
// keep track of the last next node we find that comes after in case we need to create a new stub
nodeAfterStringIndex = stringIndex;
break;
}
// otherwise, row must be a stub node
var lazyCacheNode = this.nodeMap.getBy('node', contiguouslyPreviousNode);
return this.createStubNode(lazyCacheNode.index + 1, displayIndex);
}
/**
* The code below this point is assuming we haven't found a stored node with this display index, but the node does belong in this store,
* in this case we want to create a stub node to display in the grid, so we need to calculate the store index from the display index using
* the next node found after this one (can use end index here as we have confidence it should be up to date, as we aren't inserting rows)
*/
// no node was found before this display index, so calculate based on store end index
if (nodeAfterStringIndex == null) {
var storeIndexFromEndIndex = this.store.getRowCount() - (this.store.getDisplayIndexEnd() - displayIndex);
return this.createStubNode(storeIndexFromEndIndex, displayIndex);
var adjacentNodes = this.getSurroundingNodesByDisplayIndex(displayIndex);
// if no bounds skipped includes this, calculate from end index
if (adjacentNodes == null) {
var storeIndexFromEndIndex_1 = this.store.getRowCount() - (this.store.getDisplayIndexEnd() - displayIndex);
return this.createStubNode(storeIndexFromEndIndex_1, displayIndex);
}
// important to remember this node is not necessarily directly after the node we're searching for
var nodeAfterIndex = Number(nodeAfterStringIndex);
var nodeAfter = this.nodeIndexMap[nodeAfterIndex];
// difference can be calculated from next nodes display index
var nodeAfterDisplayIndex = nodeAfter.rowIndex;
var storeIndexFromNodeAfterIndex = nodeAfterIndex - (nodeAfterDisplayIndex - displayIndex);
return this.createStubNode(storeIndexFromNodeAfterIndex, displayIndex);
var previousNode = adjacentNodes.previousNode, nextNode = adjacentNodes.nextNode;
// if the node before this node is expanded, this node might be a child of that node
if (previousNode && previousNode.expanded && ((_c = previousNode.childStore) === null || _c === void 0 ? void 0 : _c.isDisplayIndexInStore(displayIndex))) {
return (_d = previousNode.childStore) === null || _d === void 0 ? void 0 : _d.getRowUsingDisplayIndex(displayIndex);
}
// if we have the node after this node, we can calculate the store index of this node by the difference
// in display indexes between the two nodes.
if (nextNode) {
var nextSimpleRowStoreIndex = this.nodeMap.getBy('node', nextNode);
var displayIndexDiff = nextNode.rowIndex - displayIndex;
var newStoreIndex = nextSimpleRowStoreIndex.index - displayIndexDiff;
return this.createStubNode(newStoreIndex, displayIndex);
}
// if no next node, calculate from end index of this store
var storeIndexFromEndIndex = this.store.getRowCount() - (this.store.getDisplayIndexEnd() - displayIndex);
return this.createStubNode(storeIndexFromEndIndex, displayIndex);
};

@@ -136,2 +155,3 @@ /**

LazyCache.prototype.createStubNode = function (storeIndex, displayIndex) {
var _this = this;
// bounds are acquired before creating the node, as otherwise it'll use it's own empty self to calculate

@@ -142,4 +162,5 @@ var rowBounds = this.store.getRowBounds(displayIndex);

node.setRowTop(rowBounds.rowTop);
_this.nodeDisplayIndexMap.set(displayIndex, node);
});
this.rowLoader.queueLoadAction();
this.rowLoader.queueLoadCheck();
return newNode;

@@ -152,3 +173,4 @@ };

LazyCache.prototype.getRowByStoreIndex = function (index) {
return this.nodeIndexMap[index];
var _a;
return (_a = this.nodeMap.getBy('index', index)) === null || _a === void 0 ? void 0 : _a.node;
};

@@ -162,3 +184,11 @@ /**

LazyCache.prototype.skipDisplayIndexes = function (numberOfRowsToSkip, displayIndexSeq, nextRowTop) {
if (numberOfRowsToSkip === 0) {
return;
}
var defaultRowHeight = this.gridOptionsService.getRowHeightAsNumber();
// these are recorded so that the previous node can be found more quickly when a node is missing
this.skippedDisplayIndexes.push({
from: displayIndexSeq.peek(),
to: displayIndexSeq.peek() + numberOfRowsToSkip
});
displayIndexSeq.skip(numberOfRowsToSkip);

@@ -172,19 +202,37 @@ nextRowTop.value += numberOfRowsToSkip * defaultRowHeight;

LazyCache.prototype.setDisplayIndexes = function (displayIndexSeq, nextRowTop) {
var _this = this;
var nodeEntries = this.getNodeMapEntries();
// Create a map of display index nodes for access speed
this.nodeDisplayIndexMap.clear();
this.skippedDisplayIndexes = [];
// create an object indexed by store index, as this will sort all of the nodes when we iterate
// the object
var orderedMap = {};
this.nodeMap.forEach(function (lazyNode) {
orderedMap[lazyNode.index] = lazyNode.node;
});
var lastIndex = -1;
nodeEntries.forEach(function (_a) {
var _b = __read(_a, 2), stringIndex = _b[0], node = _b[1];
// iterate over the nodes in order, setting the display index on each node. When display indexes
// are skipped, they're added to the skippedDisplayIndexes array
for (var stringIndex in orderedMap) {
var node = orderedMap[stringIndex];
var numericIndex = Number(stringIndex);
// if any nodes aren't currently in the store, skip the display indexes too
var numberOfRowsToSkip = (numericIndex - 1) - lastIndex;
_this.skipDisplayIndexes(numberOfRowsToSkip, displayIndexSeq, nextRowTop);
var numberOfRowsToSkip_1 = (numericIndex - 1) - lastIndex;
this.skipDisplayIndexes(numberOfRowsToSkip_1, displayIndexSeq, nextRowTop);
// set this nodes index and row top
_this.blockUtils.setDisplayIndex(node, displayIndexSeq, nextRowTop);
this.blockUtils.setDisplayIndex(node, displayIndexSeq, nextRowTop);
this.nodeDisplayIndexMap.set(node.rowIndex, node);
var passedRows = displayIndexSeq.peek() - node.rowIndex;
if (passedRows > 1) {
this.skippedDisplayIndexes.push({
from: node.rowIndex + 1,
to: displayIndexSeq.peek()
});
}
// store this index for skipping after this
lastIndex = numericIndex;
});
}
// need to skip rows until the end of this store
var numberOfRowsToSkip = (this.numberOfRows - 1) - lastIndex;
this.skipDisplayIndexes(numberOfRowsToSkip, displayIndexSeq, nextRowTop);
// this is not terribly efficient, and could probs be improved
this.purgeExcessRows();

@@ -202,53 +250,54 @@ };

this.isLastRowKnown = isLastRowIndexKnown;
if (isLastRowIndexKnown === false) {
this.numberOfRows += 1;
}
}
this.fireStoreUpdatedEvent();
};
LazyCache.prototype.getNodeMapEntries = function () {
return Object.entries(this.nodeIndexMap);
LazyCache.prototype.getNodes = function () {
return this.nodeMap;
};
LazyCache.prototype.getAllNodes = function () {
return Object.values(this.nodeIndexMap);
LazyCache.prototype.getNodeCachedByDisplayIndex = function (displayIndex) {
var _a;
return (_a = this.nodeDisplayIndexMap.get(displayIndex)) !== null && _a !== void 0 ? _a : null;
};
LazyCache.prototype.getNodesToRefresh = function () {
return this.nodesToRefresh;
};
/**
* Get or calculate the display index for this store
* @returns the previous and next loaded row nodes surrounding the given display index
*/
LazyCache.prototype.getSurroundingNodesByDisplayIndex = function (displayIndex) {
// iterate over the skipped display indexes to find the bound this display index belongs to
for (var i in this.skippedDisplayIndexes) {
var skippedRowBound = this.skippedDisplayIndexes[i];
if (skippedRowBound.from <= displayIndex && skippedRowBound.to >= displayIndex) {
// take the node before and after the boundary and return those
var previousNode = this.nodeDisplayIndexMap.get(skippedRowBound.from - 1);
var nextNode = this.nodeDisplayIndexMap.get(skippedRowBound.to + 1);
return { previousNode: previousNode, nextNode: nextNode };
}
}
return null;
};
/**
* Get or calculate the display index for a given store index
* @param storeIndex the rows index within this store
* @returns the rows visible display index relative to all stores
* @returns the rows visible display index relative to the grid
*/
LazyCache.prototype.getDisplayIndexFromStoreIndex = function (storeIndex) {
var _a;
var nodeToReplace = this.nodeIndexMap[storeIndex];
var displayIndexStart = this.store.getDisplayIndexStart();
if (displayIndexStart == null) {
return null;
var nodesAfterThis = this.nodeMap.filter(function (lazyNode) { return lazyNode.index > storeIndex; });
if (nodesAfterThis.length === 0) {
return this.store.getDisplayIndexEnd() - (this.numberOfRows - storeIndex);
}
// if node exists, we can extract its displayIndex
if (nodeToReplace && nodeToReplace.rowIndex != null) {
return nodeToReplace.rowIndex;
}
var allNodes = this.getNodeMapEntries();
var lastNode = undefined;
var lastIndex = -1;
for (var i = 0; i < allNodes.length; i++) {
var _b = __read(allNodes[i], 2), stringNodeStoreIndex = _b[0], node = _b[1];
var numericNodeStoreIndex = Number(stringNodeStoreIndex);
if (numericNodeStoreIndex > storeIndex) {
break;
var nextNode;
for (var i = 0; i < nodesAfterThis.length; i++) {
var lazyNode = nodesAfterThis[i];
if (nextNode == null || nextNode.index > lazyNode.index) {
nextNode = lazyNode;
}
lastNode = node;
lastIndex = numericNodeStoreIndex;
}
// unlike in getRowByDisplayIndex, we have to use getDisplayIndexStart here, as nodes may
// have been inserted without updating display index end yet.
if (lastNode == null) {
return displayIndexStart + storeIndex;
}
var nodeDiff = storeIndex - lastIndex;
var childStoreEnd = (_a = lastNode.childStore) === null || _a === void 0 ? void 0 : _a.getDisplayIndexEnd();
if (childStoreEnd != null) {
return childStoreEnd + nodeDiff - 1;
}
if (lastNode.rowIndex != null) {
return lastNode.rowIndex + nodeDiff;
}
return displayIndexStart + storeIndex;
var nextDisplayIndex = nextNode.node.rowIndex;
var storeIndexDiff = nextNode.index - storeIndex;
return nextDisplayIndex - storeIndexDiff;
};

@@ -262,17 +311,17 @@ /**

LazyCache.prototype.createRowAtIndex = function (atStoreIndex, data, createNodeCallback) {
var _this = this;
var usingRowIds = this.isUsingRowIds();
// make sure an existing node isn't being overwritten
var existingNodeAtIndex = this.nodeIndexMap[atStoreIndex];
if (existingNodeAtIndex) {
existingNodeAtIndex.__needsRefresh = false;
existingNodeAtIndex.__needsRefreshWhenVisible = false;
var lazyNode = this.nodeMap.getBy('index', atStoreIndex);
// if node already exists, update it or destroy it
if (lazyNode) {
var node = lazyNode.node;
this.nodesToRefresh.delete(node);
node.__needsRefreshWhenVisible = false;
// if the node is the same, just update the content
if (this.doesNodeMatch(data, existingNodeAtIndex)) {
this.blockUtils.updateDataIntoRowNode(existingNodeAtIndex, data);
return existingNodeAtIndex;
if (this.doesNodeMatch(data, node)) {
this.blockUtils.updateDataIntoRowNode(node, data);
return node;
}
// if there's no id and this is an open group, protect this node from changes
if (!usingRowIds && existingNodeAtIndex.group && existingNodeAtIndex.expanded) {
return existingNodeAtIndex;
if (this.getRowIdFunc == null && node.group && node.expanded) {
return node;
}

@@ -282,18 +331,20 @@ // destroy the old node, might be worth caching state here

}
// if the node already exists, update it and move it to the new location
if (data && usingRowIds) {
var allNodes = this.getNodeMapEntries();
var existingNodeDetails = allNodes.find(function (_a) {
var _b = __read(_a, 2), _ = _b[0], node = _b[1];
return _this.doesNodeMatch(data, node);
});
if (existingNodeDetails) {
var _a = __read(existingNodeDetails, 2), existingStringIndex = _a[0], existingNode = _a[1];
var existingIndex = Number(existingStringIndex);
this.blockUtils.updateDataIntoRowNode(existingNode, data);
delete this.nodeIndexMap[existingIndex];
this.nodeIndexMap[atStoreIndex] = existingNode;
// mark all of the old block as needsVerify to trigger it for a refresh
this.markBlockForVerify(existingIndex);
return existingNode;
// if the node already exists elsewhere, update it and move it to the new location
if (data && this.getRowIdFunc != null) {
var id = this.getRowId(data);
var lazyNode_1 = this.nodeMap.getBy('id', id);
if (lazyNode_1) {
// delete old lazy node so we can insert it at different location
this.nodeMap.delete(lazyNode_1);
var node = lazyNode_1.node, index = lazyNode_1.index;
this.blockUtils.updateDataIntoRowNode(node, data);
this.nodeMap.set({
id: node.id,
node: node,
index: atStoreIndex
});
// mark all of the old block as needsVerify to trigger it for a refresh, as nodes
// should not be out of place
this.markBlockForVerify(index);
return node;
}

@@ -308,13 +359,12 @@ }

this.nodeManager.addRowNode(newNode);
this.nodeIds.add(newNode.id);
}
// add the new node to the store, has to be done after the display index is calculated so it doesn't take itself into account
this.nodeIndexMap[atStoreIndex] = newNode;
this.nodeMap.set({
id: newNode.id,
node: newNode,
index: atStoreIndex,
});
if (createNodeCallback) {
createNodeCallback(newNode);
}
// if this is a stub, we need to tell the loader to load rows
if (newNode.stub) {
this.rowLoader.queueLoadAction();
}
return newNode;

@@ -327,6 +377,5 @@ };

var dirtyBlocks = new Set();
this.getNodeMapEntries().forEach(function (_a) {
this.nodeMap.forEach(function (_a) {
var _b;
var _c = __read(_a, 2), stringIndex = _c[0], node = _c[1];
var index = Number(stringIndex);
var node = _a.node, index = _a.index;
var blockStart = _this.rowLoader.getBlockStartIndexForIndex(index);

@@ -343,3 +392,3 @@ if (!node.stub && !node.failedLoad) {

}
else if (node.__needsRefresh) {
else if (_this.nodesToRefresh.has(node)) {
rowState = 'needsLoading';

@@ -381,6 +430,10 @@ }

LazyCache.prototype.destroyRowAtIndex = function (atStoreIndex) {
var node = this.nodeIndexMap[atStoreIndex];
this.nodeIds.delete(node.id);
this.blockUtils.destroyRowNode(node);
delete this.nodeIndexMap[atStoreIndex];
var lazyNode = this.nodeMap.getBy('index', atStoreIndex);
if (!lazyNode) {
return;
}
this.nodeMap.delete(lazyNode);
this.nodeDisplayIndexMap.delete(lazyNode.node.rowIndex);
this.nodesToRefresh.delete(lazyNode.node);
this.blockUtils.destroyRowNode(lazyNode.node);
};

@@ -404,8 +457,7 @@ LazyCache.prototype.getSsrmParams = function () {

var _a = __read(this.rowLoader.getBlockBoundsForIndex(rowIndex), 2), start = _a[0], end = _a[1];
for (var i = start; i < end; i++) {
var node = this.nodeIndexMap[i];
if (node) {
node.__needsRefreshWhenVisible = true;
}
}
var lazyNodesInRange = this.nodeMap.filter(function (lazyNode) { return lazyNode.index >= start && lazyNode.index < end; });
lazyNodesInRange.forEach(function (_a) {
var node = _a.node;
node.__needsRefreshWhenVisible = true;
});
};

@@ -416,3 +468,3 @@ LazyCache.prototype.doesNodeMatch = function (data, node) {

}
if (this.isUsingRowIds()) {
if (this.getRowIdFunc != null) {
var id = this.getRowId(data);

@@ -432,10 +484,8 @@ return node.id === id;

var _a = __read(this.rowLoader.getBlockBoundsForIndex(lastRow), 2), _ = _a[0], lastRowBlockEnd = _a[1];
this.getNodeMapEntries().forEach(function (_a) {
var _b = __read(_a, 2), stringIndex = _b[0], node = _b[1];
var numericIndex = Number(stringIndex);
if (_this.rowLoader.isRowLoading(numericIndex)) {
this.nodeMap.forEach(function (lazyNode) {
if (_this.rowLoader.isRowLoading(lazyNode.index)) {
return;
}
if (node.stub && (numericIndex < firstRowBlockStart || numericIndex > lastRowBlockEnd)) {
_this.destroyRowAtIndex(numericIndex);
if (lazyNode.node.stub && (lazyNode.index < firstRowBlockStart || lazyNode.index > lastRowBlockEnd)) {
_this.destroyRowAtIndex(lazyNode.index);
}

@@ -462,4 +512,4 @@ });

nodes.forEach(function (_a) {
var _b = __read(_a, 2), storeIndexString = _b[0], node = _b[1];
var _c = __read(_this.rowLoader.getBlockBoundsForIndex(Number(storeIndexString)), 2), blockStart = _c[0], blockEnd = _c[1];
var node = _a.node, index = _a.index;
var _b = __read(_this.rowLoader.getBlockBoundsForIndex(index), 2), blockStart = _b[0], blockEnd = _b[1];
if (blockStart in blockDistanceToMiddle) {

@@ -471,4 +521,5 @@ return;

// may not have an end node if the block came back small
if (_this.nodeIndexMap[blockEnd - 1])
distEnd = Math.abs(_this.nodeIndexMap[blockEnd - 1].rowIndex - otherDisplayIndex);
var lastLazyNode = _this.nodeMap.getBy('index', [blockEnd - 1]);
if (lastLazyNode)
distEnd = Math.abs(lastLazyNode.node.rowIndex - otherDisplayIndex);
var farthest = distEnd == null || distStart < distEnd ? distStart : distEnd;

@@ -494,4 +545,4 @@ blockDistanceToMiddle[blockStart] = farthest;

// don't check the nodes that could have been cached out of necessity
var disposableNodes = this.getNodeMapEntries().filter(function (_a) {
var _b = __read(_a, 2), _ = _b[0], node = _b[1];
var disposableNodes = this.nodeMap.filter(function (_a) {
var node = _a.node;
return !node.stub && !_this.isNodeCached(node);

@@ -504,9 +555,9 @@ });

var disposableNodesNotInViewport = disposableNodes.filter(function (_a) {
var _b = __read(_a, 2), _ = _b[0], node = _b[1];
var node = _a.node;
var startRowNum = node.rowIndex;
if (!startRowNum) {
if (startRowNum == null || startRowNum === -1) {
// row is not displayed and can be disposed
return true;
}
if (firstRowInViewport <= startRowNum && startRowNum <= lastRowInViewport) {
if (firstRowBlockStart <= startRowNum && startRowNum < lastRowBlockEnd) {
// start row in viewport, block is in viewport

@@ -516,7 +567,7 @@ return false;

var lastRowNum = startRowNum + blockSize;
if (firstRowInViewport <= lastRowNum && lastRowNum <= lastRowInViewport) {
if (firstRowBlockStart <= lastRowNum && lastRowNum < lastRowBlockEnd) {
// end row in viewport, block is in viewport
return false;
}
if (startRowNum < firstRowInViewport && lastRowNum > lastRowInViewport) {
if (startRowNum < firstRowBlockStart && lastRowNum >= lastRowBlockEnd) {
// full block surrounds in viewport

@@ -528,2 +579,4 @@ return false;

});
// reduce the number of rows to retain by the number in viewport which were retained
numberOfRowsToRetain = numberOfRowsToRetain - (disposableNodes.length - disposableNodesNotInViewport.length);
if (!disposableNodesNotInViewport.length) {

@@ -541,8 +594,8 @@ return;

blockDistanceArray.sort(function (a, b) { return Math.sign(b[1] - a[1]); });
var blocksToRemove = blockDistanceArray.length - numberOfBlocksToRetain;
var blocksToRemove = blockDistanceArray.length - Math.max(numberOfBlocksToRetain, 0);
for (var i = 0; i < blocksToRemove; i++) {
var blockStart = Number(blockDistanceArray[i][0]);
for (var x = blockStart; x < blockStart + blockSize; x++) {
var node = this.nodeIndexMap[x];
if (!node || this.isNodeCached(node)) {
var lazyNode = this.nodeMap.getBy('index', x);
if (!lazyNode || this.isNodeCached(lazyNode.node)) {
continue;

@@ -570,3 +623,3 @@ }

var _this = this;
if (!this.isUsingRowIds()) {
if (!this.getRowIdFunc == null) {
return [];

@@ -590,3 +643,3 @@ }

return;
if (this.isUsingRowIds()) {
if (this.getRowIdFunc != null) {
var duplicates = this.extractDuplicateIds(response.rowData);

@@ -600,14 +653,16 @@ if (duplicates.length > 0) {

}
var wasRefreshing = this.nodesToRefresh.size > 0;
response.rowData.forEach(function (data, responseRowIndex) {
var _a;
var rowIndex = firstRowIndex + responseRowIndex;
var nodeFromCache = _this.nodeIndexMap[rowIndex];
var nodeFromCache = _this.nodeMap.getBy('index', rowIndex);
// if stub, overwrite
if (nodeFromCache === null || nodeFromCache === void 0 ? void 0 : nodeFromCache.stub) {
if ((_a = nodeFromCache === null || nodeFromCache === void 0 ? void 0 : nodeFromCache.node) === null || _a === void 0 ? void 0 : _a.stub) {
_this.createRowAtIndex(rowIndex, data);
return;
}
if (nodeFromCache && _this.doesNodeMatch(data, nodeFromCache)) {
_this.blockUtils.updateDataIntoRowNode(nodeFromCache, data);
nodeFromCache.__needsRefresh = false;
nodeFromCache.__needsRefreshWhenVisible = false;
if (nodeFromCache && _this.doesNodeMatch(data, nodeFromCache.node)) {
_this.blockUtils.updateDataIntoRowNode(nodeFromCache.node, data);
_this.nodesToRefresh.delete(nodeFromCache.node);
nodeFromCache.node.__needsRefreshWhenVisible = false;
return;

@@ -618,2 +673,6 @@ }

});
var finishedRefreshing = this.nodesToRefresh.size === 0;
if (wasRefreshing && finishedRefreshing) {
this.fireRefreshFinishedEvent();
}
if (response.rowCount != undefined && response.rowCount !== -1) {

@@ -638,13 +697,15 @@ // if the rowCount has been provided, set the row count

// delete any rows after the last index
var allRows = this.getNodeMapEntries();
for (var i = allRows.length - 1; i >= 0; i--) {
var numericIndex = Number(allRows[i][0]);
if (numericIndex < this.numberOfRows) {
break;
}
this.destroyRowAtIndex(numericIndex);
}
var lazyNodesAfterStoreEnd = this.nodeMap.filter(function (lazyNode) { return lazyNode.index >= _this.numberOfRows; });
lazyNodesAfterStoreEnd.forEach(function (lazyNode) { return _this.destroyRowAtIndex(lazyNode.index); });
}
this.fireStoreUpdatedEvent();
};
LazyCache.prototype.fireRefreshFinishedEvent = function () {
var finishedRefreshing = this.nodesToRefresh.size === 0;
// if anything refreshing currently, skip.
if (!finishedRefreshing) {
return;
}
this.store.fireRefreshFinishedEvent();
};
LazyCache.prototype.isLastRowIndexKnown = function () {

@@ -656,16 +717,23 @@ return this.isLastRowKnown;

return;
for (var i = firstRowIndex; i < firstRowIndex + numberOfRowsExpected; i++) {
var nodeFromCache = this.nodeIndexMap[i];
if (nodeFromCache) {
nodeFromCache.failedLoad = true;
}
}
var failedNodes = this.nodeMap.filter(function (node) { return node.index >= firstRowIndex && node.index < firstRowIndex + numberOfRowsExpected; });
failedNodes.forEach(function (node) { return node.node.failedLoad = true; });
this.fireStoreUpdatedEvent();
};
LazyCache.prototype.markNodesForRefresh = function () {
this.getAllNodes().forEach(function (node) { return node.__needsRefresh = true; });
this.rowLoader.queueLoadAction();
var _this = this;
this.nodeMap.forEach(function (lazyNode) {
if (lazyNode.node.stub) {
return;
}
_this.nodesToRefresh.add(lazyNode.node);
});
this.rowLoader.queueLoadCheck();
if (this.isLastRowKnown && this.numberOfRows === 0) {
this.numberOfRows = 1;
this.isLastRowKnown = false;
this.fireStoreUpdatedEvent();
}
};
LazyCache.prototype.isNodeInCache = function (id) {
return this.nodeIds.has(id);
return !!this.nodeMap.getBy('id', id);
};

@@ -679,8 +747,4 @@ // gets called 1) row count changed 2) cache purged 3) items inserted

};
LazyCache.prototype.isUsingRowIds = function () {
return this.gridOptionsService.getRowIdFunc() != null;
};
LazyCache.prototype.getRowId = function (data) {
var getRowIdFunc = this.gridOptionsService.getRowIdFunc();
if (getRowIdFunc == null) {
if (this.getRowIdFunc == null) {
return null;

@@ -691,3 +755,3 @@ }

var parentKeys = this.store.getParentNode().getGroupKeys();
var id = getRowIdFunc({
var id = this.getRowIdFunc({
data: data,

@@ -699,20 +763,15 @@ parentKeys: parentKeys.length > 0 ? parentKeys : undefined,

};
LazyCache.prototype.lookupRowNode = function (data) {
var _a;
if (!this.isUsingRowIds()) {
LazyCache.prototype.updateRowNodes = function (updates) {
var _this = this;
if (this.getRowIdFunc == null) {
// throw error, as this is type checked in the store. User likely abusing internal apis if here.
throw new Error('AG Grid: Insert transactions can only be applied when row ids are supplied.');
}
// find rowNode using id
var id = this.getRowId(data);
return (_a = this.getAllNodes().find(function (node) { return node.id === id; })) !== null && _a !== void 0 ? _a : null;
};
LazyCache.prototype.updateRowNodes = function (updates) {
var _this = this;
var updatedNodes = [];
updates.forEach(function (data) {
var row = _this.lookupRowNode(data);
if (row) {
_this.blockUtils.updateDataIntoRowNode(row, data);
updatedNodes.push(row);
var id = _this.getRowId(data);
var lazyNode = _this.nodeMap.getBy('id', id);
if (lazyNode) {
_this.blockUtils.updateDataIntoRowNode(lazyNode.node, data);
updatedNodes.push(lazyNode.node);
}

@@ -730,3 +789,3 @@ });

}
if (!this.isUsingRowIds()) {
if (this.getRowIdFunc == null) {
// throw error, as this is type checked in the store. User likely abusing internal apis if here.

@@ -748,22 +807,13 @@ throw new Error('AG Grid: Insert transactions can only be applied when row ids are supplied.');

}
// first move all the nodes after the addIndex out of the way
var allNodes = this.getNodeMapEntries();
// iterate backwards to avoid overwriting nodes which haven't been shifted yet
for (var i = allNodes.length - 1; i >= 0; i--) {
var _a = __read(allNodes[i], 2), stringStoreIndex = _a[0], node = _a[1];
var numericStoreIndex = Number(stringStoreIndex);
// nodes should be in order as js maps sort by numeric keys, so if index is too low can stop iterating
if (numericStoreIndex < addIndex) {
break;
}
var newIndex = numericStoreIndex + numberOfInserts;
if (this.getRowByStoreIndex(newIndex)) {
// this shouldn't happen, why would a row already exist here
throw new Error('AG Grid: Something went wrong, node in wrong place.');
}
else {
this.nodeIndexMap[numericStoreIndex + numberOfInserts] = node;
delete this.nodeIndexMap[numericStoreIndex];
}
}
var nodesToMove = this.nodeMap.filter(function (node) { return node.index >= addIndex; });
// delete all nodes which need moved first, so they don't get overwritten
nodesToMove.forEach(function (lazyNode) { return _this.nodeMap.delete(lazyNode); });
// then move the nodes to their new locations
nodesToMove.forEach(function (lazyNode) {
_this.nodeMap.set({
node: lazyNode.node,
index: lazyNode.index + numberOfInserts,
id: lazyNode.id,
});
});
// increase the store size to accommodate

@@ -774,4 +824,12 @@ this.numberOfRows += numberOfInserts;

};
LazyCache.prototype.getOrderedNodeMap = function () {
var obj = {};
this.nodeMap.forEach(function (node) { return obj[node.index] = node; });
return obj;
};
LazyCache.prototype.clearDisplayIndexes = function () {
this.nodeDisplayIndexMap.clear();
};
LazyCache.prototype.removeRowNodes = function (idsToRemove) {
if (!this.isUsingRowIds()) {
if (this.getRowIdFunc == null) {
// throw error, as this is type checked in the store. User likely abusing internal apis if here.

@@ -781,9 +839,11 @@ throw new Error('AG Grid: Insert transactions can only be applied when row ids are supplied.');

var removedNodes = [];
var allNodes = this.getNodeMapEntries();
var nodesToVerify = [];
// track how many nodes have been deleted, as when we pass other nodes we need to shift them up
var deletedNodeCount = 0;
var remainingIdsToRemove = __spread(idsToRemove);
var nodesToVerify = [];
var _loop_1 = function (i) {
var _a = __read(allNodes[i], 2), stringStoreIndex = _a[0], node = _a[1];
var allNodes = this.getOrderedNodeMap();
var contiguousIndex = -1;
var _loop_1 = function (stringIndex) {
contiguousIndex += 1;
var node = allNodes[stringIndex];
// finding the index allows the use of splice which should be slightly faster than both a check and filter

@@ -794,4 +854,4 @@ var matchIndex = remainingIdsToRemove.findIndex(function (idToRemove) { return idToRemove === node.id; });

remainingIdsToRemove.splice(matchIndex, 1);
this_1.destroyRowAtIndex(Number(stringStoreIndex));
removedNodes.push(node);
this_1.destroyRowAtIndex(Number(stringIndex));
removedNodes.push(node.node);
deletedNodeCount += 1;

@@ -804,13 +864,17 @@ return "continue";

}
var numericStoreIndex = Number(stringStoreIndex);
if (i !== numericStoreIndex) {
nodesToVerify.push(node);
var numericStoreIndex = Number(stringIndex);
if (contiguousIndex !== numericStoreIndex) {
nodesToVerify.push(node.node);
}
// shift normal node up by number of deleted prior to this point
this_1.nodeIndexMap[numericStoreIndex - deletedNodeCount] = this_1.nodeIndexMap[numericStoreIndex];
delete this_1.nodeIndexMap[numericStoreIndex];
this_1.nodeMap.delete(allNodes[stringIndex]);
this_1.nodeMap.set({
id: node.id,
node: node.node,
index: numericStoreIndex - deletedNodeCount,
});
};
var this_1 = this;
for (var i = 0; i < allNodes.length; i++) {
_loop_1(i);
for (var stringIndex in allNodes) {
_loop_1(stringIndex);
}

@@ -820,3 +884,3 @@ this.numberOfRows -= this.isLastRowIndexKnown() ? idsToRemove.length : deletedNodeCount;

nodesToVerify.forEach(function (node) { return node.__needsRefreshWhenVisible = true; });
this.rowLoader.queueLoadAction();
this.rowLoader.queueLoadCheck();
}

@@ -823,0 +887,0 @@ return removedNodes;

@@ -74,3 +74,3 @@ import { BeanStub, IServerSideStore, NumberSequence, RowBounds, RowNode, ServerSideGroupLevelParams, ServerSideGroupLevelState, ServerSideTransaction, ServerSideTransactionResult, StoreRefreshAfterParams, Column, IRowNode } from "@ag-grid-community/core";

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeepAfterFilterAndSort
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeepAfterFilterAndSort
*/

@@ -81,3 +81,3 @@ forEachStoreDeep(callback: (store: IServerSideStore, index: number) => void, sequence?: NumberSequence): void;

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeepAfterFilterAndSort
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeepAfterFilterAndSort
*/

@@ -88,3 +88,3 @@ forEachNodeDeep(callback: (rowNode: RowNode<any>, index: number) => void, sequence?: NumberSequence): void;

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeep
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeep
*/

@@ -199,5 +199,10 @@ forEachNodeDeepAfterFilterAndSort(callback: (rowNode: RowNode<any>, index: number) => void, sequence?: NumberSequence): void;

fireStoreUpdatedEvent(): void;
fireRefreshFinishedEvent(): void;
getBlockStates(): {
[key: string]: any;
};
getStoreBounds(): {
topPx: number;
heightPx: number;
};
}

@@ -160,3 +160,4 @@ "use strict";

this.displayIndexEnd = undefined;
this.cache.getAllNodes().forEach(function (rowNode) { return _this.blockUtils.clearDisplayIndex(rowNode); });
this.cache.getNodes().forEach(function (lazyNode) { return _this.blockUtils.clearDisplayIndex(lazyNode.node); });
this.cache.clearDisplayIndexes();
};

@@ -217,3 +218,3 @@ /**

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeepAfterFilterAndSort
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeepAfterFilterAndSort
*/

@@ -223,4 +224,4 @@ LazyStore.prototype.forEachStoreDeep = function (callback, sequence) {

callback(this, sequence.next());
this.cache.getAllNodes().forEach(function (rowNode) {
var childCache = rowNode.childStore;
this.cache.getNodes().forEach(function (lazyNode) {
var childCache = lazyNode.node.childStore;
if (childCache) {

@@ -234,9 +235,9 @@ childCache.forEachStoreDeep(callback, sequence);

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeepAfterFilterAndSort
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeepAfterFilterAndSort
*/
LazyStore.prototype.forEachNodeDeep = function (callback, sequence) {
if (sequence === void 0) { sequence = new core_1.NumberSequence(); }
this.cache.getAllNodes().forEach(function (rowNode) {
callback(rowNode, sequence.next());
var childCache = rowNode.childStore;
this.cache.getNodes().forEach(function (lazyNode) {
callback(lazyNode.node, sequence.next());
var childCache = lazyNode.node.childStore;
if (childCache) {

@@ -250,13 +251,15 @@ childCache.forEachNodeDeep(callback, sequence);

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeep
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeep
*/
LazyStore.prototype.forEachNodeDeepAfterFilterAndSort = function (callback, sequence) {
if (sequence === void 0) { sequence = new core_1.NumberSequence(); }
this.cache.getAllNodes().forEach(function (rowNode) {
callback(rowNode, sequence.next());
var childCache = rowNode.childStore;
var orderedNodes = this.cache.getOrderedNodeMap();
for (var key in orderedNodes) {
var lazyNode = orderedNodes[key];
callback(lazyNode.node, sequence.next());
var childCache = lazyNode.node.childStore;
if (childCache) {
childCache.forEachNodeDeepAfterFilterAndSort(callback, sequence);
}
});
}
};

@@ -267,3 +270,4 @@ /**

LazyStore.prototype.retryLoads = function () {
this.cache.getAllNodes().forEach(function (node) {
this.cache.getNodes().forEach(function (_a) {
var node = _a.node;
if (node.failedLoad) {

@@ -294,16 +298,14 @@ node.failedLoad = false;

LazyStore.prototype.getRowBounds = function (displayIndex) {
var _a;
if (!this.isDisplayIndexInStore(displayIndex)) {
return null;
}
var allNodes = this.cache.getAllNodes();
var previousNode = null;
var nextNode = null;
for (var i = 0; i < allNodes.length; i++) {
var node = allNodes[i];
if (node.rowIndex > displayIndex) {
nextNode = node;
break;
var thisNode = this.cache.getNodeCachedByDisplayIndex(displayIndex);
if (thisNode) {
var boundsFromRow = this.blockUtils.extractRowBounds(thisNode, displayIndex);
if (boundsFromRow) {
return boundsFromRow;
}
previousNode = node;
}
var _b = (_a = this.cache.getSurroundingNodesByDisplayIndex(displayIndex)) !== null && _a !== void 0 ? _a : {}, previousNode = _b.previousNode, nextNode = _b.nextNode;
// previous node may equal, or catch via detail node or child of group

@@ -355,13 +357,26 @@ if (previousNode) {

}
var allNodes = this.cache.getAllNodes();
var distToPreviousNodeTop = Number.MAX_SAFE_INTEGER;
var previousNode = null;
var distToNextNodeTop = Number.MAX_SAFE_INTEGER;
var nextNode = null;
for (var i = 0; i < allNodes.length; i++) {
var node = allNodes[i];
if (node.rowTop > pixel) {
this.cache.getNodes().forEach(function (_a) {
var node = _a.node;
var distBetween = Math.abs(pixel - node.rowTop);
// previous node
if (node.rowTop < pixel) {
if (distBetween < distToPreviousNodeTop) {
distToPreviousNodeTop = distBetween;
previousNode = node;
}
return;
}
// next node
if (distBetween < distToNextNodeTop) {
distToNextNodeTop = distBetween;
nextNode = node;
break;
}
previousNode = node;
}
});
// cast these back as typescript doesn't understand the forEach above
previousNode = previousNode;
nextNode = nextNode;
// previous node may equal, or catch via detail node or child of group

@@ -395,4 +410,7 @@ if (previousNode) {

return this.storeUtils.getChildStore(keys, this, function (key) {
var allNodes = _this.cache.getAllNodes();
return allNodes.find(function (currentRowNode) { return currentRowNode.key == key; });
var lazyNode = _this.cache.getNodes().find(function (lazyNode) { return lazyNode.node.key == key; });
if (!lazyNode) {
return null;
}
return lazyNode.node;
});

@@ -406,3 +424,4 @@ };

LazyStore.prototype.forEachChildStoreShallow = function (cb) {
this.cache.getAllNodes().forEach(function (node) {
this.cache.getNodes().forEach(function (_a) {
var node = _a.node;
if (node.childStore) {

@@ -496,14 +515,9 @@ cb(node.childStore);

}
this.cache.getAllNodes().forEach(function (rowNode) {
var hitFirstOrLast = rowNode === firstInRange || rowNode === lastInRange;
if (inActiveRange || hitFirstOrLast) {
result.push(rowNode);
}
if (hitFirstOrLast) {
inActiveRange = !inActiveRange;
}
return this.cache.getNodes().filter(function (_a) {
var node = _a.node;
return node.rowIndex >= firstInRange.rowIndex && node.rowIndex <= lastInRange.rowIndex;
}).map(function (_a) {
var node = _a.node;
return node;
});
// inActiveRange will be still true if we never hit the second rowNode
var invalidRange = inActiveRange;
return invalidRange ? [] : result;
};

@@ -558,5 +572,19 @@ /**

};
// gets called when row data updated, and no more refreshing needed
LazyStore.prototype.fireRefreshFinishedEvent = function () {
var event = {
type: core_1.Events.EVENT_STORE_REFRESHED,
route: this.parentRowNode.getRoute(),
};
this.eventService.dispatchEvent(event);
};
LazyStore.prototype.getBlockStates = function () {
return this.cache.getBlockStates();
};
LazyStore.prototype.getStoreBounds = function () {
return {
topPx: this.topPx,
heightPx: this.heightPx,
};
};
__decorate([

@@ -563,0 +591,0 @@ core_1.Autowired('ssrmBlockUtils')

@@ -18,3 +18,3 @@ import { IServerSideStore, BeanStub, StoreRefreshAfterParams, RowNode, ColumnVO, RowNodeBlock } from "@ag-grid-community/core";

}): void;
getChildStore(keys: string[], currentCache: IServerSideStore, findNodeFunc: (key: string) => RowNode): IServerSideStore | null;
getChildStore(keys: string[], currentCache: IServerSideStore, findNodeFunc: (key: string) => RowNode | null): IServerSideStore | null;
isServerRefreshNeeded(parentRowNode: RowNode, rowGroupCols: ColumnVO[], params: StoreRefreshAfterParams): boolean;

@@ -21,0 +21,0 @@ getServerSideInitialRowCount(): number;

@@ -109,3 +109,2 @@ "use strict";

TransactionManager.prototype.applyTransaction = function (transaction) {
var _this = this;
var res;

@@ -122,10 +121,2 @@ this.serverSideRowModel.executeOnStore(transaction.route, function (store) {

this.eventService.dispatchEvent({ type: core_1.Events.EVENT_STORE_UPDATED });
if (res.update && res.update.length) {
// this set timeout is necessary to queue behind the listener for EVENT_STORE_UPDATED in ssrm which recalculates the rowIndexes
// if the rowIndex isn't calculated first the binarySearchForDisplayIndex will not be able to find the required rows
setTimeout(function () {
// refresh the full width rows
_this.rowRenderer.refreshFullWidthRows(res.update);
}, 0);
}
return res;

@@ -132,0 +123,0 @@ }

@@ -1,1 +0,1 @@

export declare const VERSION = "29.2.0";
export declare const VERSION = "29.3.0";

@@ -5,2 +5,2 @@ "use strict";

// DO NOT UPDATE MANUALLY: Generated from script during build time
exports.VERSION = '29.2.0';
exports.VERSION = '29.3.0';

@@ -29,3 +29,2 @@ "use strict";

rowNode.stub = true;
rowNode.__needsRefresh = false;
rowNode.__needsRefreshWhenVisible = false;

@@ -32,0 +31,0 @@ if (rowNode.group) {

@@ -84,2 +84,6 @@ import { IServerSideStore, LoadSuccessParams, NumberSequence, RowBounds, RowNode, RowNodeBlock, ServerSideGroupLevelParams, ServerSideGroupLevelState, ServerSideTransaction, ServerSideTransactionResult, StoreRefreshAfterParams, IRowNode } from "@ag-grid-community/core";

getRowNodesInRange(firstInRange: RowNode, lastInRange: RowNode): RowNode[];
getStoreBounds(): {
topPx: number;
heightPx: number;
};
}

@@ -592,2 +592,8 @@ "use strict";

}
getStoreBounds() {
return {
topPx: this.topPx,
heightPx: this.heightPx,
};
}
}

@@ -594,0 +600,0 @@ __decorate([

@@ -11,2 +11,3 @@ import { BeanStub, RowNode, ServerSideGroupLevelParams } from "@ag-grid-community/core";

private readonly cache;
private checkForLoadQueued;
private loaderTimeout;

@@ -18,9 +19,7 @@ private nextBlockToLoad;

isRowLoading(index: number): boolean;
private doesRowNeedLoaded;
private getBlocksToLoad;
private getNodeRanges;
private getBlockToLoad;
reset(): void;
private executeLoad;
private isBlockInViewport;
private getNextBlockToLoad;
queueLoadCheck(): void;
queueLoadAction(): void;

@@ -27,0 +26,0 @@ private attemptLoad;

@@ -15,2 +15,3 @@ "use strict";

this.loadingNodes = new Set();
this.checkForLoadQueued = false;
this.loaderTimeout = undefined;

@@ -28,49 +29,47 @@ this.nextBlockToLoad = undefined;

}
doesRowNeedLoaded(index) {
// block already loading, don't duplicate request
if (this.loadingNodes.has(index)) {
return false;
getBlockToLoad() {
var _a;
const firstRowInViewport = this.api.getFirstDisplayedRow();
const lastRowInViewport = this.api.getLastDisplayedRow();
// quick look-up for priority rows needing loading in viewport.
for (let i = firstRowInViewport; i <= lastRowInViewport; i++) {
const node = this.cache.getNodeCachedByDisplayIndex(i);
if (!node) {
// if no row details, ignore, as row hasn't been created
// and it's too expensive to work out its location here
continue;
}
const lazyNode = this.cache.getNodes().getBy('node', node);
if (!lazyNode) {
continue;
}
if (this.isRowLoading(lazyNode.index)) {
continue;
}
if (node.__needsRefreshWhenVisible || (node.stub && !node.failedLoad)) {
return this.getBlockStartIndexForIndex(lazyNode.index);
}
}
const node = this.cache.getRowByStoreIndex(index);
if (!node) {
return false;
}
// user has manually refreshed this node
if (node.__needsRefresh) {
return true;
}
const firstRow = this.api.getFirstDisplayedRow();
const lastRow = this.api.getLastDisplayedRow();
const isRowInViewport = node.rowIndex != null && node.rowIndex >= firstRow && node.rowIndex <= lastRow;
// other than refreshing nodes, only ever load nodes in viewport
if (!isRowInViewport) {
return false;
}
// if node is a loading stub, or if it needs reverified, we refresh
return (node.stub && !node.failedLoad) || node.__needsRefreshWhenVisible;
}
getBlocksToLoad() {
const indexesToLoad = new Set();
// filter for nodes somewhat reasonably close to viewport, so we don't refresh all data
// sort by distance to viewport, so user is making relevant requests
this.cache.getNodeMapEntries().forEach(([stringIndex, node]) => {
const numericIndex = Number(stringIndex);
const blockStart = this.getBlockStartIndexForIndex(numericIndex);
// if node is a loading stub, or has manually been marked as needsRefresh we refresh
if (this.doesRowNeedLoaded(numericIndex)) {
indexesToLoad.add(blockStart);
const nodesToRefresh = this.cache.getNodesToRefresh();
let nodeToRefresh = null;
let nodeToRefreshDist = Number.MAX_SAFE_INTEGER;
nodesToRefresh.forEach(node => {
if (node.rowIndex == null) {
nodeToRefresh = node;
return;
}
const distToViewportTop = Math.abs(firstRowInViewport - node.rowIndex);
const distToViewportBottom = Math.abs(node.rowIndex - lastRowInViewport);
if (distToViewportTop < nodeToRefreshDist) {
nodeToRefresh = node;
nodeToRefreshDist = distToViewportTop;
}
if (distToViewportBottom < nodeToRefreshDist) {
nodeToRefresh = node;
nodeToRefreshDist = distToViewportBottom;
}
});
return [...indexesToLoad];
const lazyIndex = (_a = this.cache.getNodes().getBy('node', nodeToRefresh)) === null || _a === void 0 ? void 0 : _a.index;
return lazyIndex == null ? undefined : this.getBlockStartIndexForIndex(lazyIndex);
}
getNodeRanges() {
const ranges = {};
this.getBlocksToLoad().forEach(index => {
const rangeSize = core_1._.oneOrGreater(this.gridOptionsService.getNum('cacheBlockSize')) || LazyBlockLoader.DEFAULT_BLOCK_SIZE;
const translatedIndex = index - (index % rangeSize);
ranges[translatedIndex] = translatedIndex + rangeSize;
});
return ranges;
}
reset() {

@@ -131,32 +130,22 @@ this.loadingNodes.clear();

}
isBlockInViewport(blockStart, blockEnd) {
const firstRowInViewport = this.api.getFirstDisplayedRow();
const lastRowInViewport = this.api.getLastDisplayedRow();
const blockContainsViewport = blockStart <= firstRowInViewport && blockEnd >= lastRowInViewport;
const blockEndIsInViewport = blockEnd > firstRowInViewport && blockEnd < lastRowInViewport;
const blockStartIsInViewport = blockStart > firstRowInViewport && blockStart < lastRowInViewport;
return blockContainsViewport || blockEndIsInViewport || blockStartIsInViewport;
}
getNextBlockToLoad() {
const ranges = this.getNodeRanges();
const toLoad = Object.entries(ranges);
if (toLoad.length === 0) {
return null;
const result = this.getBlockToLoad();
if (result != null && result < 0) {
this.getBlockToLoad();
}
const firstRowInViewport = this.api.getFirstDisplayedRow();
toLoad.sort(([aStart, aEnd], [bStart, bEnd]) => {
const isAInViewport = this.isBlockInViewport(Number(aStart), aEnd);
const isBInViewport = this.isBlockInViewport(Number(bStart), bEnd);
// always prioritise loading blocks in viewport
if (isAInViewport) {
return -1;
}
// always prioritise loading blocks in viewport
if (isBInViewport) {
return 1;
}
// prioritise based on how close to the viewport the block is
return Math.abs(firstRowInViewport - Number(aStart)) - Math.abs(firstRowInViewport - Number(bStart));
if (result != null) {
return [String(result), result + this.getBlockSize()];
}
return null;
}
queueLoadCheck() {
// already going to check next cycle, ignore.
if (this.checkForLoadQueued) {
return;
}
this.checkForLoadQueued = true;
window.queueMicrotask(() => {
this.checkForLoadQueued = false;
this.queueLoadAction();
});
return toLoad[0];
}

@@ -163,0 +152,0 @@ queueLoadAction() {

import { BeanStub, LoadSuccessParams, NumberSequence, RowNode, IRowNode, ServerSideGroupLevelParams } from "@ag-grid-community/core";
import { LazyStore } from "./lazyStore";
import { MultiIndexMap } from "./multiIndexMap";
interface LazyStoreNode {
id: string;
index: number;
node: RowNode;
}
export declare class LazyCache extends BeanStub {

@@ -8,11 +14,48 @@ private api;

private nodeManager;
/**
* Indicates whether this is still the live dataset for this store (used for ignoring old requests after purge)
*/
private live;
private nodeIndexMap;
private nodeIds;
/**
* A node map indexed by the node's id, index, and node.
*/
private nodeMap;
/**
* A map of nodes indexed by the display index.
*/
private nodeDisplayIndexMap;
/**
* A set of nodes waiting to be refreshed
*/
private nodesToRefresh;
/**
* A list of display indexes bounds which are not currently present in this store, this can be due to;
* - Row stub hasn't been generated yet
* - Display index belongs to a child store
* - Display index is a detail node
*
* (Note, this is not always up to date, as stub nodes being generated do not refresh this, however
* this is a non issue as stub nodes are only ever default height and occupy 1 display index)
*/
private skippedDisplayIndexes;
/**
* End of store properties
*/
private numberOfRows;
private isLastRowKnown;
/**
* The prefix to use for node ids, this is used to ensure that node ids are unique across stores
*/
private defaultNodeIdPrefix;
/**
* Sibling services - 1-1 relationships.
*/
private store;
private rowLoader;
private storeParams;
/**
* Grid options properties - stored locally for access speed.
*/
private getRowIdFunc?;
private isMasterDetail;
constructor(store: LazyStore, numberOfRows: number, storeParams: ServerSideGroupLevelParams);

@@ -35,3 +78,3 @@ private init;

*/
getRowByStoreIndex(index: number): RowNode<any>;
getRowByStoreIndex(index: number): RowNode<any> | undefined;
/**

@@ -53,8 +96,16 @@ * Given a number of rows, skips through the given sequence & row top reference (using default row height)

setRowCount(rowCount: number, isLastRowIndexKnown?: boolean): void;
getNodeMapEntries(): [string, RowNode][];
getAllNodes(): RowNode[];
getNodes(): MultiIndexMap<LazyStoreNode>;
getNodeCachedByDisplayIndex(displayIndex: number): RowNode | null;
getNodesToRefresh(): Set<RowNode>;
/**
* Get or calculate the display index for this store
* @returns the previous and next loaded row nodes surrounding the given display index
*/
getSurroundingNodesByDisplayIndex(displayIndex: number): {
previousNode: RowNode<any> | undefined;
nextNode: RowNode<any> | undefined;
} | null;
/**
* Get or calculate the display index for a given store index
* @param storeIndex the rows index within this store
* @returns the rows visible display index relative to all stores
* @returns the rows visible display index relative to the grid
*/

@@ -95,2 +146,3 @@ getDisplayIndexFromStoreIndex(storeIndex: number): number | null;

onLoadSuccess(firstRowIndex: number, numberOfRowsExpected: number, response: LoadSuccessParams): void;
fireRefreshFinishedEvent(): void;
isLastRowIndexKnown(): boolean;

@@ -101,8 +153,11 @@ onLoadFailed(firstRowIndex: number, numberOfRowsExpected: number): void;

private fireStoreUpdatedEvent;
private isUsingRowIds;
private getRowId;
private lookupRowNode;
updateRowNodes(updates: any[]): RowNode[];
insertRowNodes(inserts: any[], indexToAdd?: number): RowNode[];
getOrderedNodeMap(): {
[key: number]: LazyStoreNode;
};
clearDisplayIndexes(): void;
removeRowNodes(idsToRemove: string[]): RowNode[];
}
export {};

@@ -12,6 +12,10 @@ "use strict";

const lazyBlockLoader_1 = require("./lazyBlockLoader");
const multiIndexMap_1 = require("./multiIndexMap");
;
class LazyCache extends core_1.BeanStub {
constructor(store, numberOfRows, storeParams) {
super();
// Indicates whether this is still the live dataset for this store (used for ignoring old requests after purge)
/**
* Indicates whether this is still the live dataset for this store (used for ignoring old requests after purge)
*/
this.live = true;

@@ -24,12 +28,19 @@ this.store = store;

init() {
this.nodeIndexMap = {};
this.nodeIds = new Set();
// initiate the node map to be indexed at 'index', 'id' and 'node' for quick look-up.
// it's important id isn't first, as stub nodes overwrite each-other, and the first index is
// used for iteration.
this.nodeMap = new multiIndexMap_1.MultiIndexMap('index', 'id', 'node');
this.nodeDisplayIndexMap = new Map();
this.nodesToRefresh = new Set();
this.defaultNodeIdPrefix = this.blockUtils.createNodeIdPrefix(this.store.getParentNode());
this.rowLoader = this.createManagedBean(new lazyBlockLoader_1.LazyBlockLoader(this, this.store.getParentNode(), this.storeParams));
this.getRowIdFunc = this.gridOptionsService.getRowIdFunc();
this.isMasterDetail = this.gridOptionsService.isMasterDetail();
}
destroyRowNodes() {
this.numberOfRows = 0;
this.blockUtils.destroyRowNodes(this.getAllNodes());
this.nodeIndexMap = {};
this.nodeIds.clear();
this.nodeMap.forEach(node => this.blockUtils.destroyRowNode(node.node));
this.nodeMap.clear();
this.nodeDisplayIndexMap.clear();
this.nodesToRefresh.clear();
this.live = false;

@@ -43,3 +54,3 @@ }

getRowByDisplayIndex(displayIndex) {
var _a;
var _a, _b, _c, _d;
// if index isn't in store, nothing to return

@@ -49,47 +60,54 @@ if (!this.store.isDisplayIndexInStore(displayIndex)) {

}
let nodeAfterStringIndex;
const nodeMapEntries = this.getNodeMapEntries();
for (let i = 0; i < nodeMapEntries.length; i++) {
const [stringIndex, node] = nodeMapEntries[i];
// if we find the index, simply return this node
if (node.rowIndex === displayIndex) {
if (node.stub || node.__needsRefreshWhenVisible) {
this.rowLoader.queueLoadAction();
}
return node;
// first try to directly look this node up in the display index map
const node = this.nodeDisplayIndexMap.get(displayIndex);
if (node) {
// if we have the node, check if it needs refreshed when rendered
if (node.stub || node.__needsRefreshWhenVisible) {
this.rowLoader.queueLoadCheck();
}
// then check if current row contains a detail row with the index
const expandedMasterRow = node.master && node.expanded;
const detailNode = node.detailNode;
if (expandedMasterRow && detailNode && detailNode.rowIndex === displayIndex) {
return detailNode;
return node;
}
// next check if this is the first row, if so return a stub node
// this is a performance optimisation, as it is the most common scenario
// and enables the node - 1 check to kick in more often.
if (displayIndex === this.store.getDisplayIndexStart()) {
return this.createStubNode(0, displayIndex);
}
// check if the row immediately prior is available in the store
const contiguouslyPreviousNode = this.nodeDisplayIndexMap.get(displayIndex - 1);
if (contiguouslyPreviousNode) {
// if previous row is master detail, and expanded, this node must be detail
if (this.isMasterDetail && contiguouslyPreviousNode.master && contiguouslyPreviousNode.expanded) {
return contiguouslyPreviousNode.detailNode;
}
// if the index belongs to a child store, recursively search
if ((_a = node.childStore) === null || _a === void 0 ? void 0 : _a.isDisplayIndexInStore(displayIndex)) {
return node.childStore.getRowUsingDisplayIndex(displayIndex);
// if previous row is expanded group, this node will belong to that group.
if (contiguouslyPreviousNode.expanded && ((_a = contiguouslyPreviousNode.childStore) === null || _a === void 0 ? void 0 : _a.isDisplayIndexInStore(displayIndex))) {
return (_b = contiguouslyPreviousNode.childStore) === null || _b === void 0 ? void 0 : _b.getRowUsingDisplayIndex(displayIndex);
}
// if current row index is higher, then the node has been passed
if (node.rowIndex > displayIndex) {
// keep track of the last next node we find that comes after in case we need to create a new stub
nodeAfterStringIndex = stringIndex;
break;
}
// otherwise, row must be a stub node
const lazyCacheNode = this.nodeMap.getBy('node', contiguouslyPreviousNode);
return this.createStubNode(lazyCacheNode.index + 1, displayIndex);
}
/**
* The code below this point is assuming we haven't found a stored node with this display index, but the node does belong in this store,
* in this case we want to create a stub node to display in the grid, so we need to calculate the store index from the display index using
* the next node found after this one (can use end index here as we have confidence it should be up to date, as we aren't inserting rows)
*/
// no node was found before this display index, so calculate based on store end index
if (nodeAfterStringIndex == null) {
const adjacentNodes = this.getSurroundingNodesByDisplayIndex(displayIndex);
// if no bounds skipped includes this, calculate from end index
if (adjacentNodes == null) {
const storeIndexFromEndIndex = this.store.getRowCount() - (this.store.getDisplayIndexEnd() - displayIndex);
return this.createStubNode(storeIndexFromEndIndex, displayIndex);
}
// important to remember this node is not necessarily directly after the node we're searching for
const nodeAfterIndex = Number(nodeAfterStringIndex);
const nodeAfter = this.nodeIndexMap[nodeAfterIndex];
// difference can be calculated from next nodes display index
const nodeAfterDisplayIndex = nodeAfter.rowIndex;
const storeIndexFromNodeAfterIndex = nodeAfterIndex - (nodeAfterDisplayIndex - displayIndex);
return this.createStubNode(storeIndexFromNodeAfterIndex, displayIndex);
const { previousNode, nextNode } = adjacentNodes;
// if the node before this node is expanded, this node might be a child of that node
if (previousNode && previousNode.expanded && ((_c = previousNode.childStore) === null || _c === void 0 ? void 0 : _c.isDisplayIndexInStore(displayIndex))) {
return (_d = previousNode.childStore) === null || _d === void 0 ? void 0 : _d.getRowUsingDisplayIndex(displayIndex);
}
// if we have the node after this node, we can calculate the store index of this node by the difference
// in display indexes between the two nodes.
if (nextNode) {
const nextSimpleRowStoreIndex = this.nodeMap.getBy('node', nextNode);
const displayIndexDiff = nextNode.rowIndex - displayIndex;
const newStoreIndex = nextSimpleRowStoreIndex.index - displayIndexDiff;
return this.createStubNode(newStoreIndex, displayIndex);
}
// if no next node, calculate from end index of this store
const storeIndexFromEndIndex = this.store.getRowCount() - (this.store.getDisplayIndexEnd() - displayIndex);
return this.createStubNode(storeIndexFromEndIndex, displayIndex);
}

@@ -105,4 +123,5 @@ /**

node.setRowTop(rowBounds.rowTop);
this.nodeDisplayIndexMap.set(displayIndex, node);
});
this.rowLoader.queueLoadAction();
this.rowLoader.queueLoadCheck();
return newNode;

@@ -115,3 +134,4 @@ }

getRowByStoreIndex(index) {
return this.nodeIndexMap[index];
var _a;
return (_a = this.nodeMap.getBy('index', index)) === null || _a === void 0 ? void 0 : _a.node;
}

@@ -125,3 +145,11 @@ /**

skipDisplayIndexes(numberOfRowsToSkip, displayIndexSeq, nextRowTop) {
if (numberOfRowsToSkip === 0) {
return;
}
const defaultRowHeight = this.gridOptionsService.getRowHeightAsNumber();
// these are recorded so that the previous node can be found more quickly when a node is missing
this.skippedDisplayIndexes.push({
from: displayIndexSeq.peek(),
to: displayIndexSeq.peek() + numberOfRowsToSkip
});
displayIndexSeq.skip(numberOfRowsToSkip);

@@ -135,5 +163,16 @@ nextRowTop.value += numberOfRowsToSkip * defaultRowHeight;

setDisplayIndexes(displayIndexSeq, nextRowTop) {
const nodeEntries = this.getNodeMapEntries();
// Create a map of display index nodes for access speed
this.nodeDisplayIndexMap.clear();
this.skippedDisplayIndexes = [];
// create an object indexed by store index, as this will sort all of the nodes when we iterate
// the object
const orderedMap = {};
this.nodeMap.forEach(lazyNode => {
orderedMap[lazyNode.index] = lazyNode.node;
});
let lastIndex = -1;
nodeEntries.forEach(([stringIndex, node]) => {
// iterate over the nodes in order, setting the display index on each node. When display indexes
// are skipped, they're added to the skippedDisplayIndexes array
for (const stringIndex in orderedMap) {
const node = orderedMap[stringIndex];
const numericIndex = Number(stringIndex);

@@ -145,8 +184,17 @@ // if any nodes aren't currently in the store, skip the display indexes too

this.blockUtils.setDisplayIndex(node, displayIndexSeq, nextRowTop);
this.nodeDisplayIndexMap.set(node.rowIndex, node);
const passedRows = displayIndexSeq.peek() - node.rowIndex;
if (passedRows > 1) {
this.skippedDisplayIndexes.push({
from: node.rowIndex + 1,
to: displayIndexSeq.peek()
});
}
// store this index for skipping after this
lastIndex = numericIndex;
});
}
// need to skip rows until the end of this store
const numberOfRowsToSkip = (this.numberOfRows - 1) - lastIndex;
this.skipDisplayIndexes(numberOfRowsToSkip, displayIndexSeq, nextRowTop);
// this is not terribly efficient, and could probs be improved
this.purgeExcessRows();

@@ -164,53 +212,54 @@ }

this.isLastRowKnown = isLastRowIndexKnown;
if (isLastRowIndexKnown === false) {
this.numberOfRows += 1;
}
}
this.fireStoreUpdatedEvent();
}
getNodeMapEntries() {
return Object.entries(this.nodeIndexMap);
getNodes() {
return this.nodeMap;
}
getAllNodes() {
return Object.values(this.nodeIndexMap);
getNodeCachedByDisplayIndex(displayIndex) {
var _a;
return (_a = this.nodeDisplayIndexMap.get(displayIndex)) !== null && _a !== void 0 ? _a : null;
}
getNodesToRefresh() {
return this.nodesToRefresh;
}
/**
* Get or calculate the display index for this store
* @returns the previous and next loaded row nodes surrounding the given display index
*/
getSurroundingNodesByDisplayIndex(displayIndex) {
// iterate over the skipped display indexes to find the bound this display index belongs to
for (let i in this.skippedDisplayIndexes) {
const skippedRowBound = this.skippedDisplayIndexes[i];
if (skippedRowBound.from <= displayIndex && skippedRowBound.to >= displayIndex) {
// take the node before and after the boundary and return those
const previousNode = this.nodeDisplayIndexMap.get(skippedRowBound.from - 1);
const nextNode = this.nodeDisplayIndexMap.get(skippedRowBound.to + 1);
return { previousNode, nextNode };
}
}
return null;
}
/**
* Get or calculate the display index for a given store index
* @param storeIndex the rows index within this store
* @returns the rows visible display index relative to all stores
* @returns the rows visible display index relative to the grid
*/
getDisplayIndexFromStoreIndex(storeIndex) {
var _a;
const nodeToReplace = this.nodeIndexMap[storeIndex];
const displayIndexStart = this.store.getDisplayIndexStart();
if (displayIndexStart == null) {
return null;
const nodesAfterThis = this.nodeMap.filter(lazyNode => lazyNode.index > storeIndex);
if (nodesAfterThis.length === 0) {
return this.store.getDisplayIndexEnd() - (this.numberOfRows - storeIndex);
}
// if node exists, we can extract its displayIndex
if (nodeToReplace && nodeToReplace.rowIndex != null) {
return nodeToReplace.rowIndex;
}
const allNodes = this.getNodeMapEntries();
let lastNode = undefined;
let lastIndex = -1;
for (let i = 0; i < allNodes.length; i++) {
const [stringNodeStoreIndex, node] = allNodes[i];
const numericNodeStoreIndex = Number(stringNodeStoreIndex);
if (numericNodeStoreIndex > storeIndex) {
break;
let nextNode;
for (let i = 0; i < nodesAfterThis.length; i++) {
const lazyNode = nodesAfterThis[i];
if (nextNode == null || nextNode.index > lazyNode.index) {
nextNode = lazyNode;
}
lastNode = node;
lastIndex = numericNodeStoreIndex;
}
// unlike in getRowByDisplayIndex, we have to use getDisplayIndexStart here, as nodes may
// have been inserted without updating display index end yet.
if (lastNode == null) {
return displayIndexStart + storeIndex;
}
const nodeDiff = storeIndex - lastIndex;
const childStoreEnd = (_a = lastNode.childStore) === null || _a === void 0 ? void 0 : _a.getDisplayIndexEnd();
if (childStoreEnd != null) {
return childStoreEnd + nodeDiff - 1;
}
if (lastNode.rowIndex != null) {
return lastNode.rowIndex + nodeDiff;
}
return displayIndexStart + storeIndex;
const nextDisplayIndex = nextNode.node.rowIndex;
const storeIndexDiff = nextNode.index - storeIndex;
return nextDisplayIndex - storeIndexDiff;
}

@@ -224,16 +273,17 @@ /**

createRowAtIndex(atStoreIndex, data, createNodeCallback) {
const usingRowIds = this.isUsingRowIds();
// make sure an existing node isn't being overwritten
const existingNodeAtIndex = this.nodeIndexMap[atStoreIndex];
if (existingNodeAtIndex) {
existingNodeAtIndex.__needsRefresh = false;
existingNodeAtIndex.__needsRefreshWhenVisible = false;
const lazyNode = this.nodeMap.getBy('index', atStoreIndex);
// if node already exists, update it or destroy it
if (lazyNode) {
const { node } = lazyNode;
this.nodesToRefresh.delete(node);
node.__needsRefreshWhenVisible = false;
// if the node is the same, just update the content
if (this.doesNodeMatch(data, existingNodeAtIndex)) {
this.blockUtils.updateDataIntoRowNode(existingNodeAtIndex, data);
return existingNodeAtIndex;
if (this.doesNodeMatch(data, node)) {
this.blockUtils.updateDataIntoRowNode(node, data);
return node;
}
// if there's no id and this is an open group, protect this node from changes
if (!usingRowIds && existingNodeAtIndex.group && existingNodeAtIndex.expanded) {
return existingNodeAtIndex;
if (this.getRowIdFunc == null && node.group && node.expanded) {
return node;
}

@@ -243,15 +293,20 @@ // destroy the old node, might be worth caching state here

}
// if the node already exists, update it and move it to the new location
if (data && usingRowIds) {
const allNodes = this.getNodeMapEntries();
const existingNodeDetails = allNodes.find(([_, node]) => this.doesNodeMatch(data, node));
if (existingNodeDetails) {
const [existingStringIndex, existingNode] = existingNodeDetails;
const existingIndex = Number(existingStringIndex);
this.blockUtils.updateDataIntoRowNode(existingNode, data);
delete this.nodeIndexMap[existingIndex];
this.nodeIndexMap[atStoreIndex] = existingNode;
// mark all of the old block as needsVerify to trigger it for a refresh
this.markBlockForVerify(existingIndex);
return existingNode;
// if the node already exists elsewhere, update it and move it to the new location
if (data && this.getRowIdFunc != null) {
const id = this.getRowId(data);
const lazyNode = this.nodeMap.getBy('id', id);
if (lazyNode) {
// delete old lazy node so we can insert it at different location
this.nodeMap.delete(lazyNode);
const { node, index } = lazyNode;
this.blockUtils.updateDataIntoRowNode(node, data);
this.nodeMap.set({
id: node.id,
node,
index: atStoreIndex
});
// mark all of the old block as needsVerify to trigger it for a refresh, as nodes
// should not be out of place
this.markBlockForVerify(index);
return node;
}

@@ -266,13 +321,12 @@ }

this.nodeManager.addRowNode(newNode);
this.nodeIds.add(newNode.id);
}
// add the new node to the store, has to be done after the display index is calculated so it doesn't take itself into account
this.nodeIndexMap[atStoreIndex] = newNode;
this.nodeMap.set({
id: newNode.id,
node: newNode,
index: atStoreIndex,
});
if (createNodeCallback) {
createNodeCallback(newNode);
}
// if this is a stub, we need to tell the loader to load rows
if (newNode.stub) {
this.rowLoader.queueLoadAction();
}
return newNode;

@@ -284,5 +338,4 @@ }

const dirtyBlocks = new Set();
this.getNodeMapEntries().forEach(([stringIndex, node]) => {
this.nodeMap.forEach(({ node, index }) => {
var _a;
const index = Number(stringIndex);
const blockStart = this.rowLoader.getBlockStartIndexForIndex(index);

@@ -299,3 +352,3 @@ if (!node.stub && !node.failedLoad) {

}
else if (node.__needsRefresh) {
else if (this.nodesToRefresh.has(node)) {
rowState = 'needsLoading';

@@ -336,6 +389,10 @@ }

destroyRowAtIndex(atStoreIndex) {
const node = this.nodeIndexMap[atStoreIndex];
this.nodeIds.delete(node.id);
this.blockUtils.destroyRowNode(node);
delete this.nodeIndexMap[atStoreIndex];
const lazyNode = this.nodeMap.getBy('index', atStoreIndex);
if (!lazyNode) {
return;
}
this.nodeMap.delete(lazyNode);
this.nodeDisplayIndexMap.delete(lazyNode.node.rowIndex);
this.nodesToRefresh.delete(lazyNode.node);
this.blockUtils.destroyRowNode(lazyNode.node);
}

@@ -359,8 +416,6 @@ getSsrmParams() {

const [start, end] = this.rowLoader.getBlockBoundsForIndex(rowIndex);
for (let i = start; i < end; i++) {
const node = this.nodeIndexMap[i];
if (node) {
node.__needsRefreshWhenVisible = true;
}
}
const lazyNodesInRange = this.nodeMap.filter((lazyNode) => lazyNode.index >= start && lazyNode.index < end);
lazyNodesInRange.forEach(({ node }) => {
node.__needsRefreshWhenVisible = true;
});
}

@@ -371,3 +426,3 @@ doesNodeMatch(data, node) {

}
if (this.isUsingRowIds()) {
if (this.getRowIdFunc != null) {
const id = this.getRowId(data);

@@ -386,9 +441,8 @@ return node.id === id;

const [_, lastRowBlockEnd] = this.rowLoader.getBlockBoundsForIndex(lastRow);
this.getNodeMapEntries().forEach(([stringIndex, node]) => {
const numericIndex = Number(stringIndex);
if (this.rowLoader.isRowLoading(numericIndex)) {
this.nodeMap.forEach(lazyNode => {
if (this.rowLoader.isRowLoading(lazyNode.index)) {
return;
}
if (node.stub && (numericIndex < firstRowBlockStart || numericIndex > lastRowBlockEnd)) {
this.destroyRowAtIndex(numericIndex);
if (lazyNode.node.stub && (lazyNode.index < firstRowBlockStart || lazyNode.index > lastRowBlockEnd)) {
this.destroyRowAtIndex(lazyNode.index);
}

@@ -413,4 +467,4 @@ });

const blockDistanceToMiddle = {};
nodes.forEach(([storeIndexString, node]) => {
const [blockStart, blockEnd] = this.rowLoader.getBlockBoundsForIndex(Number(storeIndexString));
nodes.forEach(({ node, index }) => {
const [blockStart, blockEnd] = this.rowLoader.getBlockBoundsForIndex(index);
if (blockStart in blockDistanceToMiddle) {

@@ -422,4 +476,5 @@ return;

// may not have an end node if the block came back small
if (this.nodeIndexMap[blockEnd - 1])
distEnd = Math.abs(this.nodeIndexMap[blockEnd - 1].rowIndex - otherDisplayIndex);
const lastLazyNode = this.nodeMap.getBy('index', [blockEnd - 1]);
if (lastLazyNode)
distEnd = Math.abs(lastLazyNode.node.rowIndex - otherDisplayIndex);
const farthest = distEnd == null || distStart < distEnd ? distStart : distEnd;

@@ -438,3 +493,3 @@ blockDistanceToMiddle[blockStart] = farthest;

// number of blocks to cache on top of the viewport blocks
const numberOfRowsToRetain = this.getNumberOfRowsToRetain(firstRowBlockStart, lastRowBlockEnd);
let numberOfRowsToRetain = this.getNumberOfRowsToRetain(firstRowBlockStart, lastRowBlockEnd);
if (this.store.getDisplayIndexEnd() == null || numberOfRowsToRetain == null) {

@@ -445,3 +500,3 @@ // if group is collapsed, or max blocks missing, ignore the event

// don't check the nodes that could have been cached out of necessity
const disposableNodes = this.getNodeMapEntries().filter(([_, node]) => !node.stub && !this.isNodeCached(node));
const disposableNodes = this.nodeMap.filter(({ node }) => !node.stub && !this.isNodeCached(node));
if (disposableNodes.length <= numberOfRowsToRetain) {

@@ -451,9 +506,9 @@ // not enough rows to bother clearing any

}
const disposableNodesNotInViewport = disposableNodes.filter(([_, node]) => {
const disposableNodesNotInViewport = disposableNodes.filter(({ node }) => {
const startRowNum = node.rowIndex;
if (!startRowNum) {
if (startRowNum == null || startRowNum === -1) {
// row is not displayed and can be disposed
return true;
}
if (firstRowInViewport <= startRowNum && startRowNum <= lastRowInViewport) {
if (firstRowBlockStart <= startRowNum && startRowNum < lastRowBlockEnd) {
// start row in viewport, block is in viewport

@@ -463,7 +518,7 @@ return false;

const lastRowNum = startRowNum + blockSize;
if (firstRowInViewport <= lastRowNum && lastRowNum <= lastRowInViewport) {
if (firstRowBlockStart <= lastRowNum && lastRowNum < lastRowBlockEnd) {
// end row in viewport, block is in viewport
return false;
}
if (startRowNum < firstRowInViewport && lastRowNum > lastRowInViewport) {
if (startRowNum < firstRowBlockStart && lastRowNum >= lastRowBlockEnd) {
// full block surrounds in viewport

@@ -475,2 +530,4 @@ return false;

});
// reduce the number of rows to retain by the number in viewport which were retained
numberOfRowsToRetain = numberOfRowsToRetain - (disposableNodes.length - disposableNodesNotInViewport.length);
if (!disposableNodesNotInViewport.length) {

@@ -488,8 +545,8 @@ return;

blockDistanceArray.sort((a, b) => Math.sign(b[1] - a[1]));
const blocksToRemove = blockDistanceArray.length - numberOfBlocksToRetain;
const blocksToRemove = blockDistanceArray.length - Math.max(numberOfBlocksToRetain, 0);
for (let i = 0; i < blocksToRemove; i++) {
const blockStart = Number(blockDistanceArray[i][0]);
for (let x = blockStart; x < blockStart + blockSize; x++) {
const node = this.nodeIndexMap[x];
if (!node || this.isNodeCached(node)) {
const lazyNode = this.nodeMap.getBy('index', x);
if (!lazyNode || this.isNodeCached(lazyNode.node)) {
continue;

@@ -516,3 +573,3 @@ }

extractDuplicateIds(rows) {
if (!this.isUsingRowIds()) {
if (!this.getRowIdFunc == null) {
return [];

@@ -535,3 +592,3 @@ }

return;
if (this.isUsingRowIds()) {
if (this.getRowIdFunc != null) {
const duplicates = this.extractDuplicateIds(response.rowData);

@@ -545,14 +602,16 @@ if (duplicates.length > 0) {

}
const wasRefreshing = this.nodesToRefresh.size > 0;
response.rowData.forEach((data, responseRowIndex) => {
var _a;
const rowIndex = firstRowIndex + responseRowIndex;
const nodeFromCache = this.nodeIndexMap[rowIndex];
const nodeFromCache = this.nodeMap.getBy('index', rowIndex);
// if stub, overwrite
if (nodeFromCache === null || nodeFromCache === void 0 ? void 0 : nodeFromCache.stub) {
if ((_a = nodeFromCache === null || nodeFromCache === void 0 ? void 0 : nodeFromCache.node) === null || _a === void 0 ? void 0 : _a.stub) {
this.createRowAtIndex(rowIndex, data);
return;
}
if (nodeFromCache && this.doesNodeMatch(data, nodeFromCache)) {
this.blockUtils.updateDataIntoRowNode(nodeFromCache, data);
nodeFromCache.__needsRefresh = false;
nodeFromCache.__needsRefreshWhenVisible = false;
if (nodeFromCache && this.doesNodeMatch(data, nodeFromCache.node)) {
this.blockUtils.updateDataIntoRowNode(nodeFromCache.node, data);
this.nodesToRefresh.delete(nodeFromCache.node);
nodeFromCache.node.__needsRefreshWhenVisible = false;
return;

@@ -563,2 +622,6 @@ }

});
const finishedRefreshing = this.nodesToRefresh.size === 0;
if (wasRefreshing && finishedRefreshing) {
this.fireRefreshFinishedEvent();
}
if (response.rowCount != undefined && response.rowCount !== -1) {

@@ -583,13 +646,15 @@ // if the rowCount has been provided, set the row count

// delete any rows after the last index
const allRows = this.getNodeMapEntries();
for (let i = allRows.length - 1; i >= 0; i--) {
const numericIndex = Number(allRows[i][0]);
if (numericIndex < this.numberOfRows) {
break;
}
this.destroyRowAtIndex(numericIndex);
}
const lazyNodesAfterStoreEnd = this.nodeMap.filter(lazyNode => lazyNode.index >= this.numberOfRows);
lazyNodesAfterStoreEnd.forEach(lazyNode => this.destroyRowAtIndex(lazyNode.index));
}
this.fireStoreUpdatedEvent();
}
fireRefreshFinishedEvent() {
const finishedRefreshing = this.nodesToRefresh.size === 0;
// if anything refreshing currently, skip.
if (!finishedRefreshing) {
return;
}
this.store.fireRefreshFinishedEvent();
}
isLastRowIndexKnown() {

@@ -601,16 +666,22 @@ return this.isLastRowKnown;

return;
for (let i = firstRowIndex; i < firstRowIndex + numberOfRowsExpected; i++) {
const nodeFromCache = this.nodeIndexMap[i];
if (nodeFromCache) {
nodeFromCache.failedLoad = true;
}
}
const failedNodes = this.nodeMap.filter(node => node.index >= firstRowIndex && node.index < firstRowIndex + numberOfRowsExpected);
failedNodes.forEach(node => node.node.failedLoad = true);
this.fireStoreUpdatedEvent();
}
markNodesForRefresh() {
this.getAllNodes().forEach(node => node.__needsRefresh = true);
this.rowLoader.queueLoadAction();
this.nodeMap.forEach(lazyNode => {
if (lazyNode.node.stub) {
return;
}
this.nodesToRefresh.add(lazyNode.node);
});
this.rowLoader.queueLoadCheck();
if (this.isLastRowKnown && this.numberOfRows === 0) {
this.numberOfRows = 1;
this.isLastRowKnown = false;
this.fireStoreUpdatedEvent();
}
}
isNodeInCache(id) {
return this.nodeIds.has(id);
return !!this.nodeMap.getBy('id', id);
}

@@ -624,8 +695,4 @@ // gets called 1) row count changed 2) cache purged 3) items inserted

}
isUsingRowIds() {
return this.gridOptionsService.getRowIdFunc() != null;
}
getRowId(data) {
const getRowIdFunc = this.gridOptionsService.getRowIdFunc();
if (getRowIdFunc == null) {
if (this.getRowIdFunc == null) {
return null;

@@ -636,3 +703,3 @@ }

const parentKeys = this.store.getParentNode().getGroupKeys();
const id = getRowIdFunc({
const id = this.getRowIdFunc({
data,

@@ -644,19 +711,14 @@ parentKeys: parentKeys.length > 0 ? parentKeys : undefined,

}
lookupRowNode(data) {
var _a;
if (!this.isUsingRowIds()) {
updateRowNodes(updates) {
if (this.getRowIdFunc == null) {
// throw error, as this is type checked in the store. User likely abusing internal apis if here.
throw new Error('AG Grid: Insert transactions can only be applied when row ids are supplied.');
}
// find rowNode using id
const id = this.getRowId(data);
return (_a = this.getAllNodes().find(node => node.id === id)) !== null && _a !== void 0 ? _a : null;
}
updateRowNodes(updates) {
const updatedNodes = [];
updates.forEach(data => {
const row = this.lookupRowNode(data);
if (row) {
this.blockUtils.updateDataIntoRowNode(row, data);
updatedNodes.push(row);
const id = this.getRowId(data);
const lazyNode = this.nodeMap.getBy('id', id);
if (lazyNode) {
this.blockUtils.updateDataIntoRowNode(lazyNode.node, data);
updatedNodes.push(lazyNode.node);
}

@@ -673,3 +735,3 @@ });

}
if (!this.isUsingRowIds()) {
if (this.getRowIdFunc == null) {
// throw error, as this is type checked in the store. User likely abusing internal apis if here.

@@ -691,22 +753,13 @@ throw new Error('AG Grid: Insert transactions can only be applied when row ids are supplied.');

}
// first move all the nodes after the addIndex out of the way
const allNodes = this.getNodeMapEntries();
// iterate backwards to avoid overwriting nodes which haven't been shifted yet
for (let i = allNodes.length - 1; i >= 0; i--) {
const [stringStoreIndex, node] = allNodes[i];
const numericStoreIndex = Number(stringStoreIndex);
// nodes should be in order as js maps sort by numeric keys, so if index is too low can stop iterating
if (numericStoreIndex < addIndex) {
break;
}
const newIndex = numericStoreIndex + numberOfInserts;
if (this.getRowByStoreIndex(newIndex)) {
// this shouldn't happen, why would a row already exist here
throw new Error('AG Grid: Something went wrong, node in wrong place.');
}
else {
this.nodeIndexMap[numericStoreIndex + numberOfInserts] = node;
delete this.nodeIndexMap[numericStoreIndex];
}
}
const nodesToMove = this.nodeMap.filter(node => node.index >= addIndex);
// delete all nodes which need moved first, so they don't get overwritten
nodesToMove.forEach(lazyNode => this.nodeMap.delete(lazyNode));
// then move the nodes to their new locations
nodesToMove.forEach(lazyNode => {
this.nodeMap.set({
node: lazyNode.node,
index: lazyNode.index + numberOfInserts,
id: lazyNode.id,
});
});
// increase the store size to accommodate

@@ -717,4 +770,12 @@ this.numberOfRows += numberOfInserts;

}
getOrderedNodeMap() {
const obj = {};
this.nodeMap.forEach(node => obj[node.index] = node);
return obj;
}
clearDisplayIndexes() {
this.nodeDisplayIndexMap.clear();
}
removeRowNodes(idsToRemove) {
if (!this.isUsingRowIds()) {
if (this.getRowIdFunc == null) {
// throw error, as this is type checked in the store. User likely abusing internal apis if here.

@@ -724,9 +785,11 @@ throw new Error('AG Grid: Insert transactions can only be applied when row ids are supplied.');

const removedNodes = [];
const allNodes = this.getNodeMapEntries();
const nodesToVerify = [];
// track how many nodes have been deleted, as when we pass other nodes we need to shift them up
let deletedNodeCount = 0;
const remainingIdsToRemove = [...idsToRemove];
const nodesToVerify = [];
for (let i = 0; i < allNodes.length; i++) {
const [stringStoreIndex, node] = allNodes[i];
const allNodes = this.getOrderedNodeMap();
let contiguousIndex = -1;
for (let stringIndex in allNodes) {
contiguousIndex += 1;
const node = allNodes[stringIndex];
// finding the index allows the use of splice which should be slightly faster than both a check and filter

@@ -737,4 +800,4 @@ const matchIndex = remainingIdsToRemove.findIndex(idToRemove => idToRemove === node.id);

remainingIdsToRemove.splice(matchIndex, 1);
this.destroyRowAtIndex(Number(stringStoreIndex));
removedNodes.push(node);
this.destroyRowAtIndex(Number(stringIndex));
removedNodes.push(node.node);
deletedNodeCount += 1;

@@ -747,9 +810,13 @@ continue;

}
const numericStoreIndex = Number(stringStoreIndex);
if (i !== numericStoreIndex) {
nodesToVerify.push(node);
const numericStoreIndex = Number(stringIndex);
if (contiguousIndex !== numericStoreIndex) {
nodesToVerify.push(node.node);
}
// shift normal node up by number of deleted prior to this point
this.nodeIndexMap[numericStoreIndex - deletedNodeCount] = this.nodeIndexMap[numericStoreIndex];
delete this.nodeIndexMap[numericStoreIndex];
this.nodeMap.delete(allNodes[stringIndex]);
this.nodeMap.set({
id: node.id,
node: node.node,
index: numericStoreIndex - deletedNodeCount,
});
}

@@ -759,3 +826,3 @@ this.numberOfRows -= this.isLastRowIndexKnown() ? idsToRemove.length : deletedNodeCount;

nodesToVerify.forEach(node => node.__needsRefreshWhenVisible = true);
this.rowLoader.queueLoadAction();
this.rowLoader.queueLoadCheck();
}

@@ -762,0 +829,0 @@ return removedNodes;

@@ -74,3 +74,3 @@ import { BeanStub, IServerSideStore, NumberSequence, RowBounds, RowNode, ServerSideGroupLevelParams, ServerSideGroupLevelState, ServerSideTransaction, ServerSideTransactionResult, StoreRefreshAfterParams, Column, IRowNode } from "@ag-grid-community/core";

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeepAfterFilterAndSort
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeepAfterFilterAndSort
*/

@@ -81,3 +81,3 @@ forEachStoreDeep(callback: (store: IServerSideStore, index: number) => void, sequence?: NumberSequence): void;

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeepAfterFilterAndSort
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeepAfterFilterAndSort
*/

@@ -88,3 +88,3 @@ forEachNodeDeep(callback: (rowNode: RowNode<any>, index: number) => void, sequence?: NumberSequence): void;

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeep
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeep
*/

@@ -199,5 +199,10 @@ forEachNodeDeepAfterFilterAndSort(callback: (rowNode: RowNode<any>, index: number) => void, sequence?: NumberSequence): void;

fireStoreUpdatedEvent(): void;
fireRefreshFinishedEvent(): void;
getBlockStates(): {
[key: string]: any;
};
getStoreBounds(): {
topPx: number;
heightPx: number;
};
}

@@ -123,3 +123,4 @@ "use strict";

this.displayIndexEnd = undefined;
this.cache.getAllNodes().forEach(rowNode => this.blockUtils.clearDisplayIndex(rowNode));
this.cache.getNodes().forEach(lazyNode => this.blockUtils.clearDisplayIndex(lazyNode.node));
this.cache.clearDisplayIndexes();
}

@@ -180,8 +181,8 @@ /**

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeepAfterFilterAndSort
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeepAfterFilterAndSort
*/
forEachStoreDeep(callback, sequence = new core_1.NumberSequence()) {
callback(this, sequence.next());
this.cache.getAllNodes().forEach(rowNode => {
const childCache = rowNode.childStore;
this.cache.getNodes().forEach(lazyNode => {
const childCache = lazyNode.node.childStore;
if (childCache) {

@@ -195,8 +196,8 @@ childCache.forEachStoreDeep(callback, sequence);

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeepAfterFilterAndSort
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeepAfterFilterAndSort
*/
forEachNodeDeep(callback, sequence = new core_1.NumberSequence()) {
this.cache.getAllNodes().forEach(rowNode => {
callback(rowNode, sequence.next());
const childCache = rowNode.childStore;
this.cache.getNodes().forEach(lazyNode => {
callback(lazyNode.node, sequence.next());
const childCache = lazyNode.node.childStore;
if (childCache) {

@@ -210,12 +211,14 @@ childCache.forEachNodeDeep(callback, sequence);

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeep
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeep
*/
forEachNodeDeepAfterFilterAndSort(callback, sequence = new core_1.NumberSequence()) {
this.cache.getAllNodes().forEach(rowNode => {
callback(rowNode, sequence.next());
const childCache = rowNode.childStore;
const orderedNodes = this.cache.getOrderedNodeMap();
for (let key in orderedNodes) {
const lazyNode = orderedNodes[key];
callback(lazyNode.node, sequence.next());
const childCache = lazyNode.node.childStore;
if (childCache) {
childCache.forEachNodeDeepAfterFilterAndSort(callback, sequence);
}
});
}
}

@@ -226,3 +229,3 @@ /**

retryLoads() {
this.cache.getAllNodes().forEach(node => {
this.cache.getNodes().forEach(({ node }) => {
if (node.failedLoad) {

@@ -253,16 +256,14 @@ node.failedLoad = false;

getRowBounds(displayIndex) {
var _a;
if (!this.isDisplayIndexInStore(displayIndex)) {
return null;
}
const allNodes = this.cache.getAllNodes();
let previousNode = null;
let nextNode = null;
for (let i = 0; i < allNodes.length; i++) {
const node = allNodes[i];
if (node.rowIndex > displayIndex) {
nextNode = node;
break;
const thisNode = this.cache.getNodeCachedByDisplayIndex(displayIndex);
if (thisNode) {
const boundsFromRow = this.blockUtils.extractRowBounds(thisNode, displayIndex);
if (boundsFromRow) {
return boundsFromRow;
}
previousNode = node;
}
const { previousNode, nextNode } = (_a = this.cache.getSurroundingNodesByDisplayIndex(displayIndex)) !== null && _a !== void 0 ? _a : {};
// previous node may equal, or catch via detail node or child of group

@@ -314,13 +315,25 @@ if (previousNode) {

}
const allNodes = this.cache.getAllNodes();
let distToPreviousNodeTop = Number.MAX_SAFE_INTEGER;
let previousNode = null;
let distToNextNodeTop = Number.MAX_SAFE_INTEGER;
let nextNode = null;
for (let i = 0; i < allNodes.length; i++) {
const node = allNodes[i];
if (node.rowTop > pixel) {
this.cache.getNodes().forEach(({ node }) => {
const distBetween = Math.abs(pixel - node.rowTop);
// previous node
if (node.rowTop < pixel) {
if (distBetween < distToPreviousNodeTop) {
distToPreviousNodeTop = distBetween;
previousNode = node;
}
return;
}
// next node
if (distBetween < distToNextNodeTop) {
distToNextNodeTop = distBetween;
nextNode = node;
break;
}
previousNode = node;
}
});
// cast these back as typescript doesn't understand the forEach above
previousNode = previousNode;
nextNode = nextNode;
// previous node may equal, or catch via detail node or child of group

@@ -353,4 +366,7 @@ if (previousNode) {

return this.storeUtils.getChildStore(keys, this, (key) => {
const allNodes = this.cache.getAllNodes();
return allNodes.find(currentRowNode => currentRowNode.key == key);
const lazyNode = this.cache.getNodes().find(lazyNode => lazyNode.node.key == key);
if (!lazyNode) {
return null;
}
return lazyNode.node;
});

@@ -364,3 +380,3 @@ }

forEachChildStoreShallow(cb) {
this.cache.getAllNodes().forEach(node => {
this.cache.getNodes().forEach(({ node }) => {
if (node.childStore) {

@@ -454,14 +470,5 @@ cb(node.childStore);

}
this.cache.getAllNodes().forEach(rowNode => {
const hitFirstOrLast = rowNode === firstInRange || rowNode === lastInRange;
if (inActiveRange || hitFirstOrLast) {
result.push(rowNode);
}
if (hitFirstOrLast) {
inActiveRange = !inActiveRange;
}
});
// inActiveRange will be still true if we never hit the second rowNode
const invalidRange = inActiveRange;
return invalidRange ? [] : result;
return this.cache.getNodes().filter(({ node }) => {
return node.rowIndex >= firstInRange.rowIndex && node.rowIndex <= lastInRange.rowIndex;
}).map(({ node }) => node);
}

@@ -516,5 +523,19 @@ /**

}
// gets called when row data updated, and no more refreshing needed
fireRefreshFinishedEvent() {
const event = {
type: core_1.Events.EVENT_STORE_REFRESHED,
route: this.parentRowNode.getRoute(),
};
this.eventService.dispatchEvent(event);
}
getBlockStates() {
return this.cache.getBlockStates();
}
getStoreBounds() {
return {
topPx: this.topPx,
heightPx: this.heightPx,
};
}
}

@@ -521,0 +542,0 @@ __decorate([

@@ -18,3 +18,3 @@ import { IServerSideStore, BeanStub, StoreRefreshAfterParams, RowNode, ColumnVO, RowNodeBlock } from "@ag-grid-community/core";

}): void;
getChildStore(keys: string[], currentCache: IServerSideStore, findNodeFunc: (key: string) => RowNode): IServerSideStore | null;
getChildStore(keys: string[], currentCache: IServerSideStore, findNodeFunc: (key: string) => RowNode | null): IServerSideStore | null;
isServerRefreshNeeded(parentRowNode: RowNode, rowGroupCols: ColumnVO[], params: StoreRefreshAfterParams): boolean;

@@ -21,0 +21,0 @@ getServerSideInitialRowCount(): number;

@@ -103,10 +103,2 @@ "use strict";

this.eventService.dispatchEvent({ type: core_1.Events.EVENT_STORE_UPDATED });
if (res.update && res.update.length) {
// this set timeout is necessary to queue behind the listener for EVENT_STORE_UPDATED in ssrm which recalculates the rowIndexes
// if the rowIndex isn't calculated first the binarySearchForDisplayIndex will not be able to find the required rows
setTimeout(() => {
// refresh the full width rows
this.rowRenderer.refreshFullWidthRows(res.update);
}, 0);
}
return res;

@@ -113,0 +105,0 @@ }

@@ -1,1 +0,1 @@

export declare const VERSION = "29.2.0";
export declare const VERSION = "29.3.0";

@@ -5,2 +5,2 @@ "use strict";

// DO NOT UPDATE MANUALLY: Generated from script during build time
exports.VERSION = '29.2.0';
exports.VERSION = '29.3.0';

@@ -43,3 +43,2 @@ var __extends = (this && this.__extends) || (function () {

rowNode.stub = true;
rowNode.__needsRefresh = false;
rowNode.__needsRefreshWhenVisible = false;

@@ -46,0 +45,0 @@ if (rowNode.group) {

@@ -84,2 +84,6 @@ import { IServerSideStore, LoadSuccessParams, NumberSequence, RowBounds, RowNode, RowNodeBlock, ServerSideGroupLevelParams, ServerSideGroupLevelState, ServerSideTransaction, ServerSideTransactionResult, StoreRefreshAfterParams, IRowNode } from "@ag-grid-community/core";

getRowNodesInRange(firstInRange: RowNode, lastInRange: RowNode): RowNode[];
getStoreBounds(): {
topPx: number;
heightPx: number;
};
}

@@ -620,2 +620,8 @@ var __extends = (this && this.__extends) || (function () {

};
FullStore.prototype.getStoreBounds = function () {
return {
topPx: this.topPx,
heightPx: this.heightPx,
};
};
__decorate([

@@ -622,0 +628,0 @@ Autowired('ssrmStoreUtils')

@@ -11,2 +11,3 @@ import { BeanStub, RowNode, ServerSideGroupLevelParams } from "@ag-grid-community/core";

private readonly cache;
private checkForLoadQueued;
private loaderTimeout;

@@ -18,9 +19,7 @@ private nextBlockToLoad;

isRowLoading(index: number): boolean;
private doesRowNeedLoaded;
private getBlocksToLoad;
private getNodeRanges;
private getBlockToLoad;
reset(): void;
private executeLoad;
private isBlockInViewport;
private getNextBlockToLoad;
queueLoadCheck(): void;
queueLoadAction(): void;

@@ -27,0 +26,0 @@ private attemptLoad;

@@ -36,7 +36,3 @@ var __extends = (this && this.__extends) || (function () {

};
var __spread = (this && this.__spread) || function () {
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
return ar;
};
import { BeanStub, Autowired, _, PostConstruct, RowNodeBlockLoader } from "@ag-grid-community/core";
import { BeanStub, Autowired, PostConstruct, RowNodeBlockLoader } from "@ag-grid-community/core";
var LazyBlockLoader = /** @class */ (function (_super) {

@@ -47,2 +43,3 @@ __extends(LazyBlockLoader, _super);

_this.loadingNodes = new Set();
_this.checkForLoadQueued = false;
_this.loaderTimeout = undefined;

@@ -62,52 +59,47 @@ _this.nextBlockToLoad = undefined;

};
LazyBlockLoader.prototype.doesRowNeedLoaded = function (index) {
// block already loading, don't duplicate request
if (this.loadingNodes.has(index)) {
return false;
LazyBlockLoader.prototype.getBlockToLoad = function () {
var _a;
var firstRowInViewport = this.api.getFirstDisplayedRow();
var lastRowInViewport = this.api.getLastDisplayedRow();
// quick look-up for priority rows needing loading in viewport.
for (var i = firstRowInViewport; i <= lastRowInViewport; i++) {
var node = this.cache.getNodeCachedByDisplayIndex(i);
if (!node) {
// if no row details, ignore, as row hasn't been created
// and it's too expensive to work out its location here
continue;
}
var lazyNode = this.cache.getNodes().getBy('node', node);
if (!lazyNode) {
continue;
}
if (this.isRowLoading(lazyNode.index)) {
continue;
}
if (node.__needsRefreshWhenVisible || (node.stub && !node.failedLoad)) {
return this.getBlockStartIndexForIndex(lazyNode.index);
}
}
var node = this.cache.getRowByStoreIndex(index);
if (!node) {
return false;
}
// user has manually refreshed this node
if (node.__needsRefresh) {
return true;
}
var firstRow = this.api.getFirstDisplayedRow();
var lastRow = this.api.getLastDisplayedRow();
var isRowInViewport = node.rowIndex != null && node.rowIndex >= firstRow && node.rowIndex <= lastRow;
// other than refreshing nodes, only ever load nodes in viewport
if (!isRowInViewport) {
return false;
}
// if node is a loading stub, or if it needs reverified, we refresh
return (node.stub && !node.failedLoad) || node.__needsRefreshWhenVisible;
};
LazyBlockLoader.prototype.getBlocksToLoad = function () {
var _this = this;
var indexesToLoad = new Set();
// filter for nodes somewhat reasonably close to viewport, so we don't refresh all data
// sort by distance to viewport, so user is making relevant requests
this.cache.getNodeMapEntries().forEach(function (_a) {
var _b = __read(_a, 2), stringIndex = _b[0], node = _b[1];
var numericIndex = Number(stringIndex);
var blockStart = _this.getBlockStartIndexForIndex(numericIndex);
// if node is a loading stub, or has manually been marked as needsRefresh we refresh
if (_this.doesRowNeedLoaded(numericIndex)) {
indexesToLoad.add(blockStart);
var nodesToRefresh = this.cache.getNodesToRefresh();
var nodeToRefresh = null;
var nodeToRefreshDist = Number.MAX_SAFE_INTEGER;
nodesToRefresh.forEach(function (node) {
if (node.rowIndex == null) {
nodeToRefresh = node;
return;
}
var distToViewportTop = Math.abs(firstRowInViewport - node.rowIndex);
var distToViewportBottom = Math.abs(node.rowIndex - lastRowInViewport);
if (distToViewportTop < nodeToRefreshDist) {
nodeToRefresh = node;
nodeToRefreshDist = distToViewportTop;
}
if (distToViewportBottom < nodeToRefreshDist) {
nodeToRefresh = node;
nodeToRefreshDist = distToViewportBottom;
}
});
return __spread(indexesToLoad);
var lazyIndex = (_a = this.cache.getNodes().getBy('node', nodeToRefresh)) === null || _a === void 0 ? void 0 : _a.index;
return lazyIndex == null ? undefined : this.getBlockStartIndexForIndex(lazyIndex);
};
LazyBlockLoader.prototype.getNodeRanges = function () {
var _this = this;
var ranges = {};
this.getBlocksToLoad().forEach(function (index) {
var rangeSize = _.oneOrGreater(_this.gridOptionsService.getNum('cacheBlockSize')) || LazyBlockLoader.DEFAULT_BLOCK_SIZE;
var translatedIndex = index - (index % rangeSize);
ranges[translatedIndex] = translatedIndex + rangeSize;
});
return ranges;
};
LazyBlockLoader.prototype.reset = function () {

@@ -169,35 +161,23 @@ this.loadingNodes.clear();

};
LazyBlockLoader.prototype.isBlockInViewport = function (blockStart, blockEnd) {
var firstRowInViewport = this.api.getFirstDisplayedRow();
var lastRowInViewport = this.api.getLastDisplayedRow();
var blockContainsViewport = blockStart <= firstRowInViewport && blockEnd >= lastRowInViewport;
var blockEndIsInViewport = blockEnd > firstRowInViewport && blockEnd < lastRowInViewport;
var blockStartIsInViewport = blockStart > firstRowInViewport && blockStart < lastRowInViewport;
return blockContainsViewport || blockEndIsInViewport || blockStartIsInViewport;
LazyBlockLoader.prototype.getNextBlockToLoad = function () {
var result = this.getBlockToLoad();
if (result != null && result < 0) {
this.getBlockToLoad();
}
if (result != null) {
return [String(result), result + this.getBlockSize()];
}
return null;
};
LazyBlockLoader.prototype.getNextBlockToLoad = function () {
LazyBlockLoader.prototype.queueLoadCheck = function () {
var _this = this;
var ranges = this.getNodeRanges();
var toLoad = Object.entries(ranges);
if (toLoad.length === 0) {
return null;
// already going to check next cycle, ignore.
if (this.checkForLoadQueued) {
return;
}
var firstRowInViewport = this.api.getFirstDisplayedRow();
toLoad.sort(function (_a, _b) {
var _c = __read(_a, 2), aStart = _c[0], aEnd = _c[1];
var _d = __read(_b, 2), bStart = _d[0], bEnd = _d[1];
var isAInViewport = _this.isBlockInViewport(Number(aStart), aEnd);
var isBInViewport = _this.isBlockInViewport(Number(bStart), bEnd);
// always prioritise loading blocks in viewport
if (isAInViewport) {
return -1;
}
// always prioritise loading blocks in viewport
if (isBInViewport) {
return 1;
}
// prioritise based on how close to the viewport the block is
return Math.abs(firstRowInViewport - Number(aStart)) - Math.abs(firstRowInViewport - Number(bStart));
this.checkForLoadQueued = true;
window.queueMicrotask(function () {
_this.checkForLoadQueued = false;
_this.queueLoadAction();
});
return toLoad[0];
};

@@ -204,0 +184,0 @@ LazyBlockLoader.prototype.queueLoadAction = function () {

import { BeanStub, LoadSuccessParams, NumberSequence, RowNode, IRowNode, ServerSideGroupLevelParams } from "@ag-grid-community/core";
import { LazyStore } from "./lazyStore";
import { MultiIndexMap } from "./multiIndexMap";
interface LazyStoreNode {
id: string;
index: number;
node: RowNode;
}
export declare class LazyCache extends BeanStub {

@@ -8,11 +14,48 @@ private api;

private nodeManager;
/**
* Indicates whether this is still the live dataset for this store (used for ignoring old requests after purge)
*/
private live;
private nodeIndexMap;
private nodeIds;
/**
* A node map indexed by the node's id, index, and node.
*/
private nodeMap;
/**
* A map of nodes indexed by the display index.
*/
private nodeDisplayIndexMap;
/**
* A set of nodes waiting to be refreshed
*/
private nodesToRefresh;
/**
* A list of display indexes bounds which are not currently present in this store, this can be due to;
* - Row stub hasn't been generated yet
* - Display index belongs to a child store
* - Display index is a detail node
*
* (Note, this is not always up to date, as stub nodes being generated do not refresh this, however
* this is a non issue as stub nodes are only ever default height and occupy 1 display index)
*/
private skippedDisplayIndexes;
/**
* End of store properties
*/
private numberOfRows;
private isLastRowKnown;
/**
* The prefix to use for node ids, this is used to ensure that node ids are unique across stores
*/
private defaultNodeIdPrefix;
/**
* Sibling services - 1-1 relationships.
*/
private store;
private rowLoader;
private storeParams;
/**
* Grid options properties - stored locally for access speed.
*/
private getRowIdFunc?;
private isMasterDetail;
constructor(store: LazyStore, numberOfRows: number, storeParams: ServerSideGroupLevelParams);

@@ -35,3 +78,3 @@ private init;

*/
getRowByStoreIndex(index: number): RowNode<any>;
getRowByStoreIndex(index: number): RowNode<any> | undefined;
/**

@@ -53,8 +96,16 @@ * Given a number of rows, skips through the given sequence & row top reference (using default row height)

setRowCount(rowCount: number, isLastRowIndexKnown?: boolean): void;
getNodeMapEntries(): [string, RowNode][];
getAllNodes(): RowNode[];
getNodes(): MultiIndexMap<LazyStoreNode>;
getNodeCachedByDisplayIndex(displayIndex: number): RowNode | null;
getNodesToRefresh(): Set<RowNode>;
/**
* Get or calculate the display index for this store
* @returns the previous and next loaded row nodes surrounding the given display index
*/
getSurroundingNodesByDisplayIndex(displayIndex: number): {
previousNode: RowNode<any> | undefined;
nextNode: RowNode<any> | undefined;
} | null;
/**
* Get or calculate the display index for a given store index
* @param storeIndex the rows index within this store
* @returns the rows visible display index relative to all stores
* @returns the rows visible display index relative to the grid
*/

@@ -95,2 +146,3 @@ getDisplayIndexFromStoreIndex(storeIndex: number): number | null;

onLoadSuccess(firstRowIndex: number, numberOfRowsExpected: number, response: LoadSuccessParams): void;
fireRefreshFinishedEvent(): void;
isLastRowIndexKnown(): boolean;

@@ -101,8 +153,11 @@ onLoadFailed(firstRowIndex: number, numberOfRowsExpected: number): void;

private fireStoreUpdatedEvent;
private isUsingRowIds;
private getRowId;
private lookupRowNode;
updateRowNodes(updates: any[]): RowNode[];
insertRowNodes(inserts: any[], indexToAdd?: number): RowNode[];
getOrderedNodeMap(): {
[key: number]: LazyStoreNode;
};
clearDisplayIndexes(): void;
removeRowNodes(idsToRemove: string[]): RowNode[];
}
export {};

@@ -42,2 +42,4 @@ var __extends = (this && this.__extends) || (function () {

import { LazyBlockLoader } from "./lazyBlockLoader";
import { MultiIndexMap } from "./multiIndexMap";
;
var LazyCache = /** @class */ (function (_super) {

@@ -47,3 +49,5 @@ __extends(LazyCache, _super);

var _this = _super.call(this) || this;
// Indicates whether this is still the live dataset for this store (used for ignoring old requests after purge)
/**
* Indicates whether this is still the live dataset for this store (used for ignoring old requests after purge)
*/
_this.live = true;

@@ -57,12 +61,20 @@ _this.store = store;

LazyCache.prototype.init = function () {
this.nodeIndexMap = {};
this.nodeIds = new Set();
// initiate the node map to be indexed at 'index', 'id' and 'node' for quick look-up.
// it's important id isn't first, as stub nodes overwrite each-other, and the first index is
// used for iteration.
this.nodeMap = new MultiIndexMap('index', 'id', 'node');
this.nodeDisplayIndexMap = new Map();
this.nodesToRefresh = new Set();
this.defaultNodeIdPrefix = this.blockUtils.createNodeIdPrefix(this.store.getParentNode());
this.rowLoader = this.createManagedBean(new LazyBlockLoader(this, this.store.getParentNode(), this.storeParams));
this.getRowIdFunc = this.gridOptionsService.getRowIdFunc();
this.isMasterDetail = this.gridOptionsService.isMasterDetail();
};
LazyCache.prototype.destroyRowNodes = function () {
var _this = this;
this.numberOfRows = 0;
this.blockUtils.destroyRowNodes(this.getAllNodes());
this.nodeIndexMap = {};
this.nodeIds.clear();
this.nodeMap.forEach(function (node) { return _this.blockUtils.destroyRowNode(node.node); });
this.nodeMap.clear();
this.nodeDisplayIndexMap.clear();
this.nodesToRefresh.clear();
this.live = false;

@@ -76,3 +88,3 @@ };

LazyCache.prototype.getRowByDisplayIndex = function (displayIndex) {
var _a;
var _a, _b, _c, _d;
// if index isn't in store, nothing to return

@@ -82,47 +94,54 @@ if (!this.store.isDisplayIndexInStore(displayIndex)) {

}
var nodeAfterStringIndex;
var nodeMapEntries = this.getNodeMapEntries();
for (var i = 0; i < nodeMapEntries.length; i++) {
var _b = __read(nodeMapEntries[i], 2), stringIndex = _b[0], node = _b[1];
// if we find the index, simply return this node
if (node.rowIndex === displayIndex) {
if (node.stub || node.__needsRefreshWhenVisible) {
this.rowLoader.queueLoadAction();
}
return node;
// first try to directly look this node up in the display index map
var node = this.nodeDisplayIndexMap.get(displayIndex);
if (node) {
// if we have the node, check if it needs refreshed when rendered
if (node.stub || node.__needsRefreshWhenVisible) {
this.rowLoader.queueLoadCheck();
}
// then check if current row contains a detail row with the index
var expandedMasterRow = node.master && node.expanded;
var detailNode = node.detailNode;
if (expandedMasterRow && detailNode && detailNode.rowIndex === displayIndex) {
return detailNode;
return node;
}
// next check if this is the first row, if so return a stub node
// this is a performance optimisation, as it is the most common scenario
// and enables the node - 1 check to kick in more often.
if (displayIndex === this.store.getDisplayIndexStart()) {
return this.createStubNode(0, displayIndex);
}
// check if the row immediately prior is available in the store
var contiguouslyPreviousNode = this.nodeDisplayIndexMap.get(displayIndex - 1);
if (contiguouslyPreviousNode) {
// if previous row is master detail, and expanded, this node must be detail
if (this.isMasterDetail && contiguouslyPreviousNode.master && contiguouslyPreviousNode.expanded) {
return contiguouslyPreviousNode.detailNode;
}
// if the index belongs to a child store, recursively search
if ((_a = node.childStore) === null || _a === void 0 ? void 0 : _a.isDisplayIndexInStore(displayIndex)) {
return node.childStore.getRowUsingDisplayIndex(displayIndex);
// if previous row is expanded group, this node will belong to that group.
if (contiguouslyPreviousNode.expanded && ((_a = contiguouslyPreviousNode.childStore) === null || _a === void 0 ? void 0 : _a.isDisplayIndexInStore(displayIndex))) {
return (_b = contiguouslyPreviousNode.childStore) === null || _b === void 0 ? void 0 : _b.getRowUsingDisplayIndex(displayIndex);
}
// if current row index is higher, then the node has been passed
if (node.rowIndex > displayIndex) {
// keep track of the last next node we find that comes after in case we need to create a new stub
nodeAfterStringIndex = stringIndex;
break;
}
// otherwise, row must be a stub node
var lazyCacheNode = this.nodeMap.getBy('node', contiguouslyPreviousNode);
return this.createStubNode(lazyCacheNode.index + 1, displayIndex);
}
/**
* The code below this point is assuming we haven't found a stored node with this display index, but the node does belong in this store,
* in this case we want to create a stub node to display in the grid, so we need to calculate the store index from the display index using
* the next node found after this one (can use end index here as we have confidence it should be up to date, as we aren't inserting rows)
*/
// no node was found before this display index, so calculate based on store end index
if (nodeAfterStringIndex == null) {
var storeIndexFromEndIndex = this.store.getRowCount() - (this.store.getDisplayIndexEnd() - displayIndex);
return this.createStubNode(storeIndexFromEndIndex, displayIndex);
var adjacentNodes = this.getSurroundingNodesByDisplayIndex(displayIndex);
// if no bounds skipped includes this, calculate from end index
if (adjacentNodes == null) {
var storeIndexFromEndIndex_1 = this.store.getRowCount() - (this.store.getDisplayIndexEnd() - displayIndex);
return this.createStubNode(storeIndexFromEndIndex_1, displayIndex);
}
// important to remember this node is not necessarily directly after the node we're searching for
var nodeAfterIndex = Number(nodeAfterStringIndex);
var nodeAfter = this.nodeIndexMap[nodeAfterIndex];
// difference can be calculated from next nodes display index
var nodeAfterDisplayIndex = nodeAfter.rowIndex;
var storeIndexFromNodeAfterIndex = nodeAfterIndex - (nodeAfterDisplayIndex - displayIndex);
return this.createStubNode(storeIndexFromNodeAfterIndex, displayIndex);
var previousNode = adjacentNodes.previousNode, nextNode = adjacentNodes.nextNode;
// if the node before this node is expanded, this node might be a child of that node
if (previousNode && previousNode.expanded && ((_c = previousNode.childStore) === null || _c === void 0 ? void 0 : _c.isDisplayIndexInStore(displayIndex))) {
return (_d = previousNode.childStore) === null || _d === void 0 ? void 0 : _d.getRowUsingDisplayIndex(displayIndex);
}
// if we have the node after this node, we can calculate the store index of this node by the difference
// in display indexes between the two nodes.
if (nextNode) {
var nextSimpleRowStoreIndex = this.nodeMap.getBy('node', nextNode);
var displayIndexDiff = nextNode.rowIndex - displayIndex;
var newStoreIndex = nextSimpleRowStoreIndex.index - displayIndexDiff;
return this.createStubNode(newStoreIndex, displayIndex);
}
// if no next node, calculate from end index of this store
var storeIndexFromEndIndex = this.store.getRowCount() - (this.store.getDisplayIndexEnd() - displayIndex);
return this.createStubNode(storeIndexFromEndIndex, displayIndex);
};

@@ -133,2 +152,3 @@ /**

LazyCache.prototype.createStubNode = function (storeIndex, displayIndex) {
var _this = this;
// bounds are acquired before creating the node, as otherwise it'll use it's own empty self to calculate

@@ -139,4 +159,5 @@ var rowBounds = this.store.getRowBounds(displayIndex);

node.setRowTop(rowBounds.rowTop);
_this.nodeDisplayIndexMap.set(displayIndex, node);
});
this.rowLoader.queueLoadAction();
this.rowLoader.queueLoadCheck();
return newNode;

@@ -149,3 +170,4 @@ };

LazyCache.prototype.getRowByStoreIndex = function (index) {
return this.nodeIndexMap[index];
var _a;
return (_a = this.nodeMap.getBy('index', index)) === null || _a === void 0 ? void 0 : _a.node;
};

@@ -159,3 +181,11 @@ /**

LazyCache.prototype.skipDisplayIndexes = function (numberOfRowsToSkip, displayIndexSeq, nextRowTop) {
if (numberOfRowsToSkip === 0) {
return;
}
var defaultRowHeight = this.gridOptionsService.getRowHeightAsNumber();
// these are recorded so that the previous node can be found more quickly when a node is missing
this.skippedDisplayIndexes.push({
from: displayIndexSeq.peek(),
to: displayIndexSeq.peek() + numberOfRowsToSkip
});
displayIndexSeq.skip(numberOfRowsToSkip);

@@ -169,19 +199,37 @@ nextRowTop.value += numberOfRowsToSkip * defaultRowHeight;

LazyCache.prototype.setDisplayIndexes = function (displayIndexSeq, nextRowTop) {
var _this = this;
var nodeEntries = this.getNodeMapEntries();
// Create a map of display index nodes for access speed
this.nodeDisplayIndexMap.clear();
this.skippedDisplayIndexes = [];
// create an object indexed by store index, as this will sort all of the nodes when we iterate
// the object
var orderedMap = {};
this.nodeMap.forEach(function (lazyNode) {
orderedMap[lazyNode.index] = lazyNode.node;
});
var lastIndex = -1;
nodeEntries.forEach(function (_a) {
var _b = __read(_a, 2), stringIndex = _b[0], node = _b[1];
// iterate over the nodes in order, setting the display index on each node. When display indexes
// are skipped, they're added to the skippedDisplayIndexes array
for (var stringIndex in orderedMap) {
var node = orderedMap[stringIndex];
var numericIndex = Number(stringIndex);
// if any nodes aren't currently in the store, skip the display indexes too
var numberOfRowsToSkip = (numericIndex - 1) - lastIndex;
_this.skipDisplayIndexes(numberOfRowsToSkip, displayIndexSeq, nextRowTop);
var numberOfRowsToSkip_1 = (numericIndex - 1) - lastIndex;
this.skipDisplayIndexes(numberOfRowsToSkip_1, displayIndexSeq, nextRowTop);
// set this nodes index and row top
_this.blockUtils.setDisplayIndex(node, displayIndexSeq, nextRowTop);
this.blockUtils.setDisplayIndex(node, displayIndexSeq, nextRowTop);
this.nodeDisplayIndexMap.set(node.rowIndex, node);
var passedRows = displayIndexSeq.peek() - node.rowIndex;
if (passedRows > 1) {
this.skippedDisplayIndexes.push({
from: node.rowIndex + 1,
to: displayIndexSeq.peek()
});
}
// store this index for skipping after this
lastIndex = numericIndex;
});
}
// need to skip rows until the end of this store
var numberOfRowsToSkip = (this.numberOfRows - 1) - lastIndex;
this.skipDisplayIndexes(numberOfRowsToSkip, displayIndexSeq, nextRowTop);
// this is not terribly efficient, and could probs be improved
this.purgeExcessRows();

@@ -199,53 +247,54 @@ };

this.isLastRowKnown = isLastRowIndexKnown;
if (isLastRowIndexKnown === false) {
this.numberOfRows += 1;
}
}
this.fireStoreUpdatedEvent();
};
LazyCache.prototype.getNodeMapEntries = function () {
return Object.entries(this.nodeIndexMap);
LazyCache.prototype.getNodes = function () {
return this.nodeMap;
};
LazyCache.prototype.getAllNodes = function () {
return Object.values(this.nodeIndexMap);
LazyCache.prototype.getNodeCachedByDisplayIndex = function (displayIndex) {
var _a;
return (_a = this.nodeDisplayIndexMap.get(displayIndex)) !== null && _a !== void 0 ? _a : null;
};
LazyCache.prototype.getNodesToRefresh = function () {
return this.nodesToRefresh;
};
/**
* Get or calculate the display index for this store
* @returns the previous and next loaded row nodes surrounding the given display index
*/
LazyCache.prototype.getSurroundingNodesByDisplayIndex = function (displayIndex) {
// iterate over the skipped display indexes to find the bound this display index belongs to
for (var i in this.skippedDisplayIndexes) {
var skippedRowBound = this.skippedDisplayIndexes[i];
if (skippedRowBound.from <= displayIndex && skippedRowBound.to >= displayIndex) {
// take the node before and after the boundary and return those
var previousNode = this.nodeDisplayIndexMap.get(skippedRowBound.from - 1);
var nextNode = this.nodeDisplayIndexMap.get(skippedRowBound.to + 1);
return { previousNode: previousNode, nextNode: nextNode };
}
}
return null;
};
/**
* Get or calculate the display index for a given store index
* @param storeIndex the rows index within this store
* @returns the rows visible display index relative to all stores
* @returns the rows visible display index relative to the grid
*/
LazyCache.prototype.getDisplayIndexFromStoreIndex = function (storeIndex) {
var _a;
var nodeToReplace = this.nodeIndexMap[storeIndex];
var displayIndexStart = this.store.getDisplayIndexStart();
if (displayIndexStart == null) {
return null;
var nodesAfterThis = this.nodeMap.filter(function (lazyNode) { return lazyNode.index > storeIndex; });
if (nodesAfterThis.length === 0) {
return this.store.getDisplayIndexEnd() - (this.numberOfRows - storeIndex);
}
// if node exists, we can extract its displayIndex
if (nodeToReplace && nodeToReplace.rowIndex != null) {
return nodeToReplace.rowIndex;
}
var allNodes = this.getNodeMapEntries();
var lastNode = undefined;
var lastIndex = -1;
for (var i = 0; i < allNodes.length; i++) {
var _b = __read(allNodes[i], 2), stringNodeStoreIndex = _b[0], node = _b[1];
var numericNodeStoreIndex = Number(stringNodeStoreIndex);
if (numericNodeStoreIndex > storeIndex) {
break;
var nextNode;
for (var i = 0; i < nodesAfterThis.length; i++) {
var lazyNode = nodesAfterThis[i];
if (nextNode == null || nextNode.index > lazyNode.index) {
nextNode = lazyNode;
}
lastNode = node;
lastIndex = numericNodeStoreIndex;
}
// unlike in getRowByDisplayIndex, we have to use getDisplayIndexStart here, as nodes may
// have been inserted without updating display index end yet.
if (lastNode == null) {
return displayIndexStart + storeIndex;
}
var nodeDiff = storeIndex - lastIndex;
var childStoreEnd = (_a = lastNode.childStore) === null || _a === void 0 ? void 0 : _a.getDisplayIndexEnd();
if (childStoreEnd != null) {
return childStoreEnd + nodeDiff - 1;
}
if (lastNode.rowIndex != null) {
return lastNode.rowIndex + nodeDiff;
}
return displayIndexStart + storeIndex;
var nextDisplayIndex = nextNode.node.rowIndex;
var storeIndexDiff = nextNode.index - storeIndex;
return nextDisplayIndex - storeIndexDiff;
};

@@ -259,17 +308,17 @@ /**

LazyCache.prototype.createRowAtIndex = function (atStoreIndex, data, createNodeCallback) {
var _this = this;
var usingRowIds = this.isUsingRowIds();
// make sure an existing node isn't being overwritten
var existingNodeAtIndex = this.nodeIndexMap[atStoreIndex];
if (existingNodeAtIndex) {
existingNodeAtIndex.__needsRefresh = false;
existingNodeAtIndex.__needsRefreshWhenVisible = false;
var lazyNode = this.nodeMap.getBy('index', atStoreIndex);
// if node already exists, update it or destroy it
if (lazyNode) {
var node = lazyNode.node;
this.nodesToRefresh.delete(node);
node.__needsRefreshWhenVisible = false;
// if the node is the same, just update the content
if (this.doesNodeMatch(data, existingNodeAtIndex)) {
this.blockUtils.updateDataIntoRowNode(existingNodeAtIndex, data);
return existingNodeAtIndex;
if (this.doesNodeMatch(data, node)) {
this.blockUtils.updateDataIntoRowNode(node, data);
return node;
}
// if there's no id and this is an open group, protect this node from changes
if (!usingRowIds && existingNodeAtIndex.group && existingNodeAtIndex.expanded) {
return existingNodeAtIndex;
if (this.getRowIdFunc == null && node.group && node.expanded) {
return node;
}

@@ -279,18 +328,20 @@ // destroy the old node, might be worth caching state here

}
// if the node already exists, update it and move it to the new location
if (data && usingRowIds) {
var allNodes = this.getNodeMapEntries();
var existingNodeDetails = allNodes.find(function (_a) {
var _b = __read(_a, 2), _ = _b[0], node = _b[1];
return _this.doesNodeMatch(data, node);
});
if (existingNodeDetails) {
var _a = __read(existingNodeDetails, 2), existingStringIndex = _a[0], existingNode = _a[1];
var existingIndex = Number(existingStringIndex);
this.blockUtils.updateDataIntoRowNode(existingNode, data);
delete this.nodeIndexMap[existingIndex];
this.nodeIndexMap[atStoreIndex] = existingNode;
// mark all of the old block as needsVerify to trigger it for a refresh
this.markBlockForVerify(existingIndex);
return existingNode;
// if the node already exists elsewhere, update it and move it to the new location
if (data && this.getRowIdFunc != null) {
var id = this.getRowId(data);
var lazyNode_1 = this.nodeMap.getBy('id', id);
if (lazyNode_1) {
// delete old lazy node so we can insert it at different location
this.nodeMap.delete(lazyNode_1);
var node = lazyNode_1.node, index = lazyNode_1.index;
this.blockUtils.updateDataIntoRowNode(node, data);
this.nodeMap.set({
id: node.id,
node: node,
index: atStoreIndex
});
// mark all of the old block as needsVerify to trigger it for a refresh, as nodes
// should not be out of place
this.markBlockForVerify(index);
return node;
}

@@ -305,13 +356,12 @@ }

this.nodeManager.addRowNode(newNode);
this.nodeIds.add(newNode.id);
}
// add the new node to the store, has to be done after the display index is calculated so it doesn't take itself into account
this.nodeIndexMap[atStoreIndex] = newNode;
this.nodeMap.set({
id: newNode.id,
node: newNode,
index: atStoreIndex,
});
if (createNodeCallback) {
createNodeCallback(newNode);
}
// if this is a stub, we need to tell the loader to load rows
if (newNode.stub) {
this.rowLoader.queueLoadAction();
}
return newNode;

@@ -324,6 +374,5 @@ };

var dirtyBlocks = new Set();
this.getNodeMapEntries().forEach(function (_a) {
this.nodeMap.forEach(function (_a) {
var _b;
var _c = __read(_a, 2), stringIndex = _c[0], node = _c[1];
var index = Number(stringIndex);
var node = _a.node, index = _a.index;
var blockStart = _this.rowLoader.getBlockStartIndexForIndex(index);

@@ -340,3 +389,3 @@ if (!node.stub && !node.failedLoad) {

}
else if (node.__needsRefresh) {
else if (_this.nodesToRefresh.has(node)) {
rowState = 'needsLoading';

@@ -378,6 +427,10 @@ }

LazyCache.prototype.destroyRowAtIndex = function (atStoreIndex) {
var node = this.nodeIndexMap[atStoreIndex];
this.nodeIds.delete(node.id);
this.blockUtils.destroyRowNode(node);
delete this.nodeIndexMap[atStoreIndex];
var lazyNode = this.nodeMap.getBy('index', atStoreIndex);
if (!lazyNode) {
return;
}
this.nodeMap.delete(lazyNode);
this.nodeDisplayIndexMap.delete(lazyNode.node.rowIndex);
this.nodesToRefresh.delete(lazyNode.node);
this.blockUtils.destroyRowNode(lazyNode.node);
};

@@ -401,8 +454,7 @@ LazyCache.prototype.getSsrmParams = function () {

var _a = __read(this.rowLoader.getBlockBoundsForIndex(rowIndex), 2), start = _a[0], end = _a[1];
for (var i = start; i < end; i++) {
var node = this.nodeIndexMap[i];
if (node) {
node.__needsRefreshWhenVisible = true;
}
}
var lazyNodesInRange = this.nodeMap.filter(function (lazyNode) { return lazyNode.index >= start && lazyNode.index < end; });
lazyNodesInRange.forEach(function (_a) {
var node = _a.node;
node.__needsRefreshWhenVisible = true;
});
};

@@ -413,3 +465,3 @@ LazyCache.prototype.doesNodeMatch = function (data, node) {

}
if (this.isUsingRowIds()) {
if (this.getRowIdFunc != null) {
var id = this.getRowId(data);

@@ -429,10 +481,8 @@ return node.id === id;

var _a = __read(this.rowLoader.getBlockBoundsForIndex(lastRow), 2), _ = _a[0], lastRowBlockEnd = _a[1];
this.getNodeMapEntries().forEach(function (_a) {
var _b = __read(_a, 2), stringIndex = _b[0], node = _b[1];
var numericIndex = Number(stringIndex);
if (_this.rowLoader.isRowLoading(numericIndex)) {
this.nodeMap.forEach(function (lazyNode) {
if (_this.rowLoader.isRowLoading(lazyNode.index)) {
return;
}
if (node.stub && (numericIndex < firstRowBlockStart || numericIndex > lastRowBlockEnd)) {
_this.destroyRowAtIndex(numericIndex);
if (lazyNode.node.stub && (lazyNode.index < firstRowBlockStart || lazyNode.index > lastRowBlockEnd)) {
_this.destroyRowAtIndex(lazyNode.index);
}

@@ -459,4 +509,4 @@ });

nodes.forEach(function (_a) {
var _b = __read(_a, 2), storeIndexString = _b[0], node = _b[1];
var _c = __read(_this.rowLoader.getBlockBoundsForIndex(Number(storeIndexString)), 2), blockStart = _c[0], blockEnd = _c[1];
var node = _a.node, index = _a.index;
var _b = __read(_this.rowLoader.getBlockBoundsForIndex(index), 2), blockStart = _b[0], blockEnd = _b[1];
if (blockStart in blockDistanceToMiddle) {

@@ -468,4 +518,5 @@ return;

// may not have an end node if the block came back small
if (_this.nodeIndexMap[blockEnd - 1])
distEnd = Math.abs(_this.nodeIndexMap[blockEnd - 1].rowIndex - otherDisplayIndex);
var lastLazyNode = _this.nodeMap.getBy('index', [blockEnd - 1]);
if (lastLazyNode)
distEnd = Math.abs(lastLazyNode.node.rowIndex - otherDisplayIndex);
var farthest = distEnd == null || distStart < distEnd ? distStart : distEnd;

@@ -491,4 +542,4 @@ blockDistanceToMiddle[blockStart] = farthest;

// don't check the nodes that could have been cached out of necessity
var disposableNodes = this.getNodeMapEntries().filter(function (_a) {
var _b = __read(_a, 2), _ = _b[0], node = _b[1];
var disposableNodes = this.nodeMap.filter(function (_a) {
var node = _a.node;
return !node.stub && !_this.isNodeCached(node);

@@ -501,9 +552,9 @@ });

var disposableNodesNotInViewport = disposableNodes.filter(function (_a) {
var _b = __read(_a, 2), _ = _b[0], node = _b[1];
var node = _a.node;
var startRowNum = node.rowIndex;
if (!startRowNum) {
if (startRowNum == null || startRowNum === -1) {
// row is not displayed and can be disposed
return true;
}
if (firstRowInViewport <= startRowNum && startRowNum <= lastRowInViewport) {
if (firstRowBlockStart <= startRowNum && startRowNum < lastRowBlockEnd) {
// start row in viewport, block is in viewport

@@ -513,7 +564,7 @@ return false;

var lastRowNum = startRowNum + blockSize;
if (firstRowInViewport <= lastRowNum && lastRowNum <= lastRowInViewport) {
if (firstRowBlockStart <= lastRowNum && lastRowNum < lastRowBlockEnd) {
// end row in viewport, block is in viewport
return false;
}
if (startRowNum < firstRowInViewport && lastRowNum > lastRowInViewport) {
if (startRowNum < firstRowBlockStart && lastRowNum >= lastRowBlockEnd) {
// full block surrounds in viewport

@@ -525,2 +576,4 @@ return false;

});
// reduce the number of rows to retain by the number in viewport which were retained
numberOfRowsToRetain = numberOfRowsToRetain - (disposableNodes.length - disposableNodesNotInViewport.length);
if (!disposableNodesNotInViewport.length) {

@@ -538,8 +591,8 @@ return;

blockDistanceArray.sort(function (a, b) { return Math.sign(b[1] - a[1]); });
var blocksToRemove = blockDistanceArray.length - numberOfBlocksToRetain;
var blocksToRemove = blockDistanceArray.length - Math.max(numberOfBlocksToRetain, 0);
for (var i = 0; i < blocksToRemove; i++) {
var blockStart = Number(blockDistanceArray[i][0]);
for (var x = blockStart; x < blockStart + blockSize; x++) {
var node = this.nodeIndexMap[x];
if (!node || this.isNodeCached(node)) {
var lazyNode = this.nodeMap.getBy('index', x);
if (!lazyNode || this.isNodeCached(lazyNode.node)) {
continue;

@@ -567,3 +620,3 @@ }

var _this = this;
if (!this.isUsingRowIds()) {
if (!this.getRowIdFunc == null) {
return [];

@@ -587,3 +640,3 @@ }

return;
if (this.isUsingRowIds()) {
if (this.getRowIdFunc != null) {
var duplicates = this.extractDuplicateIds(response.rowData);

@@ -597,14 +650,16 @@ if (duplicates.length > 0) {

}
var wasRefreshing = this.nodesToRefresh.size > 0;
response.rowData.forEach(function (data, responseRowIndex) {
var _a;
var rowIndex = firstRowIndex + responseRowIndex;
var nodeFromCache = _this.nodeIndexMap[rowIndex];
var nodeFromCache = _this.nodeMap.getBy('index', rowIndex);
// if stub, overwrite
if (nodeFromCache === null || nodeFromCache === void 0 ? void 0 : nodeFromCache.stub) {
if ((_a = nodeFromCache === null || nodeFromCache === void 0 ? void 0 : nodeFromCache.node) === null || _a === void 0 ? void 0 : _a.stub) {
_this.createRowAtIndex(rowIndex, data);
return;
}
if (nodeFromCache && _this.doesNodeMatch(data, nodeFromCache)) {
_this.blockUtils.updateDataIntoRowNode(nodeFromCache, data);
nodeFromCache.__needsRefresh = false;
nodeFromCache.__needsRefreshWhenVisible = false;
if (nodeFromCache && _this.doesNodeMatch(data, nodeFromCache.node)) {
_this.blockUtils.updateDataIntoRowNode(nodeFromCache.node, data);
_this.nodesToRefresh.delete(nodeFromCache.node);
nodeFromCache.node.__needsRefreshWhenVisible = false;
return;

@@ -615,2 +670,6 @@ }

});
var finishedRefreshing = this.nodesToRefresh.size === 0;
if (wasRefreshing && finishedRefreshing) {
this.fireRefreshFinishedEvent();
}
if (response.rowCount != undefined && response.rowCount !== -1) {

@@ -635,13 +694,15 @@ // if the rowCount has been provided, set the row count

// delete any rows after the last index
var allRows = this.getNodeMapEntries();
for (var i = allRows.length - 1; i >= 0; i--) {
var numericIndex = Number(allRows[i][0]);
if (numericIndex < this.numberOfRows) {
break;
}
this.destroyRowAtIndex(numericIndex);
}
var lazyNodesAfterStoreEnd = this.nodeMap.filter(function (lazyNode) { return lazyNode.index >= _this.numberOfRows; });
lazyNodesAfterStoreEnd.forEach(function (lazyNode) { return _this.destroyRowAtIndex(lazyNode.index); });
}
this.fireStoreUpdatedEvent();
};
LazyCache.prototype.fireRefreshFinishedEvent = function () {
var finishedRefreshing = this.nodesToRefresh.size === 0;
// if anything refreshing currently, skip.
if (!finishedRefreshing) {
return;
}
this.store.fireRefreshFinishedEvent();
};
LazyCache.prototype.isLastRowIndexKnown = function () {

@@ -653,16 +714,23 @@ return this.isLastRowKnown;

return;
for (var i = firstRowIndex; i < firstRowIndex + numberOfRowsExpected; i++) {
var nodeFromCache = this.nodeIndexMap[i];
if (nodeFromCache) {
nodeFromCache.failedLoad = true;
}
}
var failedNodes = this.nodeMap.filter(function (node) { return node.index >= firstRowIndex && node.index < firstRowIndex + numberOfRowsExpected; });
failedNodes.forEach(function (node) { return node.node.failedLoad = true; });
this.fireStoreUpdatedEvent();
};
LazyCache.prototype.markNodesForRefresh = function () {
this.getAllNodes().forEach(function (node) { return node.__needsRefresh = true; });
this.rowLoader.queueLoadAction();
var _this = this;
this.nodeMap.forEach(function (lazyNode) {
if (lazyNode.node.stub) {
return;
}
_this.nodesToRefresh.add(lazyNode.node);
});
this.rowLoader.queueLoadCheck();
if (this.isLastRowKnown && this.numberOfRows === 0) {
this.numberOfRows = 1;
this.isLastRowKnown = false;
this.fireStoreUpdatedEvent();
}
};
LazyCache.prototype.isNodeInCache = function (id) {
return this.nodeIds.has(id);
return !!this.nodeMap.getBy('id', id);
};

@@ -676,8 +744,4 @@ // gets called 1) row count changed 2) cache purged 3) items inserted

};
LazyCache.prototype.isUsingRowIds = function () {
return this.gridOptionsService.getRowIdFunc() != null;
};
LazyCache.prototype.getRowId = function (data) {
var getRowIdFunc = this.gridOptionsService.getRowIdFunc();
if (getRowIdFunc == null) {
if (this.getRowIdFunc == null) {
return null;

@@ -688,3 +752,3 @@ }

var parentKeys = this.store.getParentNode().getGroupKeys();
var id = getRowIdFunc({
var id = this.getRowIdFunc({
data: data,

@@ -696,20 +760,15 @@ parentKeys: parentKeys.length > 0 ? parentKeys : undefined,

};
LazyCache.prototype.lookupRowNode = function (data) {
var _a;
if (!this.isUsingRowIds()) {
LazyCache.prototype.updateRowNodes = function (updates) {
var _this = this;
if (this.getRowIdFunc == null) {
// throw error, as this is type checked in the store. User likely abusing internal apis if here.
throw new Error('AG Grid: Insert transactions can only be applied when row ids are supplied.');
}
// find rowNode using id
var id = this.getRowId(data);
return (_a = this.getAllNodes().find(function (node) { return node.id === id; })) !== null && _a !== void 0 ? _a : null;
};
LazyCache.prototype.updateRowNodes = function (updates) {
var _this = this;
var updatedNodes = [];
updates.forEach(function (data) {
var row = _this.lookupRowNode(data);
if (row) {
_this.blockUtils.updateDataIntoRowNode(row, data);
updatedNodes.push(row);
var id = _this.getRowId(data);
var lazyNode = _this.nodeMap.getBy('id', id);
if (lazyNode) {
_this.blockUtils.updateDataIntoRowNode(lazyNode.node, data);
updatedNodes.push(lazyNode.node);
}

@@ -727,3 +786,3 @@ });

}
if (!this.isUsingRowIds()) {
if (this.getRowIdFunc == null) {
// throw error, as this is type checked in the store. User likely abusing internal apis if here.

@@ -745,22 +804,13 @@ throw new Error('AG Grid: Insert transactions can only be applied when row ids are supplied.');

}
// first move all the nodes after the addIndex out of the way
var allNodes = this.getNodeMapEntries();
// iterate backwards to avoid overwriting nodes which haven't been shifted yet
for (var i = allNodes.length - 1; i >= 0; i--) {
var _a = __read(allNodes[i], 2), stringStoreIndex = _a[0], node = _a[1];
var numericStoreIndex = Number(stringStoreIndex);
// nodes should be in order as js maps sort by numeric keys, so if index is too low can stop iterating
if (numericStoreIndex < addIndex) {
break;
}
var newIndex = numericStoreIndex + numberOfInserts;
if (this.getRowByStoreIndex(newIndex)) {
// this shouldn't happen, why would a row already exist here
throw new Error('AG Grid: Something went wrong, node in wrong place.');
}
else {
this.nodeIndexMap[numericStoreIndex + numberOfInserts] = node;
delete this.nodeIndexMap[numericStoreIndex];
}
}
var nodesToMove = this.nodeMap.filter(function (node) { return node.index >= addIndex; });
// delete all nodes which need moved first, so they don't get overwritten
nodesToMove.forEach(function (lazyNode) { return _this.nodeMap.delete(lazyNode); });
// then move the nodes to their new locations
nodesToMove.forEach(function (lazyNode) {
_this.nodeMap.set({
node: lazyNode.node,
index: lazyNode.index + numberOfInserts,
id: lazyNode.id,
});
});
// increase the store size to accommodate

@@ -771,4 +821,12 @@ this.numberOfRows += numberOfInserts;

};
LazyCache.prototype.getOrderedNodeMap = function () {
var obj = {};
this.nodeMap.forEach(function (node) { return obj[node.index] = node; });
return obj;
};
LazyCache.prototype.clearDisplayIndexes = function () {
this.nodeDisplayIndexMap.clear();
};
LazyCache.prototype.removeRowNodes = function (idsToRemove) {
if (!this.isUsingRowIds()) {
if (this.getRowIdFunc == null) {
// throw error, as this is type checked in the store. User likely abusing internal apis if here.

@@ -778,9 +836,11 @@ throw new Error('AG Grid: Insert transactions can only be applied when row ids are supplied.');

var removedNodes = [];
var allNodes = this.getNodeMapEntries();
var nodesToVerify = [];
// track how many nodes have been deleted, as when we pass other nodes we need to shift them up
var deletedNodeCount = 0;
var remainingIdsToRemove = __spread(idsToRemove);
var nodesToVerify = [];
var _loop_1 = function (i) {
var _a = __read(allNodes[i], 2), stringStoreIndex = _a[0], node = _a[1];
var allNodes = this.getOrderedNodeMap();
var contiguousIndex = -1;
var _loop_1 = function (stringIndex) {
contiguousIndex += 1;
var node = allNodes[stringIndex];
// finding the index allows the use of splice which should be slightly faster than both a check and filter

@@ -791,4 +851,4 @@ var matchIndex = remainingIdsToRemove.findIndex(function (idToRemove) { return idToRemove === node.id; });

remainingIdsToRemove.splice(matchIndex, 1);
this_1.destroyRowAtIndex(Number(stringStoreIndex));
removedNodes.push(node);
this_1.destroyRowAtIndex(Number(stringIndex));
removedNodes.push(node.node);
deletedNodeCount += 1;

@@ -801,13 +861,17 @@ return "continue";

}
var numericStoreIndex = Number(stringStoreIndex);
if (i !== numericStoreIndex) {
nodesToVerify.push(node);
var numericStoreIndex = Number(stringIndex);
if (contiguousIndex !== numericStoreIndex) {
nodesToVerify.push(node.node);
}
// shift normal node up by number of deleted prior to this point
this_1.nodeIndexMap[numericStoreIndex - deletedNodeCount] = this_1.nodeIndexMap[numericStoreIndex];
delete this_1.nodeIndexMap[numericStoreIndex];
this_1.nodeMap.delete(allNodes[stringIndex]);
this_1.nodeMap.set({
id: node.id,
node: node.node,
index: numericStoreIndex - deletedNodeCount,
});
};
var this_1 = this;
for (var i = 0; i < allNodes.length; i++) {
_loop_1(i);
for (var stringIndex in allNodes) {
_loop_1(stringIndex);
}

@@ -817,3 +881,3 @@ this.numberOfRows -= this.isLastRowIndexKnown() ? idsToRemove.length : deletedNodeCount;

nodesToVerify.forEach(function (node) { return node.__needsRefreshWhenVisible = true; });
this.rowLoader.queueLoadAction();
this.rowLoader.queueLoadCheck();
}

@@ -820,0 +884,0 @@ return removedNodes;

@@ -74,3 +74,3 @@ import { BeanStub, IServerSideStore, NumberSequence, RowBounds, RowNode, ServerSideGroupLevelParams, ServerSideGroupLevelState, ServerSideTransaction, ServerSideTransactionResult, StoreRefreshAfterParams, Column, IRowNode } from "@ag-grid-community/core";

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeepAfterFilterAndSort
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeepAfterFilterAndSort
*/

@@ -81,3 +81,3 @@ forEachStoreDeep(callback: (store: IServerSideStore, index: number) => void, sequence?: NumberSequence): void;

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeepAfterFilterAndSort
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeepAfterFilterAndSort
*/

@@ -88,3 +88,3 @@ forEachNodeDeep(callback: (rowNode: RowNode<any>, index: number) => void, sequence?: NumberSequence): void;

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeep
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeep
*/

@@ -199,5 +199,10 @@ forEachNodeDeepAfterFilterAndSort(callback: (rowNode: RowNode<any>, index: number) => void, sequence?: NumberSequence): void;

fireStoreUpdatedEvent(): void;
fireRefreshFinishedEvent(): void;
getBlockStates(): {
[key: string]: any;
};
getStoreBounds(): {
topPx: number;
heightPx: number;
};
}

@@ -157,3 +157,4 @@ var __extends = (this && this.__extends) || (function () {

this.displayIndexEnd = undefined;
this.cache.getAllNodes().forEach(function (rowNode) { return _this.blockUtils.clearDisplayIndex(rowNode); });
this.cache.getNodes().forEach(function (lazyNode) { return _this.blockUtils.clearDisplayIndex(lazyNode.node); });
this.cache.clearDisplayIndexes();
};

@@ -214,3 +215,3 @@ /**

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeepAfterFilterAndSort
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeepAfterFilterAndSort
*/

@@ -220,4 +221,4 @@ LazyStore.prototype.forEachStoreDeep = function (callback, sequence) {

callback(this, sequence.next());
this.cache.getAllNodes().forEach(function (rowNode) {
var childCache = rowNode.childStore;
this.cache.getNodes().forEach(function (lazyNode) {
var childCache = lazyNode.node.childStore;
if (childCache) {

@@ -231,9 +232,9 @@ childCache.forEachStoreDeep(callback, sequence);

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeepAfterFilterAndSort
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeepAfterFilterAndSort
*/
LazyStore.prototype.forEachNodeDeep = function (callback, sequence) {
if (sequence === void 0) { sequence = new NumberSequence(); }
this.cache.getAllNodes().forEach(function (rowNode) {
callback(rowNode, sequence.next());
var childCache = rowNode.childStore;
this.cache.getNodes().forEach(function (lazyNode) {
callback(lazyNode.node, sequence.next());
var childCache = lazyNode.node.childStore;
if (childCache) {

@@ -247,13 +248,15 @@ childCache.forEachNodeDeep(callback, sequence);

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeep
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeep
*/
LazyStore.prototype.forEachNodeDeepAfterFilterAndSort = function (callback, sequence) {
if (sequence === void 0) { sequence = new NumberSequence(); }
this.cache.getAllNodes().forEach(function (rowNode) {
callback(rowNode, sequence.next());
var childCache = rowNode.childStore;
var orderedNodes = this.cache.getOrderedNodeMap();
for (var key in orderedNodes) {
var lazyNode = orderedNodes[key];
callback(lazyNode.node, sequence.next());
var childCache = lazyNode.node.childStore;
if (childCache) {
childCache.forEachNodeDeepAfterFilterAndSort(callback, sequence);
}
});
}
};

@@ -264,3 +267,4 @@ /**

LazyStore.prototype.retryLoads = function () {
this.cache.getAllNodes().forEach(function (node) {
this.cache.getNodes().forEach(function (_a) {
var node = _a.node;
if (node.failedLoad) {

@@ -291,16 +295,14 @@ node.failedLoad = false;

LazyStore.prototype.getRowBounds = function (displayIndex) {
var _a;
if (!this.isDisplayIndexInStore(displayIndex)) {
return null;
}
var allNodes = this.cache.getAllNodes();
var previousNode = null;
var nextNode = null;
for (var i = 0; i < allNodes.length; i++) {
var node = allNodes[i];
if (node.rowIndex > displayIndex) {
nextNode = node;
break;
var thisNode = this.cache.getNodeCachedByDisplayIndex(displayIndex);
if (thisNode) {
var boundsFromRow = this.blockUtils.extractRowBounds(thisNode, displayIndex);
if (boundsFromRow) {
return boundsFromRow;
}
previousNode = node;
}
var _b = (_a = this.cache.getSurroundingNodesByDisplayIndex(displayIndex)) !== null && _a !== void 0 ? _a : {}, previousNode = _b.previousNode, nextNode = _b.nextNode;
// previous node may equal, or catch via detail node or child of group

@@ -352,13 +354,26 @@ if (previousNode) {

}
var allNodes = this.cache.getAllNodes();
var distToPreviousNodeTop = Number.MAX_SAFE_INTEGER;
var previousNode = null;
var distToNextNodeTop = Number.MAX_SAFE_INTEGER;
var nextNode = null;
for (var i = 0; i < allNodes.length; i++) {
var node = allNodes[i];
if (node.rowTop > pixel) {
this.cache.getNodes().forEach(function (_a) {
var node = _a.node;
var distBetween = Math.abs(pixel - node.rowTop);
// previous node
if (node.rowTop < pixel) {
if (distBetween < distToPreviousNodeTop) {
distToPreviousNodeTop = distBetween;
previousNode = node;
}
return;
}
// next node
if (distBetween < distToNextNodeTop) {
distToNextNodeTop = distBetween;
nextNode = node;
break;
}
previousNode = node;
}
});
// cast these back as typescript doesn't understand the forEach above
previousNode = previousNode;
nextNode = nextNode;
// previous node may equal, or catch via detail node or child of group

@@ -392,4 +407,7 @@ if (previousNode) {

return this.storeUtils.getChildStore(keys, this, function (key) {
var allNodes = _this.cache.getAllNodes();
return allNodes.find(function (currentRowNode) { return currentRowNode.key == key; });
var lazyNode = _this.cache.getNodes().find(function (lazyNode) { return lazyNode.node.key == key; });
if (!lazyNode) {
return null;
}
return lazyNode.node;
});

@@ -403,3 +421,4 @@ };

LazyStore.prototype.forEachChildStoreShallow = function (cb) {
this.cache.getAllNodes().forEach(function (node) {
this.cache.getNodes().forEach(function (_a) {
var node = _a.node;
if (node.childStore) {

@@ -493,14 +512,9 @@ cb(node.childStore);

}
this.cache.getAllNodes().forEach(function (rowNode) {
var hitFirstOrLast = rowNode === firstInRange || rowNode === lastInRange;
if (inActiveRange || hitFirstOrLast) {
result.push(rowNode);
}
if (hitFirstOrLast) {
inActiveRange = !inActiveRange;
}
return this.cache.getNodes().filter(function (_a) {
var node = _a.node;
return node.rowIndex >= firstInRange.rowIndex && node.rowIndex <= lastInRange.rowIndex;
}).map(function (_a) {
var node = _a.node;
return node;
});
// inActiveRange will be still true if we never hit the second rowNode
var invalidRange = inActiveRange;
return invalidRange ? [] : result;
};

@@ -555,5 +569,19 @@ /**

};
// gets called when row data updated, and no more refreshing needed
LazyStore.prototype.fireRefreshFinishedEvent = function () {
var event = {
type: Events.EVENT_STORE_REFRESHED,
route: this.parentRowNode.getRoute(),
};
this.eventService.dispatchEvent(event);
};
LazyStore.prototype.getBlockStates = function () {
return this.cache.getBlockStates();
};
LazyStore.prototype.getStoreBounds = function () {
return {
topPx: this.topPx,
heightPx: this.heightPx,
};
};
__decorate([

@@ -560,0 +588,0 @@ Autowired('ssrmBlockUtils')

@@ -18,3 +18,3 @@ import { IServerSideStore, BeanStub, StoreRefreshAfterParams, RowNode, ColumnVO, RowNodeBlock } from "@ag-grid-community/core";

}): void;
getChildStore(keys: string[], currentCache: IServerSideStore, findNodeFunc: (key: string) => RowNode): IServerSideStore | null;
getChildStore(keys: string[], currentCache: IServerSideStore, findNodeFunc: (key: string) => RowNode | null): IServerSideStore | null;
isServerRefreshNeeded(parentRowNode: RowNode, rowGroupCols: ColumnVO[], params: StoreRefreshAfterParams): boolean;

@@ -21,0 +21,0 @@ getServerSideInitialRowCount(): number;

@@ -106,3 +106,2 @@ var __extends = (this && this.__extends) || (function () {

TransactionManager.prototype.applyTransaction = function (transaction) {
var _this = this;
var res;

@@ -119,10 +118,2 @@ this.serverSideRowModel.executeOnStore(transaction.route, function (store) {

this.eventService.dispatchEvent({ type: Events.EVENT_STORE_UPDATED });
if (res.update && res.update.length) {
// this set timeout is necessary to queue behind the listener for EVENT_STORE_UPDATED in ssrm which recalculates the rowIndexes
// if the rowIndex isn't calculated first the binarySearchForDisplayIndex will not be able to find the required rows
setTimeout(function () {
// refresh the full width rows
_this.rowRenderer.refreshFullWidthRows(res.update);
}, 0);
}
return res;

@@ -129,0 +120,0 @@ }

@@ -1,1 +0,1 @@

export declare const VERSION = "29.2.0";
export declare const VERSION = "29.3.0";
// DO NOT UPDATE MANUALLY: Generated from script during build time
export var VERSION = '29.2.0';
export var VERSION = '29.3.0';

@@ -26,3 +26,2 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {

rowNode.stub = true;
rowNode.__needsRefresh = false;
rowNode.__needsRefreshWhenVisible = false;

@@ -29,0 +28,0 @@ if (rowNode.group) {

@@ -84,2 +84,6 @@ import { IServerSideStore, LoadSuccessParams, NumberSequence, RowBounds, RowNode, RowNodeBlock, ServerSideGroupLevelParams, ServerSideGroupLevelState, ServerSideTransaction, ServerSideTransactionResult, StoreRefreshAfterParams, IRowNode } from "@ag-grid-community/core";

getRowNodesInRange(firstInRange: RowNode, lastInRange: RowNode): RowNode[];
getStoreBounds(): {
topPx: number;
heightPx: number;
};
}

@@ -589,2 +589,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {

}
getStoreBounds() {
return {
topPx: this.topPx,
heightPx: this.heightPx,
};
}
}

@@ -591,0 +597,0 @@ __decorate([

@@ -11,2 +11,3 @@ import { BeanStub, RowNode, ServerSideGroupLevelParams } from "@ag-grid-community/core";

private readonly cache;
private checkForLoadQueued;
private loaderTimeout;

@@ -18,9 +19,7 @@ private nextBlockToLoad;

isRowLoading(index: number): boolean;
private doesRowNeedLoaded;
private getBlocksToLoad;
private getNodeRanges;
private getBlockToLoad;
reset(): void;
private executeLoad;
private isBlockInViewport;
private getNextBlockToLoad;
queueLoadCheck(): void;
queueLoadAction(): void;

@@ -27,0 +26,0 @@ private attemptLoad;

@@ -7,3 +7,3 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {

};
import { BeanStub, Autowired, _, PostConstruct, RowNodeBlockLoader } from "@ag-grid-community/core";
import { BeanStub, Autowired, PostConstruct, RowNodeBlockLoader } from "@ag-grid-community/core";
export class LazyBlockLoader extends BeanStub {

@@ -13,2 +13,3 @@ constructor(cache, parentNode, storeParams) {

this.loadingNodes = new Set();
this.checkForLoadQueued = false;
this.loaderTimeout = undefined;

@@ -26,49 +27,47 @@ this.nextBlockToLoad = undefined;

}
doesRowNeedLoaded(index) {
// block already loading, don't duplicate request
if (this.loadingNodes.has(index)) {
return false;
getBlockToLoad() {
var _a;
const firstRowInViewport = this.api.getFirstDisplayedRow();
const lastRowInViewport = this.api.getLastDisplayedRow();
// quick look-up for priority rows needing loading in viewport.
for (let i = firstRowInViewport; i <= lastRowInViewport; i++) {
const node = this.cache.getNodeCachedByDisplayIndex(i);
if (!node) {
// if no row details, ignore, as row hasn't been created
// and it's too expensive to work out its location here
continue;
}
const lazyNode = this.cache.getNodes().getBy('node', node);
if (!lazyNode) {
continue;
}
if (this.isRowLoading(lazyNode.index)) {
continue;
}
if (node.__needsRefreshWhenVisible || (node.stub && !node.failedLoad)) {
return this.getBlockStartIndexForIndex(lazyNode.index);
}
}
const node = this.cache.getRowByStoreIndex(index);
if (!node) {
return false;
}
// user has manually refreshed this node
if (node.__needsRefresh) {
return true;
}
const firstRow = this.api.getFirstDisplayedRow();
const lastRow = this.api.getLastDisplayedRow();
const isRowInViewport = node.rowIndex != null && node.rowIndex >= firstRow && node.rowIndex <= lastRow;
// other than refreshing nodes, only ever load nodes in viewport
if (!isRowInViewport) {
return false;
}
// if node is a loading stub, or if it needs reverified, we refresh
return (node.stub && !node.failedLoad) || node.__needsRefreshWhenVisible;
}
getBlocksToLoad() {
const indexesToLoad = new Set();
// filter for nodes somewhat reasonably close to viewport, so we don't refresh all data
// sort by distance to viewport, so user is making relevant requests
this.cache.getNodeMapEntries().forEach(([stringIndex, node]) => {
const numericIndex = Number(stringIndex);
const blockStart = this.getBlockStartIndexForIndex(numericIndex);
// if node is a loading stub, or has manually been marked as needsRefresh we refresh
if (this.doesRowNeedLoaded(numericIndex)) {
indexesToLoad.add(blockStart);
const nodesToRefresh = this.cache.getNodesToRefresh();
let nodeToRefresh = null;
let nodeToRefreshDist = Number.MAX_SAFE_INTEGER;
nodesToRefresh.forEach(node => {
if (node.rowIndex == null) {
nodeToRefresh = node;
return;
}
const distToViewportTop = Math.abs(firstRowInViewport - node.rowIndex);
const distToViewportBottom = Math.abs(node.rowIndex - lastRowInViewport);
if (distToViewportTop < nodeToRefreshDist) {
nodeToRefresh = node;
nodeToRefreshDist = distToViewportTop;
}
if (distToViewportBottom < nodeToRefreshDist) {
nodeToRefresh = node;
nodeToRefreshDist = distToViewportBottom;
}
});
return [...indexesToLoad];
const lazyIndex = (_a = this.cache.getNodes().getBy('node', nodeToRefresh)) === null || _a === void 0 ? void 0 : _a.index;
return lazyIndex == null ? undefined : this.getBlockStartIndexForIndex(lazyIndex);
}
getNodeRanges() {
const ranges = {};
this.getBlocksToLoad().forEach(index => {
const rangeSize = _.oneOrGreater(this.gridOptionsService.getNum('cacheBlockSize')) || LazyBlockLoader.DEFAULT_BLOCK_SIZE;
const translatedIndex = index - (index % rangeSize);
ranges[translatedIndex] = translatedIndex + rangeSize;
});
return ranges;
}
reset() {

@@ -129,32 +128,22 @@ this.loadingNodes.clear();

}
isBlockInViewport(blockStart, blockEnd) {
const firstRowInViewport = this.api.getFirstDisplayedRow();
const lastRowInViewport = this.api.getLastDisplayedRow();
const blockContainsViewport = blockStart <= firstRowInViewport && blockEnd >= lastRowInViewport;
const blockEndIsInViewport = blockEnd > firstRowInViewport && blockEnd < lastRowInViewport;
const blockStartIsInViewport = blockStart > firstRowInViewport && blockStart < lastRowInViewport;
return blockContainsViewport || blockEndIsInViewport || blockStartIsInViewport;
}
getNextBlockToLoad() {
const ranges = this.getNodeRanges();
const toLoad = Object.entries(ranges);
if (toLoad.length === 0) {
return null;
const result = this.getBlockToLoad();
if (result != null && result < 0) {
this.getBlockToLoad();
}
const firstRowInViewport = this.api.getFirstDisplayedRow();
toLoad.sort(([aStart, aEnd], [bStart, bEnd]) => {
const isAInViewport = this.isBlockInViewport(Number(aStart), aEnd);
const isBInViewport = this.isBlockInViewport(Number(bStart), bEnd);
// always prioritise loading blocks in viewport
if (isAInViewport) {
return -1;
}
// always prioritise loading blocks in viewport
if (isBInViewport) {
return 1;
}
// prioritise based on how close to the viewport the block is
return Math.abs(firstRowInViewport - Number(aStart)) - Math.abs(firstRowInViewport - Number(bStart));
if (result != null) {
return [String(result), result + this.getBlockSize()];
}
return null;
}
queueLoadCheck() {
// already going to check next cycle, ignore.
if (this.checkForLoadQueued) {
return;
}
this.checkForLoadQueued = true;
window.queueMicrotask(() => {
this.checkForLoadQueued = false;
this.queueLoadAction();
});
return toLoad[0];
}

@@ -161,0 +150,0 @@ queueLoadAction() {

import { BeanStub, LoadSuccessParams, NumberSequence, RowNode, IRowNode, ServerSideGroupLevelParams } from "@ag-grid-community/core";
import { LazyStore } from "./lazyStore";
import { MultiIndexMap } from "./multiIndexMap";
interface LazyStoreNode {
id: string;
index: number;
node: RowNode;
}
export declare class LazyCache extends BeanStub {

@@ -8,11 +14,48 @@ private api;

private nodeManager;
/**
* Indicates whether this is still the live dataset for this store (used for ignoring old requests after purge)
*/
private live;
private nodeIndexMap;
private nodeIds;
/**
* A node map indexed by the node's id, index, and node.
*/
private nodeMap;
/**
* A map of nodes indexed by the display index.
*/
private nodeDisplayIndexMap;
/**
* A set of nodes waiting to be refreshed
*/
private nodesToRefresh;
/**
* A list of display indexes bounds which are not currently present in this store, this can be due to;
* - Row stub hasn't been generated yet
* - Display index belongs to a child store
* - Display index is a detail node
*
* (Note, this is not always up to date, as stub nodes being generated do not refresh this, however
* this is a non issue as stub nodes are only ever default height and occupy 1 display index)
*/
private skippedDisplayIndexes;
/**
* End of store properties
*/
private numberOfRows;
private isLastRowKnown;
/**
* The prefix to use for node ids, this is used to ensure that node ids are unique across stores
*/
private defaultNodeIdPrefix;
/**
* Sibling services - 1-1 relationships.
*/
private store;
private rowLoader;
private storeParams;
/**
* Grid options properties - stored locally for access speed.
*/
private getRowIdFunc?;
private isMasterDetail;
constructor(store: LazyStore, numberOfRows: number, storeParams: ServerSideGroupLevelParams);

@@ -35,3 +78,3 @@ private init;

*/
getRowByStoreIndex(index: number): RowNode<any>;
getRowByStoreIndex(index: number): RowNode<any> | undefined;
/**

@@ -53,8 +96,16 @@ * Given a number of rows, skips through the given sequence & row top reference (using default row height)

setRowCount(rowCount: number, isLastRowIndexKnown?: boolean): void;
getNodeMapEntries(): [string, RowNode][];
getAllNodes(): RowNode[];
getNodes(): MultiIndexMap<LazyStoreNode>;
getNodeCachedByDisplayIndex(displayIndex: number): RowNode | null;
getNodesToRefresh(): Set<RowNode>;
/**
* Get or calculate the display index for this store
* @returns the previous and next loaded row nodes surrounding the given display index
*/
getSurroundingNodesByDisplayIndex(displayIndex: number): {
previousNode: RowNode<any> | undefined;
nextNode: RowNode<any> | undefined;
} | null;
/**
* Get or calculate the display index for a given store index
* @param storeIndex the rows index within this store
* @returns the rows visible display index relative to all stores
* @returns the rows visible display index relative to the grid
*/

@@ -95,2 +146,3 @@ getDisplayIndexFromStoreIndex(storeIndex: number): number | null;

onLoadSuccess(firstRowIndex: number, numberOfRowsExpected: number, response: LoadSuccessParams): void;
fireRefreshFinishedEvent(): void;
isLastRowIndexKnown(): boolean;

@@ -101,8 +153,11 @@ onLoadFailed(firstRowIndex: number, numberOfRowsExpected: number): void;

private fireStoreUpdatedEvent;
private isUsingRowIds;
private getRowId;
private lookupRowNode;
updateRowNodes(updates: any[]): RowNode[];
insertRowNodes(inserts: any[], indexToAdd?: number): RowNode[];
getOrderedNodeMap(): {
[key: number]: LazyStoreNode;
};
clearDisplayIndexes(): void;
removeRowNodes(idsToRemove: string[]): RowNode[];
}
export {};

@@ -9,6 +9,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {

import { LazyBlockLoader } from "./lazyBlockLoader";
import { MultiIndexMap } from "./multiIndexMap";
;
export class LazyCache extends BeanStub {
constructor(store, numberOfRows, storeParams) {
super();
// Indicates whether this is still the live dataset for this store (used for ignoring old requests after purge)
/**
* Indicates whether this is still the live dataset for this store (used for ignoring old requests after purge)
*/
this.live = true;

@@ -21,12 +25,19 @@ this.store = store;

init() {
this.nodeIndexMap = {};
this.nodeIds = new Set();
// initiate the node map to be indexed at 'index', 'id' and 'node' for quick look-up.
// it's important id isn't first, as stub nodes overwrite each-other, and the first index is
// used for iteration.
this.nodeMap = new MultiIndexMap('index', 'id', 'node');
this.nodeDisplayIndexMap = new Map();
this.nodesToRefresh = new Set();
this.defaultNodeIdPrefix = this.blockUtils.createNodeIdPrefix(this.store.getParentNode());
this.rowLoader = this.createManagedBean(new LazyBlockLoader(this, this.store.getParentNode(), this.storeParams));
this.getRowIdFunc = this.gridOptionsService.getRowIdFunc();
this.isMasterDetail = this.gridOptionsService.isMasterDetail();
}
destroyRowNodes() {
this.numberOfRows = 0;
this.blockUtils.destroyRowNodes(this.getAllNodes());
this.nodeIndexMap = {};
this.nodeIds.clear();
this.nodeMap.forEach(node => this.blockUtils.destroyRowNode(node.node));
this.nodeMap.clear();
this.nodeDisplayIndexMap.clear();
this.nodesToRefresh.clear();
this.live = false;

@@ -40,3 +51,3 @@ }

getRowByDisplayIndex(displayIndex) {
var _a;
var _a, _b, _c, _d;
// if index isn't in store, nothing to return

@@ -46,47 +57,54 @@ if (!this.store.isDisplayIndexInStore(displayIndex)) {

}
let nodeAfterStringIndex;
const nodeMapEntries = this.getNodeMapEntries();
for (let i = 0; i < nodeMapEntries.length; i++) {
const [stringIndex, node] = nodeMapEntries[i];
// if we find the index, simply return this node
if (node.rowIndex === displayIndex) {
if (node.stub || node.__needsRefreshWhenVisible) {
this.rowLoader.queueLoadAction();
}
return node;
// first try to directly look this node up in the display index map
const node = this.nodeDisplayIndexMap.get(displayIndex);
if (node) {
// if we have the node, check if it needs refreshed when rendered
if (node.stub || node.__needsRefreshWhenVisible) {
this.rowLoader.queueLoadCheck();
}
// then check if current row contains a detail row with the index
const expandedMasterRow = node.master && node.expanded;
const detailNode = node.detailNode;
if (expandedMasterRow && detailNode && detailNode.rowIndex === displayIndex) {
return detailNode;
return node;
}
// next check if this is the first row, if so return a stub node
// this is a performance optimisation, as it is the most common scenario
// and enables the node - 1 check to kick in more often.
if (displayIndex === this.store.getDisplayIndexStart()) {
return this.createStubNode(0, displayIndex);
}
// check if the row immediately prior is available in the store
const contiguouslyPreviousNode = this.nodeDisplayIndexMap.get(displayIndex - 1);
if (contiguouslyPreviousNode) {
// if previous row is master detail, and expanded, this node must be detail
if (this.isMasterDetail && contiguouslyPreviousNode.master && contiguouslyPreviousNode.expanded) {
return contiguouslyPreviousNode.detailNode;
}
// if the index belongs to a child store, recursively search
if ((_a = node.childStore) === null || _a === void 0 ? void 0 : _a.isDisplayIndexInStore(displayIndex)) {
return node.childStore.getRowUsingDisplayIndex(displayIndex);
// if previous row is expanded group, this node will belong to that group.
if (contiguouslyPreviousNode.expanded && ((_a = contiguouslyPreviousNode.childStore) === null || _a === void 0 ? void 0 : _a.isDisplayIndexInStore(displayIndex))) {
return (_b = contiguouslyPreviousNode.childStore) === null || _b === void 0 ? void 0 : _b.getRowUsingDisplayIndex(displayIndex);
}
// if current row index is higher, then the node has been passed
if (node.rowIndex > displayIndex) {
// keep track of the last next node we find that comes after in case we need to create a new stub
nodeAfterStringIndex = stringIndex;
break;
}
// otherwise, row must be a stub node
const lazyCacheNode = this.nodeMap.getBy('node', contiguouslyPreviousNode);
return this.createStubNode(lazyCacheNode.index + 1, displayIndex);
}
/**
* The code below this point is assuming we haven't found a stored node with this display index, but the node does belong in this store,
* in this case we want to create a stub node to display in the grid, so we need to calculate the store index from the display index using
* the next node found after this one (can use end index here as we have confidence it should be up to date, as we aren't inserting rows)
*/
// no node was found before this display index, so calculate based on store end index
if (nodeAfterStringIndex == null) {
const adjacentNodes = this.getSurroundingNodesByDisplayIndex(displayIndex);
// if no bounds skipped includes this, calculate from end index
if (adjacentNodes == null) {
const storeIndexFromEndIndex = this.store.getRowCount() - (this.store.getDisplayIndexEnd() - displayIndex);
return this.createStubNode(storeIndexFromEndIndex, displayIndex);
}
// important to remember this node is not necessarily directly after the node we're searching for
const nodeAfterIndex = Number(nodeAfterStringIndex);
const nodeAfter = this.nodeIndexMap[nodeAfterIndex];
// difference can be calculated from next nodes display index
const nodeAfterDisplayIndex = nodeAfter.rowIndex;
const storeIndexFromNodeAfterIndex = nodeAfterIndex - (nodeAfterDisplayIndex - displayIndex);
return this.createStubNode(storeIndexFromNodeAfterIndex, displayIndex);
const { previousNode, nextNode } = adjacentNodes;
// if the node before this node is expanded, this node might be a child of that node
if (previousNode && previousNode.expanded && ((_c = previousNode.childStore) === null || _c === void 0 ? void 0 : _c.isDisplayIndexInStore(displayIndex))) {
return (_d = previousNode.childStore) === null || _d === void 0 ? void 0 : _d.getRowUsingDisplayIndex(displayIndex);
}
// if we have the node after this node, we can calculate the store index of this node by the difference
// in display indexes between the two nodes.
if (nextNode) {
const nextSimpleRowStoreIndex = this.nodeMap.getBy('node', nextNode);
const displayIndexDiff = nextNode.rowIndex - displayIndex;
const newStoreIndex = nextSimpleRowStoreIndex.index - displayIndexDiff;
return this.createStubNode(newStoreIndex, displayIndex);
}
// if no next node, calculate from end index of this store
const storeIndexFromEndIndex = this.store.getRowCount() - (this.store.getDisplayIndexEnd() - displayIndex);
return this.createStubNode(storeIndexFromEndIndex, displayIndex);
}

@@ -102,4 +120,5 @@ /**

node.setRowTop(rowBounds.rowTop);
this.nodeDisplayIndexMap.set(displayIndex, node);
});
this.rowLoader.queueLoadAction();
this.rowLoader.queueLoadCheck();
return newNode;

@@ -112,3 +131,4 @@ }

getRowByStoreIndex(index) {
return this.nodeIndexMap[index];
var _a;
return (_a = this.nodeMap.getBy('index', index)) === null || _a === void 0 ? void 0 : _a.node;
}

@@ -122,3 +142,11 @@ /**

skipDisplayIndexes(numberOfRowsToSkip, displayIndexSeq, nextRowTop) {
if (numberOfRowsToSkip === 0) {
return;
}
const defaultRowHeight = this.gridOptionsService.getRowHeightAsNumber();
// these are recorded so that the previous node can be found more quickly when a node is missing
this.skippedDisplayIndexes.push({
from: displayIndexSeq.peek(),
to: displayIndexSeq.peek() + numberOfRowsToSkip
});
displayIndexSeq.skip(numberOfRowsToSkip);

@@ -132,5 +160,16 @@ nextRowTop.value += numberOfRowsToSkip * defaultRowHeight;

setDisplayIndexes(displayIndexSeq, nextRowTop) {
const nodeEntries = this.getNodeMapEntries();
// Create a map of display index nodes for access speed
this.nodeDisplayIndexMap.clear();
this.skippedDisplayIndexes = [];
// create an object indexed by store index, as this will sort all of the nodes when we iterate
// the object
const orderedMap = {};
this.nodeMap.forEach(lazyNode => {
orderedMap[lazyNode.index] = lazyNode.node;
});
let lastIndex = -1;
nodeEntries.forEach(([stringIndex, node]) => {
// iterate over the nodes in order, setting the display index on each node. When display indexes
// are skipped, they're added to the skippedDisplayIndexes array
for (const stringIndex in orderedMap) {
const node = orderedMap[stringIndex];
const numericIndex = Number(stringIndex);

@@ -142,8 +181,17 @@ // if any nodes aren't currently in the store, skip the display indexes too

this.blockUtils.setDisplayIndex(node, displayIndexSeq, nextRowTop);
this.nodeDisplayIndexMap.set(node.rowIndex, node);
const passedRows = displayIndexSeq.peek() - node.rowIndex;
if (passedRows > 1) {
this.skippedDisplayIndexes.push({
from: node.rowIndex + 1,
to: displayIndexSeq.peek()
});
}
// store this index for skipping after this
lastIndex = numericIndex;
});
}
// need to skip rows until the end of this store
const numberOfRowsToSkip = (this.numberOfRows - 1) - lastIndex;
this.skipDisplayIndexes(numberOfRowsToSkip, displayIndexSeq, nextRowTop);
// this is not terribly efficient, and could probs be improved
this.purgeExcessRows();

@@ -161,53 +209,54 @@ }

this.isLastRowKnown = isLastRowIndexKnown;
if (isLastRowIndexKnown === false) {
this.numberOfRows += 1;
}
}
this.fireStoreUpdatedEvent();
}
getNodeMapEntries() {
return Object.entries(this.nodeIndexMap);
getNodes() {
return this.nodeMap;
}
getAllNodes() {
return Object.values(this.nodeIndexMap);
getNodeCachedByDisplayIndex(displayIndex) {
var _a;
return (_a = this.nodeDisplayIndexMap.get(displayIndex)) !== null && _a !== void 0 ? _a : null;
}
getNodesToRefresh() {
return this.nodesToRefresh;
}
/**
* Get or calculate the display index for this store
* @returns the previous and next loaded row nodes surrounding the given display index
*/
getSurroundingNodesByDisplayIndex(displayIndex) {
// iterate over the skipped display indexes to find the bound this display index belongs to
for (let i in this.skippedDisplayIndexes) {
const skippedRowBound = this.skippedDisplayIndexes[i];
if (skippedRowBound.from <= displayIndex && skippedRowBound.to >= displayIndex) {
// take the node before and after the boundary and return those
const previousNode = this.nodeDisplayIndexMap.get(skippedRowBound.from - 1);
const nextNode = this.nodeDisplayIndexMap.get(skippedRowBound.to + 1);
return { previousNode, nextNode };
}
}
return null;
}
/**
* Get or calculate the display index for a given store index
* @param storeIndex the rows index within this store
* @returns the rows visible display index relative to all stores
* @returns the rows visible display index relative to the grid
*/
getDisplayIndexFromStoreIndex(storeIndex) {
var _a;
const nodeToReplace = this.nodeIndexMap[storeIndex];
const displayIndexStart = this.store.getDisplayIndexStart();
if (displayIndexStart == null) {
return null;
const nodesAfterThis = this.nodeMap.filter(lazyNode => lazyNode.index > storeIndex);
if (nodesAfterThis.length === 0) {
return this.store.getDisplayIndexEnd() - (this.numberOfRows - storeIndex);
}
// if node exists, we can extract its displayIndex
if (nodeToReplace && nodeToReplace.rowIndex != null) {
return nodeToReplace.rowIndex;
}
const allNodes = this.getNodeMapEntries();
let lastNode = undefined;
let lastIndex = -1;
for (let i = 0; i < allNodes.length; i++) {
const [stringNodeStoreIndex, node] = allNodes[i];
const numericNodeStoreIndex = Number(stringNodeStoreIndex);
if (numericNodeStoreIndex > storeIndex) {
break;
let nextNode;
for (let i = 0; i < nodesAfterThis.length; i++) {
const lazyNode = nodesAfterThis[i];
if (nextNode == null || nextNode.index > lazyNode.index) {
nextNode = lazyNode;
}
lastNode = node;
lastIndex = numericNodeStoreIndex;
}
// unlike in getRowByDisplayIndex, we have to use getDisplayIndexStart here, as nodes may
// have been inserted without updating display index end yet.
if (lastNode == null) {
return displayIndexStart + storeIndex;
}
const nodeDiff = storeIndex - lastIndex;
const childStoreEnd = (_a = lastNode.childStore) === null || _a === void 0 ? void 0 : _a.getDisplayIndexEnd();
if (childStoreEnd != null) {
return childStoreEnd + nodeDiff - 1;
}
if (lastNode.rowIndex != null) {
return lastNode.rowIndex + nodeDiff;
}
return displayIndexStart + storeIndex;
const nextDisplayIndex = nextNode.node.rowIndex;
const storeIndexDiff = nextNode.index - storeIndex;
return nextDisplayIndex - storeIndexDiff;
}

@@ -221,16 +270,17 @@ /**

createRowAtIndex(atStoreIndex, data, createNodeCallback) {
const usingRowIds = this.isUsingRowIds();
// make sure an existing node isn't being overwritten
const existingNodeAtIndex = this.nodeIndexMap[atStoreIndex];
if (existingNodeAtIndex) {
existingNodeAtIndex.__needsRefresh = false;
existingNodeAtIndex.__needsRefreshWhenVisible = false;
const lazyNode = this.nodeMap.getBy('index', atStoreIndex);
// if node already exists, update it or destroy it
if (lazyNode) {
const { node } = lazyNode;
this.nodesToRefresh.delete(node);
node.__needsRefreshWhenVisible = false;
// if the node is the same, just update the content
if (this.doesNodeMatch(data, existingNodeAtIndex)) {
this.blockUtils.updateDataIntoRowNode(existingNodeAtIndex, data);
return existingNodeAtIndex;
if (this.doesNodeMatch(data, node)) {
this.blockUtils.updateDataIntoRowNode(node, data);
return node;
}
// if there's no id and this is an open group, protect this node from changes
if (!usingRowIds && existingNodeAtIndex.group && existingNodeAtIndex.expanded) {
return existingNodeAtIndex;
if (this.getRowIdFunc == null && node.group && node.expanded) {
return node;
}

@@ -240,15 +290,20 @@ // destroy the old node, might be worth caching state here

}
// if the node already exists, update it and move it to the new location
if (data && usingRowIds) {
const allNodes = this.getNodeMapEntries();
const existingNodeDetails = allNodes.find(([_, node]) => this.doesNodeMatch(data, node));
if (existingNodeDetails) {
const [existingStringIndex, existingNode] = existingNodeDetails;
const existingIndex = Number(existingStringIndex);
this.blockUtils.updateDataIntoRowNode(existingNode, data);
delete this.nodeIndexMap[existingIndex];
this.nodeIndexMap[atStoreIndex] = existingNode;
// mark all of the old block as needsVerify to trigger it for a refresh
this.markBlockForVerify(existingIndex);
return existingNode;
// if the node already exists elsewhere, update it and move it to the new location
if (data && this.getRowIdFunc != null) {
const id = this.getRowId(data);
const lazyNode = this.nodeMap.getBy('id', id);
if (lazyNode) {
// delete old lazy node so we can insert it at different location
this.nodeMap.delete(lazyNode);
const { node, index } = lazyNode;
this.blockUtils.updateDataIntoRowNode(node, data);
this.nodeMap.set({
id: node.id,
node,
index: atStoreIndex
});
// mark all of the old block as needsVerify to trigger it for a refresh, as nodes
// should not be out of place
this.markBlockForVerify(index);
return node;
}

@@ -263,13 +318,12 @@ }

this.nodeManager.addRowNode(newNode);
this.nodeIds.add(newNode.id);
}
// add the new node to the store, has to be done after the display index is calculated so it doesn't take itself into account
this.nodeIndexMap[atStoreIndex] = newNode;
this.nodeMap.set({
id: newNode.id,
node: newNode,
index: atStoreIndex,
});
if (createNodeCallback) {
createNodeCallback(newNode);
}
// if this is a stub, we need to tell the loader to load rows
if (newNode.stub) {
this.rowLoader.queueLoadAction();
}
return newNode;

@@ -281,5 +335,4 @@ }

const dirtyBlocks = new Set();
this.getNodeMapEntries().forEach(([stringIndex, node]) => {
this.nodeMap.forEach(({ node, index }) => {
var _a;
const index = Number(stringIndex);
const blockStart = this.rowLoader.getBlockStartIndexForIndex(index);

@@ -296,3 +349,3 @@ if (!node.stub && !node.failedLoad) {

}
else if (node.__needsRefresh) {
else if (this.nodesToRefresh.has(node)) {
rowState = 'needsLoading';

@@ -333,6 +386,10 @@ }

destroyRowAtIndex(atStoreIndex) {
const node = this.nodeIndexMap[atStoreIndex];
this.nodeIds.delete(node.id);
this.blockUtils.destroyRowNode(node);
delete this.nodeIndexMap[atStoreIndex];
const lazyNode = this.nodeMap.getBy('index', atStoreIndex);
if (!lazyNode) {
return;
}
this.nodeMap.delete(lazyNode);
this.nodeDisplayIndexMap.delete(lazyNode.node.rowIndex);
this.nodesToRefresh.delete(lazyNode.node);
this.blockUtils.destroyRowNode(lazyNode.node);
}

@@ -356,8 +413,6 @@ getSsrmParams() {

const [start, end] = this.rowLoader.getBlockBoundsForIndex(rowIndex);
for (let i = start; i < end; i++) {
const node = this.nodeIndexMap[i];
if (node) {
node.__needsRefreshWhenVisible = true;
}
}
const lazyNodesInRange = this.nodeMap.filter((lazyNode) => lazyNode.index >= start && lazyNode.index < end);
lazyNodesInRange.forEach(({ node }) => {
node.__needsRefreshWhenVisible = true;
});
}

@@ -368,3 +423,3 @@ doesNodeMatch(data, node) {

}
if (this.isUsingRowIds()) {
if (this.getRowIdFunc != null) {
const id = this.getRowId(data);

@@ -383,9 +438,8 @@ return node.id === id;

const [_, lastRowBlockEnd] = this.rowLoader.getBlockBoundsForIndex(lastRow);
this.getNodeMapEntries().forEach(([stringIndex, node]) => {
const numericIndex = Number(stringIndex);
if (this.rowLoader.isRowLoading(numericIndex)) {
this.nodeMap.forEach(lazyNode => {
if (this.rowLoader.isRowLoading(lazyNode.index)) {
return;
}
if (node.stub && (numericIndex < firstRowBlockStart || numericIndex > lastRowBlockEnd)) {
this.destroyRowAtIndex(numericIndex);
if (lazyNode.node.stub && (lazyNode.index < firstRowBlockStart || lazyNode.index > lastRowBlockEnd)) {
this.destroyRowAtIndex(lazyNode.index);
}

@@ -410,4 +464,4 @@ });

const blockDistanceToMiddle = {};
nodes.forEach(([storeIndexString, node]) => {
const [blockStart, blockEnd] = this.rowLoader.getBlockBoundsForIndex(Number(storeIndexString));
nodes.forEach(({ node, index }) => {
const [blockStart, blockEnd] = this.rowLoader.getBlockBoundsForIndex(index);
if (blockStart in blockDistanceToMiddle) {

@@ -419,4 +473,5 @@ return;

// may not have an end node if the block came back small
if (this.nodeIndexMap[blockEnd - 1])
distEnd = Math.abs(this.nodeIndexMap[blockEnd - 1].rowIndex - otherDisplayIndex);
const lastLazyNode = this.nodeMap.getBy('index', [blockEnd - 1]);
if (lastLazyNode)
distEnd = Math.abs(lastLazyNode.node.rowIndex - otherDisplayIndex);
const farthest = distEnd == null || distStart < distEnd ? distStart : distEnd;

@@ -435,3 +490,3 @@ blockDistanceToMiddle[blockStart] = farthest;

// number of blocks to cache on top of the viewport blocks
const numberOfRowsToRetain = this.getNumberOfRowsToRetain(firstRowBlockStart, lastRowBlockEnd);
let numberOfRowsToRetain = this.getNumberOfRowsToRetain(firstRowBlockStart, lastRowBlockEnd);
if (this.store.getDisplayIndexEnd() == null || numberOfRowsToRetain == null) {

@@ -442,3 +497,3 @@ // if group is collapsed, or max blocks missing, ignore the event

// don't check the nodes that could have been cached out of necessity
const disposableNodes = this.getNodeMapEntries().filter(([_, node]) => !node.stub && !this.isNodeCached(node));
const disposableNodes = this.nodeMap.filter(({ node }) => !node.stub && !this.isNodeCached(node));
if (disposableNodes.length <= numberOfRowsToRetain) {

@@ -448,9 +503,9 @@ // not enough rows to bother clearing any

}
const disposableNodesNotInViewport = disposableNodes.filter(([_, node]) => {
const disposableNodesNotInViewport = disposableNodes.filter(({ node }) => {
const startRowNum = node.rowIndex;
if (!startRowNum) {
if (startRowNum == null || startRowNum === -1) {
// row is not displayed and can be disposed
return true;
}
if (firstRowInViewport <= startRowNum && startRowNum <= lastRowInViewport) {
if (firstRowBlockStart <= startRowNum && startRowNum < lastRowBlockEnd) {
// start row in viewport, block is in viewport

@@ -460,7 +515,7 @@ return false;

const lastRowNum = startRowNum + blockSize;
if (firstRowInViewport <= lastRowNum && lastRowNum <= lastRowInViewport) {
if (firstRowBlockStart <= lastRowNum && lastRowNum < lastRowBlockEnd) {
// end row in viewport, block is in viewport
return false;
}
if (startRowNum < firstRowInViewport && lastRowNum > lastRowInViewport) {
if (startRowNum < firstRowBlockStart && lastRowNum >= lastRowBlockEnd) {
// full block surrounds in viewport

@@ -472,2 +527,4 @@ return false;

});
// reduce the number of rows to retain by the number in viewport which were retained
numberOfRowsToRetain = numberOfRowsToRetain - (disposableNodes.length - disposableNodesNotInViewport.length);
if (!disposableNodesNotInViewport.length) {

@@ -485,8 +542,8 @@ return;

blockDistanceArray.sort((a, b) => Math.sign(b[1] - a[1]));
const blocksToRemove = blockDistanceArray.length - numberOfBlocksToRetain;
const blocksToRemove = blockDistanceArray.length - Math.max(numberOfBlocksToRetain, 0);
for (let i = 0; i < blocksToRemove; i++) {
const blockStart = Number(blockDistanceArray[i][0]);
for (let x = blockStart; x < blockStart + blockSize; x++) {
const node = this.nodeIndexMap[x];
if (!node || this.isNodeCached(node)) {
const lazyNode = this.nodeMap.getBy('index', x);
if (!lazyNode || this.isNodeCached(lazyNode.node)) {
continue;

@@ -513,3 +570,3 @@ }

extractDuplicateIds(rows) {
if (!this.isUsingRowIds()) {
if (!this.getRowIdFunc == null) {
return [];

@@ -532,3 +589,3 @@ }

return;
if (this.isUsingRowIds()) {
if (this.getRowIdFunc != null) {
const duplicates = this.extractDuplicateIds(response.rowData);

@@ -542,14 +599,16 @@ if (duplicates.length > 0) {

}
const wasRefreshing = this.nodesToRefresh.size > 0;
response.rowData.forEach((data, responseRowIndex) => {
var _a;
const rowIndex = firstRowIndex + responseRowIndex;
const nodeFromCache = this.nodeIndexMap[rowIndex];
const nodeFromCache = this.nodeMap.getBy('index', rowIndex);
// if stub, overwrite
if (nodeFromCache === null || nodeFromCache === void 0 ? void 0 : nodeFromCache.stub) {
if ((_a = nodeFromCache === null || nodeFromCache === void 0 ? void 0 : nodeFromCache.node) === null || _a === void 0 ? void 0 : _a.stub) {
this.createRowAtIndex(rowIndex, data);
return;
}
if (nodeFromCache && this.doesNodeMatch(data, nodeFromCache)) {
this.blockUtils.updateDataIntoRowNode(nodeFromCache, data);
nodeFromCache.__needsRefresh = false;
nodeFromCache.__needsRefreshWhenVisible = false;
if (nodeFromCache && this.doesNodeMatch(data, nodeFromCache.node)) {
this.blockUtils.updateDataIntoRowNode(nodeFromCache.node, data);
this.nodesToRefresh.delete(nodeFromCache.node);
nodeFromCache.node.__needsRefreshWhenVisible = false;
return;

@@ -560,2 +619,6 @@ }

});
const finishedRefreshing = this.nodesToRefresh.size === 0;
if (wasRefreshing && finishedRefreshing) {
this.fireRefreshFinishedEvent();
}
if (response.rowCount != undefined && response.rowCount !== -1) {

@@ -580,13 +643,15 @@ // if the rowCount has been provided, set the row count

// delete any rows after the last index
const allRows = this.getNodeMapEntries();
for (let i = allRows.length - 1; i >= 0; i--) {
const numericIndex = Number(allRows[i][0]);
if (numericIndex < this.numberOfRows) {
break;
}
this.destroyRowAtIndex(numericIndex);
}
const lazyNodesAfterStoreEnd = this.nodeMap.filter(lazyNode => lazyNode.index >= this.numberOfRows);
lazyNodesAfterStoreEnd.forEach(lazyNode => this.destroyRowAtIndex(lazyNode.index));
}
this.fireStoreUpdatedEvent();
}
fireRefreshFinishedEvent() {
const finishedRefreshing = this.nodesToRefresh.size === 0;
// if anything refreshing currently, skip.
if (!finishedRefreshing) {
return;
}
this.store.fireRefreshFinishedEvent();
}
isLastRowIndexKnown() {

@@ -598,16 +663,22 @@ return this.isLastRowKnown;

return;
for (let i = firstRowIndex; i < firstRowIndex + numberOfRowsExpected; i++) {
const nodeFromCache = this.nodeIndexMap[i];
if (nodeFromCache) {
nodeFromCache.failedLoad = true;
}
}
const failedNodes = this.nodeMap.filter(node => node.index >= firstRowIndex && node.index < firstRowIndex + numberOfRowsExpected);
failedNodes.forEach(node => node.node.failedLoad = true);
this.fireStoreUpdatedEvent();
}
markNodesForRefresh() {
this.getAllNodes().forEach(node => node.__needsRefresh = true);
this.rowLoader.queueLoadAction();
this.nodeMap.forEach(lazyNode => {
if (lazyNode.node.stub) {
return;
}
this.nodesToRefresh.add(lazyNode.node);
});
this.rowLoader.queueLoadCheck();
if (this.isLastRowKnown && this.numberOfRows === 0) {
this.numberOfRows = 1;
this.isLastRowKnown = false;
this.fireStoreUpdatedEvent();
}
}
isNodeInCache(id) {
return this.nodeIds.has(id);
return !!this.nodeMap.getBy('id', id);
}

@@ -621,8 +692,4 @@ // gets called 1) row count changed 2) cache purged 3) items inserted

}
isUsingRowIds() {
return this.gridOptionsService.getRowIdFunc() != null;
}
getRowId(data) {
const getRowIdFunc = this.gridOptionsService.getRowIdFunc();
if (getRowIdFunc == null) {
if (this.getRowIdFunc == null) {
return null;

@@ -633,3 +700,3 @@ }

const parentKeys = this.store.getParentNode().getGroupKeys();
const id = getRowIdFunc({
const id = this.getRowIdFunc({
data,

@@ -641,19 +708,14 @@ parentKeys: parentKeys.length > 0 ? parentKeys : undefined,

}
lookupRowNode(data) {
var _a;
if (!this.isUsingRowIds()) {
updateRowNodes(updates) {
if (this.getRowIdFunc == null) {
// throw error, as this is type checked in the store. User likely abusing internal apis if here.
throw new Error('AG Grid: Insert transactions can only be applied when row ids are supplied.');
}
// find rowNode using id
const id = this.getRowId(data);
return (_a = this.getAllNodes().find(node => node.id === id)) !== null && _a !== void 0 ? _a : null;
}
updateRowNodes(updates) {
const updatedNodes = [];
updates.forEach(data => {
const row = this.lookupRowNode(data);
if (row) {
this.blockUtils.updateDataIntoRowNode(row, data);
updatedNodes.push(row);
const id = this.getRowId(data);
const lazyNode = this.nodeMap.getBy('id', id);
if (lazyNode) {
this.blockUtils.updateDataIntoRowNode(lazyNode.node, data);
updatedNodes.push(lazyNode.node);
}

@@ -670,3 +732,3 @@ });

}
if (!this.isUsingRowIds()) {
if (this.getRowIdFunc == null) {
// throw error, as this is type checked in the store. User likely abusing internal apis if here.

@@ -688,22 +750,13 @@ throw new Error('AG Grid: Insert transactions can only be applied when row ids are supplied.');

}
// first move all the nodes after the addIndex out of the way
const allNodes = this.getNodeMapEntries();
// iterate backwards to avoid overwriting nodes which haven't been shifted yet
for (let i = allNodes.length - 1; i >= 0; i--) {
const [stringStoreIndex, node] = allNodes[i];
const numericStoreIndex = Number(stringStoreIndex);
// nodes should be in order as js maps sort by numeric keys, so if index is too low can stop iterating
if (numericStoreIndex < addIndex) {
break;
}
const newIndex = numericStoreIndex + numberOfInserts;
if (this.getRowByStoreIndex(newIndex)) {
// this shouldn't happen, why would a row already exist here
throw new Error('AG Grid: Something went wrong, node in wrong place.');
}
else {
this.nodeIndexMap[numericStoreIndex + numberOfInserts] = node;
delete this.nodeIndexMap[numericStoreIndex];
}
}
const nodesToMove = this.nodeMap.filter(node => node.index >= addIndex);
// delete all nodes which need moved first, so they don't get overwritten
nodesToMove.forEach(lazyNode => this.nodeMap.delete(lazyNode));
// then move the nodes to their new locations
nodesToMove.forEach(lazyNode => {
this.nodeMap.set({
node: lazyNode.node,
index: lazyNode.index + numberOfInserts,
id: lazyNode.id,
});
});
// increase the store size to accommodate

@@ -714,4 +767,12 @@ this.numberOfRows += numberOfInserts;

}
getOrderedNodeMap() {
const obj = {};
this.nodeMap.forEach(node => obj[node.index] = node);
return obj;
}
clearDisplayIndexes() {
this.nodeDisplayIndexMap.clear();
}
removeRowNodes(idsToRemove) {
if (!this.isUsingRowIds()) {
if (this.getRowIdFunc == null) {
// throw error, as this is type checked in the store. User likely abusing internal apis if here.

@@ -721,9 +782,11 @@ throw new Error('AG Grid: Insert transactions can only be applied when row ids are supplied.');

const removedNodes = [];
const allNodes = this.getNodeMapEntries();
const nodesToVerify = [];
// track how many nodes have been deleted, as when we pass other nodes we need to shift them up
let deletedNodeCount = 0;
const remainingIdsToRemove = [...idsToRemove];
const nodesToVerify = [];
for (let i = 0; i < allNodes.length; i++) {
const [stringStoreIndex, node] = allNodes[i];
const allNodes = this.getOrderedNodeMap();
let contiguousIndex = -1;
for (let stringIndex in allNodes) {
contiguousIndex += 1;
const node = allNodes[stringIndex];
// finding the index allows the use of splice which should be slightly faster than both a check and filter

@@ -734,4 +797,4 @@ const matchIndex = remainingIdsToRemove.findIndex(idToRemove => idToRemove === node.id);

remainingIdsToRemove.splice(matchIndex, 1);
this.destroyRowAtIndex(Number(stringStoreIndex));
removedNodes.push(node);
this.destroyRowAtIndex(Number(stringIndex));
removedNodes.push(node.node);
deletedNodeCount += 1;

@@ -744,9 +807,13 @@ continue;

}
const numericStoreIndex = Number(stringStoreIndex);
if (i !== numericStoreIndex) {
nodesToVerify.push(node);
const numericStoreIndex = Number(stringIndex);
if (contiguousIndex !== numericStoreIndex) {
nodesToVerify.push(node.node);
}
// shift normal node up by number of deleted prior to this point
this.nodeIndexMap[numericStoreIndex - deletedNodeCount] = this.nodeIndexMap[numericStoreIndex];
delete this.nodeIndexMap[numericStoreIndex];
this.nodeMap.delete(allNodes[stringIndex]);
this.nodeMap.set({
id: node.id,
node: node.node,
index: numericStoreIndex - deletedNodeCount,
});
}

@@ -756,3 +823,3 @@ this.numberOfRows -= this.isLastRowIndexKnown() ? idsToRemove.length : deletedNodeCount;

nodesToVerify.forEach(node => node.__needsRefreshWhenVisible = true);
this.rowLoader.queueLoadAction();
this.rowLoader.queueLoadCheck();
}

@@ -759,0 +826,0 @@ return removedNodes;

@@ -74,3 +74,3 @@ import { BeanStub, IServerSideStore, NumberSequence, RowBounds, RowNode, ServerSideGroupLevelParams, ServerSideGroupLevelState, ServerSideTransaction, ServerSideTransactionResult, StoreRefreshAfterParams, Column, IRowNode } from "@ag-grid-community/core";

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeepAfterFilterAndSort
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeepAfterFilterAndSort
*/

@@ -81,3 +81,3 @@ forEachStoreDeep(callback: (store: IServerSideStore, index: number) => void, sequence?: NumberSequence): void;

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeepAfterFilterAndSort
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeepAfterFilterAndSort
*/

@@ -88,3 +88,3 @@ forEachNodeDeep(callback: (rowNode: RowNode<any>, index: number) => void, sequence?: NumberSequence): void;

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeep
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeep
*/

@@ -199,5 +199,10 @@ forEachNodeDeepAfterFilterAndSort(callback: (rowNode: RowNode<any>, index: number) => void, sequence?: NumberSequence): void;

fireStoreUpdatedEvent(): void;
fireRefreshFinishedEvent(): void;
getBlockStates(): {
[key: string]: any;
};
getStoreBounds(): {
topPx: number;
heightPx: number;
};
}

@@ -120,3 +120,4 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {

this.displayIndexEnd = undefined;
this.cache.getAllNodes().forEach(rowNode => this.blockUtils.clearDisplayIndex(rowNode));
this.cache.getNodes().forEach(lazyNode => this.blockUtils.clearDisplayIndex(lazyNode.node));
this.cache.clearDisplayIndexes();
}

@@ -177,8 +178,8 @@ /**

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeepAfterFilterAndSort
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeepAfterFilterAndSort
*/
forEachStoreDeep(callback, sequence = new NumberSequence()) {
callback(this, sequence.next());
this.cache.getAllNodes().forEach(rowNode => {
const childCache = rowNode.childStore;
this.cache.getNodes().forEach(lazyNode => {
const childCache = lazyNode.node.childStore;
if (childCache) {

@@ -192,8 +193,8 @@ childCache.forEachStoreDeep(callback, sequence);

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeepAfterFilterAndSort
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeepAfterFilterAndSort
*/
forEachNodeDeep(callback, sequence = new NumberSequence()) {
this.cache.getAllNodes().forEach(rowNode => {
callback(rowNode, sequence.next());
const childCache = rowNode.childStore;
this.cache.getNodes().forEach(lazyNode => {
callback(lazyNode.node, sequence.next());
const childCache = lazyNode.node.childStore;
if (childCache) {

@@ -207,12 +208,14 @@ childCache.forEachNodeDeep(callback, sequence);

*
* For the purpose of exclusively server side filtered stores, this is the same as forEachNodeDeep
* For the purpose of exclusively server side filtered stores, this is the same as getNodes().forEachDeep
*/
forEachNodeDeepAfterFilterAndSort(callback, sequence = new NumberSequence()) {
this.cache.getAllNodes().forEach(rowNode => {
callback(rowNode, sequence.next());
const childCache = rowNode.childStore;
const orderedNodes = this.cache.getOrderedNodeMap();
for (let key in orderedNodes) {
const lazyNode = orderedNodes[key];
callback(lazyNode.node, sequence.next());
const childCache = lazyNode.node.childStore;
if (childCache) {
childCache.forEachNodeDeepAfterFilterAndSort(callback, sequence);
}
});
}
}

@@ -223,3 +226,3 @@ /**

retryLoads() {
this.cache.getAllNodes().forEach(node => {
this.cache.getNodes().forEach(({ node }) => {
if (node.failedLoad) {

@@ -250,16 +253,14 @@ node.failedLoad = false;

getRowBounds(displayIndex) {
var _a;
if (!this.isDisplayIndexInStore(displayIndex)) {
return null;
}
const allNodes = this.cache.getAllNodes();
let previousNode = null;
let nextNode = null;
for (let i = 0; i < allNodes.length; i++) {
const node = allNodes[i];
if (node.rowIndex > displayIndex) {
nextNode = node;
break;
const thisNode = this.cache.getNodeCachedByDisplayIndex(displayIndex);
if (thisNode) {
const boundsFromRow = this.blockUtils.extractRowBounds(thisNode, displayIndex);
if (boundsFromRow) {
return boundsFromRow;
}
previousNode = node;
}
const { previousNode, nextNode } = (_a = this.cache.getSurroundingNodesByDisplayIndex(displayIndex)) !== null && _a !== void 0 ? _a : {};
// previous node may equal, or catch via detail node or child of group

@@ -311,13 +312,25 @@ if (previousNode) {

}
const allNodes = this.cache.getAllNodes();
let distToPreviousNodeTop = Number.MAX_SAFE_INTEGER;
let previousNode = null;
let distToNextNodeTop = Number.MAX_SAFE_INTEGER;
let nextNode = null;
for (let i = 0; i < allNodes.length; i++) {
const node = allNodes[i];
if (node.rowTop > pixel) {
this.cache.getNodes().forEach(({ node }) => {
const distBetween = Math.abs(pixel - node.rowTop);
// previous node
if (node.rowTop < pixel) {
if (distBetween < distToPreviousNodeTop) {
distToPreviousNodeTop = distBetween;
previousNode = node;
}
return;
}
// next node
if (distBetween < distToNextNodeTop) {
distToNextNodeTop = distBetween;
nextNode = node;
break;
}
previousNode = node;
}
});
// cast these back as typescript doesn't understand the forEach above
previousNode = previousNode;
nextNode = nextNode;
// previous node may equal, or catch via detail node or child of group

@@ -350,4 +363,7 @@ if (previousNode) {

return this.storeUtils.getChildStore(keys, this, (key) => {
const allNodes = this.cache.getAllNodes();
return allNodes.find(currentRowNode => currentRowNode.key == key);
const lazyNode = this.cache.getNodes().find(lazyNode => lazyNode.node.key == key);
if (!lazyNode) {
return null;
}
return lazyNode.node;
});

@@ -361,3 +377,3 @@ }

forEachChildStoreShallow(cb) {
this.cache.getAllNodes().forEach(node => {
this.cache.getNodes().forEach(({ node }) => {
if (node.childStore) {

@@ -451,14 +467,5 @@ cb(node.childStore);

}
this.cache.getAllNodes().forEach(rowNode => {
const hitFirstOrLast = rowNode === firstInRange || rowNode === lastInRange;
if (inActiveRange || hitFirstOrLast) {
result.push(rowNode);
}
if (hitFirstOrLast) {
inActiveRange = !inActiveRange;
}
});
// inActiveRange will be still true if we never hit the second rowNode
const invalidRange = inActiveRange;
return invalidRange ? [] : result;
return this.cache.getNodes().filter(({ node }) => {
return node.rowIndex >= firstInRange.rowIndex && node.rowIndex <= lastInRange.rowIndex;
}).map(({ node }) => node);
}

@@ -513,5 +520,19 @@ /**

}
// gets called when row data updated, and no more refreshing needed
fireRefreshFinishedEvent() {
const event = {
type: Events.EVENT_STORE_REFRESHED,
route: this.parentRowNode.getRoute(),
};
this.eventService.dispatchEvent(event);
}
getBlockStates() {
return this.cache.getBlockStates();
}
getStoreBounds() {
return {
topPx: this.topPx,
heightPx: this.heightPx,
};
}
}

@@ -518,0 +539,0 @@ __decorate([

@@ -18,3 +18,3 @@ import { IServerSideStore, BeanStub, StoreRefreshAfterParams, RowNode, ColumnVO, RowNodeBlock } from "@ag-grid-community/core";

}): void;
getChildStore(keys: string[], currentCache: IServerSideStore, findNodeFunc: (key: string) => RowNode): IServerSideStore | null;
getChildStore(keys: string[], currentCache: IServerSideStore, findNodeFunc: (key: string) => RowNode | null): IServerSideStore | null;
isServerRefreshNeeded(parentRowNode: RowNode, rowGroupCols: ColumnVO[], params: StoreRefreshAfterParams): boolean;

@@ -21,0 +21,0 @@ getServerSideInitialRowCount(): number;

@@ -100,10 +100,2 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {

this.eventService.dispatchEvent({ type: Events.EVENT_STORE_UPDATED });
if (res.update && res.update.length) {
// this set timeout is necessary to queue behind the listener for EVENT_STORE_UPDATED in ssrm which recalculates the rowIndexes
// if the rowIndex isn't calculated first the binarySearchForDisplayIndex will not be able to find the required rows
setTimeout(() => {
// refresh the full width rows
this.rowRenderer.refreshFullWidthRows(res.update);
}, 0);
}
return res;

@@ -110,0 +102,0 @@ }

@@ -1,1 +0,1 @@

export declare const VERSION = "29.2.0";
export declare const VERSION = "29.3.0";
// DO NOT UPDATE MANUALLY: Generated from script during build time
export const VERSION = '29.2.0';
export const VERSION = '29.3.0';
{
"name": "@ag-grid-enterprise/server-side-row-model",
"version": "29.2.0",
"version": "29.3.0",
"description": "Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue",

@@ -50,4 +50,4 @@ "main": "./dist/cjs/es5/main.js",

"dependencies": {
"@ag-grid-community/core": "~29.2.0",
"@ag-grid-enterprise/core": "~29.2.0"
"@ag-grid-community/core": "~29.3.0",
"@ag-grid-enterprise/core": "~29.3.0"
},

@@ -54,0 +54,0 @@ "devDependencies": {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc