graphile / crystal

🔮 Graphile's Crystal Monorepo; home to Grafast, PostGraphile, pg-introspection, pg-sql2 and much more!
https://graphile.org/
Other
12.62k stars 571 forks source link

use table enums in functions via domain in V5 #2214

Open tsnobip opened 1 month ago

tsnobip commented 1 month ago

Feature description

V4 has the feature to use table enums in functions via domain, I think we should port it to V5 too. I'm just not sure how to do it in V5 (possibly via build.setGraphQLTypeForPgCodec).

Motivating example

Same motivation as for the feature in V4, allowing to have nice GraphQL enums in function parameter / return types.

Breaking changes

not breaking as far as I know

Supporting development

I [tick all that apply]:

tsnobip commented 1 month ago

I made some experiments, something like this almost works:

{
      name: 'EnumDomainGraphQLTypePlugin',
      version: '0.0.0',
      schema: {
        hooks: {
          finalize(_, build) {
            for (const [key, codec] of Object.entries(build.input.pgRegistry.pgCodecs)) {
              if (codec.domainOfCodec?.name == 'text') {
                const name = build.inflection.builtin(codec.name.charAt(0).toUpperCase() + codec.name.slice(1, -4));
                build.setGraphQLTypeForPgCodec(codec, "output", name);
                build.setGraphQLTypeForPgCodec(codec, "input", name);
              }
            };
            return _;
          },
        },
      },
    }

The issue is that the domain is already registered as a scalar so it fails and I don't know how to deregister a scalar (or prevent it to get registered).

benjie commented 1 month ago

Indeed; this relates to:

You shouldn't be using the finalize hook for this, it's way too late - that's the final step when the schema is built. Instead use the init hook, and have it run before PgCodecsPlugin:

schema: {
  hooks: {
    init: {
      before: ['PgCodecsPlugin'],
      callback(_, build) { ... }
    }
  }
}