Skip to content

Conversation

@theobat
Copy link
Contributor

@theobat theobat commented Jul 1, 2020

No description provided.

@theobat theobat marked this pull request as ready for review July 2, 2020 08:05
instance Decode a => Decode (NonEmpty.NonEmpty a) where
decode = withRefinedList (maybe (Left "Expected a NonEmpty list") Right . NonEmpty.nonEmpty) decode

-- | Should this instance dedupe silently or fail on dupes ?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should fail.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, it's more coherent with the other behaviors (i.e. non empty)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or directive @Uniq will validate duplicates. and with assumption that there are no dups, decode will dedupe silently.
what do you think?

@nalchevanidze
Copy link
Member

nalchevanidze commented Jul 2, 2020

with this way Graphql client can't distinguish difference between set, non-empty and regular list.

that why may it will be better approach to add them directives? for example:

 data MyInput = MyInput {  
    list1 :: NonEmpty Int,
    list2 :: Set Int,
    list3 :: [int] 
 }

that can be represented as:

directive @NonEmty () on FIELD_DEFINITION | INPUT_FIELD_DEFINITION
directive @Uniq () on FIELD_DEFINITION | INPUT_FIELD_DEFINITION


input MyInput {  
    list1: [Int!]! @NonEmpty
    list2: [Int!]! @Uniq
    list3: [int!]! 
 }

@nalchevanidze
Copy link
Member

you can define custom directives at morpheus-graphql-core/src/Data/Morpheus/Schema/Directives.hs

to assign dirctives to fields see:

  • src/Data/Morpheus/Server/Deriving/Introspect.hs.
  • src/Data/Morpheus/Server/TH/Declare/Introspect.hs

@theobat
Copy link
Contributor Author

theobat commented Jul 2, 2020

with this way Graphql client can't distinguish difference between set, non-empty and regular list.
that why may it will be better approach to add them directives? for example:

Yeah that's a really good idea ! I was annoyed by the missing differences on the client too !

@nalchevanidze
Copy link
Member

no. introspection does not render directives. so. we can't assign them directives. :(

@nalchevanidze
Copy link
Member

only way would be:

data MyInput = MyInput {  
    list1 :: NonEmpty Int,
    list2 :: Set Int,
    list3 :: [int] 
 }

to wrapp and generate custom types for them:

input InputNonEmpty_Int {
   elems : [Int!]!
}

input InputSet_Int {
   elems : [Int!]!
}

input MyInput {  
    list1: InputNonEmpty_Int
    list2: InputSet_Int
    list3: [int!]! 
 }

is kind a too verbose but, what we can do?

@theobat
Copy link
Contributor Author

theobat commented Jul 6, 2020

Is it explicitly out of the introspection query or is it just "not mentioned" in the spec ? (I didn't find any reference to schema directives presence or absence in the introspection query).
Anyway, I think there are 4 options here:

  • drop support for list-like structures (handle the list to Set or list to NonEmpty in your resolvers).
  • support those structures "silently" (no information on the client, considered the same as lists).
  • create a superset of the spec and implement new wrapper types.
  • use custom directives on the schema, but still without information on the client (or maybe this is where we can create a superset of the spec)

At least that's the only options I see, for input types. Personally, I'm ok with 2, 3, 4 options and like 3 and 4 better.
It seems like other languages are doing 4 with no introspection info.
As far as other languages are concerned it seems the 1st option is the rule (Java).
I don't think "augmenting" the language with custom wrapper types is bad (like type script "augmented" javascript), but maybe I'm missing something...

@nalchevanidze
Copy link
Member

nalchevanidze commented Jul 6, 2020

for custom specifications compatibility problems with all graphql clients may occur. but i still think that, GraphQL should support this datatypes some way (for both Input and Output types).

one solution can be custom wrappers:

# is kind of wrapper
# rights side can of "=" :
#   - only can  appear wrapper types (like lists and custom wrappers)
#   - wrapper "!" is not allowed. e.g [a!] is invalid
wrapper NonEmpty a = [a]
wrapper Set a = [a]
wrapper Pair a b = [a, b]
wrapper Map a b = [Pair a b]
wrapper NonEmpty a =  [a]
wrapper Set a = [a]

input MyInput {
  list1: (NonEmpty Int!)!
  list2: (Set Int!)!
  list3: [int!]!
  map: (Map String! Int!)!
}

type MyOutput {
  list1: (NonEmpty Int!)!
  list2: (Set Int!)!
  list3: [int!]!
  map: (Map String! Int!)!
}

we can formalize it . and make a proposal as an issue for it on: https://github.com/graphql/graphql-spec/issues

@nalchevanidze
Copy link
Member

@theobat what do you think?

@nalchevanidze
Copy link
Member

nalchevanidze commented Jul 6, 2020

server must define serialization methods for wrappers.

wrapper NonEmpty a = [a]

haskell

class Wrapper wrapper  where
    fromList :: [a] -> Either String (wrapper a)
    toList ::  wrapper a -> [a]

instance Wrapper NonEmpty where
   fromList x = ...
   toList x = 

js

const fromList = xs => {}
const toList = nonempty => [....]

const resolverMap = {
  NonEmpty: new GraphQLWrapperType({
    name: 'NonEmpty',
    description: 'NonEmpty list',
    parseValue: fromList,
    serialize: toList,
  })
}

@theobat
Copy link
Contributor Author

theobat commented Jul 6, 2020

Yeah it feels like the right way to do it, besides the main graphql implementation is in javascript and they already have added Set so, it feels like the way to go.

@theobat
Copy link
Contributor Author

theobat commented Jul 6, 2020

So let's work on the proposal to graphql then, cause it seems like the way to go.

@theobat
Copy link
Contributor Author

theobat commented Aug 10, 2020

For the record, I'm working on this:
https://gist.github.com/theobat/beccb49724250103535229f423b9084c

I think it would be interesting to reach people at https://github.com/hasura/graphql-engine, https://github.com/graphql-java/graphql-java, https://github.com/sangria-graphql/sangria and maybe even https://github.com/graphql-rust/juniper, to get more leverage; but let's waait for a better version of the proposal (in particular I'd like to tackle the actual spec changes before submitting and requesting comments).

@theobat
Copy link
Contributor Author

theobat commented Aug 10, 2020

@nalchevanidze I'd like your review on my draft proposal when you have time. If you find it OK, I'll probably talk about the idea in other graphql libraries before submitting it to the graphql-spec process.

@nalchevanidze
Copy link
Member

@theobat
Copy link
Contributor Author

theobat commented Aug 16, 2020

@nalchevanidze I think we should do the server-side only (simple Encode, Decode like lists) for Vector, because it's semantically equivalent to Lists, I can fix the PR for this if you want

That is to say, I don't think calling a list [Person] or Vector Person on the client really important introspection wise, they behave the same... (but maybe that's just me though).

@nalchevanidze
Copy link
Member

@theobat for now we can just add missing instances without waiting of proposal wrapper types. and update library when the proposal is accepted.

@theobat
Copy link
Contributor Author

theobat commented Oct 25, 2020

Right, I'm going to rebase and clean this

@theobat theobat force-pushed the add-missing-instances branch from 0a31453 to bb2bbf0 Compare October 26, 2020 10:36
@theobat theobat force-pushed the add-missing-instances branch from cc0c62d to 39f1ff3 Compare November 4, 2020 09:35
@theobat
Copy link
Contributor Author

theobat commented Nov 4, 2020

@nalchevanidze, This should be ready now !

@nalchevanidze
Copy link
Member

@theobat hi thanks, sorry for late response. could you update changelog too?

@theobat
Copy link
Contributor Author

theobat commented Nov 4, 2020

Hi yeah sure, I guess I should add a test too

@nalchevanidze
Copy link
Member

i approved. you don't have to, but would be great if you would. you can add them in different merge request.

@nalchevanidze nalchevanidze merged commit 3a27d5d into morpheusgraphql:master Nov 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants