Skip to content

Commit

Permalink
support hasNext
Browse files Browse the repository at this point in the history
  • Loading branch information
robrichard committed Jul 7, 2020
1 parent b58a501 commit 0c5c2fb
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 3 deletions.
4 changes: 4 additions & 0 deletions packages/relay-runtime/network/RelayNetworkTypes.js
Expand Up @@ -15,6 +15,7 @@
import type {RequestParameters} from '../util/RelayConcreteNode';
import type {CacheConfig, Variables} from '../util/RelayRuntimeTypes';
import type RelayObservable, {ObservableFromValue} from './RelayObservable';
import {boolean} from 'yargs';

/**
* An interface for fetching the data for one or more (possibly interdependent)
Expand Down Expand Up @@ -51,6 +52,7 @@ export type GraphQLResponseWithData = {|
+extensions?: PayloadExtensions,
+label?: string,
+path?: Array<string | number>,
+hasNext?: boolean,
|};

export type GraphQLResponseWithoutData = {|
Expand All @@ -59,6 +61,7 @@ export type GraphQLResponseWithoutData = {|
+extensions?: PayloadExtensions,
+label?: string,
+path?: Array<string | number>,
+hasNext?: boolean,
|};

export type GraphQLResponseWithExtensionsOnly = {|
Expand All @@ -72,6 +75,7 @@ export type GraphQLResponseWithExtensionsOnly = {|
// does not necessarily indicate that there was an error.
+data: null,
+extensions: PayloadExtensions,
+hasNext?: boolean,
|};

export type GraphQLSingularResponse =
Expand Down
48 changes: 48 additions & 0 deletions packages/relay-runtime/query/__tests__/fetchQueryInternal-test.js
Expand Up @@ -964,6 +964,30 @@ describe('getObservableForActiveRequest', () => {
expect(events).toEqual(['next']);
});

it('calls next asynchronously with subsequent non-final payloads (OSS)', () => {
fetchQuery(environment, query).subscribe({});
const observable = getObservableForActiveRequest(
environment,
query.request,
);
expect(observable).not.toEqual(null);
if (!observable) {
return;
}

response = {
...response,
extensions: {},
hasNext: true,
};

observable.subscribe(observer);
expect(events).toEqual([]);

environment.mock.nextValue(gqlQuery, response);
expect(events).toEqual(['next']);
});

it('calls complete asynchronously with subsequent final payload', () => {
fetchQuery(environment, query).subscribe({});
const observable = getObservableForActiveRequest(
Expand All @@ -982,6 +1006,30 @@ describe('getObservableForActiveRequest', () => {
expect(events).toEqual(['complete']);
});

it('calls complete asynchronously with subsequent final payload (OSS)', () => {
fetchQuery(environment, query).subscribe({});
const observable = getObservableForActiveRequest(
environment,
query.request,
);
expect(observable).not.toEqual(null);
if (!observable) {
return;
}

response = {
...response,
extensions: {},
hasNext: false,
};

observable.subscribe(observer);
expect(events).toEqual([]);

environment.mock.nextValue(gqlQuery, response);
expect(events).toEqual(['complete']);
});

describe('when loading @module', () => {
let operationLoader;
let resolveModule;
Expand Down
19 changes: 16 additions & 3 deletions packages/relay-runtime/store/RelayModernQueryExecutor.js
Expand Up @@ -400,7 +400,7 @@ class Executor {
if (responsesWithData.length === 0) {
// no results with data, nothing to process
// this can occur with extensions-only payloads
const isFinal = responses.some(x => x.extensions?.is_final === true);
const isFinal = responses.some(x => responseIsFinal(x));
if (isFinal) {
this._state = 'loading_final';
this._updateActiveState();
Expand Down Expand Up @@ -1019,7 +1019,7 @@ class Executor {
incrementalPlaceholders: null,
moduleImportPayloads: null,
source: RelayRecordSource.create(),
isFinal: response.extensions?.is_final === true,
isFinal: responseIsFinal(response),
};
this._publishQueue.commitPayload(
this._operation,
Expand Down Expand Up @@ -1296,7 +1296,7 @@ function normalizeResponse(
return {
...relayPayload,
errors,
isFinal: response.extensions?.is_final === true,
isFinal: responseIsFinal(response),
};
}

Expand All @@ -1318,4 +1318,17 @@ function validateOptimisticResponsePayload(
}
}

/**
* Check for both FB specific (extensions?.is_final)
* and spec-complaint (hasNext) properties.
*/
function responseIsFinal(response: GraphQLSingularResponse): boolean {
if (response.extensions?.is_final === true) {
return true;
} else if (response.hasNext === false) {
return true;
}
return false;
}

module.exports = {execute};

0 comments on commit 0c5c2fb

Please sign in to comment.