mirror of
https://github.com/gosticks/DefinitelyTyped.git
synced 2026-08-12 13:00:19 +00:00
removing UMD style module structure from relay-runtime and moving new relay types to v1 folder
This commit is contained in:
Vendored
+71
-388
@@ -1,385 +1,86 @@
|
||||
// Type definitions for react-relay 1.3
|
||||
// Type definitions for react-relay 0.9.2
|
||||
// Project: https://github.com/facebook/relay
|
||||
// Definitions by: Johannes Schickling <https://github.com/graphcool>, Matt Martin <https://github.com/voxmatt>
|
||||
// Definitions by: Johannes Schickling <https://github.com/graphcool>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
// TypeScript Version: 2.4
|
||||
// TypeScript Version: 2.3
|
||||
|
||||
/// <reference types="relay-runtime" />
|
||||
|
||||
declare namespace __Relay {
|
||||
////////////////////////////
|
||||
// RELAY MODERN TYPES
|
||||
///////////////////////////
|
||||
namespace Modern {
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// Maybe Fix
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
type ConcreteFragment = any;
|
||||
type ConcreteBatch = any;
|
||||
type ConcreteFragmentDefinition = object;
|
||||
type ConcreteOperationDefinition = object;
|
||||
type ReactBaseComponent<T> = React.ComponentClass<T> | React.StatelessComponent<T>;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// RelayProp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// note: refetch and pagination containers augment this
|
||||
interface RelayProp {
|
||||
environment: Runtime.Environment;
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// RelayQL
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
function RelayQL(
|
||||
strings: string[],
|
||||
...substitutions: any[]
|
||||
): Common.RelayConcreteNode;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// RelayModernGraphQLTag
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
interface GeneratedNodeMap { [key: string]: GraphQLTaggedNode; }
|
||||
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.
|
||||
*/
|
||||
interface GraphqlInterface {
|
||||
(strings: string[] | TemplateStringsArray): GraphQLTaggedNode;
|
||||
experimental(strings: string[] | TemplateStringsArray): GraphQLTaggedNode;
|
||||
}
|
||||
const graphql: GraphqlInterface;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// ReactRelayQueryRenderer
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
interface QueryRendererProps {
|
||||
cacheConfig?: Common.CacheConfig;
|
||||
environment: Runtime.Environment;
|
||||
query: GraphQLTaggedNode;
|
||||
render(readyState: ReadyState): React.ReactElement<any> | undefined | null;
|
||||
variables: Common.Variables;
|
||||
rerunParamExperimental?: Common.RerunParam;
|
||||
}
|
||||
interface ReadyState {
|
||||
error: Error | undefined | null;
|
||||
props: { [propName: string]: any } | undefined | null;
|
||||
retry?(): void;
|
||||
}
|
||||
interface QueryRendererState {
|
||||
readyState: ReadyState;
|
||||
}
|
||||
class ReactRelayQueryRenderer extends React.Component<QueryRendererProps, QueryRendererState> { }
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// createFragmentContainer
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
function createFragmentContainer<T>(
|
||||
Component: ReactBaseComponent<T>,
|
||||
fragmentSpec: GraphQLTaggedNode | GeneratedNodeMap,
|
||||
): ReactBaseComponent<T>;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// createPaginationContainer
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
interface PageInfo {
|
||||
endCursor: string | undefined | null;
|
||||
hasNextPage: boolean;
|
||||
hasPreviousPage: boolean;
|
||||
startCursor: string | undefined | null;
|
||||
}
|
||||
interface ConnectionData {
|
||||
edges?: any[];
|
||||
pageInfo?: PageInfo;
|
||||
}
|
||||
type RelayPaginationProp = RelayProp & {
|
||||
hasMore(): boolean,
|
||||
isLoading(): boolean,
|
||||
loadMore(
|
||||
pageSize: number,
|
||||
callback: (error?: Error) => void,
|
||||
options?: RefetchOptions,
|
||||
): Common.Disposable | undefined | null,
|
||||
refetchConnection(
|
||||
totalCount: number,
|
||||
callback: (error?: Error) => void,
|
||||
refetchVariables?: Common.Variables,
|
||||
): Common.Disposable | undefined | null,
|
||||
};
|
||||
function FragmentVariablesGetter(
|
||||
prevVars: Common.Variables,
|
||||
totalCount: number,
|
||||
): Common.Variables;
|
||||
interface ConnectionConfig {
|
||||
direction?: 'backward' | 'forward';
|
||||
getConnectionFromProps?(props: object): ConnectionData | undefined | null;
|
||||
getFragmentVariables?: typeof FragmentVariablesGetter;
|
||||
getVariables(
|
||||
props: { [propName: string]: any },
|
||||
paginationInfo: { count: number, cursor?: string },
|
||||
fragmentVariables: Common.Variables,
|
||||
): Common.Variables;
|
||||
query: GraphQLTaggedNode;
|
||||
}
|
||||
function createPaginationContainer<T>(
|
||||
Component: ReactBaseComponent<T>,
|
||||
fragmentSpec: GraphQLTaggedNode | GeneratedNodeMap,
|
||||
connectionConfig: ConnectionConfig,
|
||||
): ReactBaseComponent<T>;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// createFragmentContainer
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
interface RefetchOptions {
|
||||
force?: boolean;
|
||||
rerunParamExperimental?: Common.RerunParam;
|
||||
}
|
||||
type RelayRefetchProp = RelayProp & {
|
||||
refetch(
|
||||
refetchVariables: Common.Variables | ((fragmentVariables: Common.Variables) => Common.Variables),
|
||||
renderVariables?: Common.Variables,
|
||||
callback?: (error?: Error) => void,
|
||||
options?: RefetchOptions,
|
||||
): Common.Disposable,
|
||||
};
|
||||
function createRefetchContainer<T>(
|
||||
Component: ReactBaseComponent<T>,
|
||||
fragmentSpec: GraphQLTaggedNode | GeneratedNodeMap,
|
||||
taggedNode: GraphQLTaggedNode,
|
||||
): ReactBaseComponent<T>;
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
// RELAY CLASSIC TYPES
|
||||
///////////////////////////
|
||||
// note: the namespace here is really for use inside of
|
||||
// relay-compat; the module declaration below
|
||||
// uses the old, pre-existing types
|
||||
namespace Classic {
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// Maybe Fix
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
type StoreReaderData = any;
|
||||
type StoreReaderOptions = any;
|
||||
type RelayStoreData = any;
|
||||
interface RelayQuery { Fragment: any; Node: any; Root: any; }
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// Environment
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
interface FragmentResolver {
|
||||
dispose(): void;
|
||||
resolve(
|
||||
fragment: RelayQuery["Fragment"],
|
||||
dataIDs: Common.DataID | Common.DataID[],
|
||||
): StoreReaderData | StoreReaderData[] | undefined | null;
|
||||
}
|
||||
interface RelayEnvironmentInterface {
|
||||
forceFetch(
|
||||
querySet: Common.RelayQuerySet,
|
||||
onReadyStateChange: Common.ReadyStateChangeCallback,
|
||||
): Common.Abortable;
|
||||
getFragmentResolver(
|
||||
fragment: RelayQuery["Fragment"],
|
||||
onNext: () => void,
|
||||
): FragmentResolver;
|
||||
getStoreData(): RelayStoreData;
|
||||
primeCache(
|
||||
querySet: Common.RelayQuerySet,
|
||||
onReadyStateChange: Common.ReadyStateChangeCallback,
|
||||
): Common.Abortable;
|
||||
read(
|
||||
node: RelayQuery["Node"],
|
||||
dataID: Common.DataID,
|
||||
options?: StoreReaderOptions,
|
||||
): StoreReaderData | void;
|
||||
readQuery(
|
||||
root: RelayQuery["Root"],
|
||||
options?: StoreReaderOptions,
|
||||
): StoreReaderData[] | void;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
// RELAY COMPAT TYPES
|
||||
///////////////////////////
|
||||
namespace Compat {
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// Maybe Fix
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
type ConcreteFragment = any;
|
||||
type ConcreteBatch = any;
|
||||
type ConcreteFragmentDefinition = object;
|
||||
type ConcreteOperationDefinition = object;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// Util
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
function getFragment(q: string, v?: Common.Variables): string;
|
||||
interface ComponentWithFragment<T> extends React.ComponentClass<T> {
|
||||
getFragment: typeof getFragment;
|
||||
}
|
||||
interface StatelessWithFragment<T> extends React.StatelessComponent<T> {
|
||||
getFragment: typeof getFragment;
|
||||
}
|
||||
type ReactFragmentComponent<T> = ComponentWithFragment<T> | StatelessWithFragment<T>;
|
||||
type ReactBaseComponent<T> = React.ComponentClass<T> | React.StatelessComponent<T>;
|
||||
type RelayClassicEnvironment = Classic.RelayEnvironmentInterface;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// RelayCompatTypes
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
type CompatEnvironment = Runtime.Environment | RelayClassicEnvironment;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// RelayCompatMutations
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
function commitUpdate(
|
||||
environment: CompatEnvironment,
|
||||
config: Runtime.MutationConfig<any>,
|
||||
): Common.Disposable;
|
||||
function applyUpdate(
|
||||
environment: CompatEnvironment,
|
||||
config: Runtime.OptimisticMutationConfig,
|
||||
): Common.Disposable;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// RelayCompatContainer
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
interface GeneratedNodeMap { [key: string]: Modern.GraphQLTaggedNode; }
|
||||
function createContainer<T>(
|
||||
Component: ReactBaseComponent<T>,
|
||||
fragmentSpec: Modern.GraphQLTaggedNode | GeneratedNodeMap,
|
||||
): ReactFragmentComponent<T>;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// injectDefaultVariablesProvider
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
type VariablesProvider = () => Common.Variables;
|
||||
function injectDefaultVariablesProvider(variablesProvider: VariablesProvider): void;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
// MODULES
|
||||
///////////////////////////
|
||||
// tslint:disable strict-export-declare-modifiers
|
||||
declare module 'react-relay' {
|
||||
export import QueryRenderer = __Relay.Modern.ReactRelayQueryRenderer;
|
||||
export import createFragmentContainer = __Relay.Modern.createFragmentContainer;
|
||||
export import createPaginationContainer = __Relay.Modern.createPaginationContainer;
|
||||
export import createRefetchContainer = __Relay.Modern.createRefetchContainer;
|
||||
export import graphql = __Relay.Modern.graphql;
|
||||
|
||||
export import commitLocalUpdate = __Relay.Runtime.commitLocalUpdate;
|
||||
export import commitMutation = __Relay.Runtime.commitRelayModernMutation;
|
||||
export import fetchQuery = __Relay.Runtime.fetchRelayModernQuery;
|
||||
export import requestSubscription = __Relay.Runtime.requestRelaySubscription;
|
||||
|
||||
// exported for convenience — not exports in the original module
|
||||
export import RelayProp = __Relay.Modern.RelayProp;
|
||||
export import RelayPaginationProp = __Relay.Modern.RelayPaginationProp;
|
||||
export import RelayRefetchProp = __Relay.Modern.RelayRefetchProp;
|
||||
}
|
||||
|
||||
declare module 'react-relay/compat' {
|
||||
export import applyOptimisticMutation = __Relay.Compat.applyUpdate;
|
||||
export import commitMutation = __Relay.Compat.commitUpdate;
|
||||
export import createFragmentContainer = __Relay.Compat.createContainer;
|
||||
export import createPaginationContainer = __Relay.Compat.createContainer;
|
||||
export import createRefetchContainer = __Relay.Compat.createContainer;
|
||||
export import injectDefaultVariablesProvider = __Relay.Compat.injectDefaultVariablesProvider;
|
||||
export import QueryRenderer = __Relay.Modern.ReactRelayQueryRenderer;
|
||||
export import graphql = __Relay.Modern.graphql;
|
||||
export import fetchQuery = __Relay.Runtime.fetchRelayModernQuery;
|
||||
}
|
||||
// tslint:enable strict-export-declare-modifiers
|
||||
|
||||
declare module "react-relay/classic" {
|
||||
declare module "react-relay" {
|
||||
import * as React from "react";
|
||||
|
||||
type ClientMutationID = string;
|
||||
|
||||
/** Fragments are a hash of functions */
|
||||
interface Fragments {
|
||||
[query: string]: ((variables?: RelayVariables) => string);
|
||||
[query: string]: ((variables?: RelayVariables) => string)
|
||||
}
|
||||
|
||||
interface CreateContainerOpts {
|
||||
initialVariables?: any;
|
||||
fragments: Fragments;
|
||||
prepareVariables?(prevVariables: RelayVariables): RelayVariables;
|
||||
initialVariables?: any
|
||||
fragments: Fragments
|
||||
prepareVariables?(prevVariables: RelayVariables): RelayVariables
|
||||
}
|
||||
|
||||
interface RelayVariables {
|
||||
[name: string]: any;
|
||||
[name: string]: any
|
||||
}
|
||||
|
||||
/** add static getFragment method to the component constructor */
|
||||
interface RelayContainerClass<T> extends React.ComponentClass<T> {
|
||||
getFragment: ((q: string, v?: RelayVariables) => string);
|
||||
getFragment: ((q: string, v?: RelayVariables) => string)
|
||||
}
|
||||
|
||||
interface RelayQueryRequestResolve {
|
||||
response: any;
|
||||
response: any
|
||||
}
|
||||
|
||||
type RelayMutationStatus =
|
||||
'UNCOMMITTED' | // Transaction hasn't yet been sent to the server. Transaction can be committed or rolled back.
|
||||
'COMMIT_QUEUED' | // Transaction was committed but another transaction with the same collision key is pending, so the transaction has been queued to send to the server.
|
||||
'COLLISION_COMMIT_FAILED' | // Transaction was queued for commit but another transaction with the same collision key failed. All transactions in the collision queue,
|
||||
// including this one, have been failed. Transaction can be recommitted or rolled back.
|
||||
'COMMITTING' | // Transaction is waiting for the server to respond.
|
||||
'COMMIT_FAILED';
|
||||
'UNCOMMITTED' | // Transaction hasn't yet been sent to the server. Transaction can be committed or rolled back.
|
||||
'COMMIT_QUEUED' | // Transaction was committed but another transaction with the same collision key is pending, so the transaction has been queued to send to the server.
|
||||
'COLLISION_COMMIT_FAILED' | //Transaction was queued for commit but another transaction with the same collision key failed. All transactions in the collision queue, including this one, have been failed. Transaction can be recommitted or rolled back.
|
||||
'COMMITTING' | // Transaction is waiting for the server to respond.
|
||||
'COMMIT_FAILED';
|
||||
|
||||
class RelayMutationTransaction {
|
||||
applyOptimistic(): RelayMutationTransaction;
|
||||
commit(): RelayMutationTransaction | null;
|
||||
recommit(): void;
|
||||
rollback(): void;
|
||||
getError(): Error;
|
||||
getStatus(): RelayMutationStatus;
|
||||
getHash(): string;
|
||||
getID(): ClientMutationID;
|
||||
applyOptimistic(): RelayMutationTransaction;
|
||||
commit(): RelayMutationTransaction | null;
|
||||
recommit(): void;
|
||||
rollback(): void;
|
||||
getError(): Error;
|
||||
getStatus(): RelayMutationStatus;
|
||||
getHash(): string;
|
||||
getID(): ClientMutationID;
|
||||
}
|
||||
|
||||
interface RelayMutationRequest {
|
||||
getQueryString(): string;
|
||||
getVariables(): RelayVariables;
|
||||
resolve(result: RelayQueryRequestResolve): any;
|
||||
reject(errors: any): any;
|
||||
getQueryString(): string
|
||||
getVariables(): RelayVariables
|
||||
resolve(result: RelayQueryRequestResolve): any
|
||||
reject(errors: any): any
|
||||
}
|
||||
|
||||
interface RelayQueryRequest {
|
||||
resolve(result: RelayQueryRequestResolve): any;
|
||||
reject(errors: any): any;
|
||||
getQueryString(): string;
|
||||
getVariables(): RelayVariables;
|
||||
getID(): string;
|
||||
getDebugName(): string;
|
||||
resolve(result: RelayQueryRequestResolve): any
|
||||
reject(errors: any): any
|
||||
|
||||
getQueryString(): string
|
||||
getVariables(): RelayVariables
|
||||
getID(): string
|
||||
getDebugName(): string
|
||||
}
|
||||
|
||||
interface RelayNetworkLayer {
|
||||
supports(...options: string[]): boolean;
|
||||
supports(...options: string[]): boolean
|
||||
}
|
||||
|
||||
class DefaultNetworkLayer implements RelayNetworkLayer {
|
||||
constructor(host: string, options?: any);
|
||||
supports(...options: string[]): boolean;
|
||||
constructor(host: string, options?: any)
|
||||
supports(...options: string[]): boolean
|
||||
}
|
||||
|
||||
function createContainer<T>(component: React.ComponentClass<T> | React.StatelessComponent<T>, params?: CreateContainerOpts): RelayContainerClass<T>;
|
||||
function injectNetworkLayer(networkLayer: RelayNetworkLayer): any;
|
||||
function isContainer(component: React.ComponentClass<any>): boolean;
|
||||
function QL(...args: any[]): string;
|
||||
function createContainer<T>(component: React.ComponentClass<T> | React.StatelessComponent<T>, params?: CreateContainerOpts): RelayContainerClass<T>
|
||||
function injectNetworkLayer(networkLayer: RelayNetworkLayer): any
|
||||
function isContainer(component: React.ComponentClass<any>): boolean
|
||||
function QL(...args: any[]): string
|
||||
|
||||
class Route {
|
||||
constructor(params?: RelayVariables)
|
||||
@@ -390,59 +91,39 @@ declare module "react-relay/classic" {
|
||||
* S is typically dynamic as it depends on the data the app is currently using, but it's possible to always
|
||||
* return some data in the payload using REQUIRED_CHILDREN which is where specifying S is the most useful.
|
||||
*/
|
||||
class Mutation<T, S> {
|
||||
props: T;
|
||||
class Mutation<T,S> {
|
||||
props: T
|
||||
|
||||
constructor(props: T);
|
||||
static getFragment(q: string): string;
|
||||
constructor(props: T)
|
||||
static getFragment(q: string): string
|
||||
}
|
||||
|
||||
interface Transaction {
|
||||
getError(): Error;
|
||||
Status(): number;
|
||||
getError(): Error
|
||||
Status(): number
|
||||
}
|
||||
|
||||
interface StoreUpdateCallbacks<T> {
|
||||
onFailure?(transaction: Transaction): any;
|
||||
onSuccess?(response: T): any;
|
||||
onFailure?(transaction: Transaction): any
|
||||
onSuccess?(response: T): any
|
||||
}
|
||||
|
||||
interface Store {
|
||||
commitUpdate(mutation: Mutation<any, any>, callbacks?: StoreUpdateCallbacks<any>): any;
|
||||
commitUpdate(mutation: Mutation<any,any>, callbacks?: StoreUpdateCallbacks<any>): any
|
||||
}
|
||||
|
||||
const Store: Store;
|
||||
var Store: Store
|
||||
|
||||
class RootContainer extends React.Component<RootContainerProps, any> { }
|
||||
class RootContainer extends React.Component<RootContainerProps,any> {}
|
||||
|
||||
interface RootContainerProps extends React.Props<RootContainer> {
|
||||
Component: RelayContainerClass<any>;
|
||||
route: Route;
|
||||
renderLoading?(): JSX.Element;
|
||||
renderFetched?(data: any): JSX.Element;
|
||||
renderFailure?(error: Error, retry: (...args: any[]) => any): JSX.Element;
|
||||
interface RootContainerProps extends React.Props<RootContainer>{
|
||||
Component: RelayContainerClass<any>
|
||||
route: Route
|
||||
renderLoading?(): JSX.Element
|
||||
renderFetched?(data: any): JSX.Element
|
||||
renderFailure?(error: Error, retry: Function): JSX.Element
|
||||
}
|
||||
|
||||
class Renderer extends React.Component<RendererProps, any> { }
|
||||
|
||||
interface RendererProps {
|
||||
Container: RelayContainerClass<any>; // Relay container that defines fragments and the view to render.
|
||||
forceFetch?: boolean; // Whether to send a server request regardless of data available on the client.
|
||||
queryConfig: Route; // `QueryConfig` or `Relay.Route` that defines the query roots.
|
||||
environment: Store; // An instance of `Relay.Environment` or any object that implements the `RelayEnvironment` interface.
|
||||
render?: RenderCallback; // Called to render when data requirements are being fulfilled.
|
||||
onReadyStateChange?: OnReadyStateChange;
|
||||
}
|
||||
|
||||
interface RenderStateConfig {
|
||||
props?: { [propName: string]: any };
|
||||
done: boolean;
|
||||
error?: Error;
|
||||
retry?(): void;
|
||||
stale: boolean;
|
||||
}
|
||||
type RenderCallback = (renderState: RenderStateConfig) => any;
|
||||
|
||||
type ReadyStateEvent =
|
||||
'ABORT' |
|
||||
'CACHE_RESTORED_REQUIRED' |
|
||||
@@ -455,23 +136,25 @@ declare module "react-relay/classic" {
|
||||
'STORE_FOUND_ALL' |
|
||||
'STORE_FOUND_REQUIRED';
|
||||
|
||||
type OnReadyStateChange = (readyState: {
|
||||
ready: boolean,
|
||||
done: boolean,
|
||||
stale: boolean,
|
||||
error?: Error,
|
||||
events: ReadyStateEvent[],
|
||||
aborted: boolean
|
||||
}) => void;
|
||||
interface OnReadyStateChange {
|
||||
(readyState: {
|
||||
ready: boolean,
|
||||
done: boolean,
|
||||
stale: boolean,
|
||||
error?: Error,
|
||||
events: Array<ReadyStateEvent>,
|
||||
aborted: boolean
|
||||
}): void
|
||||
}
|
||||
|
||||
interface RelayProp {
|
||||
readonly route: { name: string; }; // incomplete, also has params and queries
|
||||
readonly variables: any;
|
||||
readonly pendingVariables?: any;
|
||||
readonly pendingVariables?: any | null;
|
||||
setVariables(variables: any, onReadyStateChange?: OnReadyStateChange): void;
|
||||
forceFetch(variables: any, onReadyStateChange?: OnReadyStateChange): void;
|
||||
hasOptimisticUpdate(record: any): boolean;
|
||||
getPendingTransactions(record: any): RelayMutationTransaction[];
|
||||
commitUpdate(mutation: Mutation<any, any>, callbacks?: StoreUpdateCallbacks<any>): any;
|
||||
commitUpdate: (mutation: Mutation<any,any>, callbacks?: StoreUpdateCallbacks<any>) => any;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,375 +1,30 @@
|
||||
import * as React from "react";
|
||||
import {
|
||||
Environment,
|
||||
Network,
|
||||
RecordSource,
|
||||
Store,
|
||||
ConnectionHandler,
|
||||
} from 'relay-runtime';
|
||||
|
||||
////////////////////////////
|
||||
// RELAY MODERN TESTS
|
||||
///////////////////////////
|
||||
import {
|
||||
graphql,
|
||||
commitMutation,
|
||||
createFragmentContainer,
|
||||
createPaginationContainer,
|
||||
createRefetchContainer,
|
||||
requestSubscription,
|
||||
QueryRenderer,
|
||||
RelayPaginationProp,
|
||||
RelayRefetchProp
|
||||
} from "react-relay";
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// Modern Environment
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
function fetchQuery(operation: any, variables: any, cacheConfig: {}) {
|
||||
return fetch('/graphql');
|
||||
}
|
||||
const network = Network.create(fetchQuery);
|
||||
const source = new RecordSource();
|
||||
const store = new Store(source);
|
||||
const modernEnvironment = new Environment({ network, store });
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// Modern QueryRenderer
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
const MyQueryRenderer = (props: { name: string}) => (
|
||||
<QueryRenderer
|
||||
environment={ modernEnvironment }
|
||||
query={graphql`
|
||||
query ExampleQuery($pageID: ID!) {
|
||||
page(id: $pageID) {
|
||||
name
|
||||
}
|
||||
}
|
||||
`}
|
||||
variables={{
|
||||
pageID: '110798995619330',
|
||||
}}
|
||||
render={({error, props}) => {
|
||||
if (error) {
|
||||
return <div>{error.message}</div>;
|
||||
} else if (props) {
|
||||
return <div>{props.name} is great!</div>;
|
||||
}
|
||||
return <div>Loading</div>;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// Modern FragmentContainer
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
const MyFragmentContainer = createFragmentContainer(
|
||||
class TodoListView extends React.Component {
|
||||
render() {
|
||||
return <div/>;
|
||||
}
|
||||
},
|
||||
{
|
||||
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<FeedStoriesProps> {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{this.props.feed.stories.edges.map(
|
||||
edge => <Story story={edge.node} key={edge.node.id} />
|
||||
)}
|
||||
<button
|
||||
onClick={() => this._loadMore}
|
||||
title="Load More"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
_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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
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<FeedProps> {
|
||||
render() {
|
||||
return (<div>
|
||||
{this.props.user.feed.edges.map(
|
||||
edge => <Story story={edge.node} key={edge.node.id} />
|
||||
)}
|
||||
<button
|
||||
onClick={() => this._loadMore()}
|
||||
title="Load More"
|
||||
/>
|
||||
</div>);
|
||||
}
|
||||
|
||||
_loadMore() {
|
||||
if (!this.props.relay.hasMore() || this.props.relay.isLoading()) {
|
||||
return;
|
||||
}
|
||||
|
||||
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: { user: {feed: any}}) {
|
||||
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
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
const mutation = graphql`
|
||||
mutation MarkReadNotificationMutation(
|
||||
$input: MarkReadNotificationData!
|
||||
) {
|
||||
markReadNotification(data: $input) {
|
||||
notification {
|
||||
seenState
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const optimisticResponse = {
|
||||
markReadNotification: {
|
||||
notification: {
|
||||
seenState: 'SEEN',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const configs = [{
|
||||
type: 'NODE_DELETE' as 'NODE_DELETE',
|
||||
deletedIDFieldName: 'destroyedShipId',
|
||||
}, {
|
||||
type: 'RANGE_ADD' as 'RANGE_ADD',
|
||||
parentID: 'shipId',
|
||||
connectionInfo: [{
|
||||
key: 'AddShip_ships',
|
||||
rangeBehavior: 'append',
|
||||
}],
|
||||
edgeName: 'newShipEdge',
|
||||
}, {
|
||||
type: 'RANGE_DELETE' as 'RANGE_DELETE',
|
||||
parentID: 'todoId',
|
||||
connectionKeys: [{
|
||||
key: 'RemoveTags_tags',
|
||||
rangeBehavior: 'append',
|
||||
}],
|
||||
pathToConnection: ['todo', 'tags'],
|
||||
deletedIDFieldName: 'removedTagId'
|
||||
}];
|
||||
|
||||
function markNotificationAsRead(source: string, storyID: string) {
|
||||
const variables = {
|
||||
input: {
|
||||
source,
|
||||
storyID,
|
||||
},
|
||||
};
|
||||
|
||||
commitMutation(
|
||||
modernEnvironment,
|
||||
{
|
||||
configs,
|
||||
mutation,
|
||||
optimisticResponse,
|
||||
variables,
|
||||
onCompleted: (response, errors) => {
|
||||
console.log('Response received from server.');
|
||||
},
|
||||
onError: err => console.error(err),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// Modern Subscriptions
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
const subscription = graphql`
|
||||
subscription MarkReadNotificationSubscription(
|
||||
$storyID: ID!
|
||||
) {
|
||||
markReadNotification(storyID: $storyID) {
|
||||
notification {
|
||||
seenState
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
const variables = {
|
||||
storyID: '123',
|
||||
};
|
||||
requestSubscription(
|
||||
modernEnvironment, // see Environment docs
|
||||
{
|
||||
subscription,
|
||||
variables,
|
||||
// optional but recommended:
|
||||
onCompleted: () => {},
|
||||
onError: error => console.error(error),
|
||||
// example of a custom updater
|
||||
updater: store => {
|
||||
// Get the notification
|
||||
const rootField = store.getRootField('markReadNotification');
|
||||
const notification = !!rootField && rootField.getLinkedRecord('notification');
|
||||
// Add it to a connection
|
||||
const viewer = store.getRoot().getLinkedRecord('viewer');
|
||||
const notifications =
|
||||
ConnectionHandler.getConnection(viewer, 'notifications');
|
||||
const edge = ConnectionHandler.createEdge(
|
||||
store,
|
||||
notifications,
|
||||
notification,
|
||||
'<TypeOfNotificationsEdge>',
|
||||
);
|
||||
ConnectionHandler.insertEdgeAfter(notifications, edge);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
////////////////////////////
|
||||
// RELAY-CLASSIC TESTS
|
||||
///////////////////////////
|
||||
|
||||
import * as Relay from "react-relay/classic";
|
||||
import * as React from "react"
|
||||
import * as Relay from "react-relay"
|
||||
|
||||
interface Props {
|
||||
text: string;
|
||||
userId: string;
|
||||
text: string
|
||||
userId: string
|
||||
}
|
||||
|
||||
export default class AddTweetMutation extends Relay.Mutation<Props, {}> {
|
||||
getMutation() {
|
||||
return Relay.QL`mutation{addTweet}`;
|
||||
interface Response {
|
||||
}
|
||||
|
||||
export default class AddTweetMutation extends Relay.Mutation<Props, Response> {
|
||||
|
||||
getMutation () {
|
||||
return Relay.QL`mutation{addTweet}`
|
||||
}
|
||||
|
||||
getFatQuery() {
|
||||
getFatQuery () {
|
||||
return Relay.QL`
|
||||
fragment on AddTweetPayload {
|
||||
tweetEdge
|
||||
user
|
||||
}
|
||||
`;
|
||||
`
|
||||
}
|
||||
|
||||
getConfigs() {
|
||||
getConfigs () {
|
||||
return [{
|
||||
type: "RANGE_ADD",
|
||||
parentName: "user",
|
||||
@@ -379,19 +34,19 @@ export default class AddTweetMutation extends Relay.Mutation<Props, {}> {
|
||||
rangeBehaviors: {
|
||||
"": "append",
|
||||
},
|
||||
}];
|
||||
}]
|
||||
}
|
||||
|
||||
getVariables() {
|
||||
return this.props;
|
||||
getVariables () {
|
||||
return this.props
|
||||
}
|
||||
}
|
||||
|
||||
interface ArtworkProps {
|
||||
artwork: {
|
||||
title: string
|
||||
};
|
||||
relay: Relay.RelayProp;
|
||||
},
|
||||
relay: Relay.RelayProp,
|
||||
}
|
||||
|
||||
class Artwork extends React.Component<ArtworkProps> {
|
||||
@@ -400,7 +55,7 @@ class Artwork extends React.Component<ArtworkProps> {
|
||||
<a href={`/artworks/${this.props.relay.variables.artworkID}`}>
|
||||
{this.props.artwork.title}
|
||||
</a>
|
||||
);
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,7 +67,7 @@ const ArtworkContainer = Relay.createContainer(Artwork, {
|
||||
}
|
||||
`
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
class StubbedArtwork extends React.Component {
|
||||
render() {
|
||||
@@ -428,10 +83,10 @@ class StubbedArtwork extends React.Component {
|
||||
setVariables: () => {},
|
||||
forceFetch: () => {},
|
||||
hasOptimisticUpdate: () => false,
|
||||
getPendingTransactions: (): any => undefined,
|
||||
getPendingTransactions: (): Relay.RelayMutationTransaction[] => undefined,
|
||||
commitUpdate: () => {},
|
||||
}
|
||||
};
|
||||
return <ArtworkContainer {...props} />;
|
||||
}
|
||||
return <ArtworkContainer {...props} />
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
],
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"strictNullChecks": true,
|
||||
"strictNullChecks": false,
|
||||
"baseUrl": "../",
|
||||
"typeRoots": [
|
||||
"../"
|
||||
@@ -21,4 +21,4 @@
|
||||
"index.d.ts",
|
||||
"react-relay-tests.tsx"
|
||||
]
|
||||
}
|
||||
}
|
||||
Vendored
+474
@@ -0,0 +1,474 @@
|
||||
// Type definitions for react-relay 1.3
|
||||
// Project: https://github.com/facebook/relay
|
||||
// Definitions by: Johannes Schickling <https://github.com/graphcool>, Matt Martin <https://github.com/voxmatt>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
// TypeScript Version: 2.4
|
||||
|
||||
import * as React from 'react';
|
||||
import { RelayCommonTypes, RelayRuntimeTypes } from 'relay-runtime';
|
||||
|
||||
////////////////////////////
|
||||
// RELAY MODERN TYPES
|
||||
///////////////////////////
|
||||
export namespace RelayModernTypes {
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// Maybe Fix
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
type ConcreteFragment = any;
|
||||
type ConcreteBatch = any;
|
||||
type ConcreteFragmentDefinition = object;
|
||||
type ConcreteOperationDefinition = object;
|
||||
type ReactBaseComponent<T> = React.ComponentClass<T> | React.StatelessComponent<T>;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// RelayProp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// note: refetch and pagination containers augment this
|
||||
interface RelayProp {
|
||||
environment: RelayRuntimeTypes.Environment;
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// RelayQL
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
function RelayQL(
|
||||
strings: string[],
|
||||
...substitutions: any[]
|
||||
): RelayCommonTypes.RelayConcreteNode;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// RelayModernGraphQLTag
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
interface GeneratedNodeMap { [key: string]: GraphQLTaggedNode; }
|
||||
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.
|
||||
*/
|
||||
interface GraphqlInterface {
|
||||
(strings: string[] | TemplateStringsArray): GraphQLTaggedNode;
|
||||
experimental(strings: string[] | TemplateStringsArray): GraphQLTaggedNode;
|
||||
}
|
||||
const graphql: GraphqlInterface;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// ReactRelayQueryRenderer
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
interface QueryRendererProps {
|
||||
cacheConfig?: RelayCommonTypes.CacheConfig;
|
||||
environment: RelayRuntimeTypes.Environment;
|
||||
query: GraphQLTaggedNode;
|
||||
render(readyState: ReadyState): React.ReactElement<any> | undefined | null;
|
||||
variables: RelayCommonTypes.Variables;
|
||||
rerunParamExperimental?: RelayCommonTypes.RerunParam;
|
||||
}
|
||||
interface ReadyState {
|
||||
error: Error | undefined | null;
|
||||
props: { [propName: string]: any } | undefined | null;
|
||||
retry?(): void;
|
||||
}
|
||||
interface QueryRendererState {
|
||||
readyState: ReadyState;
|
||||
}
|
||||
class ReactRelayQueryRenderer extends React.Component<QueryRendererProps, QueryRendererState> { }
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// createFragmentContainer
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
function createFragmentContainer<T>(
|
||||
Component: ReactBaseComponent<T>,
|
||||
fragmentSpec: GraphQLTaggedNode | GeneratedNodeMap,
|
||||
): ReactBaseComponent<T>;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// createPaginationContainer
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
interface PageInfo {
|
||||
endCursor: string | undefined | null;
|
||||
hasNextPage: boolean;
|
||||
hasPreviousPage: boolean;
|
||||
startCursor: string | undefined | null;
|
||||
}
|
||||
interface ConnectionData {
|
||||
edges?: any[];
|
||||
pageInfo?: PageInfo;
|
||||
}
|
||||
type RelayPaginationProp = RelayProp & {
|
||||
hasMore(): boolean,
|
||||
isLoading(): boolean,
|
||||
loadMore(
|
||||
pageSize: number,
|
||||
callback: (error?: Error) => void,
|
||||
options?: RefetchOptions,
|
||||
): RelayCommonTypes.Disposable | undefined | null,
|
||||
refetchConnection(
|
||||
totalCount: number,
|
||||
callback: (error?: Error) => void,
|
||||
refetchVariables?: RelayCommonTypes.Variables,
|
||||
): RelayCommonTypes.Disposable | undefined | null,
|
||||
};
|
||||
function FragmentVariablesGetter(
|
||||
prevVars: RelayCommonTypes.Variables,
|
||||
totalCount: number,
|
||||
): RelayCommonTypes.Variables;
|
||||
interface ConnectionConfig {
|
||||
direction?: 'backward' | 'forward';
|
||||
getConnectionFromProps?(props: object): ConnectionData | undefined | null;
|
||||
getFragmentVariables?: typeof FragmentVariablesGetter;
|
||||
getVariables(
|
||||
props: { [propName: string]: any },
|
||||
paginationInfo: { count: number, cursor?: string },
|
||||
fragmentVariables: RelayCommonTypes.Variables,
|
||||
): RelayCommonTypes.Variables;
|
||||
query: GraphQLTaggedNode;
|
||||
}
|
||||
function createPaginationContainer<T>(
|
||||
Component: ReactBaseComponent<T>,
|
||||
fragmentSpec: GraphQLTaggedNode | GeneratedNodeMap,
|
||||
connectionConfig: ConnectionConfig,
|
||||
): ReactBaseComponent<T>;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// createFragmentContainer
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
interface RefetchOptions {
|
||||
force?: boolean;
|
||||
rerunParamExperimental?: RelayCommonTypes.RerunParam;
|
||||
}
|
||||
type RelayRefetchProp = RelayProp & {
|
||||
refetch(
|
||||
refetchVariables: RelayCommonTypes.Variables | ((fragmentVariables: RelayCommonTypes.Variables) => RelayCommonTypes.Variables),
|
||||
renderVariables?: RelayCommonTypes.Variables,
|
||||
callback?: (error?: Error) => void,
|
||||
options?: RefetchOptions,
|
||||
): RelayCommonTypes.Disposable,
|
||||
};
|
||||
function createRefetchContainer<T>(
|
||||
Component: ReactBaseComponent<T>,
|
||||
fragmentSpec: GraphQLTaggedNode | GeneratedNodeMap,
|
||||
taggedNode: GraphQLTaggedNode,
|
||||
): ReactBaseComponent<T>;
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
// RELAY CLASSIC TYPES
|
||||
///////////////////////////
|
||||
// note: the namespace here is really for use inside of
|
||||
// relay-compat; the module declaration below
|
||||
// uses the old, pre-existing types
|
||||
export namespace RelayClassicTypes {
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// Maybe Fix
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
type StoreReaderData = any;
|
||||
type StoreReaderOptions = any;
|
||||
type RelayStoreData = any;
|
||||
interface RelayQuery { Fragment: any; Node: any; Root: any; }
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// Environment
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
interface FragmentResolver {
|
||||
dispose(): void;
|
||||
resolve(
|
||||
fragment: RelayQuery["Fragment"],
|
||||
dataIDs: RelayCommonTypes.DataID | RelayCommonTypes.DataID[],
|
||||
): StoreReaderData | StoreReaderData[] | undefined | null;
|
||||
}
|
||||
interface RelayEnvironmentInterface {
|
||||
forceFetch(
|
||||
querySet: RelayCommonTypes.RelayQuerySet,
|
||||
onReadyStateChange: RelayCommonTypes.ReadyStateChangeCallback,
|
||||
): RelayCommonTypes.Abortable;
|
||||
getFragmentResolver(
|
||||
fragment: RelayQuery["Fragment"],
|
||||
onNext: () => void,
|
||||
): FragmentResolver;
|
||||
getStoreData(): RelayStoreData;
|
||||
primeCache(
|
||||
querySet: RelayCommonTypes.RelayQuerySet,
|
||||
onReadyStateChange: RelayCommonTypes.ReadyStateChangeCallback,
|
||||
): RelayCommonTypes.Abortable;
|
||||
read(
|
||||
node: RelayQuery["Node"],
|
||||
dataID: RelayCommonTypes.DataID,
|
||||
options?: StoreReaderOptions,
|
||||
): StoreReaderData | void;
|
||||
readQuery(
|
||||
root: RelayQuery["Root"],
|
||||
options?: StoreReaderOptions,
|
||||
): StoreReaderData[] | void;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
// RELAY COMPAT TYPES
|
||||
///////////////////////////
|
||||
export namespace RelayCompatTypes {
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// Maybe Fix
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
type ConcreteFragment = any;
|
||||
type ConcreteBatch = any;
|
||||
type ConcreteFragmentDefinition = object;
|
||||
type ConcreteOperationDefinition = object;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// Util
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
function getFragment(q: string, v?: RelayCommonTypes.Variables): string;
|
||||
interface ComponentWithFragment<T> extends React.ComponentClass<T> {
|
||||
getFragment: typeof getFragment;
|
||||
}
|
||||
interface StatelessWithFragment<T> extends React.StatelessComponent<T> {
|
||||
getFragment: typeof getFragment;
|
||||
}
|
||||
type ReactFragmentComponent<T> = ComponentWithFragment<T> | StatelessWithFragment<T>;
|
||||
type ReactBaseComponent<T> = React.ComponentClass<T> | React.StatelessComponent<T>;
|
||||
type RelayClassicEnvironment = RelayClassicTypes.RelayEnvironmentInterface;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// RelayCompatTypes
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
type CompatEnvironment = RelayRuntimeTypes.Environment | RelayClassicEnvironment;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// RelayCompatMutations
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
function commitUpdate(
|
||||
environment: CompatEnvironment,
|
||||
config: RelayRuntimeTypes.MutationConfig<any>,
|
||||
): RelayCommonTypes.Disposable;
|
||||
function applyUpdate(
|
||||
environment: CompatEnvironment,
|
||||
config: RelayRuntimeTypes.OptimisticMutationConfig,
|
||||
): RelayCommonTypes.Disposable;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// RelayCompatContainer
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
interface GeneratedNodeMap { [key: string]: RelayModernTypes.GraphQLTaggedNode; }
|
||||
function createContainer<T>(
|
||||
Component: ReactBaseComponent<T>,
|
||||
fragmentSpec: RelayModernTypes.GraphQLTaggedNode | GeneratedNodeMap,
|
||||
): ReactFragmentComponent<T>;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// injectDefaultVariablesProvider
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
type VariablesProvider = () => RelayCommonTypes.Variables;
|
||||
function injectDefaultVariablesProvider(variablesProvider: VariablesProvider): void;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// MODULES
|
||||
///////////////////////////
|
||||
export import QueryRenderer = RelayModernTypes.ReactRelayQueryRenderer;
|
||||
export import createFragmentContainer = RelayModernTypes.createFragmentContainer;
|
||||
export import createPaginationContainer = RelayModernTypes.createPaginationContainer;
|
||||
export import createRefetchContainer = RelayModernTypes.createRefetchContainer;
|
||||
export import graphql = RelayModernTypes.graphql;
|
||||
|
||||
export import commitLocalUpdate = RelayRuntimeTypes.commitLocalUpdate;
|
||||
export import commitMutation = RelayRuntimeTypes.commitRelayModernMutation;
|
||||
export import fetchQuery = RelayRuntimeTypes.fetchRelayModernQuery;
|
||||
export import requestSubscription = RelayRuntimeTypes.requestRelaySubscription;
|
||||
|
||||
// exported for convenience — not exports in the original module
|
||||
export import RelayProp = RelayModernTypes.RelayProp;
|
||||
export import RelayPaginationProp = RelayModernTypes.RelayPaginationProp;
|
||||
export import RelayRefetchProp = RelayModernTypes.RelayRefetchProp;
|
||||
|
||||
declare module 'react-relay/compat' {
|
||||
export import applyOptimisticMutation = RelayCompatTypes.applyUpdate;
|
||||
export import commitMutation = RelayCompatTypes.commitUpdate;
|
||||
export import createFragmentContainer = RelayCompatTypes.createContainer;
|
||||
export import createPaginationContainer = RelayCompatTypes.createContainer;
|
||||
export import createRefetchContainer = RelayCompatTypes.createContainer;
|
||||
export import injectDefaultVariablesProvider = RelayCompatTypes.injectDefaultVariablesProvider;
|
||||
export import QueryRenderer = RelayModernTypes.ReactRelayQueryRenderer;
|
||||
export import graphql = RelayModernTypes.graphql;
|
||||
export import fetchQuery = RelayRuntimeTypes.fetchRelayModernQuery;
|
||||
}
|
||||
// tslint:enable strict-export-declare-modifiers
|
||||
|
||||
declare module "react-relay/classic" {
|
||||
import * as React from "react";
|
||||
|
||||
type ClientMutationID = string;
|
||||
|
||||
/** Fragments are a hash of functions */
|
||||
interface Fragments {
|
||||
[query: string]: ((variables?: RelayVariables) => string);
|
||||
}
|
||||
|
||||
interface CreateContainerOpts {
|
||||
initialVariables?: any;
|
||||
fragments: Fragments;
|
||||
prepareVariables?(prevVariables: RelayVariables): RelayVariables;
|
||||
}
|
||||
|
||||
interface RelayVariables {
|
||||
[name: string]: any;
|
||||
}
|
||||
|
||||
/** add static getFragment method to the component constructor */
|
||||
interface RelayContainerClass<T> extends React.ComponentClass<T> {
|
||||
getFragment: ((q: string, v?: RelayVariables) => string);
|
||||
}
|
||||
|
||||
interface RelayQueryRequestResolve {
|
||||
response: any;
|
||||
}
|
||||
|
||||
type RelayMutationStatus =
|
||||
'UNCOMMITTED' | // Transaction hasn't yet been sent to the server. Transaction can be committed or rolled back.
|
||||
'COMMIT_QUEUED' | // Transaction was committed but another transaction with the same collision key is pending, so the transaction has been queued to send to the server.
|
||||
'COLLISION_COMMIT_FAILED' | // Transaction was queued for commit but another transaction with the same collision key failed. All transactions in the collision queue,
|
||||
// including this one, have been failed. Transaction can be recommitted or rolled back.
|
||||
'COMMITTING' | // Transaction is waiting for the server to respond.
|
||||
'COMMIT_FAILED';
|
||||
|
||||
class RelayMutationTransaction {
|
||||
applyOptimistic(): RelayMutationTransaction;
|
||||
commit(): RelayMutationTransaction | null;
|
||||
recommit(): void;
|
||||
rollback(): void;
|
||||
getError(): Error;
|
||||
getStatus(): RelayMutationStatus;
|
||||
getHash(): string;
|
||||
getID(): ClientMutationID;
|
||||
}
|
||||
|
||||
interface RelayMutationRequest {
|
||||
getQueryString(): string;
|
||||
getVariables(): RelayVariables;
|
||||
resolve(result: RelayQueryRequestResolve): any;
|
||||
reject(errors: any): any;
|
||||
}
|
||||
|
||||
interface RelayQueryRequest {
|
||||
resolve(result: RelayQueryRequestResolve): any;
|
||||
reject(errors: any): any;
|
||||
getQueryString(): string;
|
||||
getVariables(): RelayVariables;
|
||||
getID(): string;
|
||||
getDebugName(): string;
|
||||
}
|
||||
|
||||
interface RelayNetworkLayer {
|
||||
supports(...options: string[]): boolean;
|
||||
}
|
||||
|
||||
class DefaultNetworkLayer implements RelayNetworkLayer {
|
||||
constructor(host: string, options?: any);
|
||||
supports(...options: string[]): boolean;
|
||||
}
|
||||
|
||||
function createContainer<T>(component: React.ComponentClass<T> | React.StatelessComponent<T>, params?: CreateContainerOpts): RelayContainerClass<T>;
|
||||
function injectNetworkLayer(networkLayer: RelayNetworkLayer): any;
|
||||
function isContainer(component: React.ComponentClass<any>): boolean;
|
||||
function QL(...args: any[]): string;
|
||||
|
||||
class Route {
|
||||
constructor(params?: RelayVariables)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relay Mutation class, where T are the props it takes and S is the returned payload from Relay.Store.update.
|
||||
* S is typically dynamic as it depends on the data the app is currently using, but it's possible to always
|
||||
* return some data in the payload using REQUIRED_CHILDREN which is where specifying S is the most useful.
|
||||
*/
|
||||
class Mutation<T, S> {
|
||||
props: T;
|
||||
|
||||
constructor(props: T);
|
||||
static getFragment(q: string): string;
|
||||
}
|
||||
|
||||
interface Transaction {
|
||||
getError(): Error;
|
||||
Status(): number;
|
||||
}
|
||||
|
||||
interface StoreUpdateCallbacks<T> {
|
||||
onFailure?(transaction: Transaction): any;
|
||||
onSuccess?(response: T): any;
|
||||
}
|
||||
|
||||
interface Store {
|
||||
commitUpdate(mutation: Mutation<any, any>, callbacks?: StoreUpdateCallbacks<any>): any;
|
||||
}
|
||||
|
||||
const Store: Store;
|
||||
|
||||
class RootContainer extends React.Component<RootContainerProps, any> { }
|
||||
|
||||
interface RootContainerProps extends React.Props<RootContainer> {
|
||||
Component: RelayContainerClass<any>;
|
||||
route: Route;
|
||||
renderLoading?(): JSX.Element;
|
||||
renderFetched?(data: any): JSX.Element;
|
||||
renderFailure?(error: Error, retry: (...args: any[]) => any): JSX.Element;
|
||||
}
|
||||
|
||||
class Renderer extends React.Component<RendererProps, any> { }
|
||||
|
||||
interface RendererProps {
|
||||
Container: RelayContainerClass<any>; // Relay container that defines fragments and the view to render.
|
||||
forceFetch?: boolean; // Whether to send a server request regardless of data available on the client.
|
||||
queryConfig: Route; // `QueryConfig` or `Relay.Route` that defines the query roots.
|
||||
environment: Store; // An instance of `Relay.Environment` or any object that implements the `RelayEnvironment` interface.
|
||||
render?: RenderCallback; // Called to render when data requirements are being fulfilled.
|
||||
onReadyStateChange?: OnReadyStateChange;
|
||||
}
|
||||
|
||||
interface RenderStateConfig {
|
||||
props?: { [propName: string]: any };
|
||||
done: boolean;
|
||||
error?: Error;
|
||||
retry?(): void;
|
||||
stale: boolean;
|
||||
}
|
||||
type RenderCallback = (renderState: RenderStateConfig) => any;
|
||||
|
||||
type ReadyStateEvent =
|
||||
'ABORT' |
|
||||
'CACHE_RESTORED_REQUIRED' |
|
||||
'CACHE_RESTORE_FAILED' |
|
||||
'CACHE_RESTORE_START' |
|
||||
'NETWORK_QUERY_ERROR' |
|
||||
'NETWORK_QUERY_RECEIVED_ALL' |
|
||||
'NETWORK_QUERY_RECEIVED_REQUIRED' |
|
||||
'NETWORK_QUERY_START' |
|
||||
'STORE_FOUND_ALL' |
|
||||
'STORE_FOUND_REQUIRED';
|
||||
|
||||
type OnReadyStateChange = (readyState: {
|
||||
ready: boolean,
|
||||
done: boolean,
|
||||
stale: boolean,
|
||||
error?: Error,
|
||||
events: ReadyStateEvent[],
|
||||
aborted: boolean
|
||||
}) => void;
|
||||
|
||||
interface RelayProp {
|
||||
readonly route: { name: string; }; // incomplete, also has params and queries
|
||||
readonly variables: any;
|
||||
readonly pendingVariables?: any;
|
||||
setVariables(variables: any, onReadyStateChange?: OnReadyStateChange): void;
|
||||
forceFetch(variables: any, onReadyStateChange?: OnReadyStateChange): void;
|
||||
hasOptimisticUpdate(record: any): boolean;
|
||||
getPendingTransactions(record: any): RelayMutationTransaction[];
|
||||
commitUpdate(mutation: Mutation<any, any>, callbacks?: StoreUpdateCallbacks<any>): any;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,437 @@
|
||||
import * as React from "react";
|
||||
import {
|
||||
Environment,
|
||||
Network,
|
||||
RecordSource,
|
||||
Store,
|
||||
ConnectionHandler,
|
||||
} from 'relay-runtime';
|
||||
|
||||
////////////////////////////
|
||||
// RELAY MODERN TESTS
|
||||
///////////////////////////
|
||||
import {
|
||||
graphql,
|
||||
commitMutation,
|
||||
createFragmentContainer,
|
||||
createPaginationContainer,
|
||||
createRefetchContainer,
|
||||
requestSubscription,
|
||||
QueryRenderer,
|
||||
RelayPaginationProp,
|
||||
RelayRefetchProp
|
||||
} from "react-relay";
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// Modern Environment
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
function fetchQuery(operation: any, variables: any, cacheConfig: {}) {
|
||||
return fetch('/graphql');
|
||||
}
|
||||
const network = Network.create(fetchQuery);
|
||||
const source = new RecordSource();
|
||||
const store = new Store(source);
|
||||
const modernEnvironment = new Environment({ network, store });
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// Modern QueryRenderer
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
const MyQueryRenderer = (props: { name: string}) => (
|
||||
<QueryRenderer
|
||||
environment={ modernEnvironment }
|
||||
query={graphql`
|
||||
query ExampleQuery($pageID: ID!) {
|
||||
page(id: $pageID) {
|
||||
name
|
||||
}
|
||||
}
|
||||
`}
|
||||
variables={{
|
||||
pageID: '110798995619330',
|
||||
}}
|
||||
render={({error, props}) => {
|
||||
if (error) {
|
||||
return <div>{error.message}</div>;
|
||||
} else if (props) {
|
||||
return <div>{props.name} is great!</div>;
|
||||
}
|
||||
return <div>Loading</div>;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// Modern FragmentContainer
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
const MyFragmentContainer = createFragmentContainer(
|
||||
class TodoListView extends React.Component {
|
||||
render() {
|
||||
return <div/>;
|
||||
}
|
||||
},
|
||||
{
|
||||
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<FeedStoriesProps> {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{this.props.feed.stories.edges.map(
|
||||
edge => <Story story={edge.node} key={edge.node.id} />
|
||||
)}
|
||||
<button
|
||||
onClick={() => this._loadMore}
|
||||
title="Load More"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
_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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
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<FeedProps> {
|
||||
render() {
|
||||
return (<div>
|
||||
{this.props.user.feed.edges.map(
|
||||
edge => <Story story={edge.node} key={edge.node.id} />
|
||||
)}
|
||||
<button
|
||||
onClick={() => this._loadMore()}
|
||||
title="Load More"
|
||||
/>
|
||||
</div>);
|
||||
}
|
||||
|
||||
_loadMore() {
|
||||
if (!this.props.relay.hasMore() || this.props.relay.isLoading()) {
|
||||
return;
|
||||
}
|
||||
|
||||
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: { user: {feed: any}}) {
|
||||
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
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
const mutation = graphql`
|
||||
mutation MarkReadNotificationMutation(
|
||||
$input: MarkReadNotificationData!
|
||||
) {
|
||||
markReadNotification(data: $input) {
|
||||
notification {
|
||||
seenState
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const optimisticResponse = {
|
||||
markReadNotification: {
|
||||
notification: {
|
||||
seenState: 'SEEN',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const configs = [{
|
||||
type: 'NODE_DELETE' as 'NODE_DELETE',
|
||||
deletedIDFieldName: 'destroyedShipId',
|
||||
}, {
|
||||
type: 'RANGE_ADD' as 'RANGE_ADD',
|
||||
parentID: 'shipId',
|
||||
connectionInfo: [{
|
||||
key: 'AddShip_ships',
|
||||
rangeBehavior: 'append',
|
||||
}],
|
||||
edgeName: 'newShipEdge',
|
||||
}, {
|
||||
type: 'RANGE_DELETE' as 'RANGE_DELETE',
|
||||
parentID: 'todoId',
|
||||
connectionKeys: [{
|
||||
key: 'RemoveTags_tags',
|
||||
rangeBehavior: 'append',
|
||||
}],
|
||||
pathToConnection: ['todo', 'tags'],
|
||||
deletedIDFieldName: 'removedTagId'
|
||||
}];
|
||||
|
||||
function markNotificationAsRead(source: string, storyID: string) {
|
||||
const variables = {
|
||||
input: {
|
||||
source,
|
||||
storyID,
|
||||
},
|
||||
};
|
||||
|
||||
commitMutation(
|
||||
modernEnvironment,
|
||||
{
|
||||
configs,
|
||||
mutation,
|
||||
optimisticResponse,
|
||||
variables,
|
||||
onCompleted: (response, errors) => {
|
||||
console.log('Response received from server.');
|
||||
},
|
||||
onError: err => console.error(err),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
// Modern Subscriptions
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
const subscription = graphql`
|
||||
subscription MarkReadNotificationSubscription(
|
||||
$storyID: ID!
|
||||
) {
|
||||
markReadNotification(storyID: $storyID) {
|
||||
notification {
|
||||
seenState
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
const variables = {
|
||||
storyID: '123',
|
||||
};
|
||||
requestSubscription(
|
||||
modernEnvironment, // see Environment docs
|
||||
{
|
||||
subscription,
|
||||
variables,
|
||||
// optional but recommended:
|
||||
onCompleted: () => {},
|
||||
onError: error => console.error(error),
|
||||
// example of a custom updater
|
||||
updater: store => {
|
||||
// Get the notification
|
||||
const rootField = store.getRootField('markReadNotification');
|
||||
const notification = !!rootField && rootField.getLinkedRecord('notification');
|
||||
// Add it to a connection
|
||||
const viewer = store.getRoot().getLinkedRecord('viewer');
|
||||
const notifications =
|
||||
ConnectionHandler.getConnection(viewer, 'notifications');
|
||||
const edge = ConnectionHandler.createEdge(
|
||||
store,
|
||||
notifications,
|
||||
notification,
|
||||
'<TypeOfNotificationsEdge>',
|
||||
);
|
||||
ConnectionHandler.insertEdgeAfter(notifications, edge);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
////////////////////////////
|
||||
// RELAY-CLASSIC TESTS
|
||||
///////////////////////////
|
||||
|
||||
import * as Relay from "react-relay/classic";
|
||||
|
||||
interface Props {
|
||||
text: string;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export default class AddTweetMutation extends Relay.Mutation<Props, {}> {
|
||||
getMutation() {
|
||||
return Relay.QL`mutation{addTweet}`;
|
||||
}
|
||||
|
||||
getFatQuery() {
|
||||
return Relay.QL`
|
||||
fragment on AddTweetPayload {
|
||||
tweetEdge
|
||||
user
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
getConfigs() {
|
||||
return [{
|
||||
type: "RANGE_ADD",
|
||||
parentName: "user",
|
||||
parentID: this.props.userId,
|
||||
connectionName: "tweets",
|
||||
edgeName: "tweetEdge",
|
||||
rangeBehaviors: {
|
||||
"": "append",
|
||||
},
|
||||
}];
|
||||
}
|
||||
|
||||
getVariables() {
|
||||
return this.props;
|
||||
}
|
||||
}
|
||||
|
||||
interface ArtworkProps {
|
||||
artwork: {
|
||||
title: string
|
||||
};
|
||||
relay: Relay.RelayProp;
|
||||
}
|
||||
|
||||
class Artwork extends React.Component<ArtworkProps> {
|
||||
render() {
|
||||
return (
|
||||
<a href={`/artworks/${this.props.relay.variables.artworkID}`}>
|
||||
{this.props.artwork.title}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const ArtworkContainer = Relay.createContainer(Artwork, {
|
||||
fragments: {
|
||||
artwork: () => Relay.QL`
|
||||
fragment on Artwork {
|
||||
title
|
||||
}
|
||||
`
|
||||
}
|
||||
});
|
||||
|
||||
class StubbedArtwork extends React.Component {
|
||||
render() {
|
||||
const props = {
|
||||
artwork: { title: "CHAMPAGNE FORMICA FLAG" },
|
||||
relay: {
|
||||
route: {
|
||||
name: "champagne"
|
||||
},
|
||||
variables: {
|
||||
artworkID: "champagne-formica-flag",
|
||||
},
|
||||
setVariables: () => {},
|
||||
forceFetch: () => {},
|
||||
hasOptimisticUpdate: () => false,
|
||||
getPendingTransactions: (): any => undefined,
|
||||
commitUpdate: () => {},
|
||||
}
|
||||
};
|
||||
return <ArtworkContainer {...props} />;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"lib": [
|
||||
"es6",
|
||||
"dom"
|
||||
],
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"strictNullChecks": true,
|
||||
"baseUrl": "../../",
|
||||
"typeRoots": [
|
||||
"../../"
|
||||
],
|
||||
"types": [],
|
||||
"noEmit": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"jsx": "react",
|
||||
"paths": {
|
||||
"react-relay": ["react-relay/v1"],
|
||||
"react-relay/*": ["react-relay/v2/*"]
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"index.d.ts",
|
||||
"react-relay-tests.tsx",
|
||||
"lib/react-relay-classic.d.ts",
|
||||
"lib/react-relay-modern.d.ts",
|
||||
"lib/react-relay-compat.d.ts"
|
||||
]
|
||||
}
|
||||
Vendored
+1090
-1092
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user