grats icon indicating copy to clipboard operation
grats copied to clipboard

Idea for discussion: Introduce `@gqlSchema.query`, `@gqlSchema.mutation` and `@gqlSchema.subscription`

Open mandx opened this issue 1 year ago • 6 comments

These would tag a single object type as the type used in the corresponding schema declaration in the resulting SDL. So, something like this:

/**
 * @gqlType
 * @gqlSchema.query
 */
export class MyOddlyNamedQueryType {
  /** @gqlField */
  me(): string {
    return new 'yo';
  }
}

Would generate:

type MyOddlyNamedQueryType {
  me: String
}

schema {
  query: MyOddlyNamedQueryType
}

Same for @gqlSchema.mutation and @gqlSchema.subscription. Obviously, at build/introspection time, a check should run that asserts that each of these @gqlSchema.* appear only once. Defaults would still be used; so, there is a @gqlSchema.query on a type, but there's no @gqlSchema.mutation anywhere, it is assumed that the schema's mutation key would be whatever object type is named Mutation.

mandx avatar Nov 04 '23 17:11 mandx

Maybe a tag like @gqlSchema.description = "some string..." could be added to one of those query/mutation/subscription types to address #33.

mandx avatar Nov 04 '23 17:11 mandx

I think I was imagining something more like:

/**
  * An amazing schema!
  * @gqlSchema 
  */
type Schema {
  /**
   * The query operation
   * @gqlOperation */
  query: Query,
  /** @gqlOperation */
  mutation: Mutation
  /** @gqlOperation */
  subscription: Subscription
}

which would emit:

"""
An amazing schema!
"""
schema {
  """
  The query operation
  """
  query: Query
  mutation: Mutation
  subscription: Subscription
}

It's a bit more verbose, but I think it has better symmetry with our existing tags and also more closely models the SDL. It gives a place to define a top-level schema description, as well as leaving the door open for directives on each of these positions (schema definition, as well as each operation's definition).

captbaritone avatar Nov 06 '23 18:11 captbaritone

hmmmm, inspired from your example, mine could also be:

/**
 * @gqlType
 * @gqlOperation query
 */
export class MyOddlyNamedQueryType {
  /** @gqlField */
  me(): string {
    return new 'yo';
  }
}

Honestly, I like all these options equally :smile:

Question: In your example, on the object type tagged @gqlSchema, why is @gqlOperation necessary? Seems to me redundant, as this type should mirror very closely the schema SDL declaration; we already know from the start the exact "shape" this object has to have, a plain object with the query, mutation and subscription keys typed as optional, and pointing to types tagged with @gqlType. Do you foresee any extra keys needed, causing @gqlOperation to resolve ambiguity of some kind?

mandx avatar Nov 06 '23 19:11 mandx

Re verbosity: IMO that is not a problem in practice, because defining the schema is something done once and most likely it won't ever change. Verbosity could become a problem if we were discussing type-level or field-level stuff though

mandx avatar Nov 06 '23 19:11 mandx

hmmmm, inspired from your example, mine could also be: [...]

Yeah, I like that a bit better than the version with the dot syntax. However that still doesn't give a clear way to add a description to the schema itself, or a clear way to add descriptions/directives to the operation declaration itself without adding new semantics to how tags work.

Question: In your example, on the object type tagged @gqlSchema, why is @gqlOperation necessary? Seems to me redundant, as this type should mirror very closely the schema SDL declaration; we already know from the start the exact "shape" this object has to have, a plain object with the query, mutation and subscription keys typed as optional, and pointing to types tagged with @gqlType. Do you foresee any extra keys needed, causing @gqlOperation to resolve ambiguity of some kind?

Yeah. I think you're right that we could omit the @gqlOperation and just expect every field on the type to be an operation. think the only argument in favor of the @gqlOperation approach is that it is more explicitly parallel to how you define types. Combined with your point about verbosity not being an issue in this exact case, I'm tempted to err on the side of explicit.

captbaritone avatar Nov 06 '23 21:11 captbaritone

However that still doesn't give a clear way to add a description to the schema itself

True, I forgot about that. This then clearly makes your proposal the way to go! Regarding @gqlOperation, Grats could require them in the first implementation, then after some time and feedback, it could be considered to simply not require them, assuming this wouldn't incur in breaking changes.

mandx avatar Nov 06 '23 22:11 mandx