You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
9.6 KiB
200 lines
9.6 KiB
import { __assign, __rest as __rest_1, __spreadArray } from "tslib"; |
|
import { __rest } from "tslib"; |
|
import { mergeDeep } from "../common/mergeDeep.js"; |
|
// A very basic pagination field policy that always concatenates new |
|
// results onto the existing array, without examining options.args. |
|
export function concatPagination(keyArgs) { |
|
if (keyArgs === void 0) { keyArgs = false; } |
|
return { |
|
keyArgs: keyArgs, |
|
merge: function (existing, incoming) { |
|
return existing ? __spreadArray(__spreadArray([], existing, true), incoming, true) : incoming; |
|
}, |
|
}; |
|
} |
|
// A basic field policy that uses options.args.{offset,limit} to splice |
|
// the incoming data into the existing array. If your arguments are called |
|
// something different (like args.{start,count}), feel free to copy/paste |
|
// this implementation and make the appropriate changes. |
|
export function offsetLimitPagination(keyArgs) { |
|
if (keyArgs === void 0) { keyArgs = false; } |
|
return { |
|
keyArgs: keyArgs, |
|
merge: function (existing, incoming, _a) { |
|
var args = _a.args; |
|
var merged = existing ? existing.slice(0) : []; |
|
if (incoming) { |
|
if (args) { |
|
// Assume an offset of 0 if args.offset omitted. |
|
var _b = args.offset, offset = _b === void 0 ? 0 : _b; |
|
for (var i = 0; i < incoming.length; ++i) { |
|
merged[offset + i] = incoming[i]; |
|
} |
|
} |
|
else { |
|
// It's unusual (probably a mistake) for a paginated field not |
|
// to receive any arguments, so you might prefer to throw an |
|
// exception here, instead of recovering by appending incoming |
|
// onto the existing array. |
|
merged.push.apply(merged, incoming); |
|
} |
|
} |
|
return merged; |
|
}, |
|
}; |
|
} |
|
// As proof of the flexibility of field policies, this function generates |
|
// one that handles Relay-style pagination, without Apollo Client knowing |
|
// anything about connections, edges, cursors, or pageInfo objects. |
|
export function relayStylePagination(keyArgs) { |
|
if (keyArgs === void 0) { keyArgs = false; } |
|
return { |
|
keyArgs: keyArgs, |
|
read: function (existing, _a) { |
|
var canRead = _a.canRead, readField = _a.readField; |
|
if (!existing) |
|
return existing; |
|
var edges = []; |
|
var firstEdgeCursor = ""; |
|
var lastEdgeCursor = ""; |
|
existing.edges.forEach(function (edge) { |
|
// Edges themselves could be Reference objects, so it's important |
|
// to use readField to access the edge.edge.node property. |
|
if (canRead(readField("node", edge))) { |
|
edges.push(edge); |
|
if (edge.cursor) { |
|
firstEdgeCursor = firstEdgeCursor || edge.cursor || ""; |
|
lastEdgeCursor = edge.cursor || lastEdgeCursor; |
|
} |
|
} |
|
}); |
|
if (edges.length > 1 && firstEdgeCursor === lastEdgeCursor) { |
|
firstEdgeCursor = ""; |
|
} |
|
var _b = existing.pageInfo || {}, startCursor = _b.startCursor, endCursor = _b.endCursor; |
|
return __assign(__assign({}, getExtras(existing)), { edges: edges, pageInfo: __assign(__assign({}, existing.pageInfo), { |
|
// If existing.pageInfo.{start,end}Cursor are undefined or "", default |
|
// to firstEdgeCursor and/or lastEdgeCursor. |
|
startCursor: startCursor || firstEdgeCursor, endCursor: endCursor || lastEdgeCursor }) }); |
|
}, |
|
merge: function (existing, incoming, _a) { |
|
var args = _a.args, isReference = _a.isReference, readField = _a.readField; |
|
if (!existing) { |
|
existing = makeEmptyData(); |
|
} |
|
if (!incoming) { |
|
return existing; |
|
} |
|
var incomingEdges = incoming.edges ? |
|
incoming.edges.map(function (edge) { |
|
if (isReference((edge = __assign({}, edge)))) { |
|
// In case edge is a Reference, we read out its cursor field and |
|
// store it as an extra property of the Reference object. |
|
edge.cursor = readField("cursor", edge); |
|
} |
|
return edge; |
|
}) |
|
: []; |
|
if (incoming.pageInfo) { |
|
var pageInfo_1 = incoming.pageInfo; |
|
var startCursor = pageInfo_1.startCursor, endCursor = pageInfo_1.endCursor; |
|
var firstEdge = incomingEdges[0]; |
|
var lastEdge = incomingEdges[incomingEdges.length - 1]; |
|
// In case we did not request the cursor field for edges in this |
|
// query, we can still infer cursors from pageInfo. |
|
if (firstEdge && startCursor) { |
|
firstEdge.cursor = startCursor; |
|
} |
|
if (lastEdge && endCursor) { |
|
lastEdge.cursor = endCursor; |
|
} |
|
// Cursors can also come from edges, so we default |
|
// pageInfo.{start,end}Cursor to {first,last}Edge.cursor. |
|
var firstCursor = firstEdge && firstEdge.cursor; |
|
if (firstCursor && !startCursor) { |
|
incoming = mergeDeep(incoming, { |
|
pageInfo: { |
|
startCursor: firstCursor, |
|
}, |
|
}); |
|
} |
|
var lastCursor = lastEdge && lastEdge.cursor; |
|
if (lastCursor && !endCursor) { |
|
incoming = mergeDeep(incoming, { |
|
pageInfo: { |
|
endCursor: lastCursor, |
|
}, |
|
}); |
|
} |
|
} |
|
var prefix = existing.edges; |
|
var suffix = []; |
|
if (args && args.after) { |
|
// This comparison does not need to use readField("cursor", edge), |
|
// because we stored the cursor field of any Reference edges as an |
|
// extra property of the Reference object. |
|
var index = prefix.findIndex(function (edge) { return edge.cursor === args.after; }); |
|
if (index >= 0) { |
|
prefix = prefix.slice(0, index + 1); |
|
// suffix = []; // already true |
|
} |
|
} |
|
else if (args && args.before) { |
|
var index = prefix.findIndex(function (edge) { return edge.cursor === args.before; }); |
|
suffix = index < 0 ? prefix : prefix.slice(index); |
|
prefix = []; |
|
} |
|
else if (incoming.edges) { |
|
// If we have neither args.after nor args.before, the incoming |
|
// edges cannot be spliced into the existing edges, so they must |
|
// replace the existing edges. See #6592 for a motivating example. |
|
prefix = []; |
|
} |
|
var edges = __spreadArray(__spreadArray(__spreadArray([], prefix, true), incomingEdges, true), suffix, true); |
|
var pageInfo = __assign(__assign({}, incoming.pageInfo), existing.pageInfo); |
|
if (incoming.pageInfo) { |
|
var _b = incoming.pageInfo, hasPreviousPage = _b.hasPreviousPage, hasNextPage = _b.hasNextPage, startCursor = _b.startCursor, endCursor = _b.endCursor, extras = __rest_1(_b, ["hasPreviousPage", "hasNextPage", "startCursor", "endCursor"]); |
|
// If incoming.pageInfo had any extra non-standard properties, |
|
// assume they should take precedence over any existing properties |
|
// of the same name, regardless of where this page falls with |
|
// respect to the existing data. |
|
Object.assign(pageInfo, extras); |
|
// Keep existing.pageInfo.has{Previous,Next}Page unless the |
|
// placement of the incoming edges means incoming.hasPreviousPage |
|
// or incoming.hasNextPage should become the new values for those |
|
// properties in existing.pageInfo. Note that these updates are |
|
// only permitted when the beginning or end of the incoming page |
|
// coincides with the beginning or end of the existing data, as |
|
// determined using prefix.length and suffix.length. |
|
if (!prefix.length) { |
|
if (void 0 !== hasPreviousPage) |
|
pageInfo.hasPreviousPage = hasPreviousPage; |
|
if (void 0 !== startCursor) |
|
pageInfo.startCursor = startCursor; |
|
} |
|
if (!suffix.length) { |
|
if (void 0 !== hasNextPage) |
|
pageInfo.hasNextPage = hasNextPage; |
|
if (void 0 !== endCursor) |
|
pageInfo.endCursor = endCursor; |
|
} |
|
} |
|
return __assign(__assign(__assign({}, getExtras(existing)), getExtras(incoming)), { edges: edges, pageInfo: pageInfo }); |
|
}, |
|
}; |
|
} |
|
// Returns any unrecognized properties of the given object. |
|
var getExtras = function (obj) { return __rest(obj, notExtras); }; |
|
var notExtras = ["edges", "pageInfo"]; |
|
function makeEmptyData() { |
|
return { |
|
edges: [], |
|
pageInfo: { |
|
hasPreviousPage: false, |
|
hasNextPage: true, |
|
startCursor: "", |
|
endCursor: "", |
|
}, |
|
}; |
|
} |
|
//# sourceMappingURL=pagination.js.map
|