Skip to content

Commit

Permalink
babel-relay-plugin: disallow before/first after/last; inline actual e…
Browse files Browse the repository at this point in the history
…rrors

Summary: Makes the use of `field(before: .., first: ..)` or after/last an error. This combination is only supported when generated by Relay during the diffing process.

Also, the previous version replaced invalid GraphQL templates with a function that throws - while I was at it, I changed this to include the actual validation error message.

Addresses #247
Closes #252

Reviewed By: @yuzhi

Differential Revision: D2419715
  • Loading branch information
josephsavona authored and facebook-github-bot-3 committed Sep 9, 2015
1 parent a2336ba commit f679656
Show file tree
Hide file tree
Showing 10 changed files with 206 additions and 12 deletions.
30 changes: 28 additions & 2 deletions scripts/babel-relay-plugin/src/GraphQLPrinter.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ function getFragmentCode(fragment, options) {
function printQuery(query, options) {
var selections = getSelections(query);
if (selections.length !== 1) {
throw new Error('expected only single top level query');
throw new Error('Expected only single top level query');
}

// Validate the name of the root call. Throws if it doesn't exist.
Expand Down Expand Up @@ -164,7 +164,7 @@ function printQuery(query, options) {
function printOperation(operation, options) {
var selections = getSelections(operation);
if (selections.length !== 1) {
throw new Error('expected only single top level field on operation');
throw new Error('Expected only single top level field on operation');
}
var rootField = selections[0];

Expand Down Expand Up @@ -384,6 +384,23 @@ function printField(
metadata.nonFindable = true;
}

if (hasArgument(field, 'first') && hasArgument(field, 'before')) {
throw new Error(util.format(
'Connections arguments `%s(before: <cursor>, first: <count>)` are ' +
'not supported. Use `(first: <count>)` or ' +
'`(after: <cursor>, first: <count>)`. ',
fieldName
));
}
if (hasArgument(field, 'last') && hasArgument(field, 'after')) {
throw new Error(util.format(
'Connections arguments `%s(after: <cursor>, last: <count>)` are ' +
'not supported. Use `(last: <count>)` or ' +
'`(before: <cursor>, last: <count>)`. ',
fieldName
));
}

var hasEdgesSelection = false;
var selections = getSelections(field);
selections.forEach(function(subfield) {
Expand Down Expand Up @@ -743,4 +760,13 @@ function getSelections(node) {
return [];
}

function hasArgument(field, argumentName) {
for (var ix = 0; ix < field.arguments.length; ix++) {
if (getName(field.arguments[ix]) === argumentName) {
return true;
}
}
return false;
}

module.exports = GraphQLPrinter;
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ var foo = Relay.QL`

Output:
var foo = (function () {
throw new Error("Encountered a GraphQL validation error processing file `callInvalidValues.fixture`. Check your terminal for details.");
throw new Error("GraphQL validation/transform error ``Argument \"first\" expected type \"Int\" but got: \"10\". Argument \"orderby\" expected type \"[String]\" but got: Name. Argument \"find\" expected type \"String\" but got: cursor1. Argument \"isViewerFriend\" expected type \"Boolean\" but got: \"true\". Argument \"gender\" expected type \"Gender\" but got: \"MALE\".`` in file `callInvalidValues.fixture`.");
})();
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Input:
var Relay = require('react-relay');
var x = Relay.QL`
query {
node(id: 123) {
friends(last: 3, after: "foo") {
edges {
node {
id
}
}
}
}
}
`;

Output:
var Relay = require('react-relay');
var x = (function () {
throw new Error('GraphQL validation/transform error ``Connections arguments `friends(after: <cursor>, last: <count>)` are not supported. Use `(last: <count>)` or `(before: <cursor>, last: <count>)`. `` in file `connectionWithAfterLastCalls.fixture`.');
})();
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Input:
var Relay = require('react-relay');
var x = Relay.QL`
query {
node(id: 123) {
friends(first: 3, before: "foo") {
edges {
node {
id
}
}
}
}
}
`;

Output:
var Relay = require('react-relay');
var x = (function () {
throw new Error('GraphQL validation/transform error ``Connections arguments `friends(before: <cursor>, first: <count>)` are not supported. Use `(first: <count>)` or `(after: <cursor>, first: <count>)`. `` in file `connectionWithBeforeFirstCalls.fixture`.');
})();
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ var x = Relay.QL`
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.');
throw new Error('GraphQL validation/transform error ``Unsupported `nodes{...}` field on connection `friends`. Use `edges{node{...}}` instead.`` in file `connectionWithNodesField.fixture`.');
})();
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ var x = Relay.QL`fragment on NotAType{id}`;
Output:
var Relay = require('react-relay');
var x = (function () {
throw new Error('Encountered a GraphQL validation error processing file `fragmentOnBadType.fixture`. Check your terminal for details.');
throw new Error('GraphQL validation/transform error ``Unknown type "NotAType".`` in file `fragmentOnBadType.fixture`.');
})();
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ var x = Relay.QL`
Output:
var Relay = require('react-relay');
var x = (function () {
throw new Error('Encountered a GraphQL validation error processing file `nonExistantMutation.fixture`. Check your terminal for details.');
throw new Error('GraphQL validation/transform error ``Cannot query field "fakeMutation" on "Mutation".`` in file `nonExistantMutation.fixture`.');
})();
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ type NewsFeedConnectionEdge {
}

type Story implements Node {
friends(first: Int, orderby: [String], find: String, isViewerFriend: Boolean, gender: Gender): UserConnection
friends(first: Int, last: Int, orderby: [String], find: String, isViewerFriend: Boolean, gender: Gender, before: String, after: String): UserConnection
id: String
name: String
profilePicture(size: Int): ProfilePicture
Expand Down Expand Up @@ -100,15 +100,15 @@ type UserConnectionEdge {
}

interface Node {
friends(first: Int, orderby: [String], find: String, isViewerFriend: Boolean, gender: Gender): UserConnection
friends(first: Int, last: Int, orderby: [String], find: String, isViewerFriend: Boolean, gender: Gender, before: String, after: String): UserConnection
id: String
name: String
profilePicture(size: Int): ProfilePicture
websites: [String]
}

type User implements Node {
friends(first: Int, orderby: [String], find: String, isViewerFriend: Boolean, gender: Gender): UserConnection
friends(first: Int, last: Int, orderby: [String], find: String, isViewerFriend: Boolean, gender: Gender, before: String, after: String): UserConnection
id: String
name: String
profilePicture(size: Int): ProfilePicture
Expand All @@ -129,7 +129,7 @@ type FakeEdge {
}

type FakeNode implements Node {
friends(first: Int, orderby: [String], find: String, isViewerFriend: Boolean, gender: Gender): UserConnection
friends(first: Int, last: Int, orderby: [String], find: String, isViewerFriend: Boolean, gender: Gender, before: String, after: String): UserConnection
id: String
name: String
profilePicture(size: Int): ProfilePicture
Expand Down
120 changes: 120 additions & 0 deletions scripts/babel-relay-plugin/src/__tests__/testschema.rfc.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,16 @@
},
"defaultValue": null
},
{
"name": "last",
"description": null,
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "orderby",
"description": null,
Expand Down Expand Up @@ -184,6 +194,26 @@
"ofType": null
},
"defaultValue": null
},
{
"name": "before",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "after",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"type": {
Expand Down Expand Up @@ -298,6 +328,16 @@
},
"defaultValue": null
},
{
"name": "last",
"description": null,
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "orderby",
"description": null,
Expand Down Expand Up @@ -341,6 +381,26 @@
"ofType": null
},
"defaultValue": null
},
{
"name": "before",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "after",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"type": {
Expand Down Expand Up @@ -608,6 +668,16 @@
},
"defaultValue": null
},
{
"name": "last",
"description": null,
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "orderby",
"description": null,
Expand Down Expand Up @@ -651,6 +721,26 @@
"ofType": null
},
"defaultValue": null
},
{
"name": "before",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "after",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"type": {
Expand Down Expand Up @@ -933,6 +1023,16 @@
},
"defaultValue": null
},
{
"name": "last",
"description": null,
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "orderby",
"description": null,
Expand Down Expand Up @@ -976,6 +1076,26 @@
"ofType": null
},
"defaultValue": null
},
{
"name": "before",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "after",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"type": {
Expand Down
10 changes: 8 additions & 2 deletions scripts/babel-relay-plugin/src/getBabelRelayPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,12 @@ function getBabelRelayPlugin(
var filename = state.opts.filename || 'UnknownFile';
var sourceText = error.sourceText;
var validationErrors = error.validationErrors;
var errorMessages;
if (validationErrors && sourceText) {
var sourceLines = sourceText.split('\n');
validationErrors.forEach(function(validationError) {
errorMessages = errorMessages || [];
errorMessages.push(validationError.message);
console.warn(
'\n-- GraphQL Validation Error -- %s --\n',
path.basename(filename)
Expand All @@ -159,6 +162,7 @@ function getBabelRelayPlugin(
});
});
} else {
errorMessages = [error.message];
console.warn(
'\n-- Relay Transform Error -- %s --\n',
path.basename(filename)
Expand All @@ -170,9 +174,11 @@ function getBabelRelayPlugin(
}

var message = (
'Encountered a GraphQL validation error processing file `' +
'GraphQL validation/transform error ``' +
errorMessages.join(' ') +
'`` in file `' +
filename +
'`. Check your terminal for details.'
'`.'
);
code = (
'function() { throw new Error(\'' +
Expand Down

0 comments on commit f679656

Please sign in to comment.