Giter Site home page Giter Site logo

teamwalnut / rescript-urql Goto Github PK

View Code? Open in Web Editor NEW
236.0 41.0 28.0 3.16 MB

ReScript bindings for Formidable's Universal React Query Library, urql.

License: MIT License

JavaScript 0.67% ReScript 99.13% Shell 0.19%
reasonml graphql reasonreact bucklescript urql graphql-client rescript

rescript-urql's People

Contributors

allcontributors[bot] avatar amiralies avatar baransu avatar boygirl avatar cem2ran avatar dependabot[bot] avatar gugahoa avatar hulufei avatar huy-nguyen avatar idkjs avatar jeddeloh avatar jfrolich avatar jovidecroock avatar jpdriver avatar kingdutch avatar kiraarghy avatar oddlyfunctional avatar parkerziegler avatar robinweser avatar schmavery avatar tatchi avatar thangngoc89 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rescript-urql's Issues

What's the plan regarding UrqlCombinedError.t?

Hello, all!
I have been using reason-urql since hooks got in, and one of the pain points has been around error handling. Right now, there's no way to inspect the errors that happened during a request, as the error type is simply an UrqlCombinedError.t with no helper function to extract more information from that type.

What's the plan regarding error handling, and is this error API what's gonna ship with 1.0?

Add `examples` directory using yarn workspaces.

Similar to how urql has an examples directory (modeled loosely after Next's), we'll want to have some examples to demonstrate how to use reason-urql with ReasonReact. We should use yarn workspaces to manage dependencies across individual examples. Each should therefore have their own package.json and bsconfig.json. For the most part, all dependencies can be shared (bs-platform, webpack, bs-css, reason-react) and we'll take a file: dependency on reason-urql.

Update bindings for `Client`.

As part of the v1 migration, we'll need to update the bindings for Client. Probably the most significant change will be the addition of bindings for exchanges. This may be simplified by the fact that, under the hood, exchanges are powered by wonka, whose source is written in Reason. Other than that, our life is greatly simplified b/c we no longer have cache operations to keep track of in the Client.

Fix improper type inference in hooks.

cc/ @gugahoa @Schmavery I'm not totally sure how to fix this one, so reaching out for help.

In examples/2-query in Monster.re, change L37 from this:

let (result, _) = Hooks.useQuery(~request, ());

to this:

useQuery(~request, ());

and add this at the top:

open Hooks;

When doing this, I get an interesting type error:

We've found a bug for you!
  /Users/parkerziegler/Documents/repos/OSS/reason-urql/examples/2-query/src/Monster.re 38:25-46
  
  36 ┆    value passed in from GetAll */
  37 ┆ let request = GetPokemon.make(~name=pokemon, ());
  38 ┆ let ({response}, _) = useQuery(~request, ());
  39 ┆ 
  40 ┆ switch (result.response) {
  
  This has type:
    ReasonUrql.Hooks.useQueryResponse({. "pokemon": option({. "classification": 
                                                             option(string),
                                                             "height": 
                                                             option({. "maximum": 
                                                                    option(
                                                                    string)}),
                                                             "image": 
                                                             option(string),
                                                             "name": 
                                                             option(string),
                                                             "weight": 
                                                             option({. "maximum": 
                                                                    option(
                                                                    string)})})})
      (defined as
      (ReasonUrql.Hooks.useQueryState({. "pokemon": option({. "classification": 
                                                             option(string),
                                                             "height": 
                                                             option({. "maximum": 
                                                                    option(
                                                                    string)}),
                                                             "image": 
                                                             option(string),
                                                             "name": 
                                                             option(string),
                                                             "weight": 
                                                             option({. "maximum": 
                                                                    option(
                                                                    string)})})}),
      ReasonUrql.Hooks.partialOperationContextFn))
  But somewhere wanted:
    (ReasonUrql.Hooks.useSubscriptionResponse('a), 'b)
  
  The incompatible parts:
    ReasonUrql.Hooks.useQueryState({. "pokemon": option({. "classification": 
                                                          option(string),
                                                          "height": option(
                                                                    {. "maximum": 
                                                                    option(
                                                                    string)}),
                                                          "image": option(
                                                                   string),
                                                          "name": option(
                                                                  string),
                                                          "weight": option(
                                                                    {. "maximum": 
                                                                    option(
                                                                    string)})})})
      (defined as
      UrqlUseQuery.useQueryState({. "pokemon": option({. "classification": 
                                                        option(string),
                                                        "height": option(
                                                                  {. "maximum": 
                                                                    option(
                                                                    string)}),
                                                        "image": option(
                                                                 string),
                                                        "name": option(
                                                                string),
                                                        "weight": option(
                                                                  {. "maximum": 
                                                                    option(
                                                                    string)})})}))
    vs
    ReasonUrql.Hooks.useSubscriptionResponse('a) (defined as
      UrqlUseSubscription.useSubscriptionResponse('a))

I'm not totally sure why this is happening. I'm wondering if Reason is searching for the record type associated with the destrucutred { response } and it's saying, "Hey, that record is type useSubscriptionResponse" That's my best guess. If so, I'm thinking we may need to do one-off module UseQuery = UrqlUseQuery; such that only the definitions from UrqlUseQuery are brought into scope and the proper record type useQueryResponse is inferred. Any other thoughts? I also tried adding a top-level type hookReponse('ret) since our hooks have consistent return structures, but I got an error w/ the useSubscription GADT b/c type ret there would escape its scope.

Add bindings for `Subscription`.

Now that we have bindings for both Query and Mutation in place, let's complete the loop with Subscription! @kiraarghy assigning this to you for now, but feel free to pick it up only when you have time.

Hooks type safety idea

I'm pretty excited to try to use this in some projects, but just realized after reading through #64 how the typing works for the hooks api. @gugahoa brought up some really good points (I thought) about how this could potentially be improved.
I think it would be hard for me to use this in real projects if I couldn't rely on the type of the response (though @parkerziegler did provide a clever workaround in that thread!).

I was thinking about this a bit wondering what you thought about a slightly different api.
Taking useQuery as an example, it seems from one of the examples that this is a pattern for using it:
https://github.com/FormidableLabs/reason-urql/blob/14bb74d1d003b9c9a058b64f65f4b11312f3dfa7/examples/2-query/src/Monster.re#L39-L41
Where we use graphql_ppx to create a query and variables object and then pass them into useQuery. I was wondering if there would be any downsides to simply passing in the entire result from calling GetPokemon.make (in this example)?

To be clear, the usage would look something like this:

  let request = GetPokemon.make(~name=pokemon, ());
  let ({response}, _executeQuery) = useQuery(request, ());

It seems like if you did that, the type of useQuery could be:

let useQuery:
  ({
    .
    "parse": Js.Json.t => 'response,
    "query": string,
    "variables": 'vars,
  }, 
  ~requestPolicy: UrqlTypes.requestPolicy=?,
  ~pause: bool=?,
  unit) =>
  useQueryResponse('response);

instead of
https://github.com/FormidableLabs/reason-urql/blob/14bb74d1d003b9c9a058b64f65f4b11312f3dfa7/src/hooks/UrqlUseQuery.rei#L10

The takeaway, as far as the types are concerned, would be that the type checker would be able to know what the return type of useQuery is.

Implementation-wise, inside of useQuery you could access the query and variables parameters as before, with the added bonus that you could access the parse function too, if you wanted to do any runtime validation/translation of the returned object (which would have the added benefit of supporting graphql_ppx features like the super-handy @bsDecoders).

I haven't had a chance to check if the same technique could work for mutations/subscriptions yet but wanted to get people's thoughts in case this would be a big enough signature change to warrant trying to squeeze in before v1?

Add bindings for Exchanges.

Previously this issue was tracked in #26, but it's complex enough that I figured we'd make it a separate issue. We want reason-urql to add support for exchanges. This shouldn't be too difficult, as urql already has a set of exchanges that are a part of the core API. We just need to expose those using [@bs.module] declarations. Adding exchange types will be a bit more complex and should be based off of the urql/types.ts module.

Roadmap

  • Add bindings for exchange types.
  • Add support for shipped exchanges.
  • Add support and example for using some of the shipped exchanges.
  • Add support for custom exchanges.
  • Add specific config for subscriptionExchange.

Invalid requestPolicy passed to useQueryJs

[@bs.deriving abstract]
type useQueryArgs = {
  query: string,
  variables: Js.Json.t,
  [@bs.optional]
  requestPolicy: UrqlTypes.requestPolicy,
  [@bs.optional]
  pause: bool,
};

This type doesn't convert nested UrqlTypes.requestPolicy type when creating.

When doing:

let args =
    useQueryArgs(
      ~query=request##query,
      ~variables=request##variables,
      ~requestPolicy?,
      ~pause?,
      (),
    );

is should be

let args =
    useQueryArgs(
      ~query=request##query,
      ~variables=request##variables,
      ~requestPolicy=requestPolicy->Belt.Option.map(UrqlTypes.requestPolicyToJs),
      ~pause?,
      (),
    );

This way string instead of int will be passed int "requestPolicy" key in urql options.

Namespace collisions

You guys have a module called Types on ReasonUrql which will/does clash with anyone who defines a module called types in their project. Just an FYI. Please let me know if you need further explanation.

For future reference for readers. You can get around this by add namespace:true to your bsconfig.json and referencing your own types module with open MyProjectNamespace.Types; or MyProjectNamespace.Types.myfunction();

New GraphQL ppx instructions incomplete

The way to generate a graphql_schema.json is different on graphql_ppx_re so the instructions on the README right now will lead to an error when setting up a new project

We should copy the instructions from graphql_ppx_re and have another section with instructions if the user decides to use graphql_ppx only

Add hot reloading to example.

To have a really good developer experience, we should setup hot reloading for the reason-urql example project. In doing this, let's take stock of our current webpack setup, removing what feels unnecessary and adding in any niceties. Some thoughts:

  • Add webpack-dev-server.
  • Add hot reloading using the --hot CLI flag with webpack-dev-server (adds HMR automatically). See this documentation.
  • Add in url-loader for loading static assets.

Runtime error "value is null" with the latest Reason Urql version

I get the following runtime error when trying to update to Reason Urql 2:
Capture d’écran 2020-08-19 à 11 43 28

The parse function is generated by the graphql ppx and will indeed accept an object, not null.

After inverstigating a bit more, I could find that the following function (which I use), https://github.com/FormidableLabs/reason-urql/blob/main/src/Client.re#L221 will pass the parse function to https://github.com/FormidableLabs/reason-urql/blob/main/src/Client.re#L188, which in turn, will use the Belt.Option.map function to conditionally call the parse function.

The issue arises because of the type of response, which is assumed to be https://github.com/FormidableLabs/reason-urql/blob/main/src/Types.re#L81, where data is an option(Js.Json.t), which is not at runtime, it's actually a Js.Nullable.t(Js.Json.t).

But maybe I'm doing something wrong?

Edit: The error attribute is also "wrong" since it's assumed to be an option as well. Also, it seems this function https://github.com/FormidableLabs/reason-urql/blob/main/src/Types.re#L135 has the same issue 😕

Edit 2: With the -lean-parse option turned off, I get this error instead:
Capture d’écran 2020-08-19 à 12 38 14

[Proposal] Init value in response type

The logic here https://github.com/FormidableLabs/reason-urql/blob/8bb9cf6de62cc3b870bb7b7e59c79f136f04c0ca/src/components/UrqlMutation.re#L59 looks a bit off for dynamic mutations.

By definition, a dynamic mutation will occur after the hook is called, so fetching will always be false, and data and error will always be None as long as the mutation hasn't been called.

I propose to introduce an Init (or something similar) to handle this case in the response type. This will very likely require the use of a state to know whether or not the mutation has been triggered already or not.

We could even consider having a Refetching constructor if needed.

The Relude library handles this case as well: https://github.com/reazen/relude/blob/master/src/Relude_AsyncData.re#L11

Pass mutation variables when calling executeMutation

As shown in this example, mutation variables are passed when hook is created. https://github.com/FormidableLabs/reason-urql/blob/master/examples/3-mutation/src/Dog.re#L66

In my use case I want to create mutation hook at top of the component but pass variables later (for example from form submission callback function). Does reason-urql support it. I cannot find any documentation or example about such case.

let (_, executeSignInMutation) = Hooks.useMutation();

let form =
  Form.useForm(~onSubmit=(state, _) =>
    executeSignInMutation(
      ~request=
        Mutations.SignIn.make(
          ~email=state.email,
          ~password=state.password,
          (),
        ),
    )
    |> ignore
  );

Type inference in executeQuery/etc

I was just looking at making some graphql queries from a non-react (nodejs) project and realized that it seems like the type of the response from Client.executeQuery is a Wonka.Types.sourceT('a), so it seems like it exhibits the same issues as #80 and #67. Same with executeMutation and executeSubscription.

Does that sound right? I might be misreading how to use it.

Add CONTRIBUTING.md

Now that reason-urql is published to npm, we need to add a document to help contributors get started on the project!

Few mistakes in doc

I am dropping here some mistakes I got following getting started doc:

Convert to Reason

What would this look like in reason-urql?

  const mutate = React.useCallback(() => {
    executeMutation({ email, password, name })
      .then(({ data }) => {
        const token = data && data[isLogin ? 'login' : 'signup'].token
        if (token) {
          setToken(token)
          props.history.push('/')
        }
      });
  }, [executeMutation, props.history, email, password, name, isLogin]);

https://github.com/howtographql/react-urql/blob/662b62f4768e5e2147d95af5dbf8ab8565b63f72/src/components/Login.js#L33-L42

I can't seem to get the token back and setting it.

I have tried a bunch of things. Here is where I am.

  let handleToken = token => {
    Js.log2("TOKEN_DATA", token);
    Token.setToken(token);
    ReasonReactRouter.push("/");
  };

 let submitLogin = () => {
    executeLoginMutation() |> ignore;
    Js.Promise.then_(loginState => {
        Js.log2("TOKEN_loginState", loginState);
        let token = loginState##data##signup##token->Belt.Option.getExn;
        handleToken(token)
        Js.Promise.resolve();
      })
      |> ignore;
    // ReasonReactRouter.push("/");
  };

Here I try to log the response but get nothing:

let submitLogin = () => {
    executeLoginMutation()
    |> response => {
      Js.log2("submitLogin",response)
      Js.log(response)
    };
    ReasonReactRouter.push("/");
  };

I'm probably just not familiar enough with the library. Any guidance would be appreciated. Thank you.

manually running queries creates memory leak

Hi, if you're executing a query directly e.g:

ReasonUrql.Client.executeQuery(~client=Client.client, ~request, ())
        |> Wonka.subscribe((. {response}: ReasonUrql.Client.ClientTypes.clientResponse('a)) => {

There's no way to unsubscribe(if not being done in a sideeffect).

Upgrade to bs-platform 6.2.1.

With [email protected] out, we'll want to start migrating our in app examples over to this version to ensure compatibility. This will also entail upgrading the root's bs-platform devDependency to 6.2.1. Finally, this also means that all examples will need to use @baransu/graphql_ppx_re/ppx6.

Support proper `fetchOptions` binding by using `bs-fetch`.

Currently, we allow users to pass anything in their fetchOptions argument to Client as long as they provide a type for it. However, urql uses the RequestInit interface for fetch under the hood to type its fetchOptions. To support this, and to give users some guard rails when supplying fetchOptions, we should use the requestInit type from bs-fetch: https://github.com/reasonml-community/bs-fetch

We also don't need to type this parameter as a polymorphic variant. Instead, we can just make it a regular variant i.e.:

type fetchOptions = 
   | FetchObj(requestInit)
   | FetchFn(unit => requestInit);
  • Install dependency for bs-fetch
  • Rewrite fetchOptions type
  • Update example to show passing, for example, a Bearer token
  • Update README.md.

Implement CI pipeline for reason-urql.

It would be nice to start implementing a CI pipeline for reason-urql post V1 to ensure that we don't have build issues, or an Urql update causes our bindings to fail.

@kadikraman seems to be having success using Sail CI for React Native App Auth so I'm up for using that!

Goal: Implement a simple build and verification pipeline for reason-urql with the goal to expand it later on!

Add bindings for `Query` component.

urql v1 adds a specific component for Query, in addition to a useQuery hook: https://github.com/FormidableLabs/urql/blob/master/docs/api.md.

For this issue, it'd be ideal to just focus on binding these two pieces of the API. Binding Query should be as simple as using ReasonReact.wrapJsForReason and typing the props. We will want to re-use some of the nice utilities we have in place to convert fetching, data, error to a variant (see urqlDataToVariant). We should keep that function generic so we can 1) unit test it, and 2) use it for Mutation. Binding the hook should also be fairly easy using standard BuckleScript FFI for functions.

PRs for this issue should target the v1 branch.

Namespace Exports Under ReasonUrql Module

In an effort to prevent module namespace collisions with consuming apps, we'll want to ensure that all individual modules in src get prefixed with Urql, i.e. UrqlProvider and UrqlConnect. Then, in our top level ReasonUrql module, we'll want to re-export (in a sense) those modules by using module aliasing, i.e. module Provider = UrqlProvider. This should allow for nice module references, i.e. ReasonUrql.Query and ReasonUrql.Provider that don't conflict with consuming code.

[Umbrella] reason-urql v2 Refactors & Improvements

This is a good and opportune moment to take some time to reflect on a couple of reason-urql-specific structures and APIs. Specifically, reason-urql is meant to be idiomatic Reason code, but some parts of the API have been tied to bindings and expose some of the disconnect between JS/TS and Reason.

Because we're preparing to land v2, this may be a good moment to:

  • Improve APIs and make them more idiomatic and friendlier
  • Clean up the project structure and reconcile some files
  • Update APIs to use Reason idiomatic types as possible.

We can collect ideas in this umbrella issue and close it as soon as v2 is released.

Amount of Supporting Files

Currently the project is structured like a JS project with lots of files and some potentially confusing locations.

  • The Client has its own folder and is segregated from its types, a separate types file exists
  • The exchanges have their own folder with just one module
  • Do we still need component support?
  • The project's namespacing seems a little aggressive. Can we use BS namespaces better / more effectively?

Hook Context APIs

A lot of the context is typed and directly accessible. It may make sense to extend the hook API to be more idiomatic for the GraphQL bindings, and to integrate more of the context into the hooks' arguments.

  • Should the request be its own curried argument?
  • Should unit be last in those hooks? We do have the required request argument.
  • partialOperationContext could be integrated as a set of labelled optional arguments instead, right into the hook. We could write a small helper for that and pipe all arguments through. requestPolicy is duplicate for instance, url can be integrated, etc. Optimally the context itself should just be a JSON type and all relevant context options could be surfaced as labelled arguments.

Other Exchange Bindings

We haven't bound to some crucial exchanges yet and this could be an opportunity to add them?

Passing variables only when calling executeMutation

In the PR #69 by @Schmavery where typed use mutation was introduced, there was also a suggestion on making the interface for useMutation take makeWithVariables as parameter to let users pass variables later. In hindsight, it seems this is the expected behavior by users as can be seen here: https://spectrum.chat/urql/reason/usemutation-api~72b6306a-8d92-4d17-9fff-15826dd64070 and here #103

What are the thoughts on creating another useMutation/useQuery function where it's possible to pass the variables when calling executeMutation/executeQuery?

cc @parkerziegler

Working with Upload types

Hi, first of all, tons of love for making this lib happen! amazing job!
Not sure if i missed something, but couldnt find a way to work with Upload types.
(tried but couldnt make it work)

upgrade urql version

Hey, seems like urql is at 1.8.2 and specifically it seems like some major critical bugs have landed there.
Anything specific preventing from following up more closely with mainline urql?

Add support for SSR and Suspense.

urql v1.1.0 introduced server-side rendering and basic support for Suspense on the server via react-ssr-prepass. With the new goal being to bind reason-urql's next version to urql v1.1.3, this becomes a major priority for us. The responsibility on the binding side is actually quite small (relatively) here:

  • Upgrade urql dependency to v1.1.3. This is the v1.1.x version that contains several important bug fixes before jumping to 1.2.0, which may require a change to the bindings to work properly.
  • Add suspense flag to Client configuration.
  • Create bindings for react-ssr-prepass – this should be done in a separate repo at FormidableLabs/bs-react-ssr-prepass.
  • Bind ssrExchange.
  • Add unit tests for ssrExchange.
  • Create a working NextJS example – we'll likely want to copy the one Zeit has already in place for starters: https://github.com/zeit/next.js/tree/canary/examples/with-reasonml

Implement better type inference in components.

Based off on work in #68, #69, and #60, we'll want to ensure our components have the same level of type safety as our hooks now do. This gets trickiest with Subscription, whose return data type will differ based on whether a handler is supplied or not. We may consider doing what we did w/ the hooks implementation where we have separate Subscription and SubscriptionWithHandler components to handle this polymorphism.

Subscription and useSubscription API discussion.

@Schmavery @gugahoa I'm opening this issue here as a place for us to track API ideas for Subscription and useSubscription. I checked out the implementation here: https://reasonml.github.io/en/try?rrjsx=true&reason=C4TwDgpgBAThCOBXCBnYAKA5AIwJRQF4AoKKAHygCEB7ADyzwG4ijRIoALAQwDsATADYQYWLgBooOCZgDG+YqQoAJXoIjp01MMACW1HqNzS8hAHySuuAFydVQkVt37Dx6ZZLkoAOWor+Qm25-YXQAfVdJJhY2aEQUCABlRGwUGRgdbT0DTHFI6TlCD3QAPyC1GEC7EJyI2SMoYrgkVGAbJuQ0Blx5c1lmIiFgKAAzampC0nQYqFzp7AlpmQlSqorbYJFc+ag5ZfaWtoQOjDxrHbMoAG8PUkGqOnQYeVgjluZSUhQAdx1gGQ4oOgyvZ8NcPp4-GogatQsMeD11uVYQYfDwIBInjdPD5IUILjAsQBfd5QYkeIijaglYHCAg4qp7V5oAg0egAVm6zEp1NWdN8DIa+2ZrPQACI2aLORSxjyNgRcep0FwZEsoHwuMBLBcwVBvr9-oDlQUdRRUdACOYANrqzUAXQ8FAS1AAtuoBAiBFAAAJQa0arj20iEoiE+qNJnAFkPDm4RhAA and I'll confess I don't 100% understand it, but it seems like an interesting idea. I guess the major discussions to have are:

  1. Do we want to consolidate the API surface into 1 hook / 1 component or do 2 hooks / 2 components to handle handler?
  2. If we go for 1 hook / 1 component can we simplify @gugahoa's implementation in any way or use @Schmavery's idea of a default handler that'd behave like (~prevSubscriptions as _, ~subscription) => subscription?
  3. If we go for 2 hooks / 2 components, can we find a nice way to consolidate the shared pieces?

I'd say let's discuss things here and folks can feel free to submit PRs w/ suggested implementations. Thanks to you both so much for all these contributions too, I can really feel the lib getting better and better.

[Proposal] Adopt redoc for documentation

Hello, everyone!
There's this great tool called redoc that could benefit the project.
It generates a good looking documentation website using implementation files and docblocks.

I see two main benefits in adopting it:

  • Nice searchable documentation to refer to future users
  • Increase the amount of documentation inside the code for future contributors

What's everyone's opinion?

urql should be peer dependency

urql should be a peer dependency of this package. Because the package has no "JS compilation step" (which it doesn't need), bs.module declarations like this:

https://github.com/FormidableLabs/reason-urql/blob/d31d0e508dd5dccb8ad6d495f1c6b1c75296ce72/src/UrqlClient.re#L135-L144

will be transpiled into naked import Urql from "urql" statements in a JS code base, which causes the bundler (webpack in my case) to look for urql in the project's top-level node_modules, which it won't find because urql is specified as a direct dependency instead of peer dependency. Specifying urql as a peer dependency reminds the developer to install urql alongside this package.

Move off of Sail CI.

We have five builds in a pending state in Sail, and a build hasn't gone through since Tuesday. Sail just feels too flaky to really be worth it. I'd be open to using Travis or CircleCI if anyone wants to pick this up before I get to it. The project previously was on Travis and the builds always worked pretty well, but Circle could be fun to setup too.

Add tests and setup Travis CI.

We'll want to add tests and basic CI using Travis for this repo.

The leading platform for testing in Reason for the moment seems to be bs.jest, so we'll likely want to use that. Tests should be placed in a __tests__ directory at the root.

CI should be setup using Travis. We'll want to add a .travis.yml file at the root once we add sufficient tests.

Should combinederror contain both network and graphql errors?

Not sure if you have any insight/ideas on this -- It seems like ocaml-graphql-server makes the response a status code 500 when you want to return a graphql error. This is normally fine, except for that our service that uses reason-urql just returns a network error in this case and doesn't seem to attempt to parse any graphql errors once it sees a 500.

I've tracked this down to urql here:
https://github.com/FormidableLabs/urql/blob/f4b11379e43ef14bbc2a5bf563a6aa2cc09b4271/src/utils/error.ts#L3-L19

I'm happy to make a PR to urql to let it aggregate both kinds of error, but not sure what the best policy is here, as I'm not sure what the best practices for graphql are re: status codes. Any thoughts?

Edit: actually I'm not sure if this is right, will investigate further I guess

Update API documentation on CombinedError.

Currently our API documentation on CombinedError is non-existent. This is an important part of the urql API and deserves to be covered in more depth. API documentation should include the following:

  • Type signature and description of the CombinedError.combinedError record.
  • Examples showing how to pattern match combinedError on the networkError and graphQLErrors fields.
  • Example showing the message field added in #105.

In addition, we should add a .rei file for this module as long as we're here.

Consider using `graphql_ppx` for GraphQL queries.

graphql_ppx is a PPX rewriter for Reason / BuckleScript. It allows us to construct type safe, validated queries at compile time given a GraphQL schema. Users would be able to generate schema for their projects using the built in script helpers yarn send-introspection-query http://my-api.example.com/api. While this adds some slight overhead for users, it does give the benefit of type checking queries at compile time. We should develop a potential framework for this on a separate branch and test it on the example project.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.