Skip to content

Commit

Permalink
Fixes issue ardatan#901: WrapQuery - add support for...
Browse files Browse the repository at this point in the history
query wrapper to return selection set node.
Docs - add example where WrapQuery query wrapper
function returns a SelectionSet.
  • Loading branch information
jjbeavers-lifeomic committed Jul 24, 2018
1 parent d307398 commit ff48b89
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 5 deletions.
40 changes: 40 additions & 0 deletions docs/source/schema-transforms.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,46 @@ transforms: [
],
```

`WrapQuery` can also be used to expand multiple top level query fields

```js
transforms: [
// Wrap document takes a subtree as an AST node
new WrapQuery(
// path at which to apply wrapping and extracting
['userById'],
(subtree: SelectionSetNode) => {
const newSelectionSet = {
kind: Kind.SELECTION_SET,
selections: subtree.selections.map(selection => {
// just append fragments, not interesting for this
// test
if (selection.kind === Kind.INLINE_FRAGMENT ||
selection.kind === Kind.FRAGMENT_SPREAD) {
return selection;
}
// prepend `address` to name and camelCase
const oldFieldName = selection.name.value;
return {
kind: Kind.FIELD,
name: {
kind: Kind.NAME,
value: 'address' +
oldFieldName.charAt(0).toUpperCase() +
oldFieldName.slice(1)
}
};
})
};
return newSelectionSet;
},
// how to process the data result at path
result => ({
streetAddress: result.addressStreetAddress,
zip: result.addressZip
})
```
* `ReplaceFieldWithFragment(targetSchema: GraphQLSchema, fragments: Array<{ field: string; fragment: string; }>)`: Replace the given fields with an inline fragment. Used by `mergeSchemas` to handle the `fragment` option.
<h2 id="other-built-in">delegateToSchema transforms</h2>
Expand Down
125 changes: 125 additions & 0 deletions src/test/testTransforms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -478,4 +478,129 @@ describe('transforms', () => {
});
});
});
describe('WrapQuery', () => {
let data: any;
let subSchema: GraphQLSchema;
let schema: GraphQLSchema;
before(() => {
data = {
u1: {
id: 'user1',
addressStreetAddress: 'Windy Shore 21 A 7',
addressZip: '12345'
}
};
subSchema = makeExecutableSchema({
typeDefs: `
type User {
id: ID!
addressStreetAddress: String
addressZip: String
}
type Query {
userById(id: ID!): User
}
`,
resolvers: {
Query: {
userById(parent, { id }) {
return data[id];
},
}
},
});
schema = makeExecutableSchema({
typeDefs: `
type User {
id: ID!
address: Address
}
type Address {
streetAddress: String
zip: String
}
type Query {
addressByUser(id: ID!): Address
}
`,
resolvers: {
Query: {
addressByUser(parent, { id }, context, info) {
return delegateToSchema({
schema: subSchema,
operation: 'query',
fieldName: 'userById',
args: { id },
context,
info,
transforms: [
// Wrap document takes a subtree as an AST node
new WrapQuery(
// path at which to apply wrapping and extracting
['userById'],
(subtree: SelectionSetNode) => {
const newSelectionSet = {
kind: Kind.SELECTION_SET,
selections: subtree.selections.map(selection => {
// just append fragments, not interesting for this
// test
if (selection.kind === Kind.INLINE_FRAGMENT ||
selection.kind === Kind.FRAGMENT_SPREAD) {
return selection;
}
// prepend `address` to name and camelCase
const oldFieldName = selection.name.value;
return {
kind: Kind.FIELD,
name: {
kind: Kind.NAME,
value: 'address' +
oldFieldName.charAt(0).toUpperCase() +
oldFieldName.slice(1)
}
};
})
};
return newSelectionSet;
},
// how to process the data result at path
result => ({
streetAddress: result.addressStreetAddress,
zip: result.addressZip
})
),
],
});
},
},
},
});
});

it('wrapping delegation, returning selectionSet', async () => {
const result = await graphql(
schema,
`
query {
addressByUser(id: "u1") {
streetAddress
zip
}
}
`,
);

expect(result).to.deep.equal({
data: {
addressByUser: {
streetAddress: 'Windy Shore 21 A 7',
zip: '12345',
},
},
});
});
});
});
13 changes: 8 additions & 5 deletions src/transforms/WrapQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from 'graphql';
import { Transform, Request, Result } from '../Interfaces';

export type QueryWrapper = (subtree: SelectionSetNode) => SelectionNode;
export type QueryWrapper = (subtree: SelectionSetNode) => SelectionNode | SelectionSetNode;

export default class WrapQuery implements Transform {
private wrapper: QueryWrapper;
Expand All @@ -34,12 +34,15 @@ export default class WrapQuery implements Transform {
fieldPath.push(node.name.value);
if (ourPath === JSON.stringify(fieldPath)) {
const selection = this.wrapper(node.selectionSet);
const selectionSet = selection.kind === Kind.SELECTION_SET ?
selection :
{
kind: Kind.SELECTION_SET,
selections: [selection]
};
return {
...node,
selectionSet: {
kind: Kind.SELECTION_SET,
selections: [selection],
},
selectionSet
};
}
},
Expand Down

0 comments on commit ff48b89

Please sign in to comment.