teamwalnut / graphql-ppx Goto Github PK
View Code? Open in Web Editor NEWGraphQL language primitives for ReScript/ReasonML written in ReasonML
Home Page: https://graphql-ppx.com
License: MIT License
GraphQL language primitives for ReScript/ReasonML written in ReasonML
Home Page: https://graphql-ppx.com
License: MIT License
Instead of having a bunch of mutations handling a single field update, I thought I'd look at how graphql_ppx_re handles INPUT_OBJECT
. The expected type for my input field is pretty gnarly: a closed object with every field being an option
. Constructing such an object is not going to be pretty, so I thought I'd see if there were generated helper functions that I overlooked. Unfortunately, I couldn't find any examples of how one would use an INPUT_OBJECT
in the documentation. I tried digging through the source and didn't find anything there, either. I think adding an example to the README would be very helpful.
Reason is to emit minimal strictly necessary code. make
and makeWithVariables
are easy to create yourself with Query.definition
as input. makeWithVariables
is not necessary anymore once we transition to records.
Right now the amount of configuration is not that huge. Mostly we have
graphql_schema.json
filebut I expect in future to have more options like #5 or ability to specify global decoder for __typename
(apollographql/reason-apollo#157).
It would be more readable than passing flags to ppx or setting env variables.
When using this lib in a docker container built from alpine you'll get errors saying things like
Command line: /app/node_modules/@baransu/graphql_ppx_re/ppx '/tmp/camlppx375570' '/tmp/camlppx57df4b'
and
FAILED: packages/worker/src/Foo.reast
/app/node_modules/bs-platform/lib/bsc.exe -w -30-40+6+7+27+32..39+44+45+101+A-9-40-42-48-102 -warn-error +A-3-44 -color always -bs-jsx 3 -ppx /app/node_modules/@baransu/graphql_ppx_re/ppx -o packages/worker/src/Foo.reast -bs-syntax-only -bs-binary-ast /app/packages/worker/src/Foo.re
sh: /app/node_modules/@baransu/graphql_ppx_re/ppx: not found
Switching to a container that's not built on Alpine fixes the issue.
I just tried updating to graphql_ppx 1.0, but this, previously working, code:
module UpdateAvatar = [%graphql
{|
mutation UpdateAvatar($id: ID!, $base64: String!) {
updateIdentityPicture(encodedImage: $base64, id: $id) {
id
}
}
|}
];
Now raises this error when used with ReasonUrql:
the previous type of definition
for the above module was:
(Js.Json.t => UpdateAvatar.t, string,
(Js.Json.t => 'a, ~id: string, ~base64: string, unit) => 'a)
But it's now (notice the ~f
labelled parameter:
(Js.Json.t => UpdateAvatar.t, string,
(~f: Js.Json.t => 'a, ~id: string, ~base64: string, unit) => 'a)
This seems to be a major breaking change (?)
Hi, first of all thanks for continuing maintenance of this useful ppx!
I'd like to migrate to graphql_ppx_re
for BuckleScript 6 support, but my app breaks because of the addition of filter_out_null_values
to outputted code. Apart from introducing polymorphic comparison, my GraphQL server implemented using ocaml-graphql-server
don't seem to like missing variables.
Here's a diff comparing graphql_ppx and graphql_ppx_re outputs compiled using BuckleScript:
return {
query: ppx_printed_query,
variables: Js_dict.fromArray(/* array */[/* tuple */[
- "after",
- after !== undefined ? Caml_option.valFromOption(after) : null
- ]]),
+ "after",
+ after !== undefined ? Caml_option.valFromOption(after) : null
+ ]].filter((function (param) {
+ return Caml_obj.caml_notequal(param[1], null);
+ }))),
parse: parse
};
When I pass None
for this "after"
variable which stands for an optional GraphQL Cursor, I get Missing variable 'after'
back from the server.
Does this change implement something that's spec-compliant and highlights a problem in ocaml-graphql-server
, or is there another reason for it?
Would you consider required args that also have default values as passing or failing validation?
After migrating to graphql_ppx_re from graphql_ppx I have been getting errors for this redundant but allowable case.
I know default values are supposed to be for optional arguments but there is nothing stopping the schema author from making something required and also providing a default value and the spec below says...
Arguments can be required. An argument is required if the argument type is non‐null and does not have a default value. Otherwise, the argument is optional.
https://spec.graphql.org/June2018/#sec-Required-Arguments
The graphql playground will not complain about missing args if a default is present.
For now I will wander around my code and add the default value from the schema to the arg params. But it might be nice to let these pass.
Graphql tools, such as graphqurl
and apollo-cli
generate json schema that is not wrapped in data
, and it seems like it breaks the extension with the error:
Fatal error: exception Yojson.Basic.Util.Type_error("Can't get member '__schema' of non-object type null", 870828711)
File "", line 1:
Error: Error while running external preprocessor
In the old repo (graphql_ppx
) there was a script sendIntrospection.js
that generated schema in the format that worked. Why was the script removed? Is there any way to fix this issue so that it doesnt require your schema be in a different format that other graphql tools generate?
In: https://www.npmjs.com/package/@baransu/graphql_ppx_re there is information: "Unable to find a readme for @baransu/[email protected]"
Interesting that on yarn: https://yarnpkg.com/en/package/@baransu/graphql_ppx_re it display properly.
Please consider adding a changelog to the project. I think a file in the repo is friendlier than relying on GitHub's Releases functionality, but I'd even settle for that. There have been four releases in the past 8 days and it's not readily apparent what changed.
Fortunately, the project is small enough where auditing commits is an option, otherwise I wouldn't have known about the new makeVariables
support. But reviewing commits in general to piece together the changes is a bit tedious because GitHub renders the commits in the opposite direction you'd normally want to read them.
I am using GitHub's GraphQL API. The following query worked fine with ppx_graphql
(the __typename
were required though) but it does not work with graphql_ppx_re
:
query issueMilestone($owner: String!, $repo: String!, $number: Int!) {
repository(owner:$owner, name:$repo) {
issue(number:$number) {
id
milestone { id }
timelineItems(itemTypes:[CLOSED_EVENT],last:1) {
totalCount
nodes {
__typename
... on ClosedEvent {
closer {
__typename
... on PullRequest {
id
milestone { id }
}
... on Commit {
associatedPullRequests(first: 2) {
nodes {
id
milestone { id }
}
}
}
}
}
}
}
}
}
}
The error is:
Fatal error: exception Graphql_ppx_base__Schema.Invalid_type("Type IssueTimelineItems doesn't have any fields")
Given that it is GitHub's GraphQL schema, I am pretty confident that this is a valid schema.
Since this error looks specific to the handling of union types, I think it is the same as mhallin/graphql_ppx#74.
Is it a bug or a known limitation? Is there a known workaround? Thanks!
Setup CI
Before release, we have to provide documentation about features and how all things work
Right now we're releasing under @baransu/graphql_ppx
. As we're in the @reasonml-community
organization it would be great to release in the same org on npm or some other organization with high credibility like @reason/graphql_ppx
.
I would like this to take effect from the upcoming 1.0 release.
/cc @ryyppy @anmonteiro
Currently, we validate if all required operation variables are provided when using make
function but we don't validate it for example id: $id
is exposed in operation.
I think the third parameter of the unified definition can easily be constructed from the simpler makeVariables function in user land (correctly if I am wrong). It will also save generated code, because we can just pass in makeVariables. So it will be (query, parse, makeVariables), and just generate a JS-Array of existing variables.
I also think it's better for it to be a record, so it's more easily extendable without breaking changes, and it also improves readability of the generated source.
We should mandatory generate Other
case for enums.
Original issue: mhallin/graphql_ppx#69
It would be great to have the result of the graphql query to always compile to records in the new bucklescript as there is no conversion overhead anymore.
As per the spec
https://graphql.org/learn/schema/#interfaces
query HeroForEpisode($ep: Episode!) {
hero(episode: $ep) {
name
... on Droid {
primaryFunction
}
}
}
See https://reasonml.chat/t/2210 for a full explanation.
Check for required mutation/query/subscription variables
It's pretty tricky currently to write a new PPX because of all the tooling necessary to eventually publish it to NPM. Having a starter that people can fork with the build configuration, and github actions etc. set up would be a huge help.
Because this repo has a pretty great set up, it would be nice if we can fork this repo and remove all graphql_ppx code but leave everything else (perhaps with a really simple dummy PPX). Then everyone can fork from that repo and pull in any improvements in the configuration or CI.
All contributions to CI + configuration is then in a reusable Repo. Any thoughs?
module CreateGoalFeedItemMutation = [%graphql
{|
mutation CreateGoalFeedItem($goalFeedItem: CreateGoalFeedItemInput!) {
createGoalFeedItem(goalFeedItem: $goalFeedItem) {
id
}
}
|}
];
to:
[%graphql
{|
mutation CreateGoalFeedItem($goalFeedItem: CreateGoalFeedItemInput!) {
createGoalFeedItem(goalFeedItem: $goalFeedItem) {
id
}
}
|}
];
In other words skip the module declaration as we already have the name of the mutation and query which is not reflected in the data, so it is an ideal identifier we can use as the module name so we have less repetition. Any thoughts? Do I miss certain use cases?
I'm using Hasura as my GraphQL server and use UUIDs for all of my object IDs. This may be a bug or quirk of Hasura, but instead of using the standard ID
GraphQL type it reports these as a custom scalar type named uuid
. The only real way to interact with these values is as strings. While I can use Js.Json.decodeString
and Js.Json.string
to deal with them, it's really tedious. And since virtually every response from the GraphQL server will include one of these uuid
values, it'd be handy if I could just provide serializers for the uuid
type that would apply to all my queries.
Warning number 32
(No file name)
unused value query.
Warning number 32
(No file name)
unused value make.
Warning number 32
(No file name)
unused value makeWithVariables.
Warning number 32
(No file name)
unused value query.
Warning number 32
(No file name)
unused value make.
Warning number 32
(No file name)
unused value makeWithVariables.
Warning number 32
(No file name)
unused value query.
Warning number 32
(No file name)
unused value make.
Warning number 32
(No file name)
unused value makeWithVariables.
When I only expose what I need using an interface file, I get a lot of warnings of unused variables. Perhaps this can be solved by not declaring variables on the root, but only within the module.
I'm trying to use fragment spreads with the @bsRecord option and am getting the following error:
The value name can't be found in FragmentModuleName
.
The fragment spreads seem to work fine without the @bsRecord
option and the code runs fine with fragment embedded (i.e. not using an external fragment). Some example code below.
type subType = {
id: string,
otherField: string
};
type mainType = {
id: string,
subTypes: array(subType)
};
module Graphql = [%graphql
{|
query getMainTypeQuery($id: ID!) {
getMainTypeQuery(id: $id) @bsRecord {
id
subTypes @bsRecord {
id
otherField
}
}
}
|}
];
module Query = ReasonApollo.CreateQuery(Graphql);
[@react.component]
let make = (~id, ~children) => {
let query = Graphql.make(~id, ());
<Query variables=query##variables>
...{({result}) =>
switch (result) {
| Loading => <Ui__Loader />
| Error(error) => React.string(error##message)
| Data(response) => children(response##getMainTypeQuery)
}
}
</Query>;
};
type subType = {
id: string,
otherField: string
};
type mainType = {
id: string,
subTypes: array(subType)
};
module MainTypeFragmenet = [%graphql
{|
fragment mainType on MainType @bsRecord {
id
subTypes @bsRecord {
id
otherField
}
}
|}
];
module Graphql = [%graphql
{|
query getMainTypeQuery($id: ID!) {
getMainTypeQuery(id: $id) {
...MainTypeFragmenet
}
}
|}
];
module Query = ReasonApollo.CreateQuery(Graphql);
[@react.component]
let make = (~id, ~children) => {
let query = Graphql.make(~id, ());
<Query variables=query##variables>
...{({result}) =>
switch (result) {
| Loading => <Ui__Loader />
| Error(error) => React.string(error##message)
| Data(response) => children(response##getMainTypeQuery)
}
}
</Query>;
};
Any advice? Not sure if this a bug or I just have an issue with my syntax?
Lmk if you need any more info to reproduce the issue.
So I'm getting a weird error from the following code snippet:
type stuff = {
id: string,
name: option(string),
fileName: string,
};
module GetStuff = [%graphql
{|
query Stuffs {
stuffs @bsRecord {
id
name
fileName
}
}
|}
];
The error I get is this:
We've found a bug for you!
id
**name**
fileName
This has type:
string
But somewhere wanted:
option(string)
Does anyone know why this might be happening? Thanks in advance!
When using vscode-reasonml plugin it shows an merlin error saying Uninterpreted extension 'graphql'
when using the ppx. Also type hinting for resulting module doesn't work. Tested on both bucklescript 5.2.1 and 7.0.1. However, mhalin/graphql_ppx seems to work fine.
To reproduce just create empty project with graphql_ppx and any graphql_schema.json and try to use it. Project builds just fine, but the plugin keeps complaining.
Hey! I am having troubles using a JsonScalar value with a filter_query
parameter inside the graphql statement.
Not sure why this is. Here is the example graphql statement:
module CardsQuery = [%graphql
{|
query {
EventItems(
filter_query: {featured: { in: true } }) {
items {
slug
content {
date
title
cover_photo
}
}
}
}
|}
];
Here you can find the graphql_schema.json
:
https://gist.github.com/ryyppy/34c01942b4bdc8aa9f7a42d171645aae
The error it yields:
Fatal error: exception Graphql_ppx_base__Schema.Invalid_type("Type JsonScalar doesn't have any input fields")
Not sure if this is intentional, or a bug?
Discussion and working version using multiple endpoints by
here: mhallin/graphql_ppx#86 and here: mhallin/graphql_ppx#82
GraphQL considers adding an enum to be a non-breaking change, because most type systems it seems aren't sound and so the developer always has to include a catch-all. In this world, adding a value to an enum means the old application should (mostly?) keep working, even when it encounters a value it doesn't understand.
Right now, we can't really do that for clients with graphql_ppx. It might be nice to have some option (or even required) to have a catch-all `Other(stringValue) to make apps much safer in the face of GraphQL's "non-breaking" [😄] changes.
Hey all, I'm working on converting some of our app queries from Js.t to @bsRecord syntax. I'm running into and issue where @bsRecord doesn't see to be mapping to the right record type when I have two fields of the same name/structure.
Here is the code:
type user = {
id: string,
firstName: option(string),
lastName: option(string),
};
type actor = {user: option(user)};
type target = {user};
type activity = {
id: string,
createdAt: Js.Date.t,
type_: [ | `USER_POST | `CALENDLY | `APPLICATION],
body: option(string),
actor: option(actor),
target,
};
module Fragment = [%graphql
{|
fragment Activity on Activity @bsRecord {
id
createdAt @bsDecoder(fn: "Decoders.dateDecoder")
type_: type
body
actor @bsRecord {
user @bsRecord {
id
firstName
lastName
}
}
target @bsRecord {
user @bsRecord {
id
firstName
lastName
}
}
}
|}
];
The code compiles fine if I only want the actor or target fields individually but if I try to have both, I get the following error:
26 ┆ body
27 ┆ actor @bsRecord {
28 ┆ user @bsRecord {
29 ┆ id
30 ┆ firstName
31 ┆ lastName
32 ┆ }
33 ┆ }
34 ┆
This has type:
option(user)
But somewhere wanted:
user
It doesn't seem to pick up the actor should have an optional user and target should have a non-optional user.
Here are the graphql type defs:
type ActivityActor {
user: User
}
type ActivityTarget {
user: User!
}
type Activity {
id: ID!
createdAt: Date!
type: ActivityType!
body: String
actor: ActivityActor
target: ActivityTarget!
}
Would love any help on this one. Once again, not sure if this an issue with my syntax or an actual bug? 😅
Thanks a ton!
Right now we only focus on BuckleScript target. It would be great to support native too.
Most of the code is there, what's left is build system.
Thanks for getting this project moving. Right now it doesn't seem like it's possible to depend on this package in newer versions of OCaml. I had to add the following to my esy resolutions:
"@baransu/graphql_ppx_re": {
"source": "baransu/graphql_ppx_re:esy.json#c7fab6c",
"override": {
"build": "dune build -p graphql_ppx",
"dependencies": {
"@opam/ocaml-migrate-parsetree": "*",
"@esy-ocaml/reason": "*",
"refmterr": null
}
}
}
I think these could get integrated in master. I don't know what refmterr is but it just doesn't build on OCaml 4.09 which is what I was testing, and removing it works fine. The esy.json
also looks weird, and many of its dependencies are very outdated (e.g. Menhir, OMP). I can submit an enhancement PR if you want.
Hey @baransu, thanks for porting this for native as well, works great!
One thing I'm missing right now is the fact that t
is not exposed. I noticed that there seemed to be some magic involved in order to get the return-type which looks commented out in the native-code. Did you run into issues with it? Can I help?
EDIT:
As discussed in Discord, I think this might be related: https://github.com/baransu/graphql_ppx_re/blob/master/src/native/output_native_module.re#L229
https://github.com/baransu/graphql_ppx_re/blob/master/src/native/output_native_module.re#L280
https://github.com/baransu/graphql_ppx_re/blob/master/src/native/output_native_module.re#L30
subscription NewMessage($organizationId: String!, $conversationId: String!) {
__typename
newMessage(organizationId: $organizationId, conversationId: $conversationId) {
__typename
...Event
}
}
We should prevent from adding __typename
to all top-level objects. Right now we're adding it to all operations (queries and mutations also) but only subscriptions are failing.
It would be great to have a bit more API surface to make a nicer API for consuming libraries. Sometimes you'd want to set up a mutation, and provide the variables dynamically. For instance with react-apollo a hook that returns a function that accepts variables. Because the make
functions needs the variables, we cannot get back the data structure that includes the mutation itself and the parse function.
A workaround for now is to
make
function at the last moment and initially create an empty mutation in the hook.query
attribute and parse
method to the hook and the variables
attribute of make
later.Both not great options. I would propose a makeVariables
function to make the variables data structure, and a makeMutation
(better naming ideas?) that does the same thing as make
but returns the data structure without variables. Any thoughts?
Happy to try to set up a PR for this, but interested in feedback on this first.
Out current CI uses Travis CI to create prebuild binaries for Linux and macOS. We want to provide prebuild Windows binaries as well. Currently, it would require move whole CI to Azure or using it only for Windows builds.
Just recently GitHub announced GitHub Actions CI/CD and it would be great to wait for it to have one place for whole CI pipeline.
It's important for us to know when we are using field that's been deprecated so we can keep up to date with the backend.
I've tried to change from graphql_ppx to graphql_ppx_re and ran into an issue where none of my configuration values provided in bsconfig.json
are supported. I previously had used the following:
"ppx-flags": [
["graphql_ppx/ppx", "-verbose", "-apollo-mode", "-schema=src/graphql/schema.json"]
]
I see in the README that there are GRAPHQL_PPX_APOLLO_MODE
and GRAPHQL_PPX_SCHEMA
environment variables to support some of this functionality. However, it's considerably more convenient to have this as part of the checked-in source code where it can be managed per-project. Additionally, the BuckleScript build configuration docs recommend not using environment variables for build configuration.
If the ability to pass command-line arguments won't be reinstated, I think it'd be helpful to document how to migrate from graphql_ppx
.
The parse function has a lot of checks on the data, and it looks like it's expanding into hundreds or even thousands of lines of code for non-trivial queries making bsb very slow. In principle the parse function could (almost) be compiled to identity because we always should get back the data in the same way (even if our resolvers change).
I think this is related to mhallin/graphql_ppx#85, but not sure.
Example it generates this code for the following query.
module HomeScreenQuery = [%graphql
{|
query HomeScreen($after: String) {
dailyContent {
item {
id
title
description
duration
}
}
goals {
id
scheduledAt
item {
id
title
description
duration
}
}
feed(after: $after) {
edges {
cursor
node {
... on GoalFeedItem {
id
completedAt
rating
participants {
id
name
}
item {
id
title
description
duration
}
}
... on ActivityFeedItem {
id
duration
completedAt
rating
participants {
id
name
}
activity {
id
title
description
duration
}
}
}
}
}
}
|}
];
Code:
var ppx_printed_query = "query HomeScreen($after: String) {\ndailyContent {\nitem {\nid \ntitle \ndescription \nduration \n}\n\n}\n\ngoals {\nid \nscheduledAt \nitem {\nid \ntitle \ndescription \nduration \n}\n\n}\n\nfeed(after: $after) {\nedges {\ncursor \nnode {\n__typename\n...on GoalFeedItem {\nid \ncompletedAt \nrating \nparticipants {\nid \nname \n}\n\nitem {\nid \ntitle \ndescription \nduration \n}\n\n}\n\n...on ActivityFeedItem {\nid \nduration \ncompletedAt \nrating \nparticipants {\nid \nname \n}\n\nactivity {\nid \ntitle \ndescription \nduration \n}\n\n}\n\n}\n\n}\n\n}\n\n}\n";
function parse(value) {
var match = Js_json.decodeObject(value);
if (match !== undefined) {
var value$1 = Caml_option.valFromOption(match);
var match$1 = Js_dict.get(value$1, "dailyContent");
var tmp;
if (match$1 !== undefined) {
var value$2 = Caml_option.valFromOption(match$1);
var match$2 = Js_json.decodeNull(value$2);
if (match$2 !== undefined) {
tmp = undefined;
} else {
var match$3 = Js_json.decodeObject(value$2);
var tmp$1;
if (match$3 !== undefined) {
var match$4 = Js_dict.get(Caml_option.valFromOption(match$3), "item");
var tmp$2;
if (match$4 !== undefined) {
var value$3 = Caml_option.valFromOption(match$4);
var match$5 = Js_json.decodeNull(value$3);
if (match$5 !== undefined) {
tmp$2 = undefined;
} else {
var match$6 = Js_json.decodeObject(value$3);
var tmp$3;
if (match$6 !== undefined) {
var value$4 = Caml_option.valFromOption(match$6);
var match$7 = Js_dict.get(value$4, "id");
var tmp$4;
if (match$7 !== undefined) {
var value$5 = Caml_option.valFromOption(match$7);
var match$8 = Js_json.decodeString(value$5);
tmp$4 = match$8 !== undefined ? match$8 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$5));
} else {
tmp$4 = Js_exn.raiseError("graphql_ppx: Field id on type Item is missing");
}
var match$9 = Js_dict.get(value$4, "title");
var tmp$5;
if (match$9 !== undefined) {
var value$6 = Caml_option.valFromOption(match$9);
var match$10 = Js_json.decodeNull(value$6);
if (match$10 !== undefined) {
tmp$5 = undefined;
} else {
var match$11 = Js_json.decodeString(value$6);
tmp$5 = match$11 !== undefined ? match$11 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$6));
}
} else {
tmp$5 = undefined;
}
var match$12 = Js_dict.get(value$4, "description");
var tmp$6;
if (match$12 !== undefined) {
var value$7 = Caml_option.valFromOption(match$12);
var match$13 = Js_json.decodeNull(value$7);
if (match$13 !== undefined) {
tmp$6 = undefined;
} else {
var match$14 = Js_json.decodeString(value$7);
tmp$6 = match$14 !== undefined ? match$14 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$7));
}
} else {
tmp$6 = undefined;
}
var match$15 = Js_dict.get(value$4, "duration");
var tmp$7;
if (match$15 !== undefined) {
var value$8 = Caml_option.valFromOption(match$15);
var match$16 = Js_json.decodeNull(value$8);
if (match$16 !== undefined) {
tmp$7 = undefined;
} else {
var match$17 = Js_json.decodeNumber(value$8);
tmp$7 = match$17 !== undefined ? match$17 | 0 : Js_exn.raiseError("graphql_ppx: Expected int, got " + JSON.stringify(value$8));
}
} else {
tmp$7 = undefined;
}
tmp$3 = {
id: tmp$4,
title: tmp$5,
description: tmp$6,
duration: tmp$7
};
} else {
tmp$3 = Js_exn.raiseError("graphql_ppx: Object is not a value");
}
tmp$2 = Caml_option.some(tmp$3);
}
} else {
tmp$2 = undefined;
}
tmp$1 = {
item: tmp$2
};
} else {
tmp$1 = Js_exn.raiseError("graphql_ppx: Object is not a value");
}
tmp = Caml_option.some(tmp$1);
}
} else {
tmp = undefined;
}
var match$18 = Js_dict.get(value$1, "goals");
var tmp$8;
if (match$18 !== undefined) {
var value$9 = Caml_option.valFromOption(match$18);
var match$19 = Js_json.decodeNull(value$9);
if (match$19 !== undefined) {
tmp$8 = undefined;
} else {
var match$20 = Js_json.decodeArray(value$9);
tmp$8 = match$20 !== undefined ? match$20.map((function (value) {
var match = Js_json.decodeNull(value);
if (match !== undefined) {
return ;
} else {
var match$1 = Js_json.decodeObject(value);
var tmp;
if (match$1 !== undefined) {
var value$1 = Caml_option.valFromOption(match$1);
var match$2 = Js_dict.get(value$1, "id");
var tmp$1;
if (match$2 !== undefined) {
var value$2 = Caml_option.valFromOption(match$2);
var match$3 = Js_json.decodeString(value$2);
tmp$1 = match$3 !== undefined ? match$3 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$2));
} else {
tmp$1 = Js_exn.raiseError("graphql_ppx: Field id on type Goal is missing");
}
var match$4 = Js_dict.get(value$1, "scheduledAt");
var match$5 = Js_dict.get(value$1, "item");
var tmp$2;
if (match$5 !== undefined) {
var match$6 = Js_json.decodeObject(Caml_option.valFromOption(match$5));
if (match$6 !== undefined) {
var value$3 = Caml_option.valFromOption(match$6);
var match$7 = Js_dict.get(value$3, "id");
var tmp$3;
if (match$7 !== undefined) {
var value$4 = Caml_option.valFromOption(match$7);
var match$8 = Js_json.decodeString(value$4);
tmp$3 = match$8 !== undefined ? match$8 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$4));
} else {
tmp$3 = Js_exn.raiseError("graphql_ppx: Field id on type Item is missing");
}
var match$9 = Js_dict.get(value$3, "title");
var tmp$4;
if (match$9 !== undefined) {
var value$5 = Caml_option.valFromOption(match$9);
var match$10 = Js_json.decodeNull(value$5);
if (match$10 !== undefined) {
tmp$4 = undefined;
} else {
var match$11 = Js_json.decodeString(value$5);
tmp$4 = match$11 !== undefined ? match$11 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$5));
}
} else {
tmp$4 = undefined;
}
var match$12 = Js_dict.get(value$3, "description");
var tmp$5;
if (match$12 !== undefined) {
var value$6 = Caml_option.valFromOption(match$12);
var match$13 = Js_json.decodeNull(value$6);
if (match$13 !== undefined) {
tmp$5 = undefined;
} else {
var match$14 = Js_json.decodeString(value$6);
tmp$5 = match$14 !== undefined ? match$14 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$6));
}
} else {
tmp$5 = undefined;
}
var match$15 = Js_dict.get(value$3, "duration");
var tmp$6;
if (match$15 !== undefined) {
var value$7 = Caml_option.valFromOption(match$15);
var match$16 = Js_json.decodeNull(value$7);
if (match$16 !== undefined) {
tmp$6 = undefined;
} else {
var match$17 = Js_json.decodeNumber(value$7);
tmp$6 = match$17 !== undefined ? match$17 | 0 : Js_exn.raiseError("graphql_ppx: Expected int, got " + JSON.stringify(value$7));
}
} else {
tmp$6 = undefined;
}
tmp$2 = {
id: tmp$3,
title: tmp$4,
description: tmp$5,
duration: tmp$6
};
} else {
tmp$2 = Js_exn.raiseError("graphql_ppx: Object is not a value");
}
} else {
tmp$2 = Js_exn.raiseError("graphql_ppx: Field item on type Goal is missing");
}
tmp = {
id: tmp$1,
scheduledAt: match$4 !== undefined ? Caml_option.valFromOption(match$4) : Js_exn.raiseError("graphql_ppx: Field scheduledAt on type Goal is missing"),
item: tmp$2
};
} else {
tmp = Js_exn.raiseError("graphql_ppx: Object is not a value");
}
return Caml_option.some(tmp);
}
})) : Js_exn.raiseError("graphql_ppx: Expected array, got " + JSON.stringify(value$9));
}
} else {
tmp$8 = undefined;
}
var match$21 = Js_dict.get(value$1, "feed");
var tmp$9;
if (match$21 !== undefined) {
var value$10 = Caml_option.valFromOption(match$21);
var match$22 = Js_json.decodeNull(value$10);
if (match$22 !== undefined) {
tmp$9 = undefined;
} else {
var match$23 = Js_json.decodeObject(value$10);
var tmp$10;
if (match$23 !== undefined) {
var match$24 = Js_dict.get(Caml_option.valFromOption(match$23), "edges");
var tmp$11;
if (match$24 !== undefined) {
var value$11 = Caml_option.valFromOption(match$24);
var match$25 = Js_json.decodeNull(value$11);
if (match$25 !== undefined) {
tmp$11 = undefined;
} else {
var match$26 = Js_json.decodeArray(value$11);
tmp$11 = match$26 !== undefined ? match$26.map((function (value) {
var match = Js_json.decodeNull(value);
if (match !== undefined) {
return ;
} else {
var match$1 = Js_json.decodeObject(value);
var tmp;
if (match$1 !== undefined) {
var value$1 = Caml_option.valFromOption(match$1);
var match$2 = Js_dict.get(value$1, "cursor");
var tmp$1;
if (match$2 !== undefined) {
var value$2 = Caml_option.valFromOption(match$2);
var match$3 = Js_json.decodeNull(value$2);
if (match$3 !== undefined) {
tmp$1 = undefined;
} else {
var match$4 = Js_json.decodeString(value$2);
tmp$1 = match$4 !== undefined ? match$4 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$2));
}
} else {
tmp$1 = undefined;
}
var match$5 = Js_dict.get(value$1, "node");
var tmp$2;
if (match$5 !== undefined) {
var value$3 = Caml_option.valFromOption(match$5);
var match$6 = Js_json.decodeNull(value$3);
if (match$6 !== undefined) {
tmp$2 = undefined;
} else {
var match$7 = Js_json.decodeObject(value$3);
var tmp$3;
if (match$7 !== undefined) {
var match$8 = Js_dict.get(Caml_option.valFromOption(match$7), "__typename");
if (match$8 !== undefined) {
var match$9 = Js_json.decodeString(Caml_option.valFromOption(match$8));
if (match$9 !== undefined) {
var typename = match$9;
switch (typename) {
case "ActivityFeedItem" :
var match$10 = Js_json.decodeObject(value$3);
var tmp$4;
if (match$10 !== undefined) {
var value$4 = Caml_option.valFromOption(match$10);
var match$11 = Js_dict.get(value$4, "id");
var tmp$5;
if (match$11 !== undefined) {
var value$5 = Caml_option.valFromOption(match$11);
var match$12 = Js_json.decodeString(value$5);
tmp$5 = match$12 !== undefined ? match$12 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$5));
} else {
tmp$5 = Js_exn.raiseError("graphql_ppx: Field id on type ActivityFeedItem is missing");
}
var match$13 = Js_dict.get(value$4, "duration");
var tmp$6;
if (match$13 !== undefined) {
var value$6 = Caml_option.valFromOption(match$13);
var match$14 = Js_json.decodeNull(value$6);
if (match$14 !== undefined) {
tmp$6 = undefined;
} else {
var match$15 = Js_json.decodeNumber(value$6);
tmp$6 = match$15 !== undefined ? match$15 | 0 : Js_exn.raiseError("graphql_ppx: Expected int, got " + JSON.stringify(value$6));
}
} else {
tmp$6 = undefined;
}
var match$16 = Js_dict.get(value$4, "completedAt");
var match$17 = Js_dict.get(value$4, "rating");
var tmp$7;
if (match$17 !== undefined) {
var value$7 = Caml_option.valFromOption(match$17);
var match$18 = Js_json.decodeNull(value$7);
if (match$18 !== undefined) {
tmp$7 = undefined;
} else {
var match$19 = Js_json.decodeNumber(value$7);
tmp$7 = match$19 !== undefined ? match$19 | 0 : Js_exn.raiseError("graphql_ppx: Expected int, got " + JSON.stringify(value$7));
}
} else {
tmp$7 = undefined;
}
var match$20 = Js_dict.get(value$4, "participants");
var tmp$8;
if (match$20 !== undefined) {
var value$8 = Caml_option.valFromOption(match$20);
var match$21 = Js_json.decodeArray(value$8);
tmp$8 = match$21 !== undefined ? match$21.map((function (value) {
var match = Js_json.decodeObject(value);
if (match !== undefined) {
var value$1 = Caml_option.valFromOption(match);
var match$1 = Js_dict.get(value$1, "id");
var tmp;
if (match$1 !== undefined) {
var value$2 = Caml_option.valFromOption(match$1);
var match$2 = Js_json.decodeString(value$2);
tmp = match$2 !== undefined ? match$2 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$2));
} else {
tmp = Js_exn.raiseError("graphql_ppx: Field id on type User is missing");
}
var match$3 = Js_dict.get(value$1, "name");
var tmp$1;
if (match$3 !== undefined) {
var value$3 = Caml_option.valFromOption(match$3);
var match$4 = Js_json.decodeString(value$3);
tmp$1 = match$4 !== undefined ? match$4 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$3));
} else {
tmp$1 = Js_exn.raiseError("graphql_ppx: Field name on type User is missing");
}
return {
id: tmp,
name: tmp$1
};
} else {
return Js_exn.raiseError("graphql_ppx: Object is not a value");
}
})) : Js_exn.raiseError("graphql_ppx: Expected array, got " + JSON.stringify(value$8));
} else {
tmp$8 = Js_exn.raiseError("graphql_ppx: Field participants on type ActivityFeedItem is missing");
}
var match$22 = Js_dict.get(value$4, "activity");
var tmp$9;
if (match$22 !== undefined) {
var match$23 = Js_json.decodeObject(Caml_option.valFromOption(match$22));
if (match$23 !== undefined) {
var value$9 = Caml_option.valFromOption(match$23);
var match$24 = Js_dict.get(value$9, "id");
var tmp$10;
if (match$24 !== undefined) {
var value$10 = Caml_option.valFromOption(match$24);
var match$25 = Js_json.decodeString(value$10);
tmp$10 = match$25 !== undefined ? match$25 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$10));
} else {
tmp$10 = Js_exn.raiseError("graphql_ppx: Field id on type Activity is missing");
}
var match$26 = Js_dict.get(value$9, "title");
var tmp$11;
if (match$26 !== undefined) {
var value$11 = Caml_option.valFromOption(match$26);
var match$27 = Js_json.decodeNull(value$11);
if (match$27 !== undefined) {
tmp$11 = undefined;
} else {
var match$28 = Js_json.decodeString(value$11);
tmp$11 = match$28 !== undefined ? match$28 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$11));
}
} else {
tmp$11 = undefined;
}
var match$29 = Js_dict.get(value$9, "description");
var tmp$12;
if (match$29 !== undefined) {
var value$12 = Caml_option.valFromOption(match$29);
var match$30 = Js_json.decodeNull(value$12);
if (match$30 !== undefined) {
tmp$12 = undefined;
} else {
var match$31 = Js_json.decodeString(value$12);
tmp$12 = match$31 !== undefined ? match$31 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$12));
}
} else {
tmp$12 = undefined;
}
var match$32 = Js_dict.get(value$9, "duration");
var tmp$13;
if (match$32 !== undefined) {
var value$13 = Caml_option.valFromOption(match$32);
var match$33 = Js_json.decodeNull(value$13);
if (match$33 !== undefined) {
tmp$13 = undefined;
} else {
var match$34 = Js_json.decodeNumber(value$13);
tmp$13 = match$34 !== undefined ? match$34 | 0 : Js_exn.raiseError("graphql_ppx: Expected int, got " + JSON.stringify(value$13));
}
} else {
tmp$13 = undefined;
}
tmp$9 = {
id: tmp$10,
title: tmp$11,
description: tmp$12,
duration: tmp$13
};
} else {
tmp$9 = Js_exn.raiseError("graphql_ppx: Object is not a value");
}
} else {
tmp$9 = Js_exn.raiseError("graphql_ppx: Field activity on type ActivityFeedItem is missing");
}
tmp$4 = {
id: tmp$5,
duration: tmp$6,
completedAt: match$16 !== undefined ? Caml_option.valFromOption(match$16) : Js_exn.raiseError("graphql_ppx: Field completedAt on type ActivityFeedItem is missing"),
rating: tmp$7,
participants: tmp$8,
activity: tmp$9
};
} else {
tmp$4 = Js_exn.raiseError("graphql_ppx: Object is not a value");
}
tmp$3 = /* `ActivityFeedItem */[
886006944,
tmp$4
];
break;
case "GoalFeedItem" :
var match$35 = Js_json.decodeObject(value$3);
var tmp$14;
if (match$35 !== undefined) {
var value$14 = Caml_option.valFromOption(match$35);
var match$36 = Js_dict.get(value$14, "id");
var tmp$15;
if (match$36 !== undefined) {
var value$15 = Caml_option.valFromOption(match$36);
var match$37 = Js_json.decodeString(value$15);
tmp$15 = match$37 !== undefined ? match$37 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$15));
} else {
tmp$15 = Js_exn.raiseError("graphql_ppx: Field id on type GoalFeedItem is missing");
}
var match$38 = Js_dict.get(value$14, "completedAt");
var match$39 = Js_dict.get(value$14, "rating");
var tmp$16;
if (match$39 !== undefined) {
var value$16 = Caml_option.valFromOption(match$39);
var match$40 = Js_json.decodeNull(value$16);
if (match$40 !== undefined) {
tmp$16 = undefined;
} else {
var match$41 = Js_json.decodeNumber(value$16);
tmp$16 = match$41 !== undefined ? match$41 | 0 : Js_exn.raiseError("graphql_ppx: Expected int, got " + JSON.stringify(value$16));
}
} else {
tmp$16 = undefined;
}
var match$42 = Js_dict.get(value$14, "participants");
var tmp$17;
if (match$42 !== undefined) {
var value$17 = Caml_option.valFromOption(match$42);
var match$43 = Js_json.decodeArray(value$17);
tmp$17 = match$43 !== undefined ? match$43.map((function (value) {
var match = Js_json.decodeObject(value);
if (match !== undefined) {
var value$1 = Caml_option.valFromOption(match);
var match$1 = Js_dict.get(value$1, "id");
var tmp;
if (match$1 !== undefined) {
var value$2 = Caml_option.valFromOption(match$1);
var match$2 = Js_json.decodeString(value$2);
tmp = match$2 !== undefined ? match$2 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$2));
} else {
tmp = Js_exn.raiseError("graphql_ppx: Field id on type User is missing");
}
var match$3 = Js_dict.get(value$1, "name");
var tmp$1;
if (match$3 !== undefined) {
var value$3 = Caml_option.valFromOption(match$3);
var match$4 = Js_json.decodeString(value$3);
tmp$1 = match$4 !== undefined ? match$4 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$3));
} else {
tmp$1 = Js_exn.raiseError("graphql_ppx: Field name on type User is missing");
}
return {
id: tmp,
name: tmp$1
};
} else {
return Js_exn.raiseError("graphql_ppx: Object is not a value");
}
})) : Js_exn.raiseError("graphql_ppx: Expected array, got " + JSON.stringify(value$17));
} else {
tmp$17 = Js_exn.raiseError("graphql_ppx: Field participants on type GoalFeedItem is missing");
}
var match$44 = Js_dict.get(value$14, "item");
var tmp$18;
if (match$44 !== undefined) {
var match$45 = Js_json.decodeObject(Caml_option.valFromOption(match$44));
if (match$45 !== undefined) {
var value$18 = Caml_option.valFromOption(match$45);
var match$46 = Js_dict.get(value$18, "id");
var tmp$19;
if (match$46 !== undefined) {
var value$19 = Caml_option.valFromOption(match$46);
var match$47 = Js_json.decodeString(value$19);
tmp$19 = match$47 !== undefined ? match$47 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$19));
} else {
tmp$19 = Js_exn.raiseError("graphql_ppx: Field id on type Item is missing");
}
var match$48 = Js_dict.get(value$18, "title");
var tmp$20;
if (match$48 !== undefined) {
var value$20 = Caml_option.valFromOption(match$48);
var match$49 = Js_json.decodeNull(value$20);
if (match$49 !== undefined) {
tmp$20 = undefined;
} else {
var match$50 = Js_json.decodeString(value$20);
tmp$20 = match$50 !== undefined ? match$50 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$20));
}
} else {
tmp$20 = undefined;
}
var match$51 = Js_dict.get(value$18, "description");
var tmp$21;
if (match$51 !== undefined) {
var value$21 = Caml_option.valFromOption(match$51);
var match$52 = Js_json.decodeNull(value$21);
if (match$52 !== undefined) {
tmp$21 = undefined;
} else {
var match$53 = Js_json.decodeString(value$21);
tmp$21 = match$53 !== undefined ? match$53 : Js_exn.raiseError("graphql_ppx: Expected string, got " + JSON.stringify(value$21));
}
} else {
tmp$21 = undefined;
}
var match$54 = Js_dict.get(value$18, "duration");
var tmp$22;
if (match$54 !== undefined) {
var value$22 = Caml_option.valFromOption(match$54);
var match$55 = Js_json.decodeNull(value$22);
if (match$55 !== undefined) {
tmp$22 = undefined;
} else {
var match$56 = Js_json.decodeNumber(value$22);
tmp$22 = match$56 !== undefined ? match$56 | 0 : Js_exn.raiseError("graphql_ppx: Expected int, got " + JSON.stringify(value$22));
}
} else {
tmp$22 = undefined;
}
tmp$18 = {
id: tmp$19,
title: tmp$20,
description: tmp$21,
duration: tmp$22
};
} else {
tmp$18 = Js_exn.raiseError("graphql_ppx: Object is not a value");
}
} else {
tmp$18 = Js_exn.raiseError("graphql_ppx: Field item on type GoalFeedItem is missing");
}
tmp$14 = {
id: tmp$15,
completedAt: match$38 !== undefined ? Caml_option.valFromOption(match$38) : Js_exn.raiseError("graphql_ppx: Field completedAt on type GoalFeedItem is missing"),
rating: tmp$16,
participants: tmp$17,
item: tmp$18
};
} else {
tmp$14 = Js_exn.raiseError("graphql_ppx: Object is not a value");
}
tmp$3 = /* `GoalFeedItem */[
688985060,
tmp$14
];
break;
default:
tmp$3 = Js_exn.raiseError("graphql_ppx: Union FeedItem returned unknown type " + typename);
}
} else {
tmp$3 = Js_exn.raiseError("graphql_ppx: Union FeedItem has a __typename field that is not a string");
}
} else {
tmp$3 = Js_exn.raiseError("graphql_ppx: Union FeedItem is missing the __typename field");
}
} else {
tmp$3 = Js_exn.raiseError("graphql_ppx: Expected union FeedItem to be an object, got " + JSON.stringify(value$3));
}
tmp$2 = tmp$3;
}
} else {
tmp$2 = undefined;
}
tmp = {
cursor: tmp$1,
node: tmp$2
};
} else {
tmp = Js_exn.raiseError("graphql_ppx: Object is not a value");
}
return Caml_option.some(tmp);
}
})) : Js_exn.raiseError("graphql_ppx: Expected array, got " + JSON.stringify(value$11));
}
} else {
tmp$11 = undefined;
}
tmp$10 = {
edges: tmp$11
};
} else {
tmp$10 = Js_exn.raiseError("graphql_ppx: Object is not a value");
}
tmp$9 = Caml_option.some(tmp$10);
}
} else {
tmp$9 = undefined;
}
return {
dailyContent: tmp,
goals: tmp$8,
feed: tmp$9
};
} else {
return Js_exn.raiseError("graphql_ppx: Object is not a value");
}
}
I think it is the same issue as this one from graphql_ppx
, and there is this unmerged PR which is a one-liner 😄
Is it possible to include this quick fix? Would be really helpful!
Thanks!
Edit: I think it is this block of code that can be edited to include "bsField"
, I am not sure though what other consequences this change might have. Why is it required to have "bsField"
when spreading multiple fragments anyway? Is it specified somewhere in the readme?
👋
We're using this library in a project that has the Bucklescript Warning 102 (polymorphic comparison introduced (maybe unsafe)
) set to error and it looks like that's used in the generated code from this ppx somewhere.
So somewhere it's doing a comparison using a ==
, >
, <
, <=
, or >=
operator. I'm not sure where in the code that would be happening yet but it seems (I don't think it does at least) that a comparison like that is needed.
The above warning is very useful and I'd hate to leave it turned off. Would people be open to removing comparisons like that from the lib?
I also want to note that the original graphql_ppx` did not trigger this warning.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.