WIP - add extractor, generate snippet_data
This commit is contained in:
512
node_modules/relay-runtime/lib/RelayConnectionHandler.js
generated
vendored
Normal file
512
node_modules/relay-runtime/lib/RelayConnectionHandler.js
generated
vendored
Normal file
@ -0,0 +1,512 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var CONNECTION = 'connection'; // Per-instance incrementing index used to generate unique edge IDs
|
||||
|
||||
var NEXT_EDGE_INDEX = '__connection_next_edge_index';
|
||||
/**
|
||||
* @public
|
||||
*
|
||||
* A default runtime handler for connection fields that appends newly fetched
|
||||
* edges onto the end of a connection, regardless of the arguments used to fetch
|
||||
* those edges.
|
||||
*/
|
||||
|
||||
function update(store, payload) {
|
||||
var record = store.get(payload.dataID);
|
||||
|
||||
if (!record) {
|
||||
return;
|
||||
}
|
||||
|
||||
var _RelayConnectionInter = require("./RelayConnectionInterface").get(),
|
||||
EDGES = _RelayConnectionInter.EDGES,
|
||||
END_CURSOR = _RelayConnectionInter.END_CURSOR,
|
||||
HAS_NEXT_PAGE = _RelayConnectionInter.HAS_NEXT_PAGE,
|
||||
HAS_PREV_PAGE = _RelayConnectionInter.HAS_PREV_PAGE,
|
||||
PAGE_INFO = _RelayConnectionInter.PAGE_INFO,
|
||||
PAGE_INFO_TYPE = _RelayConnectionInter.PAGE_INFO_TYPE,
|
||||
START_CURSOR = _RelayConnectionInter.START_CURSOR;
|
||||
|
||||
var serverConnection = record.getLinkedRecord(payload.fieldKey);
|
||||
var serverPageInfo = serverConnection && serverConnection.getLinkedRecord(PAGE_INFO);
|
||||
|
||||
if (!serverConnection) {
|
||||
record.setValue(null, payload.handleKey);
|
||||
return;
|
||||
}
|
||||
|
||||
var clientConnection = record.getLinkedRecord(payload.handleKey);
|
||||
var clientPageInfo = clientConnection && clientConnection.getLinkedRecord(PAGE_INFO);
|
||||
|
||||
if (!clientConnection) {
|
||||
// Initial fetch with data: copy fields from the server record
|
||||
var connection = store.create(require("./generateRelayClientID")(record.getDataID(), payload.handleKey), serverConnection.getType());
|
||||
connection.setValue(0, NEXT_EDGE_INDEX);
|
||||
connection.copyFieldsFrom(serverConnection);
|
||||
var serverEdges = serverConnection.getLinkedRecords(EDGES);
|
||||
|
||||
if (serverEdges) {
|
||||
serverEdges = serverEdges.map(function (edge) {
|
||||
return buildConnectionEdge(store, connection, edge);
|
||||
});
|
||||
connection.setLinkedRecords(serverEdges, EDGES);
|
||||
}
|
||||
|
||||
record.setLinkedRecord(connection, payload.handleKey);
|
||||
clientPageInfo = store.create(require("./generateRelayClientID")(connection.getDataID(), PAGE_INFO), PAGE_INFO_TYPE);
|
||||
clientPageInfo.setValue(false, HAS_NEXT_PAGE);
|
||||
clientPageInfo.setValue(false, HAS_PREV_PAGE);
|
||||
clientPageInfo.setValue(null, END_CURSOR);
|
||||
clientPageInfo.setValue(null, START_CURSOR);
|
||||
|
||||
if (serverPageInfo) {
|
||||
clientPageInfo.copyFieldsFrom(serverPageInfo);
|
||||
}
|
||||
|
||||
connection.setLinkedRecord(clientPageInfo, PAGE_INFO);
|
||||
} else {
|
||||
var _connection = clientConnection; // Subsequent fetches:
|
||||
// - updated fields on the connection
|
||||
// - merge prev/next edges, de-duplicating by node id
|
||||
// - synthesize page info fields
|
||||
|
||||
var _serverEdges = serverConnection.getLinkedRecords(EDGES);
|
||||
|
||||
if (_serverEdges) {
|
||||
_serverEdges = _serverEdges.map(function (edge) {
|
||||
return buildConnectionEdge(store, _connection, edge);
|
||||
});
|
||||
}
|
||||
|
||||
var prevEdges = _connection.getLinkedRecords(EDGES);
|
||||
|
||||
var prevPageInfo = _connection.getLinkedRecord(PAGE_INFO);
|
||||
|
||||
_connection.copyFieldsFrom(serverConnection); // Reset EDGES and PAGE_INFO fields
|
||||
|
||||
|
||||
if (prevEdges) {
|
||||
_connection.setLinkedRecords(prevEdges, EDGES);
|
||||
}
|
||||
|
||||
if (prevPageInfo) {
|
||||
_connection.setLinkedRecord(prevPageInfo, PAGE_INFO);
|
||||
}
|
||||
|
||||
var nextEdges = [];
|
||||
var args = payload.args;
|
||||
|
||||
if (prevEdges && _serverEdges) {
|
||||
if (args.after != null) {
|
||||
// Forward pagination from the end of the connection: append edges
|
||||
if (clientPageInfo && args.after === clientPageInfo.getValue(END_CURSOR)) {
|
||||
var nodeIDs = new Set();
|
||||
mergeEdges(prevEdges, nextEdges, nodeIDs);
|
||||
mergeEdges(_serverEdges, nextEdges, nodeIDs);
|
||||
} else {
|
||||
process.env.NODE_ENV !== "production" ? require("fbjs/lib/warning")(false, 'RelayConnectionHandler: Unexpected after cursor `%s`, edges must ' + 'be fetched from the end of the list (`%s`).', args.after, clientPageInfo && clientPageInfo.getValue(END_CURSOR)) : void 0;
|
||||
return;
|
||||
}
|
||||
} else if (args.before != null) {
|
||||
// Backward pagination from the start of the connection: prepend edges
|
||||
if (clientPageInfo && args.before === clientPageInfo.getValue(START_CURSOR)) {
|
||||
var _nodeIDs = new Set();
|
||||
|
||||
mergeEdges(_serverEdges, nextEdges, _nodeIDs);
|
||||
mergeEdges(prevEdges, nextEdges, _nodeIDs);
|
||||
} else {
|
||||
process.env.NODE_ENV !== "production" ? require("fbjs/lib/warning")(false, 'RelayConnectionHandler: Unexpected before cursor `%s`, edges must ' + 'be fetched from the beginning of the list (`%s`).', args.before, clientPageInfo && clientPageInfo.getValue(START_CURSOR)) : void 0;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// The connection was refetched from the beginning/end: replace edges
|
||||
nextEdges = _serverEdges;
|
||||
}
|
||||
} else if (_serverEdges) {
|
||||
nextEdges = _serverEdges;
|
||||
} else {
|
||||
nextEdges = prevEdges;
|
||||
} // Update edges only if they were updated, the null check is
|
||||
// for Flow (prevEdges could be null).
|
||||
|
||||
|
||||
if (nextEdges != null && nextEdges !== prevEdges) {
|
||||
_connection.setLinkedRecords(nextEdges, EDGES);
|
||||
} // Page info should be updated even if no new edge were returned.
|
||||
|
||||
|
||||
if (clientPageInfo && serverPageInfo) {
|
||||
if (args.after == null && args.before == null) {
|
||||
// The connection was refetched from the beginning/end: replace
|
||||
// page_info
|
||||
clientPageInfo.copyFieldsFrom(serverPageInfo);
|
||||
} else if (args.before != null || args.after == null && args.last) {
|
||||
clientPageInfo.setValue(!!serverPageInfo.getValue(HAS_PREV_PAGE), HAS_PREV_PAGE);
|
||||
var startCursor = serverPageInfo.getValue(START_CURSOR);
|
||||
|
||||
if (typeof startCursor === 'string') {
|
||||
clientPageInfo.setValue(startCursor, START_CURSOR);
|
||||
}
|
||||
} else if (args.after != null || args.before == null && args.first) {
|
||||
clientPageInfo.setValue(!!serverPageInfo.getValue(HAS_NEXT_PAGE), HAS_NEXT_PAGE);
|
||||
var endCursor = serverPageInfo.getValue(END_CURSOR);
|
||||
|
||||
if (typeof endCursor === 'string') {
|
||||
clientPageInfo.setValue(endCursor, END_CURSOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @public
|
||||
*
|
||||
* Given a record and the name of the schema field for which a connection was
|
||||
* fetched, returns the linked connection record.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* Given that data has already been fetched on some user `<id>` on the `friends`
|
||||
* field:
|
||||
*
|
||||
* ```
|
||||
* fragment FriendsFragment on User {
|
||||
* friends(first: 10) @connection(key: "FriendsFragment_friends") {
|
||||
* edges {
|
||||
* node {
|
||||
* id
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The `friends` connection record can be accessed with:
|
||||
*
|
||||
* ```
|
||||
* store => {
|
||||
* const user = store.get('<id>');
|
||||
* const friends = RelayConnectionHandler.getConnection(user, 'FriendsFragment_friends');
|
||||
* // Access fields on the connection:
|
||||
* const edges = friends.getLinkedRecords('edges');
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* TODO: t15733312
|
||||
* Currently we haven't run into this case yet, but we need to add a `getConnections`
|
||||
* that returns an array of the connections under the same `key` regardless of the variables.
|
||||
*/
|
||||
|
||||
|
||||
function getConnection(record, key, filters) {
|
||||
var handleKey = require("./getRelayHandleKey")(CONNECTION, key, null);
|
||||
|
||||
return record.getLinkedRecord(handleKey, filters);
|
||||
}
|
||||
/**
|
||||
* @public
|
||||
*
|
||||
* Inserts an edge after the given cursor, or at the end of the list if no
|
||||
* cursor is provided.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* Given that data has already been fetched on some user `<id>` on the `friends`
|
||||
* field:
|
||||
*
|
||||
* ```
|
||||
* fragment FriendsFragment on User {
|
||||
* friends(first: 10) @connection(key: "FriendsFragment_friends") {
|
||||
* edges {
|
||||
* node {
|
||||
* id
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* An edge can be appended with:
|
||||
*
|
||||
* ```
|
||||
* store => {
|
||||
* const user = store.get('<id>');
|
||||
* const friends = RelayConnectionHandler.getConnection(user, 'FriendsFragment_friends');
|
||||
* const edge = store.create('<edge-id>', 'FriendsEdge');
|
||||
* RelayConnectionHandler.insertEdgeAfter(friends, edge);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
|
||||
|
||||
function insertEdgeAfter(record, newEdge, cursor) {
|
||||
var _RelayConnectionInter2 = require("./RelayConnectionInterface").get(),
|
||||
CURSOR = _RelayConnectionInter2.CURSOR,
|
||||
EDGES = _RelayConnectionInter2.EDGES;
|
||||
|
||||
var edges = record.getLinkedRecords(EDGES);
|
||||
|
||||
if (!edges) {
|
||||
record.setLinkedRecords([newEdge], EDGES);
|
||||
return;
|
||||
}
|
||||
|
||||
var nextEdges;
|
||||
|
||||
if (cursor == null) {
|
||||
nextEdges = edges.concat(newEdge);
|
||||
} else {
|
||||
nextEdges = [];
|
||||
var foundCursor = false;
|
||||
|
||||
for (var ii = 0; ii < edges.length; ii++) {
|
||||
var edge = edges[ii];
|
||||
nextEdges.push(edge);
|
||||
|
||||
if (edge == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var edgeCursor = edge.getValue(CURSOR);
|
||||
|
||||
if (cursor === edgeCursor) {
|
||||
nextEdges.push(newEdge);
|
||||
foundCursor = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundCursor) {
|
||||
nextEdges.push(newEdge);
|
||||
}
|
||||
}
|
||||
|
||||
record.setLinkedRecords(nextEdges, EDGES);
|
||||
}
|
||||
/**
|
||||
* @public
|
||||
*
|
||||
* Creates an edge for a connection record, given a node and edge type.
|
||||
*/
|
||||
|
||||
|
||||
function createEdge(store, record, node, edgeType) {
|
||||
var _RelayConnectionInter3 = require("./RelayConnectionInterface").get(),
|
||||
NODE = _RelayConnectionInter3.NODE; // An index-based client ID could easily conflict (unless it was
|
||||
// auto-incrementing, but there is nowhere to the store the id)
|
||||
// Instead, construct a client ID based on the connection ID and node ID,
|
||||
// which will only conflict if the same node is added to the same connection
|
||||
// twice. This is acceptable since the `insertEdge*` functions ignore
|
||||
// duplicates.
|
||||
|
||||
|
||||
var edgeID = require("./generateRelayClientID")(record.getDataID(), node.getDataID());
|
||||
|
||||
var edge = store.get(edgeID);
|
||||
|
||||
if (!edge) {
|
||||
edge = store.create(edgeID, edgeType);
|
||||
}
|
||||
|
||||
edge.setLinkedRecord(node, NODE);
|
||||
return edge;
|
||||
}
|
||||
/**
|
||||
* @public
|
||||
*
|
||||
* Inserts an edge before the given cursor, or at the beginning of the list if
|
||||
* no cursor is provided.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* Given that data has already been fetched on some user `<id>` on the `friends`
|
||||
* field:
|
||||
*
|
||||
* ```
|
||||
* fragment FriendsFragment on User {
|
||||
* friends(first: 10) @connection(key: "FriendsFragment_friends") {
|
||||
* edges {
|
||||
* node {
|
||||
* id
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* An edge can be prepended with:
|
||||
*
|
||||
* ```
|
||||
* store => {
|
||||
* const user = store.get('<id>');
|
||||
* const friends = RelayConnectionHandler.getConnection(user, 'FriendsFragment_friends');
|
||||
* const edge = store.create('<edge-id>', 'FriendsEdge');
|
||||
* RelayConnectionHandler.insertEdgeBefore(friends, edge);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
|
||||
|
||||
function insertEdgeBefore(record, newEdge, cursor) {
|
||||
var _RelayConnectionInter4 = require("./RelayConnectionInterface").get(),
|
||||
CURSOR = _RelayConnectionInter4.CURSOR,
|
||||
EDGES = _RelayConnectionInter4.EDGES;
|
||||
|
||||
var edges = record.getLinkedRecords(EDGES);
|
||||
|
||||
if (!edges) {
|
||||
record.setLinkedRecords([newEdge], EDGES);
|
||||
return;
|
||||
}
|
||||
|
||||
var nextEdges;
|
||||
|
||||
if (cursor == null) {
|
||||
nextEdges = [newEdge].concat(edges);
|
||||
} else {
|
||||
nextEdges = [];
|
||||
var foundCursor = false;
|
||||
|
||||
for (var ii = 0; ii < edges.length; ii++) {
|
||||
var edge = edges[ii];
|
||||
|
||||
if (edge != null) {
|
||||
var edgeCursor = edge.getValue(CURSOR);
|
||||
|
||||
if (cursor === edgeCursor) {
|
||||
nextEdges.push(newEdge);
|
||||
foundCursor = true;
|
||||
}
|
||||
}
|
||||
|
||||
nextEdges.push(edge);
|
||||
}
|
||||
|
||||
if (!foundCursor) {
|
||||
nextEdges.unshift(newEdge);
|
||||
}
|
||||
}
|
||||
|
||||
record.setLinkedRecords(nextEdges, EDGES);
|
||||
}
|
||||
/**
|
||||
* @public
|
||||
*
|
||||
* Remove any edges whose `node.id` matches the given id.
|
||||
*/
|
||||
|
||||
|
||||
function deleteNode(record, nodeID) {
|
||||
var _RelayConnectionInter5 = require("./RelayConnectionInterface").get(),
|
||||
EDGES = _RelayConnectionInter5.EDGES,
|
||||
NODE = _RelayConnectionInter5.NODE;
|
||||
|
||||
var edges = record.getLinkedRecords(EDGES);
|
||||
|
||||
if (!edges) {
|
||||
return;
|
||||
}
|
||||
|
||||
var nextEdges;
|
||||
|
||||
for (var ii = 0; ii < edges.length; ii++) {
|
||||
var edge = edges[ii];
|
||||
var node = edge && edge.getLinkedRecord(NODE);
|
||||
|
||||
if (node != null && node.getDataID() === nodeID) {
|
||||
if (nextEdges === undefined) {
|
||||
nextEdges = edges.slice(0, ii);
|
||||
}
|
||||
} else if (nextEdges !== undefined) {
|
||||
nextEdges.push(edge);
|
||||
}
|
||||
}
|
||||
|
||||
if (nextEdges !== undefined) {
|
||||
record.setLinkedRecords(nextEdges, EDGES);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* Creates a copy of an edge with a unique ID based on per-connection-instance
|
||||
* incrementing edge index. This is necessary to avoid collisions between edges,
|
||||
* which can occur because (edge) client IDs are assigned deterministically
|
||||
* based on the path from the nearest node with an id.
|
||||
*
|
||||
* Example: if the first N edges of the same connection are refetched, the edges
|
||||
* from the second fetch will be assigned the same IDs as the first fetch, even
|
||||
* though the nodes they point to may be different (or the same and in different
|
||||
* order).
|
||||
*/
|
||||
|
||||
|
||||
function buildConnectionEdge(store, connection, edge) {
|
||||
if (edge == null) {
|
||||
return edge;
|
||||
}
|
||||
|
||||
var _RelayConnectionInter6 = require("./RelayConnectionInterface").get(),
|
||||
EDGES = _RelayConnectionInter6.EDGES;
|
||||
|
||||
var edgeIndex = connection.getValue(NEXT_EDGE_INDEX);
|
||||
!(typeof edgeIndex === 'number') ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'RelayConnectionHandler: Expected %s to be a number, got `%s`.', NEXT_EDGE_INDEX, edgeIndex) : require("fbjs/lib/invariant")(false) : void 0;
|
||||
|
||||
var edgeID = require("./generateRelayClientID")(connection.getDataID(), EDGES, edgeIndex);
|
||||
|
||||
var connectionEdge = store.create(edgeID, edge.getType());
|
||||
connectionEdge.copyFieldsFrom(edge);
|
||||
connection.setValue(edgeIndex + 1, NEXT_EDGE_INDEX);
|
||||
return connectionEdge;
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* Adds the source edges to the target edges, skipping edges with
|
||||
* duplicate node ids.
|
||||
*/
|
||||
|
||||
|
||||
function mergeEdges(sourceEdges, targetEdges, nodeIDs) {
|
||||
var _RelayConnectionInter7 = require("./RelayConnectionInterface").get(),
|
||||
NODE = _RelayConnectionInter7.NODE;
|
||||
|
||||
for (var ii = 0; ii < sourceEdges.length; ii++) {
|
||||
var edge = sourceEdges[ii];
|
||||
|
||||
if (!edge) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var node = edge.getLinkedRecord(NODE);
|
||||
var nodeID = node && node.getValue('id');
|
||||
|
||||
if (nodeID) {
|
||||
if (nodeIDs.has(nodeID)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nodeIDs.add(nodeID);
|
||||
}
|
||||
|
||||
targetEdges.push(edge);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
buildConnectionEdge: buildConnectionEdge,
|
||||
createEdge: createEdge,
|
||||
deleteNode: deleteNode,
|
||||
getConnection: getConnection,
|
||||
insertEdgeAfter: insertEdgeAfter,
|
||||
insertEdgeBefore: insertEdgeBefore,
|
||||
update: update
|
||||
};
|
||||
Reference in New Issue
Block a user