Skip to content

Commit

Permalink
feat(fragment): add fragment support with broken projection
Browse files Browse the repository at this point in the history
  • Loading branch information
Peter Marton committed Aug 1, 2015
1 parent 5feca41 commit 25fc49c
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 46 deletions.
24 changes: 12 additions & 12 deletions example/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,21 @@ var schema = getSchema([User]);

mongoose.connect('mongodb://localhost/graphql');

var query = `{
user(_id: "559645cd1a38532d14349246") {
var query = `
query GetUser {
user(_id: "559645cd1a38532d14349246") {
...UserFragment
friends {
...UserFragment
}
}
}
fragment UserFragment on User {
name
age
createdAt
nums
bools
strings
removed
friends {
name
age
}
}
}`;
`;

// query = `{
// users(age: 19) {
Expand Down
88 changes: 62 additions & 26 deletions src/e2e.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ describe('e2e', () => {
_schemaConfig: {
query: {
name: 'RootQueryType',
description: 'Query schema for Graffiti'
description: 'Query schema for Graffiti'
}
}
});
Expand Down Expand Up @@ -99,37 +99,73 @@ describe('e2e', () => {
});
});

it('should support inline fragments', function* () {
let result = yield graphql(schema, `{
user(_id: "${user2._id}") {
_id
name,
... on User {
describe('with fragments', () => {
it('should support fragments', function* () {
let result = yield graphql(schema, `
query GetUser {
user(_id: "${user2._id}") {
...UserFragment
friends {
...UserFragment
}
}
}
fragment UserFragment on User {
_id
name
age
}
friends {
`);

expect(result).to.be.eql({
data: {
user: {
_id: user2._id.toString(),
name: 'Bar',
age: 28,
friends: [{
_id: user1._id.toString(),
name: 'Foo',
age: 28
}]
},
}
});
});

it('should support inline fragments', function* () {
let result = yield graphql(schema, `{
user(_id: "${user2._id}") {
_id
name,
... on User {
name
age
}
friends {
_id
... on User {
name
},
age
}
}
}`);

expect(result).to.be.eql({
data: {
user: {
_id: user2._id.toString(),
name: 'Bar',
age: 28,
friends: [{
_id: user1._id.toString(),
name: 'Foo',
age: 28
}]
},
age
}
}
}`);

expect(result).to.be.eql({
data: {
user: {
_id: user2._id.toString(),
name: 'Bar',
age: 28,
friends: [{
_id: user1._id.toString(),
name: 'Foo',
age: 28
}]
},
}
});
});
});
});
Expand Down
37 changes: 29 additions & 8 deletions src/projection.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,47 @@
import {find} from 'lodash';

/**
* Generate projection object for mongoose
* TODO: Handle sub-documents
* @method get
* @method getProjection
* @param {Object} fieldASTs
* @return {Project}
* @return {Object} projection
*/
export function getProjection(fieldASTs) {
const { selections } = fieldASTs.selectionSet;
function getProjection(fieldASTs) {
const {selections} = fieldASTs.selectionSet;

/*
* FIXME: there is no way currently to get the required fields from "FragmentSpread"
* workaround: don't do projection, select all of the fields
* related issue: https://github.com/graphql/graphql-js/issues/96
*/
let isFragmentSpread = find(selections, {
kind: 'FragmentSpread'
});

if (isFragmentSpread) {
return {};
}

// Get projection object
return selections.reduce((projs, selection) => {
switch (selection.kind) {
case 'Field':
return {
...projs,
[selection.name.value]: 1
...projs, [selection.name.value]: 1
};

case 'InlineFragment':
return {
...projs,
...getProjection(selection),
};

default:
throw 'Unsupported query';
throw new Error('Unsupported query selection: ' + selection.kind);
}
}, {});
}

export {
getProjection
}
3 changes: 3 additions & 0 deletions src/projection.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ describe('utils', () => {
});
});

// TODO: see related method
it('should support fragments');

it('should support inline fragments', () => {
const projectionResult = getProjection({
selectionSet: {
Expand Down

0 comments on commit 25fc49c

Please sign in to comment.