cashay
cashay copied to clipboard
Implement `NOT_NULL` and `INTERFACE` schema kinds
I'm currently evaluating a few alternatives to Relay and I wanted to see if I could drop cashay in and get a feel for it. Right now it doesn't handle NOT_NULL and INTERFACE kinds properly.
I'm talking about this function: https://github.com/mattkrick/cashay/blob/3a4bfbcdc2b17f497dd4626a9c8083f49c283898/src/normalize/denormalizeStore.js#L80
From the GraphQL docs about NON_NULL:
// http://graphql.org/docs/api-reference-type-system/#graphqlnonnull
A non-null is a kind of type marker, a wrapping type which points to
another type. Non-null types enforce that their values are never null
and can ensure an error is raised if this ever occurs during a
request. It is useful for fields which you can make a strong guarantee
on non-nullability, for example usually the id field of a database row
will never be null.
And here's the thing for INTERFACE:
When a field can return one of a heterogeneous set of types, a
Interface type is used to describe what types are possible, what fields
are in common across all types, as well as a function to determine
which type is actually used when the field is resolved.
the only time non-null is useful is to create variableDefinitions. Aside from that, non-null is an annoying shell we have to take off when walking the ast. https://github.com/mattkrick/cashay/blob/3a4bfbcdc2b17f497dd4626a9c8083f49c283898/src/normalize/denormalizeStore.js#L57
Interface info is irrelevant, since there's no good reason to know what fields are guaranteed, only what fields are provided. In the future, i'll remove this entirely from the client schema to make the payload even smaller.
I'm pretty confident cashay can handle just about anything you can throw at it, and there are tests to prove that it works with everything you mentioned: https://github.com/mattkrick/cashay/blob/3a4bfbcdc2b17f497dd4626a9c8083f49c283898/src/normalize/tests/denormalizeStore-tests.js
If you can find something that cannot be denormalized, please add a test for it here :smile:
Hm, it doesn't denormalize NON_NULL properly as of now. In my particular case, the subState is a normalized string that should be visited using visitNormalizedString, but is not.
Can you paste a snippet of your client schema?
{
"kind":"OBJECT",
"name":"Me",
"fields":{
"account":{
"name":"account",
"type":{
"kind":"NON_NULL",
"ofType":{
"kind":"INTERFACE",
"name":"Account"
}
}
},
"clientEncryptionKey":{
"name":"clientEncryptionKey",
"type":{
"kind":"NON_NULL",
"ofType":{
"kind":"SCALAR",
"name":"String"
}
}
}
}
}
account isn't deserialised properly
i've never used an interface as a field before, usually i build an interface internally & then other fields use that: https://github.com/mattkrick/cashay/blob/master/src/tests/schema.js#L75
Could you help me understand why account needs to be an interface? Or come up with an example that i could use to make a test case?
Right now I can't tell you why it needs to be an interface, as I'm not responsible for the API / schema, I'm only consuming it. I'm not sure when I'll have time to dig into creating a working schema for the test cases
Talk to your back end dude, seems like account should be an object or maybe a union, but if theres a good use case for it I'll be glad to add it, I've just never come across one...
We're using an Interface instead of a Union, since it makes querying for all common fields that are shared by all implementations easier. I have tried a few times now to come up with either failing tests or a working solution, but there's quite a few things that haven't been working (like updating the schema), but I'll create separate tickets for that.
oh for sure, still very much in alpha as stuff is changing on the daily, but i think we (finally) got a good flow for schema creation as of this morning (yay!). The getState param in the mutationHandlers callback is still broken, but everything else should be working. I'm on a sprint for building a subscription method, but after that's done i should have some time to write some more proper unit tests.
WRT interfaces, i'd settle for a comparison of how you write the query for interface vs. how you'd have to write it for a union. For unions I'd write something like:
query {
getObj {
foo,
bar,
... on TypeA {baz}
... on TypeB {faz}
}
}
If it's easier to use an interface, I'd love to learn! Just cuz i can walk an AST doesn't mean i'm an expert by any means :smile:
From what I understood is that you can't directly query the foo field in a Union, but you have to put it into each subtype. I'm not at the computer right now, but I'll verify this and report back. If querying doesn't look any different, I suppose there's not much reason to choose one over the other.
Shouldn't it be supported anyway if there's no advantage to use either Union or Interface? Solely because the spec allows it, I mean. Don't feel pushed, though, I'm merely experimenting with cashay at this point. ☺️
Absolutely, if the spec allows it, cashay should support it, i just desperately need an example that fits into the test schema so I can write tests against it.