afv-library/samples/webapp-template-app-react-sample-b2x-experimental/.a4drules/skills/feature-graphql-graphql-data-access/docs/generate-mutation-query.md

10 KiB

GraphQL Mutation Query Generation

Triggering conditions

  1. Only if the schema exploration phase completed successfully
  2. Only if the query to generate is a mutation query

Your Role

You are a GraphQL expert and your role is to help generate Salesforce compatible GraphQL mutation queries once the exploration phase has completed.

You will leverage the context provided by the requesting user as well as the validation phase provided by the schema exploration. This tool will also provide you with a method to dynamically query the target org instance that you will use to test the generated query.

If the schema exploration has not been executed yet, you MUST run it first, and then get back to mutation query generation.

Mutation Queries General Information

IMPORTANT:

  1. Mutation Types: The GraphQL engine supports Create, Update and Delete operations
  2. Id Based Mutations: Update and Delete operations operate on Id-based entity identification
  3. Mutation Schema: Defined in the mutation query schema section

Mutation Query Generation Workflow

Strictly follow the rules below when generating the GraphQL mutation query:

  1. Input Fields Validation - Validate that the set of fields validate input field constraints
  2. Output Fields Validation - Validate that the set of fields used in the select part of the query validate the output fields constraints
  3. Type Consistency - Make sure variables used as query arguments and their related fields share the same GraphQL type
  4. Report Phase - Use the Mutation Query Report Template below to report on the previous validation phases
  5. Input Arguments - input is the default name for the argument, unless otherwise specified
  6. Output Field - For Create and Update operations, the output field is always named Record, and is of type EntityName
  7. Query Generation - Use the mutation query template and adjust it based on the selected operation
  8. Output Format - Use the standalone
  9. Test the Query - Use the Generated Mutation Query Testing workflow to test the generated query
    1. Report First - Always report first, using the proper output format, before testing

Mutation Query Schema

Important: In the schema fragments below, replace EntityName occurrences by the real entity name (i.e. Account, Case...). Important: Delete operations all share the same generic Record entity name for both input and payload, only exposing the standard Id field.

input EntityNameCreateRepresentation {
  # Subset of EntityName fields here
}
input EntityNameCreateInput { EntityName: EntityNameCreateRepresentation! }
type EntityNameCreatePayload { Record: EntityName! }

input EntityNameUpdateRepresentation {
  # Subset of EntityName fields here
}
input EntityNameUpdateInput { Id: IdOrRef! EntityName: EntityNameUpdateRepresentation! }
type EntityNameUpdatePayload { Record: EntityName! }

input RecordDeleteInput { Id: IdOrRef! }
type RecordDeletePayload { Id: ID }

type UIAPIMutations {
  EntityNameCreate(input: EntityNameCreateInput!): EntityNameCreatePayload
  EntityNameDelete(input: RecordDeleteInput!): RecordDeletePayload
  EntityNameUpdate(input: EntityNameUpdateInput!): EntityNameUpdatePayload
}

Mutation Queries Input Field Constraints

  1. Create Mutation Queries:
    1. MUST include all required fields
    2. MUST only include createable fields
    3. Child relationships can't be set and MUST be excluded
    4. Fields with type REFERENCE can only be assigned IDs through their ApiName name
  2. Update Mutation Queries:
    1. MUST include the id of the entity to update
    2. MUST only include updateable fields
    3. Child relationships can't be set and MUST be excluded
    4. Fields with type REFERENCE can only be assigned IDs through their ApiName name
  3. Delete Mutation Queries:
    1. MUST include the id of the entity to delete

Mutation Queries Output Field Constraints

  1. Create and Update Mutation Queries:
    1. MUST exclude all child relationships
    2. MUST exclude all REFERENCE fields, unless accessed through their ApiName member (no navigation to referenced entity)
    3. Inaccessible fields will be reported as part of the errors attribute in the returned payload
    4. Child relationships CAN'T be queried as part of a mutation
    5. Fields with type REFERENCE can only be queried through their ApiName (no referenced entities navigation, no sub fields)
  2. Delete Mutation Queries:
    1. MUST only include the Id field

Mutation Query Report Template

Input arguments:

  • Required fields: FieldName1 (Type1), FieldName2 (Type2)...
  • Other fields: FieldName3 (Type3)... Output fields: FieldNameA (TypeA), FieldNameB (TypeB)...

Mutation Query Templates

mutation mutateEntityName(
  # arguments
) {
  uiapi {
    EntityNameOperation(input: {
      # the following is for `Create` and `Update` operations only
      EntityName: {
        # Input fields
      }
      # the following is for `Update` and `Delete` operations only
      Id: ... # id here
    }) {
      # the following is for `Create` and `Update` operations only
      Record {
        # Output fields
      }
      # the following is for `Delete` operations only
      Id: ... # id here
    }
  }
}

Mutation Standalone (Default) Output Format - CLEAN CODE ONLY

import { gql } from 'api/graphql.ts';
const QUERY_NAME = gql`
  mutation mutateEntity($input: EntityNameOperationInput!) {
    uiapi {
      EntityNameOperation(input: $input) {
        # select output fields here depending on operation type
      }
    }
  }
`;

const QUERY_VARIABLES = {
  input: {
    // The following is for `Create` and `Update` operations only
    EntityName: {
      // variables here
    },
    // The following is for `Update` and `Delete` operations only
    Id: ... // id here
  }
};

DO NOT INCLUDE:

  • Explanatory comments about the query
  • Field descriptions
  • Additional text about what the query does
  • Workflow step descriptions

ONLY INCLUDE:

  • Raw query string
  • Variables object
  • Nothing else

Generated Mutation Query Testing

Triggering conditions - ALL CONDITIONS MUST VALIDATE*

  1. Only if the Mutation Query Generation Workflow step global status is SUCCESS and you have a generated query
  2. Only if the query to generate is a mutation query
  3. Only if non manual method was used during schema exploration to retrieve introspection data

Workflow

  1. Report Step - Explain that you are able to test the query using the same method used during introspection
    1. You MUST report the method you will use, based on the one you used during schema exploration
  2. Interactive Step - Ask the user whether they want you to test the query using the proposed method
    1. WAIT for the user's answer.
  3. Input Arguments - You MUST ask the user for the input arguments to use
    1. WAIT for the user's answer.
  4. Test Query - If the user are OK with you testing the query:
    1. Use the selected method to test the query
    2. IMPORTANT - If you use the Salesforce CLI sf api request graphql command, you will need to inject the variable values directly into the query, as this command doesn't accept variables as a parameter
  5. Result Analysis - Retrieve the data and errors attributes from the returned payload, and report the result of the test as one of the following options:
    1. PARTIAL if data is not an empty object, but errors is not an empty list - Explanation: some of the queried fields are not accessible on mutations
    2. FAILED if data is an empty object - Explanation: the query is not valid
    3. SUCCESS if errors is an empty list
  6. Remediation Step - If status is not SUCCESS, use the FAILED or PARTIAL status handling workflows

FAILED Status Handling Workflow

The query is invalid:

  1. Error Analysis - Parse and categorize the specific error messages
  2. Root Cause Identification - Use error message to identify the root cause:
    • Execution - Error contains invalid cross reference id or entity is deleted
    • Syntax - Error contains invalid syntax
    • Validation - Error contains validation error
    • Type - Error contains VariableTypeMismatch or UnknownType
    • Navigation - Error contains is not currently available in mutation results
    • API Version - Query deals with updates, you're testing with Connect API and error contains Cannot invoke JsonElement.isJsonObject()
  3. Targeted Resolution - Depending on the root cause categorization
    • Execution - You're trying to update or delete an unknown/no longer available entity: either create an entity first, if you have generated the related query, or ask for a valid entity id to use
    • Syntax - Update the query using the error message information to fix the syntax errors
    • Validation - This field's name is most probably invalid, ask user for clarification and WAIT for the user's answer
    • Type - Use the error details and GraphQL schema to correct argument's type, and adjust variables accordingly
    • Navigation - Use the PARTIAL status handling workflow below
    • API Version - Record selection is only available with API version 64 and higher, report the issue, and try again with API version 64
  4. Test Again - Resume the query testing workflow with the updated query (increment and track attempt counter)
  5. Escalation Path - If targeted resolution fails after 2 attempts, ask for additional details and restart the entire GraphQL workflow, going again through the introspection phase

PARTIAL Status Handling Workflow

The query can be improved:

  1. Report the fields mentioned in the errors list
  2. Explain that these fields can't be queried as part of a mutation query
  3. Explain that the query might be considered as failing, as it will report errors
  4. Offer to remove the offending fields
  5. WAIT for the user's answer
  6. If they are OK with removing the fields restart the generation workflow with the new field list