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.17k stars 2.77k forks source link

actions: Allow to reuse already existing types #5001

Open xzilja opened 4 years ago

xzilja commented 4 years ago

Current Behaviour

We have to explicitly define action types for inputs and outputs, even if we are returning types that already exist (i.e. want to return characters type associated to already existing characters table, yet have to type it all out manually in action as a new type).

This creates few barriers, especially when we have to type out larger responses. It creates a lot of duplicate types, which get in the way when using tools like https://graphql-code-generator.com And makes it really hard to work with typescript, where it expects some values to be of enum type, but we can't re-use enums in actions (See #4513)

Right now this is a single peace of functionality in hasura (at least for our team) that requires a lot of manual work / workarounds to get them working correctly with typescript and apolo cache (apollo cache doesn't get updated correctly as actions don't return existing types we use with queries for example).

Right now editing / deleting custom types doesn't update hasura's hdb_custom_types correctly as well, making this issue of "a lot of unnecessary types" even worse (See #4967)

Doing so with approach described here https://hasura.io/docs/1.0/graphql/manual/actions/reuse-types-actions.html is viable, but perhaps a simpler method where we just define return types would be better?

Expected Behaviour

Actions should allow access to all types that already exist in our graphql schema (those generated when we create tables / enums etc...). We should be able to create actions without defining any custom types if action output uses already existing type (i.e. see characters example above). When "Derive Action" option is clicked from Graphiql, generated action should reuse types from the code we typed out in Graphiql instead of creating it's own custom types. Generated action schema should have correctly inherited __typename fields, so if it returns an existing type it will work correctly with tools like apollo cache.

I am not sure about this one, but it would add to dev experience if we could get type auto completion in actions text fields as well.

katya450 commented 4 years ago

Not sure if I should open another ticket about my problem, but as it seems to be quite similar with this one, I'll just comment here (stressing the importance of this while ticket doing so :) )

I have a (derived) action like this:

Type Mutation {
  InsertStuff (
    name: String
    type: MyTypesEnum
    colors: SelectedColors
): InsertStuffOutput
}

My issue is with the "type" and "colors" -field types.

I already have "type" defined in Hasura as an enum-table, and Hasura has auto-generated a type of it; "hasura_stuff_types_enum". I have similar auto-generated Hasura-type defined for colors, which is a list of objects; "[hasura_stuff_colors_insert_input]".

Now, when I try to use these existing, auto-generated types as my action's input types, they get not accepted as they are not defined in custom types.

It works if I re-define the same things as MyTypeEnum and SelectedColors in the Action console Types definition - but I'm having really hard time believing that this is the wanted and proper way to do this, because Hasura should already know these types. As my mutation is really much larger than this example I wrote, the action would create over 2000 lines of custom types required by this, some of which are enums already once defined in the schema.

Like mentioned above, there is a Hasura manual page about re-using existing types, but that seems to work only with output-types. My issue is with the input-types.

pacoccino commented 3 years ago

Up ! This becomes really problematic with typescript, not to say that defining the same enum in different places is bad design.

jjangga0214 commented 3 years ago

In my humble opinion,

I guess the limit is introduced by technical uncertainty.

For instance, what should be done when existing types 'directly'(not depending on Relationship) used in action schema are modified or deleted? Should action be cascaded, or the change restricted?

For another example, for existing types directly used by actions, is it enough for an action handler to respond with just pk?

Current

type MyCustomType {
  fooId: String!
  # foo: Foo! # This will be dynamically created by Hasura by Relationship, if you set.
  bar: Int!
}

Expected

type MyCustomType {
  foo: Foo!
  bar: Int!
}

And action handler can return pk only, similar to the way Apollo Federation works?

{
  "foo": {
    "id": "helloworld" // This is pk.
     // foo's other fields are automatically queried by Hasura, if a client requests.
     // Action handler does not have to do that.
  },
  "bar": 123
}

There are a few things to decide first, and I feel the issue can be resolved, at least it looks far from being impossible.

rfieve commented 3 years ago

Up ! Manually duplicating types representing the same entities is indeed error-prone and introduces unnecessary overhead. Allowing actions input types to consume enums from the schema is required to maintain a single source of truth regarding typing.

omieliekh commented 3 years ago

Upvoting for this one. I'm trying to setup custom Action with Metadata Config v2.

I expect that adding new mutation should be as straightforward as this

# metadata/actions.graphql

type Mutation {
  insert_users_one_custom(object: residents_insert_input): users
}
# metadata/actions.yaml

actions:
  - name: insert_users_one_custom
    definition:
      kind: synchronous
      handler: '{{ACTION_BASE_URL}}/insert_users_one_custom' # custom route that's defined separately
      forward_client_headers: true
custom_types:
  enums: []
  input_objects: []
  objects: []
  scalars: []

Where

But looks like it's not possible to do with current setup 😕

MarkNBroadhead commented 3 years ago

When attempting to use an existing input object, the following error message reason is produced: "Inconsistent object: in action \"myAction\"; the type: \"user_set_input\" is not defined in custom types or it is not a scalar/enum/input_object" If this takes a while to fix, I would suggest changing the error message to include: "the type \"user_set_input\" must be defined in custom types and be of type scalar, enum, or input_object"

joelbqz commented 3 years ago

I wish this could be implemented soon 😢 I'm facing an issue where I have a large table of 60+ columns, then I'm using an insert_ mutation but I need to validate some data with other services, then it becomes a mess of custom duplicated types when tried to derivate into an action.

bhm-wathan commented 2 years ago

+1

snipebin commented 2 years ago

to keep things DRY we need this feature. Lots of duplication going on at the moment

NMCarv commented 2 years ago

Hey, any forecasts on this?

AaronActu commented 2 years ago

Hey @0x777,

We do really appreciate your job 👍

Could you explain us why this in not implemented ?

denis-ryzhkov commented 2 years ago

Please let me know if you have a better workaround:

Custom mutations

Scripts used:

tombrouwer commented 2 years ago

I'm not really a Go or Haskell programmer but maybe I can help with developing a concept. Or think along.

karibertils commented 2 years ago

Any news on this one ?

ilijaNL commented 2 years ago

bump

heberuriegas commented 2 years ago

+1

testbuddy commented 2 years ago

bump

Omnean commented 1 year ago

bump

iangabrielsanchez commented 1 year ago

+1

joelbqz commented 1 year ago

+1

soorajshankar commented 1 year ago

Hey Folks,

Appreciate your patience, I noticed that there are 2 use cases here,

  1. Redefining an already existing type is a lot of effort
  2. I want “Hasura” to use the auto-generated types on Action definitions and keep that updated with tracked tables. Note that this means that if some customisation or permission is added to the table then the type would dynamically keep changing.

Point 2 is much harder and probably not a good architecture considering the dynamism of auto-generated types. But we are working on Point 1 - a feature that would allow the users to re-use the table shape without manually typing it - I hope this could help reducing the time spend on writing the action type definition, will this be useful for your problem?

soorajshankar commented 1 year ago

Hey Folks,

Update: We developed a console feature on the point 1 that I mentioned above and this feature will be available from the next release (v2.17)

Also I created a discussion https://github.com/hasura/graphql-engine/discussions/9273 describing the first iteration of the feature and possible enhancements, please take a look and let us know your thoughts.

rahulagarwal13 commented 1 year ago

Thanks all for the feature request. We would like to update you that reuse enum types in Actions, is currently on the roadmap. We’ll get started in the next few months - would love to get you as a design partner when we get started, so please let us know if you are interested to collaborate.

Reusing other database types in Actions is still being considered and we cannot provide a timeline at this point. As @soorajshankar mentioned above it is more complex. Most of the comments in this issue mention the reuse of enums. We would be interested to know how many users are affected with the lack of support of other database types and what are the examples of those types/use-cases? Also what is the kind of behavior you would expect when the database types changes? Do the action types remain in sync or would they be modified manually?

lukepolo commented 1 year ago

We ran into this today, we have a pretty large number of columns in a particular table. We want to create an action to replace the standard insert, because it starts a transaction that has multiple steps (hidden from the user).

We were using events, but ran into race conditions. It would have been nice to reuse our existing insert type on this table to save a lot of headache.

Update: reuse enums i believe would fix our issue for the most part

joanrodriguez commented 11 months ago

This would be a nice feature indeed

manasag commented 11 months ago

Thanks everyone for your comments and patience on this issue. We have been closely listening into all the feedback and requests from the community, and have been working on a re-imagined, re-architectured Hasura, that tackles many of these from ground up. We are pleased to announce that we are launching V3-Alpha of Hasura (Data Delivery Network) on our next Community call on Nov 30. The new metadata structure in V3 is designed to be highly flexible and declarative, to support the perfect GraphQL schema you would like to achieve. In V3, we give user the controls to define the types and the mappings to objects (which includes actions), which helps solve this issue in a systemic manner. We would request to join this community call to learn more about Hasura V3. Post launch, we will update this issue with relevant details.