Skip to content

Commit 03d28b1

Browse files
committed
chore: documentation cleanup
1 parent 3292e85 commit 03d28b1

File tree

8 files changed

+183
-333
lines changed

8 files changed

+183
-333
lines changed

packages/graphiql-create-fetcher/src/createFetcher.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export function createGraphiQLFetcher(options: CreateFetcherOptions): Fetcher {
3535
if (!httpFetch) {
3636
throw Error('No valid fetcher implementation available');
3737
}
38-
38+
// simpler fetcher for schema requests
3939
const simpleFetcher = createSimpleFetcher(options, httpFetch);
4040

4141
if (options.subscriptionUrl) {
@@ -49,12 +49,15 @@ export function createGraphiQLFetcher(options: CreateFetcherOptions): Fetcher {
4949
? createMultipartFetcher(options, httpFetch)
5050
: simpleFetcher;
5151

52-
return (graphQLParams, opts) => {
52+
return (graphQLParams, fetcherOpts) => {
5353
if (graphQLParams.operationName === 'IntrospectionQuery') {
54-
return simpleFetcher(graphQLParams, opts);
54+
return (options.schemaFetcher || simpleFetcher)(
55+
graphQLParams,
56+
fetcherOpts,
57+
);
5558
}
5659
const isSubscription = isSubscriptionWithName(
57-
opts?.documentAST!,
60+
fetcherOpts?.documentAST!,
5861
graphQLParams.operationName,
5962
);
6063
if (isSubscription) {
@@ -69,6 +72,6 @@ export function createGraphiQLFetcher(options: CreateFetcherOptions): Fetcher {
6972
}
7073
return wsFetcher(graphQLParams);
7174
}
72-
return httpFetcher(graphQLParams, opts);
75+
return httpFetcher(graphQLParams, fetcherOpts);
7376
};
7477
}

packages/graphiql-create-fetcher/src/lib.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { DocumentNode, visit } from 'graphql';
22
import { meros } from 'meros';
3-
import { createClient, Client } from 'graphql-ws';
3+
import { createClient, Client, ClientOptions } from 'graphql-ws';
44
import { SubscriptionClient } from 'subscriptions-transport-ws';
55
import {
66
isAsyncIterable,
@@ -67,7 +67,10 @@ export const createSimpleFetcher = (
6767
return data.json();
6868
};
6969

70-
export const createWebsocketsFetcherFromUrl = (url: string) => {
70+
export const createWebsocketsFetcherFromUrl = (
71+
url: string,
72+
connectionParams?: ClientOptions['connectionParams'],
73+
) => {
7174
let wsClient: Client | null = null;
7275
let legacyClient: SubscriptionClient | null = null;
7376
if (url) {
@@ -76,12 +79,13 @@ export const createWebsocketsFetcherFromUrl = (url: string) => {
7679
// TODO: defaults?
7780
wsClient = createClient({
7881
url,
82+
connectionParams,
7983
});
8084
if (!wsClient) {
81-
legacyClient = new SubscriptionClient(url);
85+
legacyClient = new SubscriptionClient(url, { connectionParams });
8286
}
8387
} catch (err) {
84-
legacyClient = new SubscriptionClient(url);
88+
legacyClient = new SubscriptionClient(url, { connectionParams });
8589
}
8690
} catch (err) {
8791
console.error(`Error creating websocket client for:\n${url}\n\n${err}`);

packages/graphiql-create-fetcher/src/types.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import type { Client } from 'graphql-ws';
1+
import type { Client, ClientOptions } from 'graphql-ws';
22
import type { SubscriptionClient } from 'subscriptions-transport-ws';
3+
import type { Fetcher } from '@graphiql/toolkit';
34

45
export type WebsocketsClient = Client | SubscriptionClient;
56

@@ -27,6 +28,10 @@ export interface CreateFetcherOptions {
2728
* A header you set statically here, it will be overriden by their value.
2829
*/
2930
headers?: Record<string, string>;
31+
/**
32+
* Websockets connection params used when you provide subscriptionUrl. graphql-ws `ClientOptions.connectionParams`
33+
*/
34+
wsConnectionParams?: ClientOptions['connectionParams'];
3035
/**
3136
* You can disable the usage of the `fetch-multipart-graphql` library
3237
* entirely, defaulting to a simple fetch POST implementation.
@@ -38,4 +43,9 @@ export interface CreateFetcherOptions {
3843
* default fetch behavior yet.
3944
*/
4045
fetch?: typeof fetch;
46+
/**
47+
* An optional custom fetcher specifically for your schema. For most cases
48+
* the `url` and `headers` property should have you covered.
49+
*/
50+
schemaFetcher?: Fetcher;
4151
}

packages/graphiql-toolkit/src/types.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,16 @@ export type FetcherResultPayload =
3939
| {
4040
data: IntrospectionQuery;
4141
errors?: Array<any>;
42-
hasNext?: boolean;
4342
}
44-
| { data?: any; errors?: Array<any>; hasNext?: boolean }
45-
// for IncrementalDelivery
43+
// normal result payloads
44+
| { data?: any; errors?: Array<any> }
45+
// for the initial Stream/Defer payload
46+
| { data?: any; errors?: Array<any>; hasNext: boolean }
47+
// for successive Stream/Defer payloads
4648
| {
4749
data?: any;
4850
errors?: any[];
49-
path?: (string | number)[];
51+
path: (string | number)[];
5052
hasNext: boolean;
5153
};
5254

packages/graphiql/README.md

Lines changed: 99 additions & 304 deletions
Large diffs are not rendered by default.

packages/graphiql/cypress/integration/incrementalDelivery.spec.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,16 @@ const mockStreamSuccess = {
4444
hasNext: false,
4545
};
4646

47+
const testDeferQuery = /* GraphQL */ `
48+
query DeferQuery($delay: Int) {
49+
streamable(delay: $delay) @stream(initialCount: 2) {
50+
text
51+
}
52+
}
53+
`;
54+
4755
describe('IncrementalDelivery support via fetcher', () => {
48-
it('Expects slower streams to resolve in several increments', () => {
56+
it('Expects slower streams to resolve in several increments, and the payloads to patch properly', () => {
4957
const delay = 100;
5058
const timeout = mockStreamSuccess.data.streamable.length * (delay * 1.5);
5159

packages/graphiql/src/components/GraphiQL.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,7 +1068,8 @@ export class GraphiQL extends React.Component<GraphiQLProps, GraphiQLState> {
10681068
);
10691069
}
10701070

1071-
const totalResponse: FetcherResultPayload = { data: {} };
1071+
// when dealing with defer or stream, we need to aggregate results
1072+
const fullResponse: FetcherResultPayload = { data: {}, hasNext: false };
10721073

10731074
// _fetchQuery may return a subscription.
10741075
const subscription = await this._fetchQuery(
@@ -1080,36 +1081,36 @@ export class GraphiQL extends React.Component<GraphiQLProps, GraphiQLState> {
10801081
(result: FetcherResult) => {
10811082
if (queryID === this._editorQueryID) {
10821083
if (
1083-
typeof result === 'object' &&
1084+
typeof result !== 'string' &&
10841085
result !== null &&
10851086
'hasNext' in result
10861087
) {
10871088
if (result.errors) {
10881089
// We dont care about "index" here, just concat.
1089-
totalResponse.errors = [
1090-
...(totalResponse?.errors || []),
1090+
fullResponse.errors = [
1091+
...(fullResponse?.errors || []),
10911092
...result?.errors,
10921093
];
10931094
}
10941095

1095-
totalResponse.hasNext = result.hasNext;
1096+
fullResponse.hasNext = result.hasNext;
10961097

10971098
if ('path' in result) {
10981099
if (!('data' in result)) {
10991100
throw new Error(
11001101
`Expected part to contain a data property, but got ${result}`,
11011102
);
11021103
}
1103-
dset(totalResponse.data, result.path!.map(String), result.data);
1104+
dset(fullResponse.data, result.path, result.data);
11041105
} else if ('data' in result) {
11051106
// If there is no path, we don't know what to do with the payload,
11061107
// so we just set it.
1107-
totalResponse.data = result.data;
1108+
fullResponse.data = result.data;
11081109
}
11091110

11101111
this.setState({
11111112
isWaitingForResponse: false,
1112-
response: GraphiQL.formatResult(totalResponse),
1113+
response: GraphiQL.formatResult(fullResponse),
11131114
});
11141115
} else {
11151116
this.setState({

packages/graphiql/test/schema.js

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,34 @@ const Greeting = new GraphQLObjectType({
137137
},
138138
});
139139

140+
const delayArgument = (defaultValue = 400) => ({
141+
description:
142+
'delay in milleseconds for subsequent results, for demonstration purposes',
143+
type: GraphQLInt,
144+
defaultValue,
145+
});
146+
147+
const DeferrableObject = new GraphQLObjectType({
148+
name: 'Deferrable',
149+
fields: {
150+
normalString: {
151+
type: GraphQLString,
152+
resolve: () => `Nice`,
153+
},
154+
deferredString: {
155+
args: {
156+
delay: delayArgument(600),
157+
},
158+
type: GraphQLString,
159+
resolve: async function lazilyReturnValue(_value, args) {
160+
const seconds = args.delay / 1000;
161+
await sleep(args.delay);
162+
return `Oops, this took ${seconds} seconds longer than I thought it would!`;
163+
},
164+
},
165+
},
166+
});
167+
140168
const sleep = async timeout => new Promise(res => setTimeout(res, timeout));
141169

142170
const TestType = new GraphQLObjectType({
@@ -147,15 +175,14 @@ const TestType = new GraphQLObjectType({
147175
description: '`test` field from `Test` type.',
148176
resolve: () => ({}),
149177
},
178+
deferrable: {
179+
type: DeferrableObject,
180+
resolve: () => ({}),
181+
},
150182
streamable: {
151183
type: new GraphQLList(Greeting),
152184
args: {
153-
delay: {
154-
description:
155-
'delay in milleseconds for subsequent results, for demonstration purposes',
156-
type: GraphQLInt,
157-
defaultValue: 400,
158-
},
185+
delay: delayArgument(300),
159186
},
160187
resolve: async function* sayHiInSomeLanguages(_value, args) {
161188
let i = 0;

0 commit comments

Comments
 (0)