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

console and CLI: throw intuitive error messages when unsupported defintions are used in custom types #4666

Open
frossi85 opened this issue May 4, 2020 · 12 comments · May be fixed by #5434
Open
Labels
c/actions Related to actions c/console Related to console

Comments

@frossi85
Copy link

frossi85 commented May 4, 2020

Hi,

I am trying to create an action to call one of my rest endpoints but it seems that Hasura does not support fully GraphQL specs. Here is the action definition:

type Query {
  searchAssets (search: String): [Asset]
}


#4579 Types definitions

type Asset {
  friendlyName: String!
  description: String!
  symbol: String!
  type: AssetType!
  logo: String
  metadata: AssetMetadata
}

enum AssetType {
  Stock
  Future
  Bond
  Securities
  InternationalStock
  Check
  Option
  TreasuryBills
  FixedIncomeSecurities
  Mocked
}

union AssetMetadata = CompanyMetadata | OtherMetadata

type CompanyMetadata {
  ceo: String!
  headQuarters: String!
  foundedAt: Int!
  employees: Int!
}

type OtherMetadata {
  other: String!
}

When I click on the Create button basically nothing is happening, there is not error or any feedback. So my guess was that probably union was not supported, even if it was part of GraphQL spec. So when I removed all the metadata related types and field the action was created. Then I tried to create just one metadata type with all optional types like this:

type Query {
  searchAssets (search: String): [Asset]
}


Types definition

type Asset {
  friendlyName: String!
  description: String!
  symbol: String!
  type: AssetType!
  logo: String
  metadata: Metadata
}

enum AssetType {
  Stock
  Future
  Bond
  Securities
  InternationalStock
  Check
  Option
  TreasuryBills
  FixedIncomeSecurities
  Mocked
}

type Metadata {
  ceo: String
  headQuarters: String
  foundedAt: Int
  employees: Int
  other: String
}

I got this error:

validation for the given custom types failed because the type "Metadata" of the field "metadata" in the object type "Asset" is object type which isn't allowed

Which is strange because GraphQl also supports it, and seems a really important feature to be able to a couple already implemented APIs with Hasura Action. The first issue while I would love to see it is not a real stopper but the seconds one it is.

So the question if these are bug or current limitations, and when you are planning to implement them if that is the case.

Thanks

@wawhal
Copy link
Contributor

wawhal commented May 5, 2020

Hey @frossi85
You ran into some limitations of custom types with Hasura.

  1. It is currently not possible to define Interfaces and Union types as custom types
  2. Hasura does not allow a field of an object type to be another object type, i.e. the fields of an object type can only be scalars and enums. For a more complicated structure, the object types can be connected to the rest of the graph via relationships.

Read more about custom types here.

However, not getting a valid feedback on an error is a bug, so I am rescoping this issue to return proper feedback when an error happens.

@wawhal wawhal changed the title [Bug] Action's types definition console and CLI: throw intuitive error messages when unsupported defintions are used in custom types May 5, 2020
@wawhal wawhal added c/actions Related to actions c/console Related to console labels May 5, 2020
@frossi85
Copy link
Author

frossi85 commented May 5, 2020

Thanks for the quick response, I did not get this:

For a more complicated structure, the object types can be connected to the rest of the graph via relationships.

I read the docs but not sure how that can be achieved with my current API. Are you suggesting that I split my API in 2, one for the root object, and other for the metadata object and then relate them in some way?

Also, the Hasura team has plans to implement Interfaces and Union types as custom types? If it is a yes, do you have an estimate like 2020 Q4 or some approx?

@frossi85
Copy link
Author

frossi85 commented May 5, 2020

Also in cases like this, I think that having a way to define some mapping function in the actions to map API responses to the output type, plus cache over those API calls and relationships between Actions not only with a table will solve this issue without implementing that objects can contain objects.

How? In my example, I would create two actions calling the same API URL, in one I would define the type:

type Metadata {
  ceo: String
  headQuarters: String
  foundedAt: Int
  employees: Int
  other: String
}

with a mapping function like this: response.map(x => x.metadata)

Then define another action with this type:

type Asset {
  friendlyName: String!
  description: String!
  symbol: String!
  type: AssetType!
  logo: String
}

And then define a relationship from Asset to Metadata.

So if the cache is in place my API will be called just one time and I will be able to construct more advanced graphql schemas without changing my old API.

The idea to create a graphql server to overcome the limitations of Hasura goes against the philosophy of Hasura (at least si what I see that you are trying to do) of developing Graphql API as fast as u can without friction and with the ability of reuse old APIs that you already built.

I know you are doing the best guys and this is great but this is just an idea on how maybe you can enhance the product because mapping function will not help just in this scenario but in many other, like my old API use this casing in the response: { my_prop } but with Hasura we are trying to use this: { myProp } or the other way around.

I hope the feedback helps you to keep rocking it.

@FickleLife
Copy link

FickleLife commented May 13, 2020

FYI, I have stumbled across this issue trying to use Actions to deliver results to Dart types (Flutter), using Artemis to code gen all the types based on the gql schema and queries. I'll have to rethink how to strongly type nested Actions outputs.

The somewhat cryptic error I get is the type "HourlyResult" of the field "hourlyResult" in the object type "Hourly" is object type which isn't allowed

@rikinsk rikinsk added c/server Related to server and removed c/server Related to server labels Jun 2, 2020
@kolharsam kolharsam linked a pull request Jul 21, 2020 that will close this issue
2 tasks
@abdullah2993
Copy link
Contributor

any roadmap for implementing the feature?

@kolharsam
Copy link
Contributor

kolharsam commented Nov 18, 2020

@abdullah2993 as you can see, work had started in #5434 and it's been stalled at the moment. The changes on the console are done, and similar changes on the CLI were required. We will pick this up again, soon.

cc @beerose

@jifeon
Copy link

jifeon commented Feb 14, 2021

@frossi85

And then define a relationship from Asset to Metadata.

According to docs you can define only relation between action and table, but not between 2 actions. Probably I missed something?

@AlexKenbo
Copy link

We need to make a response for an action.

And the response must contain a list of objects.
But we get an error that the type of the field cannot be an object.

Hasura v 1.3.3

Снимок экрана 2021-05-28 в 11 50 37

@AlexKenbo
Copy link

We found such a solution - use jsonb

type Response {
   items: jsonb!
}

@jumpdol
Copy link

jumpdol commented Aug 12, 2021

Also in cases like this, I think that having a way to define some mapping function in the actions to map API responses to the output type, plus cache over those API calls and relationships between Actions not only with a table will solve this issue without implementing that objects can contain objects.

How? In my example, I would create two actions calling the same API URL, in one I would define the type:

type Metadata {
  ceo: String
  headQuarters: String
  foundedAt: Int
  employees: Int
  other: String
}

with a mapping function like this: response.map(x => x.metadata)

Then define another action with this type:

type Asset {
  friendlyName: String!
  description: String!
  symbol: String!
  type: AssetType!
  logo: String
}

And then define a relationship from Asset to Metadata.

So if the cache is in place my API will be called just one time and I will be able to construct more advanced graphql schemas without changing my old API.

The idea to create a graphql server to overcome the limitations of Hasura goes against the philosophy of Hasura (at least si what I see that you are trying to do) of developing Graphql API as fast as u can without friction and with the ability of reuse old APIs that you already built.

I know you are doing the best guys and this is great but this is just an idea on how maybe you can enhance the product because mapping function will not help just in this scenario but in many other, like my old API use this casing in the response: { my_prop } but with Hasura we are trying to use this: { myProp } or the other way around.

I hope the feedback helps you to keep rocking it.

did u fix that issue?

@rossano-gallardo
Copy link

Gents, I have a service that will return a complex object as output, I need all those arrays of objects and other properties as objects to serve my front end.
Without this feature I will have to make my front end do a call to this service to then call hasura with the returned data.
actions without been able to do arrays of object types and object types as properties seem only to work when you don't need much data from other datasources

@aindong
Copy link

aindong commented Sep 22, 2021

We found such a solution - use jsonb

type Response {
   items: jsonb!
}

Having the same problem but yeah, using just jsonb solves it

@kolharsam kolharsam removed their assignment Sep 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c/actions Related to actions c/console Related to console
Projects
None yet
Development

Successfully merging a pull request may close this issue.