zth / rescript-relay

Use Relay with ReScript.
https://rescript-relay-documentation.vercel.app/docs/getting-started
337 stars 50 forks source link

Support null variables #426

Closed zth closed 1 year ago

zth commented 1 year ago

Closes https://github.com/zth/rescript-relay/issues/348

This introduces a directive @rescriptRelayNullableVariables on operations that will allow you to leverage Js.Nullable.t to send null explicitly to your APIs.

You can test this in your project by running yarn add rescript-relay@support-nullable-variables.

How it works in a nutshell:

module Mutation = %relay(`
    mutation TestNullableVariablesMutation($avatarUrl: String) @rescriptRelayNullableVariables {
      updateUserAvatar(avatarUrl: $avatarUrl) {
        user {
          avatarUrl
        }
      }
    }
`)

// All optional variables in this operation can now be `null`, which will be preserved and sent to your server.
Mutation.commitMutation(~environment=RelayEnvironment.environment, ~variables={avatarUrl: Js.Nullable.null}, ())

// Or if you want to send a value:
Mutation.commitMutation(~environment=RelayEnvironment.environment, ~variables={avatarUrl: Js.Nullable.return("some-avatar-url")}, ())

This works for:

The reason for this being an explicit directive and not applied globally is that this isn't the default you want, working with options is still so much easier.

Notes:

mununki commented 1 year ago
type Input {
  a: Int!
  b: Int
  c: int
}
module M = %relay(`
  mutation Test($input: Input!) @rescriptRelayNullableVariables {
    test(input: $input) {
      result
    }
  }
`)

M.commitMutation(~variables=M.makeVarialbes(~input=M.makeVariables_input(~a=1, ~b=Js.Nullable.null, ())))

The variables on the network request would be something like{a: 1, b: null}?

zth commented 1 year ago
type Input {
  a: Int!
  b: Int
  c: int
}
module M = %relay(`
  mutation Test($input: Input!) @rescriptRelayNullableVariables {
    test(input: $input) {
      result
    }
  }
`)

M.commitMutation(~variables=M.makeVarialbes(~input=M.makeVariables_input(~a=1, ~b=Js.Nullable.null, ())))

The variables on the network request would be something like{a: 1, b: null}?

Not 100%, you'll need to wrap everything with Js.Nullable. I haven't added support for object makers (most likely won't since they might be going away in the future), so it'd need to be:

M.commitMutation(~variables=(input: Js.Nullable.return({a: Js.Nullable.return(1), b: Js.Nullable.null})}, ())

But then yes, the network request would be: {input: {a: 1, b: null}}

zth commented 1 year ago

Has anyone tried this for real yet? Cc @lozlow

zth commented 1 year ago

Will merge this and we can iterate on it more if needed.