Merge pull request #1858 from justinr1234/upsert-mutation

Add upsert mutation
This commit is contained in:
Sacha Greif 2018-01-29 13:33:24 +09:00 committed by GitHub
commit ef867f30e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 99 additions and 1 deletions

View file

@ -0,0 +1,59 @@
/*
Generic mutation wrapper to upsert a document in a collection.
Sample mutation:
mutation moviesUpsert($search: MoviesInput, $set: MoviesInput, $unset: MoviesUnset) {
moviesUpsert(search: $search, set: $set, unset: $unset) {
...MoviesUpsertFormFragment
}
}
Arguments:
- search: the search fields to match on in the database
- set: an object containing all the fields to modify and their new values
- unset: an object containing the fields to unset
Child Props:
- upsertMutation(search, set, unset)
*/
import React, { Component } from 'react';
import { graphql } from 'react-apollo';
import gql from 'graphql-tag';
import { getFragment, getFragmentName, getCollection } from 'meteor/vulcan:core';
export default function withUpsert(options) {
let { collection, collectionName } = options;
if (!collection) {
collection = getCollection(collectionName);
}
const fragment = options.fragment || getFragment(options.fragmentName);
const fragmentName = getFragmentName(fragment);
collectionName = collection.options.collectionName;
const mutationName = collection.options.mutations.upsert.name;
return graphql(gql`
mutation ${mutationName}($search: ${collectionName}Input, $set: ${collectionName}Input, $unset: ${collectionName}Unset) {
${mutationName}(search: $search, set: $set, unset: $unset) {
...${fragmentName}
}
}
${fragment}
`, {
alias: 'withUpsert',
props: ({ ownProps, mutate }) => ({
upsertMutation: ({ search, set, unset }) => {
return mutate({
variables: { search, set, unset }
});
}
}),
});
}

View file

@ -96,7 +96,32 @@ export const getDefaultMutations = (collectionName, options = {}) => {
},
},
// mutation for upserting a specific document
upsert: {
name: `${collectionName}Upsert`,
description: `Mutation for upserting a ${collectionName} document`,
async mutation(root, { search, set, unset }, context) {
const collection = context[collectionName];
// check if document exists already
const existingDocument = collection.findOne(search, { fields: { _id: 1 } });
if (existingDocument) {
const editArgs = {
documentId: existingDocument._id,
set,
unset,
};
return await collection.options.mutations.edit.mutation(root, editArgs, context);
} else {
return await collection.options.mutations.new.mutation(root, { document: set }, context);
}
},
},
// mutation for removing a specific document (same checks as edit mutation)
remove: {

View file

@ -34,3 +34,4 @@ export { default as withEdit } from './containers/withEdit.js';
export { default as withRemove } from './containers/withRemove.js';
export { default as withCurrentUser } from './containers/withCurrentUser.js';
export { default as withMutation } from './containers/withMutation.js';
export { default as withUpsert } from './containers/withMutation.js';

View file

@ -202,6 +202,19 @@ export const createCollection = options => {
) : ${typeName}`, mutations.edit.description);
mutationResolvers[mutations.edit.name] = mutations.edit.mutation.bind(mutations.edit);
}
// upsert
if (mutations.upsert) { // e.g. "moviesUpsert(search: moviesInput, set: moviesInput, unset: moviesUnset) : Movie"
addGraphQLMutation(
`${mutations.upsert.name}(
# The document to search for (or partial document)
search: ${collectionName}Input,
# An array of fields to insert
set: ${collectionName}Input,
# An array of fields to delete
unset: ${collectionName}Unset
) : ${typeName}`, mutations.upsert.description);
mutationResolvers[mutations.upsert.name] = mutations.upsert.mutation.bind(mutations.upsert);
}
// remove
if (mutations.remove) { // e.g. "moviesRemove(documentId: String) : Movie"
addGraphQLMutation(