Comments (7)
Hi @toddtarsi, I was hoping you could hep me out. I have trouble getting this library to work with Apollo 2.0. I was hoping you could help me in my implementation to see what I'm doing wrong.
This is how I'm implementing my Apollo client.
const link = ApolloLink.from([addHeaders, stateLink, restLink, httpLink]); const apolloClient = new ApolloClient({ cache, link });
const newApolloClient = addPersistedQueries(apolloClient, queryMap);
export default newApolloClient;`
I'm using the apollo graphql
function from react-apollo
for querying but the queries don't seem to be getting transformed.
Any help would be greatly appreciated.
Thank you!
from persistgraphql.
I'll do my best @oluwie -
Okay, so this is how I'm using persistgraphql with a small commander script to build my queries:
// @flow
/* eslint-disable no-console */
/* eslint-disable import/no-extraneous-dependencies */
import program from 'commander';
import { ExtractGQL } from 'persistgraphql/lib/src/ExtractGQL';
import queryTransformers from '../helpers/queryTransformers';
program
.version('0.1.0')
.usage('[options] <file...>')
.option('-i, --input <p>', 'Input Directory', '')
.option('-o, --output <p>', 'Output file', '')
.parse(process.argv);
new ExtractGQL({
inputFilePath: program.input,
outputFilePath: program.output,
queryTransformers,
}).extract();
My queryTransformers file is the following. It looks a bit crazy, but uses the addTypename transform, as well as another transform I wrote to strip all client fields. I intend to open source that this weekend (edit: i fixed the d.name.value check later):
// @flow
/* eslint-disable no-console */
/* eslint-disable import/no-extraneous-dependencies */
import {
DefinitionNode,
DocumentNode,
} from 'graphql';
import { QueryTransformer } from 'persistgraphql/lib/src/common';
import { addTypenameTransformer } from 'persistgraphql/lib/src/queryTransformers';
function removeClientFieldsFromSelectionSet(selectionSet) {
if (selectionSet.selections) {
// eslint-disable-next-line no-param-reassign
selectionSet.selections = selectionSet.selections.map((selection) => {
if (selection.directives && selection.directives.length) {
const hasClient = selection.directives.find(d => d.name.value === 'client');
if (hasClient) return false;
}
if (selection.kind === 'Field' || selection.kind === 'InlineFragment') {
if (selection.selectionSet) {
removeClientFieldsFromSelectionSet(selection.selectionSet);
}
}
return selection;
}).filter(s => !!s);
}
return selectionSet;
}
const removeClientFieldsTransformer: QueryTransformer = (doc: DocumentNode) => {
const docClone = JSON.parse(JSON.stringify(doc));
docClone.definitions.forEach((definition: DefinitionNode) => {
const isRoot = definition.kind === 'OperationDefinition';
removeClientFieldsFromSelectionSet(definition.selectionSet, isRoot);
});
return docClone;
};
export default [
addTypenameTransformer,
removeClientFieldsTransformer,
];
As a note, it's currently impossible to use custom transforms with https://github.com/leoasis/graphql-persisted-document-loader until leoasis/graphql-persisted-document-loader#2 is accepted, at which point you'll be able to pass in your own queryTransformers via the webpack loader. I have a fork doing this, which I'm using here: https://github.com/toddtarsi/graphql-persisted-document-loader. This is what that looks like inline with the webpack stuff:
import persistedQueries from './persistedQueries.json';
import queryTransformers from './queryTransformers';
...
{
exclude: /node_modules/,
test: /\.(graphql|gql)$/,
use: [
{
loader: 'graphql-persisted-document-loader',
options: {
generateId: query => persistedQueries[query],
queryTransformers,
},
}, // <= Before graphql-tag/loader!
{ loader: 'graphql-tag/loader' },
],
},
...
Note, if this isn't accepted, we're both over a barrel, hah!
Also, in case it's an issue in the link ordering, this is the overall order of my link components too:
[error, context, state, persisted-queries, http]
.
Hope this helps!
from persistgraphql.
Oh, @oluwie - This is how I'm building my persisted-queries link more granularly:
const persistOpts = {
generateHash: ({ documentId }) => documentId,
useGETForHashedQueries: false,
};
const httpLink = from([
createPersistedQueryLink(persistOpts),
new HttpLink(network),
]);
from persistgraphql.
To provide a bit more explanation of why this is needed (last post honest):
In 2.0, our issue is this:
By the time the query has reached the http request, it has been transformed since the initial expectation (in our case, missing client fields). If we remove these fields from the fragments, we lose our data dependencies. If we keep these fields, the serverside queries will fail to match what the client sent up.
So, to get our shape back to matching, we have to transform our persisted queries to be the correct shape right before it goes out over http. By trimming our client fields here, the persisted query looked up on the server will match what the client actually sends after the whole apollo-link-state transformation.
from persistgraphql.
@toddtarsi I see. You're using the apollo-link-persisted-queries
for the actual as the network interface. From the README, I was under the impression that you use the addPersistedQueries
function exported by the ApolloNetworkInterface.ts
file to modify the network interface to use the queryMap object provided to that function.
I'm looking for a way to use the network interface provided by this module w/o having to import the apollo-link-persisted-queries
library.
from persistgraphql.
In that case, I don't have too much I can offer to help, but I see in your initial comment this:
const link = ApolloLink.from([addHeaders, stateLink, restLink, httpLink]);
const apolloClient = new ApolloClient({ cache, link });
const newApolloClient = addPersistedQueries(apolloClient, queryMap);
export default newApolloClient;
I think addPersistedQueries takes a networkInterface, not an apollo client instance. The whole networkInterface API around 2.x was converted to simple network options for httpLink. If you're on 1.x, then you'd instead pass it in to something like this:
const networkInterface = createNetworkInterface({
uri: 'http://api.example.com/graphql'
});
const client = new ApolloClient({
networkInterface: addPersistedQueries(networkInterface)
});
On a side note, if you're using stateLink and httpLink, I really think you should look at the persisted queries link again. It fits right in with that code paradigm quite nicely. Otherwise, you'll need an intermediate link before the httpLink and after the stateLink to vacuum your query down to the variables and id in your request. If you use this anywhere else, you either won't be able to resolve the client fields using apollo-link-state, or you won't have the client fields persisted in the query body. All in all, its a lot of stress and headaches, for a solution that's already mostly there.
from persistgraphql.
Hey all, I hope I am not raising too much trouble. I'll namespace the query transformer script above as:
persistgraphql-query-transform-trim-client-fields
Thanks again for the amazing tools, and you all are awesome!
from persistgraphql.
Related Issues (20)
- Maximum call stack error when using cloneDeep in query transformer
- [Idea] replace json property names with ordinals to reduce bandwidth HOT 4
- Must provide a query error when use with graphql-subscription
- Mixing .graphql files with tagged template literals HOT 1
- Server and client sync
- Can it be used with Relay Modern? HOT 2
- can't install on Windows HOT 2
- [BUG] persistgraphql serializes *differently* from apollo client, breaking the whitelist HOT 1
- Register query manually
- Support glob syntax [feature request]
- [BUG] template strings within attributes not parsed correctly
- Hapi17 Example
- Relax dependency requirements HOT 5
- Does not recognize .gql file extension HOT 1
- Commented out query causes syntax error during javascript extraction
- Queries from both external graphql files and JS extraction aren't output together
- This tool can only generate 1 query when scan a directory that contains multiple ".graphql" files HOT 2
- Add / enable Travis CI
- Support babel compiled AST.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from persistgraphql.