vadistic/graphql-extra

Idea: "Field.isScalar()" helper

GavinRay97 opened this issue · 2 comments

I have this which I use to find whether a Field of an Object node is a scalar or not:

export const isScalar = (doc: DocumentApi, field: FieldDefinitionApi) => {
  const baseScalars = ['ID', 'Int', 'Float', 'String', 'Boolean']
  const customScalars = doc.getAllScalarTypes().map((s) => s.getName())
  const allScalars = [...baseScalars, ...customScalars]
  return allScalars.some((scalar) =>
    field.getTypename().includes(scalar)
  )
}

And I use something similar to this pretty often, I was curious whether there might be interest in adding it as a native operation =)

Following up on this, I have been trying for days to figure out a way to test if a type node is a scalar without needing the context of the DocumentApi in the function.

Is this possible @vadistic?

This works below in raw graphql.js for GraphQLInputType but I can't seem to figure it out for TypeNode. Not sure if this is possible.

Maybe the other solution is to expose the context of the root document to the mixins so that they can refer back to the schema that they exist in?

const rootQueryType = schema.getQueryType()
const fields = rootQueryType?.getFields()

const forms = Object.keys(fields).map((fieldName) => {
  console.log('fieldname', fieldName)

  const field = fields[fieldName]
  const args = field.args

  console.log('field.type', field.type)

  for (let arg of args) {
    const nullableType = getNullableType(arg.type)
    console.log('arg.name:', arg.name)
    console.log('arg.type:', arg.type)
    console.log('getNullableType(arg.type):', nullableType)
    console.log('isScalar:', isScalarType(nullableType))
  }
})

Finally realized why I was having so much trouble with writing this functionality in myself.

I hadn't quite realized that the concepts for working with GraphQL schemas inside of graphql.js are divided into two sub-types.

  1. The Document type, from /graphql/language/ast, for representing just AST nodes
  2. The GraphQLSchema type, from /graphql/graphql, for the actual schema itself

The type names that are used between each of them aren't very different either, IE, GraphQLObjectType vs ObjectTypeDefinition etc.

So I figured out that this is the shortest/easiest way to tell whether a node is a scalar type or not, but it won't map to the existing library code well because it requires isScalar() which requires a GraphQLSchema and not a Document 🙁

import { isScalarType, GraphQLSchema } from 'graphql'
import { DocumentApi, TypeApi } from 'graphql-extra'

let cachedSchema: GraphQLSchema
function isScalar(doc: DocumentApi, type: TypeApi) {
  if (!cachedSchema) cachedSchema = doc.toSchema()
  const schemaType = cachedSchema.getType(type.getTypename())
  return isScalarType(schemaType)
}

If there's a way to store the result of document.toSchema() on the global DocumentApi instance when created after addSDL(), and then provide the value of GraphQLSchema to context of instance of graphql-extra/src/api/type.ts then it would work but that's a bit beyond my comprehension.