Skip to content

Commit

Permalink
Merge pull request #185 from josephsavona/babel-plugin-generalize-nod…
Browse files Browse the repository at this point in the history
…es-warning

babel-relay-plugin: generalize warning about `nodes` fields
  • Loading branch information
josephsavona committed Aug 28, 2015
2 parents 1314b71 + e41cac7 commit ecc163a
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 18 deletions.
2 changes: 1 addition & 1 deletion scripts/babel-relay-plugin/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "babel-relay-plugin",
"version": "0.1.3",
"version": "0.2.0",
"description": "Babel Relay Plugin for transpiling GraphQL queries for use with Relay.",
"license": "BSD-3-Clause",
"repository": "facebook/relay",
Expand Down
49 changes: 32 additions & 17 deletions scripts/babel-relay-plugin/src/GraphQLPrinter.js
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,8 @@ function printField(
metadata.pk = 'id';
}

if (isConnection(options.schema, fieldDecl)) {
var connectionMetadata = getConnectionMetadata(options.schema, fieldDecl);
if (connectionMetadata) {
metadata.connection = true;

if (!getArgNamed(fieldDecl, 'find')) {
Expand All @@ -387,16 +388,23 @@ function printField(
var selections = getSelections(field);
selections.forEach(function(subfield) {
var subfieldName = getName(subfield);
if (subfieldName === 'nodes') {
var subfieldDecl =
types.getNamedType(fieldDecl.type).getFields()[subfieldName];
var subfieldType = types.getNamedType(subfieldDecl.type);
if (subfieldName === 'edges') {
hasEdgesSelection = true;
} else if (
isList(subfieldDecl.type) &&
subfieldType.name === connectionMetadata.nodeType.name
) {
// Detect eg `nodes{...}` instead of `edges{node{...}}`
throw new Error(util.format(
'Unsupported "nodes" field on connection, `%s`. Instead, use ' +
'"edges{node{...}}".',
'Unsupported `%s{...}` field on connection `%s`. Use ' +
'`edges{node{...}}` instead.',
subfieldName,
fieldName
));
}
if (subfieldName === 'edges') {
hasEdgesSelection = true;
}
});
if (hasEdgesSelection && !!fieldDecl.type.getFields()['pageInfo']) {
subRequisiteFields.pageInfo = true;
Expand Down Expand Up @@ -647,46 +655,53 @@ function getArgNamed(field, name) {
return remaining.length === 1 ? remaining[0] : null;
}

function isConnection(schema, fieldDecl) {
function getConnectionMetadata(schema, fieldDecl) {
if (!isConnectionType(fieldDecl.type)) {
return false;
return null;
}
// Connections must be limitable.
if (!getArgNamed(fieldDecl, 'first') && !getArgNamed(fieldDecl, 'last')) {
return false;
return null;
}
var fieldType = types.getNamedType(fieldDecl.type);

// Connections must have a non-scalar `edges` field.
var edgesField = fieldType.getFields()['edges'];
if (!edgesField) {
return false;
return null;
}
var edgesType = types.getNamedType(edgesField.type);
if (edgesType instanceof types.GraphQLScalarType) {
return false;
return null;
}

// Connections' `edges` field must have a non-scalar `node` field.
var edgesType = types.getNamedType(edgesField.type);
var nodeField = edgesType.getFields()['node'];
if (!nodeField) {
return false;
return null;
}
var nodeType = types.getNamedType(nodeField.type);
if (nodeType instanceof types.GraphQLScalarType) {
return false;
return null;
}
// Connections' `edges` field must have a scalar `cursor` field.
var cursorField = edgesType.getFields()['cursor'];
if (!cursorField) {
return false;
return null;
}
var cursorType = types.getNamedType(cursorField.type);
if (!(cursorType instanceof types.GraphQLScalarType)) {
return false;
return null;
}
return true;
return {
cursorType,
cursorField,
edgesType,
edgesField,
nodeType,
nodeField,
};
}

function trimArray(arr) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Input:
var Relay = require('react-relay');
var x = Relay.QL`
query {
node(id: 123) {
friends(first: 3) {
nodes {
id
}
}
}
}
`;

Output:
var Relay = require('react-relay');
var x = (function () {
throw new Error('Encountered a GraphQL validation error processing file `connectionWithNodesField.fixture`. Check your terminal for details.');
})();
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ type PendingPost {
type UserConnection {
count: Int
edges: [UserConnectionEdge]
nodes: [User]
pageInfo: PageInfo
}

Expand Down
16 changes: 16 additions & 0 deletions scripts/babel-relay-plugin/src/__tests__/testschema.rfc.json
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,22 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "nodes",
"description": null,
"args": [],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "User",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "pageInfo",
"description": null,
Expand Down

0 comments on commit ecc163a

Please sign in to comment.