Skip to content
This repository has been archived by the owner on Jun 6, 2019. It is now read-only.

Commit

Permalink
feat(contextware for dataloaders): added kind of middleware that is r…
Browse files Browse the repository at this point in the history
…un on each operation to initial
  • Loading branch information
dacz committed Nov 29, 2017
1 parent ed36039 commit 0ea6843
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 7 deletions.
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,24 @@ import { InMemoryCache } from 'apollo-cache-inmemory';
import schema from './schema';

// your resolvers (see example)
import reolvers from './resolvers';
import resolvers from './resolvers';

// if you want to mock anything in the schema (that has not resolver or doesn't return data)
const mock = true;

// if you want to push something down to the resolvers in context
const context = {
graphQl: 'is cool'
}
graphQl: 'is cool',
};

// do something with actual context and operation of gql operation
// and return object that will be shallow merged to context
// use for init dataloader with token for example
// see example... https://github.com/dacz/apollo-bridge-link-example
const contextware = (ctx, operation) => ({ inContext: 'from contextware' });

export const client = new ApolloClient({
link: BridgeLink({ schema, resolvers, mock, context });
link: BridgeLink({ schema, resolvers, mock, context, contextware });
cache: new InMemoryCache({ addTypename: true }),
});
```
Expand Down
18 changes: 16 additions & 2 deletions src/bridgeLink.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ import { addMockFunctionsToSchema, makeExecutableSchema } from 'graphql-tools';
import { ApolloLink } from 'apollo-link';
import Observable from 'zen-observable';

export const createBridgeLink = ({ schema, resolvers, mock, context = {} }) => {
export const createBridgeLink = ({
schema,
resolvers,
mock,
context = {},
contextware = [],
}) => {
let executableSchema;
if (typeof schema === 'string') {
executableSchema = makeExecutableSchema({ typeDefs: schema, resolvers });
Expand All @@ -31,12 +37,20 @@ export const createBridgeLink = ({ schema, resolvers, mock, context = {} }) => {
operation =>
new Observable(observer => {
const { headers, credentials } = operation.getContext();
const ctx = {
const ctxInitial = {
...context,
headers,
credentials,
};

// contextware
const ctx = [].concat(contextware).reduce((acc, fn) => {
const rv = fn(acc, operation);
return typeof rv === 'object' && !Array.isArray(rv)
? { ...acc, ...rv }
: acc;
}, ctxInitial);

graphql(
executableSchema,
print(operation.query),
Expand Down
19 changes: 18 additions & 1 deletion src/bridgeLink.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,23 @@ test('BridgeLink mocks data', async t => {
t.truthy(res.data.posts[0].author.id, 'should have mocked author');
});

test('BridgeLink calls contextware', async t => {
const returning = { middle: 'data' };
const init = sinon.mock().returns(returning);
const opts = {
schema: schemaExample,
mock: true,
contextware: init,
};
const link = new BridgeLink(opts);
const cache = new InMemoryCache();
const client = new ApolloClient({ link, cache });
const res = await client.query({ query: POSTS });
t.true(res.data.posts.length > 0, 'should get some mocked data');
t.truthy(res.data.posts[0].author.id, 'should have mocked author');
t.true(init.calledOnce);
});

test('BridgeLink should accept executable schema', async t => {
const posts = [
{
Expand Down Expand Up @@ -170,7 +187,7 @@ test('createBridgeLink - creates link', t => {
const schema = schemaExample;
const resolvers = {};
const mock = false;
const context = {};
const context = { gq: 'is cool' };
const link = createBridgeLink({ schema, resolvers, mock, context });
t.true(link instanceof ApolloLink);
});
Expand Down

0 comments on commit 0ea6843

Please sign in to comment.