hasura / graphql-engine

Blazing fast, instant realtime GraphQL APIs on your DB with fine grained access control, also trigger webhooks on database events.
https://hasura.io
Apache License 2.0
31.19k stars 2.77k forks source link

Action typescript codegen jsonb type incorrect #5636

Open aaronhayes opened 4 years ago

aaronhayes commented 4 years ago

Currently for actions the generated jsonb type is incorrectly typed as a string, under typescript-express.

type jsonb = string
GavinRay97 commented 4 years ago

@aaronhayes Hey, thanks for reporting this.

I need to double-check why this is happening, but I think that because jsonb is a custom scalar it's defaulting to string (this is the same behavior with graphql-code-generator).

The bit of code responsible for converting GQL types to other language types is pretty compact:

This line is what determines it: let T = isScalar(type) ? scalarMap[type] : type Where type is the result of calling field.getTypename(). So I think jsonb as a custom scalar is coming back as string.

export const serialize = (field: Fieldlike) => ({
  name: field.getName(),
  required: field.isNonNullType(),
  list: field.isListType(),
  type: field.getTypename(),
})

// Typescript converter's map of GQL scalars to TS type names + field formatter
const scalarMap = {
  [ScalarTypes.ID]: 'number',
  [ScalarTypes.INT]: 'number',
  [ScalarTypes.FLOAT]: 'number',
  [ScalarTypes.STRING]: 'string',
  [ScalarTypes.BOOLEAN]: 'boolean',
}

const fieldFormatter = (field: Fieldlike) => {
  let { name, required, list, type } = serialize(field)
  let T = isScalar(type) ? scalarMap[type] : type
  // string -> Maybe<string>
  if (!required) T = `Maybe<${T}>`
  // Maybe<string> -> Array<Maybe<string>>
  if (list) T = `Array<${T}>`
  // Array<Maybe<string>> -> Maybe<Array<Maybe<string>>>
  if (!required && list) T = `Maybe<${T}>`
  // username: string -> username?: string
  if (!required) name = `${name}?`
  return { name, type: T }
}
aaronhayes commented 4 years ago

@GavinRay97 for what it's worth the typescript-zeit codegen outputs different values

/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
  ID: string;
  String: string;
  Boolean: boolean;
  Int: number;
  Float: number;
  uuid: any;
  timestamptz: any;
  jsonb: any;
  citext: any;
};

vs typescript-express

type Maybe<T> = T | null
type uuid = string
type timestamptz = string
type citext = string
type jsonb = string
GavinRay97 commented 4 years ago

Ah yeah this is because the earliest codegens used graphql-code-generator, but the later ones we had to write a custom codegen implemenation because graphql-code-generator doesn't have plugins for Python, (at the time) JSDoc, or Go.

Technically could swap the typescript-express to use graphql-code-generator and that would fix it, or try to alter the function to check whether the scalar is custom and default to any if it is.

rossng commented 3 years ago

I just bumped into this problem as well - would be really nice to have it work properly for typescript-express.

manasag commented 7 months ago

Hi, I want to update that we are launching Hasura V3 (DDN) this month. In V3, actions can directly be integrated using our new Typescript connector which introspects your functions and automatically expose the graphql types and schema to Hasura (you don't have to manage manually). Also with CLI tooling, the metadata is deterministically owned and managed by you, and not the state of the server. This paradigm may help you setup your CI/CD and assert the state of Hasura is a much better manner (and leveraging the typescript+express ecosystem to build your business logic).

I would highly suggest to join us to see the full power of Hasura DDN at the Hasura Dev Day on April 16 🎉. Sign up here: https://hasura.io/dev-day. Can't make it? Sign up anyway and we'll send you the recording.