Skip to content

Allow multiple sourceType for scalar #784

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Sytten opened this issue Jan 13, 2021 · 2 comments
Open

Allow multiple sourceType for scalar #784

Sytten opened this issue Jan 13, 2021 · 2 comments
Labels
effort/modest scope/types Having to do with types type/improve Something existing is made better, does not affect the interface (example: better error message)

Comments

@Sytten
Copy link
Collaborator

Sytten commented Jan 13, 2021

Currently the sourceType only allows for one type, it happens that you need to accept multiple types.
For example our DateTime scalar accepts the JS Date and luxon DateTime.
For now what we do is we created a new type that we use in the global sourceTypes.
Ideally it would be nice to have an input type and an output type, but only one is also fine if thats too big of refactor.

@Sytten Sytten added effort/modest scope/types Having to do with types type/improve Something existing is made better, does not affect the interface (example: better error message) labels Jan 13, 2021
@jasonkuhrt
Copy link
Contributor

Can you share some code examples of what you wish the API allowed you to do, and usage examples.

@Sytten
Copy link
Collaborator Author

Sytten commented Jan 16, 2021

So this is our implementation of datetime:

import { GraphQLError } from 'graphql/error'
import { Kind } from 'graphql/language'
import { DateTime } from 'luxon'
import { scalarType } from 'nexus'

const validate = (value: any) => {
  if (typeof value !== 'string') {
    throw new TypeError(`Value is not string: ${value}`)
  }
  const dateTime = DateTime.fromISO(value)
  if (!dateTime.isValid) throw new TypeError(`Value is not DateTime: ${value}`)
  return dateTime
}

export const GraphQLDateTime = scalarType({
  asNexusMethod: 'datetime',
  description: 'The `DateTime` scalar type represents an ISO 8601 DateTime',
  name: 'DateTime',
  parseLiteral(ast) {
    if (ast.kind !== Kind.STRING) {
      throw new GraphQLError(`Can only sanitize DateTime strings, but got: ${ast.kind}`)
    }

    return validate(ast.value)
  },
  parseValue: validate,
  serialize: (value: DateTime | Date) => {
    if (value instanceof DateTime) {
      return value.toISO()
    }
    if (value instanceof Date) {
      return value.toISOString()
    }
    throw new TypeError(`Value is not DateTime: ${value}`)
  },
  // sourceType: {
  //   export: 'DateTime',
  //   module: 'luxon',
  // },
})

So currently I cannot type it directly because I can only specify one sourceType for it, but I do accept Date and DateTime because prisma doesn't yet allow us to customize it. This is a bit annoying because in input I always parse as a DateTime so created this little hack:

export const jsDateOrDateTimeToDateTime = (
  input: DateTime | Date | null | undefined
): DateTime | null | undefined =>
  DateTime.isDateTime(input)
    ? input
    : input === null
    ? null
    : input === undefined
    ? undefined
    : DateTime.fromJSDate(input)

Ideally I would like to be able to have a different type for when the scalar is used in the input and when it is used in the output.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
effort/modest scope/types Having to do with types type/improve Something existing is made better, does not affect the interface (example: better error message)
Projects
None yet
Development

No branches or pull requests

2 participants