From c41956752fec523b4f47c5bc9bd60014a4da98bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eloy=20Dur=C3=A1n?= Date: Tue, 30 Jan 2018 15:29:12 +0100 Subject: [PATCH] [relay] Cleanup of where types are defined and scope tests. --- types/react-relay/compat.d.ts | 3 +- types/react-relay/index.d.ts | 30 +- types/react-relay/test/react-relay-tests.tsx | 284 ++++++++++--------- types/relay-runtime/index.d.ts | 23 +- 4 files changed, 185 insertions(+), 155 deletions(-) diff --git a/types/react-relay/compat.d.ts b/types/react-relay/compat.d.ts index 6c659382af..b74efc4ac2 100644 --- a/types/react-relay/compat.d.ts +++ b/types/react-relay/compat.d.ts @@ -4,14 +4,13 @@ import { RelayPaginationProp as RelayModernPaginationProp, RelayRefetchProp as RelayModernRefetchProp, } from "./index"; +export { ConcreteFragment, ConcreteRequest, ConcreteBatchRequest } from "relay-runtime"; import * as RelayRuntimeTypes from "relay-runtime"; import { RelayEnvironmentInterface } from "./classic"; // ~~~~~~~~~~~~~~~~~~~~~ // Maybe Fix // ~~~~~~~~~~~~~~~~~~~~~ -export type ConcreteFragment = any; -export type ConcreteBatch = any; export type ConcreteFragmentDefinition = object; export type ConcreteOperationDefinition = object; diff --git a/types/react-relay/index.d.ts b/types/react-relay/index.d.ts index 2a36ef4ec4..91a1bbbe1d 100644 --- a/types/react-relay/index.d.ts +++ b/types/react-relay/index.d.ts @@ -11,6 +11,7 @@ export { commitLocalUpdate, commitRelayModernMutation as commitMutation, fetchRelayModernQuery as fetchQuery, + GraphQLTaggedNode, requestRelaySubscription as requestSubscription, } from "relay-runtime"; @@ -20,8 +21,6 @@ import * as RelayRuntimeTypes from "relay-runtime"; // ~~~~~~~~~~~~~~~~~~~~~ // Maybe Fix // ~~~~~~~~~~~~~~~~~~~~~ -export type ConcreteFragment = any; -export type ConcreteBatch = any; export type ConcreteFragmentDefinition = object; export type ConcreteOperationDefinition = object; @@ -39,24 +38,19 @@ export interface RelayProp { export function RelayQL(strings: string[], ...substitutions: any[]): RelayRuntimeTypes.RelayConcreteNode; // ~~~~~~~~~~~~~~~~~~~~~ -// RelayModernGraphQLTag +// ReactRelayTypes // ~~~~~~~~~~~~~~~~~~~~~ export interface GeneratedNodeMap { - [key: string]: GraphQLTaggedNode; + [key: string]: RelayRuntimeTypes.GraphQLTaggedNode; } -export type GraphQLTaggedNode = - | (() => ConcreteFragment | ConcreteBatch) - | { - modern(): ConcreteFragment | ConcreteBatch; - classic(relayQL: typeof RelayQL): ConcreteFragmentDefinition | ConcreteOperationDefinition; - }; + /** * Runtime function to correspond to the `graphql` tagged template function. * All calls to this function should be transformed by the plugin. */ export interface GraphqlInterface { - (strings: string[] | TemplateStringsArray): GraphQLTaggedNode; - experimental(strings: string[] | TemplateStringsArray): GraphQLTaggedNode; + (strings: string[] | TemplateStringsArray): RelayRuntimeTypes.GraphQLTaggedNode; + experimental(strings: string[] | TemplateStringsArray): RelayRuntimeTypes.GraphQLTaggedNode; } export const graphql: GraphqlInterface; @@ -66,7 +60,7 @@ export const graphql: GraphqlInterface; export interface QueryRendererProps { cacheConfig?: RelayRuntimeTypes.CacheConfig; environment: RelayRuntimeTypes.Environment; - query: GraphQLTaggedNode; + query: RelayRuntimeTypes.GraphQLTaggedNode; render(readyState: ReadyState): React.ReactElement | undefined | null; variables: RelayRuntimeTypes.Variables; rerunParamExperimental?: RelayRuntimeTypes.RerunParam; @@ -87,7 +81,7 @@ export class QueryRenderer extends ReactRelayQueryRenderer {} // ~~~~~~~~~~~~~~~~~~~~~ export function createFragmentContainer( Component: React.ComponentType, - fragmentSpec: GraphQLTaggedNode | GeneratedNodeMap + fragmentSpec: RelayRuntimeTypes.GraphQLTaggedNode | GeneratedNodeMap ): React.ComponentType; // ~~~~~~~~~~~~~~~~~~~~~ @@ -130,11 +124,11 @@ export interface ConnectionConfig { paginationInfo: { count: number; cursor?: string }, fragmentVariables: RelayRuntimeTypes.Variables ): RelayRuntimeTypes.Variables; - query: GraphQLTaggedNode; + query: RelayRuntimeTypes.GraphQLTaggedNode; } export function createPaginationContainer( Component: React.ComponentType, - fragmentSpec: GraphQLTaggedNode | GeneratedNodeMap, + fragmentSpec: RelayRuntimeTypes.GraphQLTaggedNode | GeneratedNodeMap, connectionConfig: ConnectionConfig ): React.ComponentType; @@ -157,6 +151,6 @@ export type RelayRefetchProp = RelayProp & { }; export function createRefetchContainer( Component: React.ComponentType, - fragmentSpec: GraphQLTaggedNode | GeneratedNodeMap, - taggedNode: GraphQLTaggedNode + fragmentSpec: RelayRuntimeTypes.GraphQLTaggedNode | GeneratedNodeMap, + taggedNode: RelayRuntimeTypes.GraphQLTaggedNode ): React.ComponentType; diff --git a/types/react-relay/test/react-relay-tests.tsx b/types/react-relay/test/react-relay-tests.tsx index 54a81df1c9..9385922dcf 100644 --- a/types/react-relay/test/react-relay-tests.tsx +++ b/types/react-relay/test/react-relay-tests.tsx @@ -10,7 +10,8 @@ import { requestSubscription, QueryRenderer, RelayRefetchProp, - RelayPaginationProp + RelayPaginationProp, + RelayProp } from "react-relay"; // ~~~~~~~~~~~~~~~~~~~~~ @@ -54,160 +55,185 @@ const MyQueryRenderer = (props: { name: string }) => ( // ~~~~~~~~~~~~~~~~~~~~~ // Modern FragmentContainer // ~~~~~~~~~~~~~~~~~~~~~ -const MyFragmentContainer = createFragmentContainer( - class TodoListView extends React.Component { - render() { - return
; - } - }, - { - item: graphql` - fragment TodoItem_item on Todo { - text - isComplete - } - `, + +() => { + interface Props { + relay: RelayProp; + publicProp: string; } -); + + class TodoListView extends React.Component { + render() { + this.props.relay.environment; + return
{this.props.publicProp}
; + } + } + + const MyFragmentContainer = createFragmentContainer( + TodoListView, + { + item: graphql` + fragment TodoItem_item on Todo { + text + isComplete + } + `, + } + ); +}; // ~~~~~~~~~~~~~~~~~~~~~ // Modern RefetchContainer // ~~~~~~~~~~~~~~~~~~~~~ -interface StoryInterface { - id: string; -} -interface FeedStoriesProps { - relay: RelayRefetchProp; - feed: { - stories: { edges: Array<{ node: StoryInterface }> }; - }; -} -class Story extends React.Component<{ story: StoryInterface }> {} -class FeedStories extends React.Component { - render() { - return ( -
- {this.props.feed.stories.edges.map(edge => )} -
- ); + +() => { + interface StoryInterface { + id: string; + } + interface Props { + relay: RelayRefetchProp; + loadMoreTitle: string; + feed: { + stories: { edges: Array<{ node: StoryInterface }> }; + }; + } + class Story extends React.Component<{ story: StoryInterface }> {} + class FeedStories extends React.Component { + render() { + return ( +
+ {this.props.feed.stories.edges.map(edge => )} +
+ ); + } + + _loadMore() { + // Increments the number of stories being rendered by 10. + const refetchVariables = (fragmentVariables: { count: number }) => ({ + count: fragmentVariables.count + 10, + }); + this.props.relay.refetch(refetchVariables); + } } - _loadMore() { - // Increments the number of stories being rendered by 10. - const refetchVariables = (fragmentVariables: { count: number }) => ({ - count: fragmentVariables.count + 10, - }); - this.props.relay.refetch(refetchVariables); - } -} - -const FeedRefetchContainer = createRefetchContainer( - FeedStories, - { - feed: graphql.experimental` - fragment FeedStories_feed on Feed @argumentDefinitions(count: { type: "Int", defaultValue: 10 }) { - stories(first: $count) { - edges { - node { - id - ...Story_story + const FeedRefetchContainer = createRefetchContainer( + FeedStories, + { + feed: graphql.experimental` + fragment FeedStories_feed on Feed @argumentDefinitions(count: { type: "Int", defaultValue: 10 }) { + stories(first: $count) { + edges { + node { + id + ...Story_story + } } } } + `, + }, + graphql.experimental` + query FeedStoriesRefetchQuery($count: Int) { + feed { + ...FeedStories_feed @arguments(count: $count) + } } - `, - }, - graphql.experimental` - query FeedStoriesRefetchQuery($count: Int) { - feed { - ...FeedStories_feed @arguments(count: $count) - } - } - ` -); + ` + ); +}; // ~~~~~~~~~~~~~~~~~~~~~ // Modern PaginationContainer // ~~~~~~~~~~~~~~~~~~~~~ -interface FeedProps { - user: { feed: { edges: Array<{ node: StoryInterface }> } }; - relay: RelayPaginationProp; -} -class Feed extends React.Component { - render() { - return ( -
- {this.props.user.feed.edges.map(edge => )} -
- ); - } - _loadMore() { - if (!this.props.relay.hasMore() || this.props.relay.isLoading()) { - return; +() => { + interface StoryInterface { + id: string; + } + class Story extends React.Component<{ story: StoryInterface }> {} + + interface Props { + relay: RelayPaginationProp; + loadMoreTitle: string; + user: { feed: { edges: Array<{ node: StoryInterface }> } }; + } + class Feed extends React.Component { + render() { + return ( +
+ {this.props.user.feed.edges.map(edge => )} +
+ ); } - this.props.relay.loadMore( - 10, // Fetch the next 10 feed items - e => { - console.log(e); + _loadMore() { + if (!this.props.relay.hasMore() || this.props.relay.isLoading()) { + return; } - ); - } -} -const FeedPaginationContainer = createPaginationContainer( - Feed, - { - user: graphql` - fragment Feed_user on User { - feed( - first: $count - after: $cursor - orderby: $orderBy # other variables - ) @connection(key: "Feed_feed") { - edges { - node { - id - ...Story_story + this.props.relay.loadMore( + 10, // Fetch the next 10 feed items + e => { + console.log(e); + } + ); + } + } + + const FeedPaginationContainer = createPaginationContainer( + Feed, + { + user: graphql` + fragment Feed_user on User { + feed( + first: $count + after: $cursor + orderby: $orderBy # other variables + ) @connection(key: "Feed_feed") { + edges { + node { + id + ...Story_story + } } } } - } - `, - }, - { - direction: "forward", - getConnectionFromProps(props) { - return props.user && props.user.feed; + `, }, - getFragmentVariables(prevVars, totalCount) { - return { - ...prevVars, - count: totalCount, - }; - }, - getVariables(props, { count, cursor }, fragmentVariables) { - return { - count, - cursor, - // in most cases, for variables other than connection filters like - // `first`, `after`, etc. you may want to use the previous values. - orderBy: fragmentVariables.orderBy, - }; - }, - query: graphql` - query FeedPaginationQuery($count: Int!, $cursor: String, $orderby: String!) { - user { - # You could reference the fragment defined previously. - ...Feed_user + { + direction: "forward", + getConnectionFromProps(props) { + return props.user && props.user.feed; + }, + getFragmentVariables(prevVars, totalCount) { + return { + ...prevVars, + count: totalCount, + }; + }, + getVariables(props, { count, cursor }, fragmentVariables) { + return { + count, + cursor, + // in most cases, for variables other than connection filters like + // `first`, `after`, etc. you may want to use the previous values. + orderBy: fragmentVariables.orderBy, + }; + }, + query: graphql` + query FeedPaginationQuery($count: Int!, $cursor: String, $orderby: String!) { + user { + # You could reference the fragment defined previously. + ...Feed_user + } } - } - `, + `, + } + ); } -); +}; // ~~~~~~~~~~~~~~~~~~~~~ // Modern Mutations diff --git a/types/relay-runtime/index.d.ts b/types/relay-runtime/index.d.ts index 74b24ca1b8..a11a632956 100644 --- a/types/relay-runtime/index.d.ts +++ b/types/relay-runtime/index.d.ts @@ -17,8 +17,6 @@ export type RelayConcreteNode = any; export type RelayMutationTransaction = any; export type RelayMutationRequest = any; export type RelayQueryRequest = any; -export type ConcreteFragment = any; -export type ConcreteBatch = any; export type ConcreteFragmentDefinition = object; export type ConcreteOperationDefinition = object; @@ -32,6 +30,19 @@ export type ConcreteOperationDefinition = object; */ export type RelayContainer = any; +// ~~~~~~~~~~~~~~~~~~~~~ +// Used in artifacts +// emitted by +// relay-compiler +// ~~~~~~~~~~~~~~~~~~~~~ + +// File: https://github.com/facebook/relay/blob/fe0e70f10bbcba1fff89911313ea69f24569464b/packages/relay-runtime/util/RelayConcreteNode.js +export type ConcreteFragment = any; +export type ConcreteRequest = any; +export type ConcreteBatchRequest = any; + +export type RequestNode = ConcreteRequest | ConcreteBatchRequest; + // ~~~~~~~~~~~~~~~~~~~~~ // RelayQL // ~~~~~~~~~~~~~~~~~~~~~ @@ -44,9 +55,9 @@ export interface GeneratedNodeMap { [key: string]: GraphQLTaggedNode; } export type GraphQLTaggedNode = - | (() => ConcreteFragment | ConcreteBatch) + | (() => ConcreteFragment | RequestNode) | { - modern(): ConcreteFragment | ConcreteBatch; + modern(): ConcreteFragment | RequestNode; classic(relayQL: RelayQL): ConcreteFragmentDefinition | ConcreteOperationDefinition; }; // ~~~~~~~~~~~~~~~~~~~~~ @@ -85,7 +96,7 @@ export interface PayloadError { * May return an Observable or Promise of a raw server response. */ export function FetchFunction( - operation: ConcreteBatch, + operation: RequestNode, variables: Variables, cacheConfig: CacheConfig, uploadables?: UploadableMap @@ -99,7 +110,7 @@ export function FetchFunction( * fourth parameter. */ export type SubscribeFunction = ( - operation: ConcreteBatch, + operation: RequestNode, variables: Variables, cacheConfig: CacheConfig, observer: LegacyObserver