Skip to content

Commit

Permalink
Merge pull request #747 from apollostack/graphql-anywhere-refactor
Browse files Browse the repository at this point in the history
Refactor query reading to use graphql-anywhere
  • Loading branch information
Sashko Stubailo authored Oct 6, 2016
2 parents d9269e5 + b6f10c9 commit 0acec91
Show file tree
Hide file tree
Showing 11 changed files with 209 additions and 491 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ Expect active development and potentially significant breaking changes in the `0

### vNEXT

- **Refactor**: Reimplement internal store reading in terms of the [graphql-anywhere](https://github.com/apollostack/graphql-anywhere) package, which cleanly separates the GraphQL execution logic from Apollo's specific cache format. This will allow us to make the store reading much more extensible, including enabling developers to write their own custom client-side resolvers to implement client-side computed fields, read from Redux with GraphQL, and redirect cache reads.
- **Feature removal**: Remove query diffing functionality to make client more predictable and simplify implementation. Queries will still read from the store, and if the store does not have all of the necessary data the entire query will fetch from the server. Read justification and discussion in [Issue #615](https://github.com/apollostack/apollo-client/issues/615) [PR #693](https://github.com/apollostack/apollo-client/pull/693)
- **Breaking change**: Move batching to network interface and split off query merging into separate package [PR #734](https://github.com/apollostack/apollo-client/pull/734)
- **Feature removal**: No more `(read|diff)(Fragment|SelectionSet)FromStore`.

### v0.4.20
- Fix: Warn but do not fail when refetchQueries includes an unknown query name [PR #700](https://github.com/apollostack/apollo-client/pull/700)
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"license": "MIT",
"dependencies": {
"es6-promise": "^4.0.3",
"graphql-anywhere": "^0.1.11",
"graphql-tag": "^0.1.13",
"lodash.assign": "^4.0.8",
"lodash.clonedeep": "^4.3.2",
Expand Down
60 changes: 41 additions & 19 deletions src/core/QueryManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,17 @@ import {
/* tslint:disable */
SelectionSet,
/* tslint:enable */
OperationDefinition,
} from 'graphql';

import { print } from 'graphql-tag/printer';

import {
readSelectionSetFromStore,
readQueryFromStore,
} from '../data/readFromStore';

import {
diffSelectionSetAgainstStore,
diffQueryAgainstStore,
} from '../data/diffAgainstStore';

import {
Expand Down Expand Up @@ -343,13 +344,12 @@ export class QueryManager {
} else {
try {
const resultFromStore = {
data: readSelectionSetFromStore({
data: readQueryFromStore({
store: this.getDataWithOptimisticResults(),
rootId: queryStoreValue.query.id,
selectionSet: queryStoreValue.query.selectionSet,
query: makeDocument(
queryStoreValue.query.selectionSet, 'ROOT_QUERY', queryStoreValue.fragmentMap),
variables: queryStoreValue.previousVariables || queryStoreValue.variables,
returnPartialData: options.returnPartialData || options.noFetch,
fragmentMap: queryStoreValue.fragmentMap,
}),
loading: queryStoreValue.loading,
};
Expand Down Expand Up @@ -619,22 +619,20 @@ export class QueryManager {
// results including previous optimistic updates. Otherwise, apply it
// on top of the real data only.
store: isOptimistic ? this.getDataWithOptimisticResults() : this.getApolloState().data,
rootId: 'ROOT_QUERY',
selectionSet: querySelectionSet,
query: makeDocument(querySelectionSet, 'ROOT_QUERY', createFragmentMap(queryFragments || [])),
variables: queryVariables,
fragmentMap: createFragmentMap(queryFragments || []),
returnPartialData: false,
};
try {
// first try reading the full result from the store
const data = readSelectionSetFromStore(readOptions);
const data = readQueryFromStore(readOptions);
return { data, partial: false };
} catch (e) {
// next, try reading partial results, if we want them
if (queryOptions.returnPartialData || queryOptions.noFetch) {
try {
readOptions.returnPartialData = true;
const data = readSelectionSetFromStore(readOptions);
const data = readQueryFromStore(readOptions);
return { data, partial: true };
} catch (e) {
// fall through
Expand Down Expand Up @@ -838,13 +836,11 @@ export class QueryManager {
// ensure result is combined with data already in store
// this will throw an error if there are missing fields in
// the results if returnPartialData is false.
resultFromStore = readSelectionSetFromStore({
resultFromStore = readQueryFromStore({
store: this.getApolloState().data,
rootId: querySS.id,
selectionSet: querySS.selectionSet,
variables,
returnPartialData: returnPartialData || noFetch,
fragmentMap,
query,
});
// ensure multiple errors don't get thrown
/* tslint:disable */
Expand Down Expand Up @@ -898,13 +894,11 @@ export class QueryManager {
// If this is not a force fetch, we want to diff the query against the
// store before we fetch it from the network interface.
if (!forceFetch) {
const { isMissing, result } = diffSelectionSetAgainstStore({
selectionSet: queryDef.selectionSet,
const { isMissing, result } = diffQueryAgainstStore({
query: queryDoc,
store: this.reduxRootSelector(this.store.getState()).data,
throwOnMissingField: false,
rootId: querySS.id,
variables,
fragmentMap,
});

// If we're in here, only fetch if we have missing fields
Expand Down Expand Up @@ -1001,3 +995,31 @@ export class QueryManager {
return requestId;
}
}

// Shim to use graphql-anywhere, to be removed
function makeDocument(
selectionSet: SelectionSet,
rootId: string,
fragmentMap: FragmentMap
): Document {
if (rootId !== 'ROOT_QUERY') {
throw new Error('only supports query');
}

const op: OperationDefinition = {
kind: 'OperationDefinition',
operation: 'query',
selectionSet,
};

const frags: FragmentDefinition[] = fragmentMap ?
Object.keys(fragmentMap).map((name) => fragmentMap[name]) :
[];

const doc: Document = {
kind: 'Document',
definitions: [op, ...frags],
};

return doc;
}
1 change: 0 additions & 1 deletion src/data/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import isObject = require('lodash.isobject');
import omit = require('lodash.omit');
import mapValues = require('lodash.mapvalues');


export function stripLoc(obj: Object) {
if (isArray(obj)) {
return obj.map(stripLoc);
Expand Down
Loading

0 comments on commit 0acec91

Please sign in to comment.