graphql#VariableDefinitionNode TypeScript Examples

The following examples show how to use graphql#VariableDefinitionNode. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: generate-query.ts    From graphql-query-generator with MIT License 6 votes vote down vote up
function getVariableDefinition(
  name: string,
  type: TypeNode
): VariableDefinitionNode {
  return {
    kind: Kind.VARIABLE_DEFINITION,
    type: type,
    variable: {
      kind: Kind.VARIABLE,
      name: getName(name)
    }
  }
}
Example #2
Source File: buildGqlQuery.ts    From ra-data-prisma with MIT License 6 votes vote down vote up
buildApolloArgs = (
  query: Query,
  variables: { [key: string]: any } = {},
) => {
  if (query.args.length === 0) {
    return [];
  }

  const validVariables = Object.keys(variables).filter(
    (k) => typeof variables[k] !== "undefined",
  );

  return query.args
    .filter((arg) => validVariables.includes(arg.name))
    .reduce(
      (acc: VariableDefinitionNode[], arg) => [
        ...acc,
        gqlTypes.variableDefinition(
          gqlTypes.variable(gqlTypes.name(arg.name)),
          getArgType(arg),
        ),
      ],
      [] as VariableDefinitionNode[],
    );
}
Example #3
Source File: gqlTypes.ts    From ra-data-prisma with MIT License 6 votes vote down vote up
operationDefinition = (
  operation: OperationTypeNode,
  selectionSet: SelectionSetNode,
  name: NameNode,
  variableDefinitions: VariableDefinitionNode[],
): OperationDefinitionNode => ({
  kind: Kind.OPERATION_DEFINITION,
  operation,
  selectionSet,
  name,
  variableDefinitions,
})
Example #4
Source File: gqlTypes.ts    From ra-data-prisma with MIT License 5 votes vote down vote up
variableDefinition = (
  variable: VariableNode,
  type: TypeNode,
): VariableDefinitionNode => ({
  kind: Kind.VARIABLE_DEFINITION,
  variable,
  type,
})
Example #5
Source File: generate-query.ts    From graphql-query-generator with MIT License 4 votes vote down vote up
function getArgsAndVars(
  field: FieldDefinitionNode,
  nodeName: string,
  config: InternalConfiguration,
  schema: GraphQLSchema,
  providedValues: { [varName: string]: any }
): {
  args: ArgumentNode[]
  variableDefinitionsMap: { [varName: string]: VariableDefinitionNode }
  variableValues: { [varName: string]: any }
} {
  const fieldName = field.name.value
  const allArgs = field.arguments
  const args: ArgumentNode[] = []

  const variableDefinitionsMap: {
    [varName: string]: VariableDefinitionNode
  } = {}

  const requiredArguments = allArgs.filter((arg) =>
    considerArgument(arg, config)
  )

  /**
   * Check for slicing arguments defined in a @listSize directive that should
   * be present:
   */
  const missingSlicingArg = getMissingSlicingArg(
    requiredArguments,
    field,
    schema
  )

  /**
   * Check if missingSlicingArg is already in requiredArguments
   *
   * Because slicing arguments may be deeply nested (input object types), there
   * isn't a simple way to check for conflicts
   */
  if (
    missingSlicingArg &&
    !requiredArguments.find((arg) => {
      return arg.name.value === missingSlicingArg.name.value
    })
  ) {
    requiredArguments.push(missingSlicingArg)
  }

  requiredArguments.forEach((arg) => {
    const varName = `${nodeName}__${fieldName}__${arg.name.value}`
    args.push(getVariable(arg.name.value, varName))
    variableDefinitionsMap[varName] = getVariableDefinition(varName, arg.type)
  })

  const variableValues: { [varName: string]: any } = {}

  // First, check for providers based on type__field query
  // (Note: such a provider must return a value which is an object)
  const { providerFound, value } = getProviderValue(
    `${nodeName}__${fieldName}`,
    config,
    providedValues
  )
  if (providerFound && typeof value === 'object') {
    Object.entries(value).forEach(([argName, value]) => {
      const varName = `${nodeName}__${fieldName}__${argName}`
      // Only consider required arguments (provider can provide more than necessary)
      if (Object.keys(variableDefinitionsMap).includes(varName)) {
        variableValues[varName] = value
      }
    })
  }

  // Second, check for providers based on type__field__argument query
  // (Note: they overwrite possibly already provided values)
  requiredArguments.forEach((arg) => {
    const varName = `${nodeName}__${fieldName}__${arg.name.value}`
    const argType = schema.getType(getTypeName(arg.type))
    const { providerFound, value } = getProviderValue(
      varName,
      config,
      { ...variableValues, ...providedValues }, // pass already used variable values
      argType
    )
    if (providerFound) {
      variableValues[varName] = value
    }
  })

  // Third, populate all so-far neglected require variables with defaults or null
  requiredArguments.forEach((arg) => {
    const varName = `${nodeName}__${fieldName}__${arg.name.value}`
    const argType = schema.getType(getTypeName(arg.type))
    if (typeof variableValues[varName] === 'undefined') {
      if (isEnumType(argType)) {
        // Enum values can be randomly selected
        variableValues[varName] = getRandomEnum(argType)
      } else if (config.providePlaceholders) {
        variableValues[varName] = getDefaultArgValue(schema, config, arg.type)

        // Add default values for unfulfilled listSize directive if applicable
        const listSizeDirective = getListSizeDirective(field)
        if (listSizeDirective) {
          const value = getListSizeDirectiveDefaultValue(
            listSizeDirective,
            arg.type,
            config,
            schema
          )

          if (value !== undefined) {
            if (typeof value !== 'object') {
              variableValues[varName] = value
            } else {
              variableValues[varName] = merge.recursive(
                value,
                variableValues[varName]
              )
            }
          }
        }
      } else if (arg.type.kind === 'NonNullType') {
        throw new Error(
          `Missing provider for non-null variable "${varName}" of type "${print(
            arg.type
          )}". ` +
            `Either add a provider (e.g., using a wildcard "*__*" or "*__*__*"), ` +
            `or set providePlaceholders configuration option to true.`
        )
      } else {
        variableValues[varName] = null
      }
    }
  })

  return {
    args,
    variableDefinitionsMap,
    variableValues
  }
}
Example #6
Source File: generate-query.ts    From graphql-query-generator with MIT License 4 votes vote down vote up
function getSelectionSetAndVars(
  schema: GraphQLSchema,
  node: DefinitionNode,
  config: InternalConfiguration,
  depth: number = 0
): {
  selectionSet: SelectionSetNode
  variableDefinitionsMap: {
    [variableName: string]: VariableDefinitionNode
  }
  variableValues: {
    [variableName: string]: any
  }
} {
  let selections: SelectionNode[] = []
  let variableDefinitionsMap: {
    [variableName: string]: VariableDefinitionNode
  } = {}
  let variableValues: { [variableName: string]: any } = {}

  // Abort at leaf nodes:
  if (depth === config.maxDepth) {
    return {
      selectionSet: undefined,
      variableDefinitionsMap,
      variableValues
    }
  }

  if (node.kind === Kind.OBJECT_TYPE_DEFINITION) {
    let fields = getRandomFields(node.fields, config, schema, depth)

    fields.forEach((field) => {
      // Recurse, if field has children:
      const nextNode = schema.getType(getTypeName(field.type)).astNode
      let selectionSet: SelectionSetNode = undefined
      if (typeof nextNode !== 'undefined') {
        const res = getSelectionSetAndVars(schema, nextNode, config, depth + 1)

        // Update counts and nodeFactor:
        config.resolveCount += config.nodeFactor
        config.nodeFactor *= getNextNodefactor(res.variableValues)
        config.typeCount += config.nodeFactor

        selectionSet = res.selectionSet
        variableDefinitionsMap = {
          ...variableDefinitionsMap,
          ...res.variableDefinitionsMap
        }
        variableValues = { ...variableValues, ...res.variableValues }
      }

      const avs = getArgsAndVars(
        field,
        node.name.value,
        config,
        schema,
        variableValues
      )
      variableDefinitionsMap = {
        ...variableDefinitionsMap,
        ...avs.variableDefinitionsMap
      }
      variableValues = { ...variableValues, ...avs.variableValues }

      selections.push({
        kind: Kind.FIELD,
        name: getName(field.name.value),
        selectionSet,
        arguments: avs.args
      })
    })
  } else if (node.kind === Kind.INTERFACE_TYPE_DEFINITION) {
    let fields = getRandomFields(node.fields, config, schema, depth)

    fields.forEach((field) => {
      // Recurse, if field has children:
      const nextNode = schema.getType(getTypeName(field.type)).astNode
      let selectionSet: SelectionSetNode = undefined
      if (typeof nextNode !== 'undefined') {
        const res = getSelectionSetAndVars(schema, nextNode, config, depth + 1)

        // Update counts and nodeFactor:
        config.resolveCount += config.nodeFactor
        config.nodeFactor *= getNextNodefactor(res.variableValues)
        config.typeCount += config.nodeFactor

        selectionSet = res.selectionSet
        variableDefinitionsMap = {
          ...variableDefinitionsMap,
          ...res.variableDefinitionsMap
        }
        variableValues = { ...variableValues, ...res.variableValues }
      }

      const avs = getArgsAndVars(
        field,
        node.name.value,
        config,
        schema,
        variableValues
      )
      variableDefinitionsMap = {
        ...variableDefinitionsMap,
        ...avs.variableDefinitionsMap
      }
      variableValues = { ...variableValues, ...avs.variableValues }

      selections.push({
        kind: Kind.FIELD,
        name: getName(field.name.value),
        selectionSet,
        arguments: avs.args
      })
    })

    // Get all objects that implement an interface
    let objectsImplementingInterface = Object.values(
      schema.getTypeMap()
    ).filter((namedType) => {
      if (
        namedType.astNode &&
        namedType.astNode.kind === 'ObjectTypeDefinition'
      ) {
        let interfaceNames = namedType.astNode.interfaces.map(
          (interfaceNamedType) => {
            return interfaceNamedType.name.value
          }
        )

        if (interfaceNames.includes(node.name.value)) {
          return true
        }
      }

      return false
    })

    // Randomly select named types from the union
    let pickObjectsImplementingInterface = objectsImplementingInterface.filter(
      () => {
        if (typeof config.breadthProbability === 'number') {
          return random(config) <= config.breadthProbability
        } else {
          return random(config) <= config.breadthProbability(depth)
        }
      }
    )

    // If no named types are selected, select any one
    if (pickObjectsImplementingInterface.length === 0) {
      const forcedCleanIndex = Math.floor(
        random(config) * objectsImplementingInterface.length
      )
      pickObjectsImplementingInterface.push(
        objectsImplementingInterface[forcedCleanIndex]
      )
    }

    pickObjectsImplementingInterface.forEach((namedType) => {
      if (namedType.astNode) {
        let type = namedType.astNode

        // Unions can only contain objects
        if (type.kind === Kind.OBJECT_TYPE_DEFINITION) {
          // Get selections
          let selectionSet: SelectionSetNode = undefined
          const res = getSelectionSetAndVars(schema, type, config, depth)
          selectionSet = res.selectionSet
          variableDefinitionsMap = {
            ...variableDefinitionsMap,
            ...res.variableDefinitionsMap
          }
          variableValues = { ...variableValues, ...res.variableValues }

          let fragment: InlineFragmentNode = {
            kind: Kind.INLINE_FRAGMENT,
            typeCondition: {
              kind: Kind.NAMED_TYPE,
              name: {
                kind: Kind.NAME,
                value: type.name.value
              }
            },
            selectionSet: selectionSet
          }

          selections.push(fragment)
        } else {
          throw Error(
            `There should only be object types ` +
              `in the selectionSet but found: ` +
              `"${JSON.stringify(type, null, 2)}"`
          )
        }
      } else {
        selections.push({
          kind: Kind.FIELD,
          name: {
            kind: Kind.NAME,
            value: namedType.name
          }
        })
      }
    })
  } else if (node.kind === Kind.UNION_TYPE_DEFINITION) {
    // Get the named types in the union
    let unionNamedTypes = node.types.map((namedTypeNode) => {
      return schema.getType(namedTypeNode.name.value)
    })

    // Randomly select named types from the union
    let pickUnionNamedTypes = unionNamedTypes.filter(() => {
      if (typeof config.breadthProbability === 'number') {
        return random(config) <= config.breadthProbability
      } else {
        return random(config) <= config.breadthProbability(depth)
      }
    })

    // If no named types are selected, select any one
    if (pickUnionNamedTypes.length === 0) {
      const forcedCleanIndex = Math.floor(
        random(config) * unionNamedTypes.length
      )
      pickUnionNamedTypes.push(unionNamedTypes[forcedCleanIndex])
    }

    pickUnionNamedTypes.forEach((namedType) => {
      if (namedType.astNode) {
        let type = namedType.astNode

        // Unions can only contain objects
        if (type.kind === Kind.OBJECT_TYPE_DEFINITION) {
          // Get selections
          let selectionSet: SelectionSetNode = undefined
          const res = getSelectionSetAndVars(schema, type, config, depth)
          selectionSet = res.selectionSet
          variableDefinitionsMap = {
            ...variableDefinitionsMap,
            ...res.variableDefinitionsMap
          }
          variableValues = { ...variableValues, ...res.variableValues }

          let fragment: InlineFragmentNode = {
            kind: Kind.INLINE_FRAGMENT,
            typeCondition: {
              kind: Kind.NAMED_TYPE,
              name: {
                kind: Kind.NAME,
                value: type.name.value
              }
            },
            selectionSet: selectionSet
          }

          selections.push(fragment)
        } else {
          throw Error(
            `There should only be object types ` +
              `in the selectionSet but found: ` +
              `"${JSON.stringify(type, null, 2)}"`
          )
        }
      } else {
        selections.push({
          kind: Kind.FIELD,
          name: {
            kind: Kind.NAME,
            value: namedType.name
          }
        })
      }
    })
  }

  let aliasIndexes: { [fieldName: string]: number } = {}
  let cleanselections: SelectionNode[] = []

  // Ensure unique field names/aliases
  selections.forEach((selectionNode) => {
    if (selectionNode.kind === Kind.FIELD) {
      let fieldName = selectionNode.name.value
      if (fieldName in aliasIndexes) {
        cleanselections.push({
          ...selectionNode,
          ...{
            alias: {
              kind: Kind.NAME,
              value: `${fieldName}${aliasIndexes[fieldName]++}`
            }
          }
        })
      } else {
        aliasIndexes[fieldName] = 2
        cleanselections.push(selectionNode)
      }
    } else if (selectionNode.kind === Kind.INLINE_FRAGMENT) {
      let cleanFragmentSelections: SelectionNode[] = []
      selectionNode.selectionSet.selections.forEach((fragmentSelectionNode) => {
        if (fragmentSelectionNode.kind === Kind.FIELD) {
          let fieldName = fragmentSelectionNode.name.value
          if (fieldName in aliasIndexes) {
            cleanFragmentSelections.push({
              ...fragmentSelectionNode,
              ...{
                alias: {
                  kind: Kind.NAME,
                  value: `${fieldName}${aliasIndexes[fieldName]++}`
                }
              }
            })
          } else {
            aliasIndexes[fieldName] = 2
            cleanFragmentSelections.push(fragmentSelectionNode)
          }
        }
      })

      selectionNode.selectionSet.selections = cleanFragmentSelections
      cleanselections.push(selectionNode)
    } else {
      throw Error(
        `There should not be any fragment spreads in the selectionNode "${JSON.stringify(
          selectionNode,
          null,
          2
        )}"`
      )
    }
  })

  return {
    selectionSet:
      cleanselections.length > 0
        ? {
            kind: Kind.SELECTION_SET,
            selections: cleanselections
          }
        : undefined,
    variableDefinitionsMap,
    variableValues
  }
}