fix(connectionPlugin): allow first and last to be zero (#436)
Co-authored-by: Jason Kuhrt <jason.kuhrt@dialogue.co>
This commit is contained in:
parent
bf0df64ebd
commit
5b900b156a
|
|
@ -839,12 +839,12 @@ function defaultPageInfoFromNodes(nodes: any[], args: PaginationArgs) {
|
||||||
function defaultHasNextPage(nodes: any[], args: PaginationArgs) {
|
function defaultHasNextPage(nodes: any[], args: PaginationArgs) {
|
||||||
// If we're paginating forward, and we don't have an "after", we'll assume that we don't have
|
// If we're paginating forward, and we don't have an "after", we'll assume that we don't have
|
||||||
// a previous page, otherwise we will assume we have one, unless the after cursor === "0".
|
// a previous page, otherwise we will assume we have one, unless the after cursor === "0".
|
||||||
if (args.first) {
|
if (typeof args.first === "number") {
|
||||||
return nodes.length >= args.first;
|
return nodes.length >= args.first;
|
||||||
}
|
}
|
||||||
// If we're paginating backward, and there are as many results as we asked for, then we'll assume
|
// If we're paginating backward, and there are as many results as we asked for, then we'll assume
|
||||||
// that we have a previous page
|
// that we have a previous page
|
||||||
if (args.last) {
|
if (typeof args.last === "number") {
|
||||||
if (args.before && args.before !== "0") {
|
if (args.before && args.before !== "0") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -860,7 +860,7 @@ function defaultHasNextPage(nodes: any[], args: PaginationArgs) {
|
||||||
function defaultHasPreviousPage(nodes: any[], args: PaginationArgs) {
|
function defaultHasPreviousPage(nodes: any[], args: PaginationArgs) {
|
||||||
// If we're paginating forward, and we don't have an "after", we'll assume that we don't have
|
// If we're paginating forward, and we don't have an "after", we'll assume that we don't have
|
||||||
// a previous page, otherwise we will assume we have one, unless the after cursor === "0".
|
// a previous page, otherwise we will assume we have one, unless the after cursor === "0".
|
||||||
if (args.first) {
|
if (typeof args.first === "number") {
|
||||||
if (args.after && args.after !== "0") {
|
if (args.after && args.after !== "0") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -868,7 +868,7 @@ function defaultHasPreviousPage(nodes: any[], args: PaginationArgs) {
|
||||||
}
|
}
|
||||||
// If we're paginating backward, and there are as many results as we asked for, then we'll assume
|
// If we're paginating backward, and there are as many results as we asked for, then we'll assume
|
||||||
// that we have a previous page
|
// that we have a previous page
|
||||||
if (args.last) {
|
if (typeof args.last === "number") {
|
||||||
return nodes.length >= args.last;
|
return nodes.length >= args.last;
|
||||||
}
|
}
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
|
|
@ -888,7 +888,7 @@ function defaultCursorFromNode(
|
||||||
let cursorIndex = index;
|
let cursorIndex = index;
|
||||||
// If we're paginating forward, assume we're incrementing from the offset provided via "after",
|
// If we're paginating forward, assume we're incrementing from the offset provided via "after",
|
||||||
// e.g. [0...20] (first: 5, after: "cursor:5") -> [cursor:6, cursor:7, cursor:8, cursor:9, cursor: 10]
|
// e.g. [0...20] (first: 5, after: "cursor:5") -> [cursor:6, cursor:7, cursor:8, cursor:9, cursor: 10]
|
||||||
if (args.first) {
|
if (typeof args.first === "number") {
|
||||||
if (args.after) {
|
if (args.after) {
|
||||||
const offset = parseInt(args.after, 10);
|
const offset = parseInt(args.after, 10);
|
||||||
cursorIndex = offset + index + 1;
|
cursorIndex = offset + index + 1;
|
||||||
|
|
@ -897,7 +897,7 @@ function defaultCursorFromNode(
|
||||||
|
|
||||||
// If we're paginating backward, assume we're working backward from the assumed length
|
// If we're paginating backward, assume we're working backward from the assumed length
|
||||||
// e.g. [0...20] (last: 5, before: "cursor:20") -> [cursor:15, cursor:16, cursor:17, cursor:18, cursor:19]
|
// e.g. [0...20] (last: 5, before: "cursor:20") -> [cursor:15, cursor:16, cursor:17, cursor:18, cursor:19]
|
||||||
if (args.last) {
|
if (typeof args.last === "number") {
|
||||||
if (args.before) {
|
if (args.before) {
|
||||||
const offset = parseInt(args.before, 10);
|
const offset = parseInt(args.before, 10);
|
||||||
cursorIndex = offset - args.last + index;
|
cursorIndex = offset - args.last + index;
|
||||||
|
|
@ -1010,7 +1010,7 @@ function defaultValidateArgs(
|
||||||
args: Record<string, any> = {},
|
args: Record<string, any> = {},
|
||||||
info: GraphQLResolveInfo
|
info: GraphQLResolveInfo
|
||||||
) {
|
) {
|
||||||
if (!args.first && !args.last) {
|
if (!(args.first || args.first === 0) && !(args.last || args.last === 0)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`The ${info.parentType}.${info.fieldName} connection field requires a "first" or "last" argument`
|
`The ${info.parentType}.${info.fieldName} connection field requires a "first" or "last" argument`
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -347,6 +347,50 @@ describe("connectionPlugin", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("default arg validation: allows first to be zero", async () => {
|
||||||
|
const schema = testConnectionSchema({});
|
||||||
|
const result = await execute({
|
||||||
|
schema,
|
||||||
|
document: UsersFieldFirst,
|
||||||
|
variableValues: { first: 0 },
|
||||||
|
});
|
||||||
|
expect(result).toEqual({
|
||||||
|
data: {
|
||||||
|
users: {
|
||||||
|
edges: [],
|
||||||
|
pageInfo: {
|
||||||
|
endCursor: null,
|
||||||
|
hasNextPage: true,
|
||||||
|
hasPreviousPage: false,
|
||||||
|
startCursor: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("default arg validation: allows last to be zero", async () => {
|
||||||
|
const schema = testConnectionSchema({});
|
||||||
|
const result = await execute({
|
||||||
|
schema,
|
||||||
|
document: UsersFieldLast,
|
||||||
|
variableValues: { last: 0 },
|
||||||
|
});
|
||||||
|
expect(result).toEqual({
|
||||||
|
data: {
|
||||||
|
users: {
|
||||||
|
edges: [],
|
||||||
|
pageInfo: {
|
||||||
|
endCursor: null,
|
||||||
|
hasNextPage: false,
|
||||||
|
hasPreviousPage: true,
|
||||||
|
startCursor: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("default arg validation: throws if both first & last are provided", async () => {
|
it("default arg validation: throws if both first & last are provided", async () => {
|
||||||
const schema = testConnectionSchema({});
|
const schema = testConnectionSchema({});
|
||||||
const result = await execute({
|
const result = await execute({
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue