Skip to content

Commit

Permalink
Add RelaySelector helper class, start of updated Environment interface
Browse files Browse the repository at this point in the history
Summary:
Defines the `Selector` interface and implements helpers for converting fragment
props into Selectors. This is a building block for implementing
`FragmentSpecResolver` that will be the foundation of the new container APIs.

As part of making the test work I had to fix an issue with `BabelPluginGraphQL`.
It outputs a root fragment for a query, but this conflicted because the test
schema uses the name "Root" for the query type instead of the defacto standard
"Query". This then necessitated a fix to our validation of the `node` field,
which needed to check that the `node` field was not on the query type.

Reviewed By: wincent

Differential Revision: D4309955

fbshipit-source-id: e97c767dcb37974d3359165f011ff0fe63f87304
  • Loading branch information
josephsavona authored and Facebook Github Bot committed Dec 12, 2016
1 parent 44b24f3 commit 73c100b
Show file tree
Hide file tree
Showing 12 changed files with 1,031 additions and 7 deletions.
2 changes: 1 addition & 1 deletion scripts/babel-relay-plugin/lib/HASH
Original file line number Diff line number Diff line change
@@ -1 +1 @@
rmZo763xq6oGqjdkqeGl1CqgLvU=
SzFLdHGEENZur/dboJUZxgpY5zU=
5 changes: 5 additions & 0 deletions scripts/babel-relay-plugin/lib/RelayQLAST.js
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,11 @@ var RelayQLType = function () {
value: function isNonNull() {
return this.isNonNullType;
}
}, {
key: 'isQueryType',
value: function isQueryType() {
return this.schemaUnmodifiedType === this.context.schema.getQueryType();
}
}, {
key: 'isConnection',
value: function isConnection() {
Expand Down
2 changes: 1 addition & 1 deletion scripts/babel-relay-plugin/lib/RelayQLPrinter.js
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ module.exports = function (t, options) {
if (field.getName() === 'node') {
var argTypes = field.getDeclaredArguments();
var argNames = Object.keys(argTypes);
if (argNames.length === 1 && argNames[0] === ID) {
if (!parentType.isQueryType() && argNames.length === 1 && argNames[0] === ID) {
throw new RelayTransformError(util.format('You defined a `node(%s: %s)` field on type `%s`, but Relay requires ' + 'the `node` field to be defined on the root type. See the Object ' + 'Identification Guide: \n' + 'http://facebook.github.io/relay/docs/graphql-object-identification.html', ID, argNames[0] && argTypes[argNames[0]].getName({ modifiers: true }), parentType.getName({ modifiers: false })), field.getLocation());
}
}
Expand Down
6 changes: 5 additions & 1 deletion scripts/babel-relay-plugin/src/RelayQLAST.js
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,10 @@ class RelayQLType {
return this.isNonNullType;
}

isQueryType(): boolean {
return this.schemaUnmodifiedType === this.context.schema.getQueryType();
}

isConnection(): boolean {
if (!/Connection$/.test(this.getName({modifiers: false}))) {
return false;
Expand Down Expand Up @@ -816,7 +820,7 @@ class RelayQLArgumentType {
this.schemaUnmodifiedArgType === GraphQLID ||
this.schemaUnmodifiedArgType === GraphQLInt ||
this.schemaUnmodifiedArgType === GraphQLString
)
);
}

isEnum(): boolean {
Expand Down
6 changes: 5 additions & 1 deletion scripts/babel-relay-plugin/src/RelayQLPrinter.js
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,11 @@ module.exports = function(t: any, options: PrinterOptions): Function {
if (field.getName() === 'node') {
var argTypes = field.getDeclaredArguments();
var argNames = Object.keys(argTypes);
if (argNames.length === 1 && argNames[0] === ID) {
if (
!parentType.isQueryType() &&
argNames.length === 1 &&
argNames[0] === ID
) {
throw new RelayTransformError(
util.format(
'You defined a `node(%s: %s)` field on type `%s`, but Relay requires ' +
Expand Down
4 changes: 2 additions & 2 deletions scripts/jest/testschema.graphql
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
schema {
query: Root
query: Query
mutation: Mutation
subscription: Subscription
}

type Root {
type Query {
checkinSearchQuery(query: CheckinSearchInput): CheckinSearchResult
defaultSettings: Settings,
route(waypoints: [WayPoint!]!): Route
Expand Down
45 changes: 45 additions & 0 deletions src/environment/RelayEnvironmentTypes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule RelayEnvironmentTypes
* @flow
*/

'use strict';

import type {
ConcreteFragmentDefinition,
} from 'ConcreteQuery';
import type {DataID} from 'RelayInternalTypes';
import type RelayQuery from 'RelayQuery';
import type {Variables} from 'RelayTypes';

/**
* A selector defines the starting point for a traversal into the graph for the
* purposes of targeting a subgraph.
*/
export type Selector = {
dataID: DataID,
node: ConcreteFragmentDefinition,
variables: Variables,
};

/**
* An operation selector describes a specific instance of a GraphQL operation
* with variables applied.
*
* - `fragment`: a selector intended for use in reading or subscribing to
* the results of the the operation.
* - `queries`: an object of queries that can be used to fetch the data for this
* operation.
*/
export type OperationSelector = {
fragment: Selector,
queries: Array<RelayQuery.Root>,
variables: Variables,
};
Loading

0 comments on commit 73c100b

Please sign in to comment.