Skip to content

Commit

Permalink
feat(mutations): support add and update mutations
Browse files Browse the repository at this point in the history
  • Loading branch information
tothandras committed Oct 12, 2015
1 parent aa81f33 commit 477105b
Show file tree
Hide file tree
Showing 9 changed files with 344 additions and 85 deletions.
59 changes: 51 additions & 8 deletions src/e2e.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@ describe('e2e', () => {
let motherUser;
let user1;
let user2;
let schema;

before(() => {
schema = getSchema([User]);
});
const schema = getSchema([User]);

beforeEach(async function Test1() {
motherUser = new User({
Expand Down Expand Up @@ -101,9 +97,7 @@ describe('e2e', () => {
friends {
edges {
node {
_id
name
age
...UserFragment
}
}
}
Expand Down Expand Up @@ -201,5 +195,54 @@ describe('e2e', () => {
});
});
});

describe('mutations', () => {
it('should add data to the database', async function Test8() {
const result = await graphql(schema, `
mutation addUserMutation {
addUser(input: {name: "Test User", clientMutationId: "1"}) {
_id
name
}
}
`);

expect(typeof result.data.addUser._id).to.be.eql('string');
expect(result).to.containSubset({
data: {
addUser: {
name: 'Test User'
}
}
});
});

it('should update data', async function Test9() {
let result = await graphql(schema, `
mutation addUserMutation {
addUser(input: {name: "Test User", clientMutationId: "1"}) {
_id
name
}
}
`);
const id = result.data.addUser._id;

result = await graphql(schema, `
mutation updateUserMutation {
updateUser(input: {id: "${id}", name: "Updated Test User", clientMutationId: "2"}) {
name
}
}
`);
expect(result).to.containSubset({
data: {
updateUser: {
name: 'Updated Test User'
}
}
});
});
});
});
});
163 changes: 143 additions & 20 deletions src/field/field.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@ import {
GraphQLID,
GraphQLObjectType,
GraphQLSchema,
GraphQLScalarType
GraphQLScalarType,
GraphQLInputObjectType
} from 'graphql';
import {getModels} from './../model';
import {getTypes, nodeInterface} from './../type';
import {
getIdFetcher,
getOneResolver,
getListResolver
getListResolver,
getAddOneResolver,
getUpdateOneResolver
} from './../query';

function getField(graffitiModel, type) {
function getQueryField(graffitiModel, type) {
const {name} = type;
const singularName = name.toLowerCase();
const pluralName = `${name.toLowerCase()}s`;
Expand Down Expand Up @@ -58,38 +61,157 @@ function getField(graffitiModel, type) {
};
}

function getMutationField(graffitiModel, type) {
const {name} = type;

const allField = type._typeConfig.fields();
const args = reduce(allField, (args, field) => {
if (field.type instanceof GraphQLObjectType) {
if (field.type.name.endsWith('Connection')) {
args[field.name] = {
name: field.name,
type: new GraphQLList(GraphQLID)
};
}
// TODO support objects
// else {
// args = {...args, ...field.type._typeConfig.fields()};
// }
}
if (!(field.type instanceof GraphQLObjectType) && field.name !== 'id' && !field.name.startsWith('_')) {
args[field.name] = field;
}
return args;
}, {});

const addInputType = new GraphQLNonNull(new GraphQLInputObjectType({
name: `${name}AddInput`,
fields: () => ({
...args,
clientMutationId: {
name: 'clientMutationId',
type: new GraphQLNonNull(GraphQLID)
}
})
}));

const updateInputType = new GraphQLNonNull(new GraphQLInputObjectType({
name: `${name}UpdateInput`,
fields: () => ({
...args,
clientMutationId: {
name: 'clientMutationId',
type: new GraphQLNonNull(GraphQLID)
},
id: {
type: new GraphQLNonNull(GraphQLID),
description: `The ID of a ${name}`
}
})
}));

const outputType = new GraphQLObjectType({
name: `${name}Payload`,
fields: () => ({
...allField,
clientMutationId: {
name: 'clientMutationId',
type: new GraphQLNonNull(GraphQLID)
}
})
});

return {
[`add${name}`]: {
type: outputType,
args: {
input: {
name: 'input',
type: addInputType
}
},
resolve: (root, args, info) => {
const clientMutationId = args.input.clientMutationId;
delete args.input.clientMutationId;
return getAddOneResolver(graffitiModel)(root, args.input, info).then((result) => {
return {
clientMutationId,
...result
};
});
},
resolveType: outputType
},
[`update${name}`]: {
type: outputType,
args: {
input: {
name: 'input',
type: updateInputType
}
},
resolve: (root, args, info) => {
const clientMutationId = args.input.clientMutationId;
delete args.input.clientMutationId;
return getUpdateOneResolver(graffitiModel)(root, {id: args.id, ...args.input}, info).then((result) => {
return {
clientMutationId,
...result
};
});
},
resolveType: outputType
}
};
}

function getFields(graffitiModels) {
const types = getTypes(graffitiModels);

const queries = reduce(types, (queries, type, key) => {
const {queries, mutations} = reduce(types, ({queries, mutations}, type, key) => {
type.name = type.name || key;
const graffitiModel = graffitiModels[type.name];
return {
...queries,
...getField(graffitiModel, type)
queries: {
...queries,
...getQueryField(graffitiModel, type)
},
mutations: {
...mutations,
...getMutationField(graffitiModel, type)
}
};
}, {});

queries.node = {
name: 'node',
description: 'Fetches an object given its ID',
type: nodeInterface,
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The ID of an object'
}, {
queries: {
node: {
name: 'node',
description: 'Fetches an object given its ID',
type: nodeInterface,
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The ID of an object'
}
},
resolve: getIdFetcher(graffitiModels)
}
},
resolve: getIdFetcher(graffitiModels)
};
mutations: {}
});

const RootQuery = new GraphQLObjectType({
name: 'RootQuery',
fields: queries
});

const RootMutation = new GraphQLObjectType({
name: 'RootMutation',
fields: mutations
});

return {
query: RootQuery
query: RootQuery,
mutation: RootMutation
};
}

Expand All @@ -100,7 +222,8 @@ function getSchema(mongooseModels) {
}

export default {
getField,
getQueryField,
getMutationField,
getFields,
getSchema
};
Loading

0 comments on commit 477105b

Please sign in to comment.