简体   繁体   English

使用服务器端验证进行中继突变

[英]Relay Mutation with serverside validation

I am trying to code a relay mutation that will allow server side validation. 我正在尝试编写一个允许服务器端验证的中继突变。 Such as a record with that name already exists. 例如具有该名称的记录已经存在。

Below is my GraphQL mutation. 下面是我的GraphQL变异。

/* @flow weak */
import {mutationWithClientMutationId,offsetToCursor} from "graphql-relay";
import {GraphQLString, GraphQLList, GraphQLNonNull} from "graphql";
import NominationConnection from '../NominationsConnection';
import ViewerType from '../../../types/ViewerType';
import Helper from '../../../helper/helper';
import Nomination from '../../../model/Nomination';


const mongo = require('mongodb');

/**
 * mutationWithClientMutationId()
 *
 * This helper function helps us create Relay-compliant GraphQL mutations it takes an object with the following params
 * { name: "", inputField: { }, outputFields: {},  mutateAndGetPayload: function({}) }
 *
 */
export default mutationWithClientMutationId({

  // Name of the Mutation
  name: "Nomination_Add",

  // Describes the fields that should be used when invoking the mutation
  inputFields: {
    name: {
      type: new GraphQLNonNull(GraphQLString)
    },
    description: {
      type: new GraphQLNonNull(GraphQLString)
    },
    books: {
      type: new GraphQLList(GraphQLString)
    }

  },

  // response that will be sent back when the mutation is complete
  outputFields: {
    NominationsEdge: {
      type: NominationConnection.edgeType,
      resolve: ( {local_id}, { ...args }, context, { rootValue: objectManager } ) =>
      {
        //RT: local_id is the object that was inserted into DB.;
        let nomination = local_id[0];
        console.log("nomination: ", nomination);
        if(nomination.Errors.length > 0){

          return objectManager.getListBy('Nomination', nomination, {}, {})
              .then((arr) => {

                return ( {
                  cursor: null,
                  node: nomination,
                } )
              })
        }else {

          let an_Object;
          return objectManager.getOneByParam('Nomination', nomination, {_id: nomination.id})
              .then((retrieved_Object) => {


                an_Object = retrieved_Object;

              })

              .then(() => objectManager.getListBy('Nomination', an_Object, {}, {}, objectManager.getViewerUserId()))
              .then((arr) => {


                return ( {
                  cursor: Helper.cursorForObjectInConnection(arr, an_Object, "id"),
                  node: an_Object,
                } )
              })
              ;
        }
      }
    },

    Viewer: {
      type: ViewerType,
      resolve: (parent, args, context, {rootValue: objectManager}) => objectManager.getOneById('User', objectManager.getViewerUserId())
    }
  },

  mutateAndGetPayload: ({name, description, books}, context, {rootValue: objectManager}) => {
    if(!books){
      books = [];
    }

    return objectManager.add('Nomination', {
      name,
      description,
      books
    }, {name: name}).then((local_id) => ( {local_id} ));
  }
});

Below is my relay mutation. 以下是我的接力突变。

/* @flow weak */

import Relay from 'react-relay';

export default class Nomination_addMutation extends Relay.Mutation {
  // static fragments = {
  //   Viewer: () => Relay.QL`
  //     fragment on Viewer {
  //       id,
  //     }
  //   `,
  // };
  getMutation() {

    return Relay.QL`mutation{Nomination_Add}`;
  }
  getFatQuery() {


    return Relay.QL`
      fragment on Nomination_AddPayload {
      NominationsEdge,
        Viewer {
         Nominations(first:500){
         edges{
          node{
             id,
            Name,
            Description
            }
          }
         }
        }
      }
    `;
  }
  getConfigs() {

    return [{
      type: 'RANGE_ADD',
      parentName: 'Viewer',
      parentID: this.props.Viewer.id,
      connectionName: 'Nominations',
      edgeName: 'NominationsEdge',
      rangeBehaviors: {
        // When the ships connection is not under the influence
        // of any call, append the ship to the end of the connection
        '': 'append',
        // Prepend the ship, wherever the connection is sorted by age
       // 'orderby(newest)': 'prepend',
      },
    }];
  }
  getVariables() {

    return {

      name: this.props.name,
      description: this.props.description,
      books: this.props.books,
    };
  }
  getOptimisticResponse() {


    return {
      Nomination: {

        name: this.props.name,
        description: this.props.description,
        books: this.props.books,

    },
      Viewer: {
      id: this.props.Viewer.id,
    },
    };
  }
}

Here is how i call on it. 这是我如何呼吁它。

 Relay.Store.commitUpdate(
        new Nomination_Add( {name: fields.name , description: fields.desc ,Viewer:this.props.Viewer}),
          {
            onSuccess: response => {
             console.log(response);
              console.log(response.Nomination_Add);
            },
          }
      );

My response object only has the Viewer.id and clientmuationID nothing else. 我的响应对象只有Viewer.id和clientmuationID。 When i call on this mutation via graphql it looks like this. 当我通过graphql调用此突变时,它看起来像这样。

mutation{
  Nomination_Add(input:{name:"test", description:"test", clientMutationId:"2"}){
  NominationsEdge{
    node{
      Name,
      Description,
    Errors {
      Message
    }
      Books{
        Title
      }
    }
  }
  }

}

with a response of this. 对此作出回应。

{
  "data": {
    "Nomination_Add": {
      "NominationsEdge": {
        "node": {
          "Name": "test",
          "Description": "test",
          "Errors": [
            {
              "Message": "Nomination Already Exists"
            }
          ],
          "Books": []
        }
      }
    }
  }
}

How can i get my server validation error messages back to the client via relay to write logic against? 如何通过中继写入逻辑来将我的服务器验证错误消息返回给客户端?

also tried this as my fat query 也试过这个作为我的胖查询

 return Relay.QL`
      fragment on Nomination_AddPayload {
      NominationsEdge {
        node{
            Errors {
              Message
            }
          }
        },
        Viewer {
         Nominations(first:500){
         edges{
          node{
             id,
            Name,
            Description
            }
          }
         }
        }
      }
    `;

response looks like this: 响应看起来像这样:

{,…}
data
:
{Nomination_Add: {clientMutationId: "0", Viewer: {id: "00000000-0000-0000-0000-000000000000"}}}
Nomination_Add
:
{clientMutationId: "0", Viewer: {id: "00000000-0000-0000-0000-000000000000"}}
Viewer
:
{id: "00000000-0000-0000-0000-000000000000"}
id
:
"00000000-0000-0000-0000-000000000000"
clientMutationId
:
"0"

You're not receiving server-side validation error messages because you haven't told Relay that you want them. 您没有收到服务器端验证错误消息,因为您没有告诉Relay您想要它们。 Take a look at your GraphiQL mutation and your relay mutation's fat query. 看看你的GraphiQL变异和你的中继突变的胖查询。 You have included Errors in the former, but not in the latter. 您在前者中包含了Errors ,但在后者中没有。

Include Errors in your relay mutation's ( Nomination_addMutation ) fat query like below: 在您的中继变异( Nomination_addMutation )胖查询中包含Errors ,如下所示:

fragment on Nomination_AddPayload {
  NominationsEdge {
      node {
        Errors {
          Message
        }
      }
  },
  Viewer {
    Nominations(first:500){
      edges{
        node{
          id,
          Name,
          Description
        }
      }
    }
  }
}

I can throw a error on mutateAndGetPayload: This will be shipped as a error message to the onFailure callback of the mutation with the error message being what I throw. 我可以在mutateAndGetPayload上抛出一个错误:这将作为错误消息发送到突变的onFailure回调,错误信息就是我抛出的。

  mutateAndGetPayload: ({name, description, books}, context, {rootValue: objectManager}) => {
    if(!books){
      books = [];
    }

    return objectManager.add('Nomination', {
      name,
      description,
      books
    }, {name: name}).then((nominations) => {

      //RT: readability
    let nomination = nominations[0];

      //RT: if Mongo id is not assigned.
      // No records where created.
         if(nomination.id == null)
          throw nomination.Errors[0].Message;

      return ( {nomination}

      )});
  }

This does not seem like the correct way to do this. 这似乎不是正确的方法。 Has anyone seen any better examples? 有没有人见过更好的例子?

Edit: Cleaned up code and decided to do this based off of theses examples. 编辑:清理代码并决定基于这些示例执行此操作。 Doesn't seem right. 似乎不对。

https://medium.com/@fcpgate/i-think-what-eslam-mentioned-is-more-on-the-right-track-cdd07519bf97#.na73ulbxj (Read comments.) https://medium.com/@fcpgate/i-think-what-eslam-tioned-is-more-on-the-right-track-cdd07519bf97#.na73ulbxj (阅读评论。)

https://facebook.github.io/relay/docs/api-reference-relay-store.html https://facebook.github.io/relay/docs/api-reference-relay-store.html

http://stackoverflow.duapp.com/questions/37044914/how-to-tackle-server-side-input-validation-using-relay?rq=1 http://stackoverflow.duapp.com/questions/37044914/how-to-tackle-server-side-input-validation-using-relay?rq=1

https://github.com/facebook/relay/issues/696 https://github.com/facebook/relay/issues/696

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM