react-relay
Version:
A framework for building GraphQL-driven React applications.
98 lines (86 loc) • 2.42 kB
Flow
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
* @oncall relay
*/
;
import type {Direction, ReaderFragment} from 'relay-runtime';
const invariant = require('invariant');
const {ConnectionInterface, getValueAtPath} = require('relay-runtime');
function getConnectionState(
direction: Direction,
fragmentNode: ReaderFragment,
fragmentData: mixed,
connectionPathInFragmentData: $ReadOnlyArray<string | number>,
): {
cursor: ?string,
hasMore: boolean,
} {
const {
EDGES,
PAGE_INFO,
HAS_NEXT_PAGE,
HAS_PREV_PAGE,
END_CURSOR,
START_CURSOR,
} = ConnectionInterface.get();
const connection = getValueAtPath(fragmentData, connectionPathInFragmentData);
if (connection == null) {
return {cursor: null, hasMore: false};
}
invariant(
typeof connection === 'object',
'Relay: Expected connection in fragment `%s` to have been `null`, or ' +
'a plain object with %s and %s properties. Instead got `%s`.',
fragmentNode.name,
EDGES,
PAGE_INFO,
connection,
);
const edges = connection[EDGES];
const pageInfo = connection[PAGE_INFO];
if (edges == null || pageInfo == null) {
return {cursor: null, hasMore: false};
}
invariant(
Array.isArray(edges),
'Relay: Expected connection in fragment `%s` to have a plural `%s` field. ' +
'Instead got `%s`.',
fragmentNode.name,
EDGES,
edges,
);
invariant(
typeof pageInfo === 'object',
'Relay: Expected connection in fragment `%s` to have a `%s` field. ' +
'Instead got `%s`.',
fragmentNode.name,
PAGE_INFO,
pageInfo,
);
const cursor =
direction === 'forward'
? pageInfo[END_CURSOR] ?? null
: pageInfo[START_CURSOR] ?? null;
invariant(
cursor === null || typeof cursor === 'string',
'Relay: Expected page info for connection in fragment `%s` to have a ' +
'valid `%s`. Instead got `%s`.',
fragmentNode.name,
START_CURSOR,
cursor,
);
let hasMore;
if (direction === 'forward') {
hasMore = cursor != null && pageInfo[HAS_NEXT_PAGE] === true;
} else {
hasMore = cursor != null && pageInfo[HAS_PREV_PAGE] === true;
}
return {cursor, hasMore};
}
module.exports = getConnectionState;