redux-devtools/packages/react-json-tree/src/getCollectionEntries.ts
renovate[bot] 7e4cea6fa9
chore(deps): update typescript-eslint monorepo to v5 (major) (#907)
* chore(deps): update typescript-eslint monorepo to v5

* Update

Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Nathan Bierema <nbierema@gmail.com>
2021-10-21 19:08:35 +00:00

147 lines
3.4 KiB
TypeScript

function getLength(type: string, collection: any) {
if (type === 'Object') {
// eslint-disable-next-line @typescript-eslint/ban-types
return Object.keys(collection as {}).length;
} else if (type === 'Array') {
return (collection as unknown[]).length;
}
return Infinity;
}
function isIterableMap(collection: any) {
return typeof (collection as Map<any, any>).set === 'function';
}
function getEntries(
type: string,
collection: any,
sortObjectKeys?: ((a: any, b: any) => number) | boolean | undefined,
from = 0,
to = Infinity
): { entries: { key: string | number; value: any }[]; hasMore?: boolean } {
let res;
if (type === 'Object') {
let keys = Object.getOwnPropertyNames(collection);
if (sortObjectKeys) {
keys.sort(sortObjectKeys === true ? undefined : sortObjectKeys);
}
keys = keys.slice(from, to + 1);
res = {
entries: keys.map((key) => ({ key, value: collection[key] })),
};
} else if (type === 'Array') {
res = {
entries: collection
.slice(from, to + 1)
.map((val: unknown, idx: number) => ({ key: idx + from, value: val })),
};
} else {
let idx = 0;
const entries = [];
let done = true;
const isMap = isIterableMap(collection);
for (const item of collection) {
if (idx > to) {
done = false;
break;
}
if (from <= idx) {
if (isMap && Array.isArray(item)) {
if (typeof item[0] === 'string' || typeof item[0] === 'number') {
entries.push({ key: item[0], value: item[1] });
} else {
entries.push({
key: `[entry ${idx}]`,
value: {
'[key]': item[0],
'[value]': item[1],
},
});
}
} else {
entries.push({ key: idx, value: item });
}
}
idx++;
}
res = {
hasMore: !done,
entries,
};
}
return res;
}
function getRanges(from: number, to: number, limit: number) {
const ranges = [];
while (to - from > limit * limit) {
limit = limit * limit;
}
for (let i = from; i <= to; i += limit) {
ranges.push({ from: i, to: Math.min(to, i + limit - 1) });
}
return ranges;
}
export default function getCollectionEntries(
type: string,
collection: any,
sortObjectKeys: ((a: any, b: any) => number) | boolean | undefined,
limit: number,
from = 0,
to = Infinity
) {
const getEntriesBound = getEntries.bind(
null,
type,
collection,
sortObjectKeys
);
if (!limit) {
return getEntriesBound().entries;
}
const isSubset = to < Infinity;
const length = Math.min(to - from, getLength(type, collection));
if (type !== 'Iterable') {
if (length <= limit || limit < 7) {
return getEntriesBound(from, to).entries;
}
} else {
if (length <= limit && !isSubset) {
return getEntriesBound(from, to).entries;
}
}
let limitedEntries;
if (type === 'Iterable') {
const { hasMore, entries } = getEntriesBound(from, from + limit - 1);
limitedEntries = hasMore
? [...entries, ...getRanges(from + limit, from + 2 * limit - 1, limit)]
: entries;
} else {
limitedEntries = isSubset
? getRanges(from, to, limit)
: [
...getEntriesBound(0, limit - 5).entries,
...getRanges(limit - 4, length - 5, limit),
...getEntriesBound(length - 4, length - 1).entries,
];
}
return limitedEntries;
}