Skip to content
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

Adding custom scalars #43

Open
macmillen opened this issue Dec 29, 2020 · 8 comments
Open

Adding custom scalars #43

macmillen opened this issue Dec 29, 2020 · 8 comments
Assignees
Labels
community Something initiated by the community enhancement New feature or request priority:high This issue is important and will be done first

Comments

@macmillen
Copy link

It would be useful if there would be a way to map certain primitive field scalars from certain types of the prisma schema to custom graphql scalars for example with graphql-scalars to have an even stricter type system which also reduces the need for class-validator since the validation takes place directly at the resolver level. It would be really nice to have this feature to have more control over the schema generation.

Example:

type definition of Person in prisma.schema with the primitive type String:

model Person {
  email String
}

type definition of Person in schema.graphql with a custom scalar EmailAddrress:

type Person {
  email: EmailAddress
}

generated type definition of Person as a typegraphql object type with custom scalar resolver:

import { EmailAddressResolver } from 'graphql-scalars';

@ObjectType()
export class Person {
  @Field(() => EmailAddressResolver)
  email!: string;
}
@MichalLytek MichalLytek added the enhancement New feature or request label Dec 29, 2020
@MichalLytek
Copy link
Owner

MichalLytek commented Jan 6, 2021

I'm afraid it's more complicated than it looks 😕

I wanted to do this by the custom attributes:

model User {
  /// @TypeGraphQL.scalar(name: "EmailAddress")
  email  String  @unique
}

But I realized I can only refer to built-in scalars as I don't know what import statement should it generate.
For decorators it was solved by doing by TS file in runtime but TypeGraphQL has no way to alter already generated schema.

I need to find a better way to compose generation phase with TS values. Currently I'm thinking of exposing config object:

// typegraphql-config.ts
import { EmailAddressResolver } from 'graphql-scalars';

const config: TypeGraphQLGeneratorConfig = {
  scalars: {
    "EmailAddress": EmailAdressResolver,
  },
};
export default config;

Which would be then registered in generator config:

generator typegraphql {
  provider        = "node ../src/cli/dev.ts"
  output          = "../prisma/generated/type-graphql"
  config          = "../typegraphql-config"
}

So the generator would be able to generate import for that file, so the scalar can be safely referenced:

import TypeGraphQLGeneratorConfig from "../some-relative-path/typegraphql-config";

@ObjectType()
export class Person {
  @Field(() => TypeGraphQLGeneratorConfig.scalars["EmailAddress"])
  email!: string;
}

The only drawback of this approach is that the config file would need to be as much static and independent (no custom code imports) as it's possible 🤔

Secondly, it's really complicated to apply such validation or scalars to input types, based on model type metadata. DMMF doesn't provide enough info about how the types are related to each other.

I try to apply some regex-like heuristic to detect that and rename types or fields. In case of scalars, it's one level more complicated because the types can be a complex StringFilter which are harder to replace with custom scalar than simple field.

All in all, this feature might take a long time to implement, so for now I would recommend waiting a bit for applyInputTypesEnhanceMap support and just use class-validator on the fields you need 😉

@macmillen
Copy link
Author

Ok that makes sense, thanks for looking into it though. 👍 I'm already looking forward to the applyInputTypesEnhanceMap.

@stevefan1999-personal
Copy link

stevefan1999-personal commented Feb 17, 2021

@MichalLytek You can refer to unlight/prisma-nestjs-graphql, where he added options to generator field:

generator nestgraphql {
  provider = "node node_modules/prisma-nestjs-graphql"
  output   = "../src/generated/prisma/nestgraphql"

  # typescript declaration type
  types_EmailAddress_fieldType = "string"
  # graphql scalar type for @Field
  types_EmailAddress_graphqlType = "EmailAddressResolver"
  types_EmailAddress_graphqlModule = "graphql-scalars"
}

model Foo {
  /// @TypeGraphQL.scalar(name: "EmailAddress")
  email  String  @unique
}

Then it should generate:

import { EmailAddressResolver } from "graphql-scalars";

@ObjectType()
export class Foo {
  @Field(() => EmailAddressResolver)
  email!: string;
}

which should solve your problem

Also I think we can introduce default scalars in graphql-scalars freely as we should be battery packed as much as possible. This mean we could let people to opt-out using it by import_default_types = false

@fivethreeo
Copy link

fivethreeo commented Aug 19, 2021

If you could output just resolvers and a .graphql schema you could just import all types from graphql-codegen built from that .graphql. Could also output a codegen.yml with the model mappings mapped to the prisma models.

@MichalLytek
Copy link
Owner

@fivethreeo typegraphql-prisma emits resolver classes, not schema. TypeGraphQL can build typeDefs and resolvers but this breaks some of graphql-js features like directives and extensions, so it's not a solution to force users to do that.

@MichalLytek MichalLytek added the priority:medium This issue has a medium priority label Nov 10, 2021
@carlocorradini
Copy link
Contributor

Any update? 😥

@calvinl
Copy link

calvinl commented Sep 15, 2022

Just came across this. Would be great to use custom scalars in the generated code!

@MichalLytek MichalLytek added priority:high This issue is important and will be done first community Something initiated by the community and removed priority:medium This issue has a medium priority labels Mar 22, 2023
@MichalLytek MichalLytek self-assigned this Mar 22, 2023
@sebmellen
Copy link

Would love to see this get merged! It would help us a lot @cerebruminc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
community Something initiated by the community enhancement New feature or request priority:high This issue is important and will be done first
Projects
None yet
Development

No branches or pull requests

7 participants