All notable changes to
the dillonkearns/elm-graphql
elm package
will be documented in this file.
The format is based on Keep a Changelog and this project adheres to Semantic Versioning.
- Fix bug where hashes would sometimes be omitted in cases where they are needed to disambiguate between sibling fields when they have different types for sibling fields with the same name. See #633.
- JSON objects are not valid in GraphQL because object properties are unquoted in GraphQL syntax. This release includes a fix that will remove quotes from JSON object properties in the serialized GraphQL query to make them valid GraphQL syntax. Note that not all JSON can be made valid with this approach because some keys need to be quoted (see #606 for a discussion of a possible approach to handle those cases). This release fixes #570. See #605. Thank you @SiriusStarr for the fix!
-
Hashes are now only included in the GraphQL query when they are needed to disambiguate between other sibling fields that would cause a name collision. These details aren't important if you don't depend on any internals, but they will reduce noise when inspecting requests for debugging purposes. Note that it's still important not to depend on any low-level details - be sure not to write code that depends on whether or not field aliases with hashes are used as
elm-graphql
abstracts away these details.This change means that many fields will be unhashed now:
query {
- avatar2648687506: avatar(size: 1)
+ avatar(size: 1)
}
However, a query like this will still have hashed field aliases because the hashes are needed to avoid a name collision when we query avatar twice at the same level within a selection set:
query {
avatar0: avatar
avatar2648687506: avatar(size: 1)
}
Thank you @hariroshan for thinking of this improvement and implementing it! See PR #596.
- Query params are now passed through for POST requests (they were always empty before).
- Order is now correctly preserved. Version 5.0.6 broke this condition, which is required by the GraphQL spec for mutations so they can be performed in a specific order. Thank you @kyasu1 for the PR! See #575.
operationName
is now passed in the body of mutation requests (see #566). Thank you @galdiuz for the PR!
- Merge duplicate Leaf and Composite fields so that there are never more than 1 field in a selection set with the same field name. See #556. Fixes #495. Technically having Leaf fields with the same field alias or field name is allowed by the GraphQL Spec, but this change makes field aliases and names unique for both Leaf and Composite fields.
- The input object loop detection had some false positives. This fix prevents using nested input object loop wrappers for some deeply nested input objects that are actually not circular. See #475. Thank you @mcasper!
- The README now shows a badge with the GitHub Actions CI status (Travis is deprecated and is no longer being used here).
- Renamed
SelectionSet decodesTo typeLock
type variable toSelectionSet decodesTo scope
. See #407.
- Pulled in vendor code for murmur3 package because of a GitHub username change that started causing problems installing that package from the Elm package repository. Thank you neslinesli93 for the fix! See #397.
- The optional
operationName
field is now sent in the POST body, or GET query parameters, when a request is performed. Even though it's optional, some tooling depends on that field being present, so this may make some server-side tools happy. See #388. Thank you to Yoni for this contribution!
- (MAJOR API change) Fix order of arguments for Http pipeline function,
withOperationName
(fixes #254). - (MAJOR API change) Switch
discardParsedErrorData
from returning a()
to an unconstraineda
. This makes it a little more flexible for users in terms of the types it allows, without changing the behavior. See #245 (thank you @Jayshua!). - (MAJOR API change) fix typo in internal function name (
exhuastiveFragmentSelection
->exhaustiveFragmentSelection
).
- Expose
Graphql.Http.withOperationName
function (which was mistakenly left out last release).
Graphql.Http.withOperationName
allows you to (optionally) add operation names to your GraphQL queries (thank you @asterite for your PR! #195)
- Parse pre-execution GraphQL response that has "error" but no "data" (see #168).
- Added
SeletionSet.foldl
- Added
OptionalArgument.fromMaybeWithNull
- Don't use field aliases for __typename fields (see PR #121).
SelectionSet.list
lets you combine aList
ofSelectionSet value scope
s into a singleSelectionSet (List value) scope
.SelectionSet.dict
lets you combine aList
of(String, SelectionSet value scope)
s into a singleSelectionSet (Dict String value) scope
. TheString
s in the list are used as the key in theDict
.- Expose type
Graphql.Codec
(for use with the--scalar-codecs
CLI flag, see this example).
- Expose type
Graphql.Http.HttpError
-
elm/[email protected]
removed some important data fromHttp.Error
. It's now just (BadStatus Int
rather thanBadStatus (Response String)
). See the type definitions here: https://package.elm-lang.org/packages/elm/http/1.0.0/Http#Error https://package.elm-lang.org/packages/elm/http/latest/Http#ErrorIn order to allow
dillonkearns/elm-graphql
users to capture the body of responses with a bad status, we need to do a major version bump.In a nutshell, this change introduces a custom type that looks like this:
module Graphql.Http.Error exposing -- ..
type alias Error parsedData =
RawError parsedData HttpError
type RawError parsedData httpError
= GraphqlError (GraphqlError.PossiblyParsedData parsedData) (List GraphqlError.GraphqlError)
| HttpError httpError
type HttpError
= BadUrl String
| Timeout
| NetworkError
| BadStatus Http.Metadata String
| BadPayload Json.Decode.Error
See the full details here: #89
Note that this will only require you to change your code if you were destructuring
the Graphql.Http.HttpError
values. And the changes introduce a function to map
into the old type easily:
withSimpleHttpError : Result (Error parsedData) decodesTo -> Result (RawError parsedData Http.Error) decodesTo
Well, not exactly the old type, the old type was Graphql.Http.Error parsedData
,
the new type is written out as Graphql.Http.RawError parsedData Http.Error
,
but it would contains the same data as before.
Graphql.Http.fromHttpError
was removed as it no longer makes sense with the default type wrappingGraphql.Http.HttpError
instead ofHttp.Error
. See theGraphql.Http.withSimpleHttpError
docs if you are looking to combine a Graphql response with an Http response.- Removed
ignoreParsedErrorData
to avoid confusion. It's easier to usediscardParsedErrorData
, use that function instead. It maps the entire result so you don't have to use it in combination withGraphql.Http.mapError
.
- Only the internal code changed in this release, so you won't need to do anything to upgrade your own code besides re-running the latest CLI tool. The change includes the type information of a field in its field alias hash. Since the alias is now unique to each field's type and argument values, you can no longer encounter validation errors when you build up a query using unions or interfaces that include fields with the same names but different types. See #95 for more details.
-
The
Field
module has been removed. With this change, think of aField
as just a special case of aSelectionSet
. TheSelectionSet
is now used for both a single element or multiple (much like a singleCmd msg
or multiple withCmd.batch [cmd1, cmd2]
). This means that any functions you called onField
before are now inSelectionSet
(so it'sSelectionSet.nonNullOrFail
,SelectionSet.map
, etc). The latest docs page forSelectionSet
now has a nice tutorial in it that walks you through the new way thatSelectionSet
s work. If you're trying to wrap your head around the new design, I highly recommend you read this page!To migrate to the new version, just follow these steps:
- Find and delete all calls to
import Graphql.Field
in your code entirely - Anywhere you called
SelectionSet.fieldSelection
can simply be removed now. - Anywhere you called
Field.map
,mapOrFail
, etc., is justSelectionSet.map
, etc. now. - Remove any calls to
<GeneratedModule>.selection
and replace it withSelectionSet.succeed
(for Union types, theselection
function has been renamed tofragments
, see the last point below). - Any annotations which were
Field decodesTo scope
, simply change them toSelectionSet decodesTo scope
- Find and delete all calls to
-
The
.selection
function for Unions has been renamed to.fragments
to be consistent with the naming for Interfaces.
- Add
SelectionSet.mapN
functions for an alternate syntax to the pipeline syntax (starting a pipeline withSelectionSet.succeed
). - New
SeletionSet.withDefault
. Just a convenience function which is equivalent toSelectionSet.map Maybe.withDefault
.
- The
withCredentials
was inverted with release 1.4.0. So it would use theHttp.risky
andHttp.riskyTask
versions if you didn't callwithCredentials
, and it would use the regularHttp.request
andHttp.task
builders if you did. Thank you @kyasu1 for reporting the problem! See #97.
- Add new internal builder function, for use with the new generated code for building exhaustive Union and Interface fragments. See this diff to understand the changes and how to migrate: e530d94.
- Bump underlying
elm/http
andelm/json
packages.
- Add
Graphql.Http.sendWithTracker
function, see theHttp.request
docs for details and functions to track Http requests in Elm.
- Add
discardParsedErrorData
to make it easier to map errors into a type that can be easily merged together (something that looks likeResult (Error ()) decodesTo
). - Add
parseableErrorAsSuccess
, which treats any GraphQL errors like successful responses (throws away the GraphQL error) as long as it is able to successfully run the decoder (it won't be able to if the data returned is partial).
SelectionSet.withFragment
allows you to include fields from aSelectionSet
when you are defining aSelectionSet
. This is a nice tool for modularizing your queries! Check out an example in action.SelectionSet.map2
allows you to combine twoSelectionSet
s into one.- New
OptionalArgument.map
funciton, thanks Romario! (See PR #73).
- The generated selection sets now will include at least a
__typename
to ensure they are valid (empty selection sets are invalid in GraphQL). Previously you could get an invalid GraphQL query if you usedSelectionSet.hardcoded
. - (Internal implementation details, not public facing though the generated
queries will look slightly different now) - The
alias
generation has changed to be independent of surrounding context. The new algorithm will generate analias
for any field if and only if that field has arguments. You can read more about the details and rationale on this thread.
- Extracted
scalarDecoder
constant and moved to module in thedillonkearns/elm-graphql
package. This is only used in generated code. This change allows us to remove allDebug.toString
calls in generated code so that users can compile their code with the--optimize
flag. This resolves #68.
Take a look at the dillonkearns/elm-graphql
Elm 0.19 upgrade guide.
- Subscriptions Low-Level Data-Transfer Layer As before, this library will
generate code based on the subscriptions defined in your GraphQL schema.
And you will be able to use
Graphql.Document.serializeSubscription
to get aString
that you can send over to your server when you open a subscription. Then you'll be able to use theGraphql.Document.decoder
from your subscription to decode the JSON responses from the server. What's been removed is just the low level protocols for doing the websocket connection. As per this issue, this responsibility will be moved out of the coredillonkearns/elm-graphql
package in order to decouple this library from the low-level details which differ between different GraphQL server implementations.
The low-level data transfer logic for connecting over websockets to a subscription has been removed from this package. #43
- Rename package from
dillonkearns/graphqelm
todillonkearns/elm-graphql
to follow the elm literal naming convention (see issue #23).
BELOW THIS IS FOR dillonkearns/graphqelm
(before the rename to dillonkearns/elm-graphql
)
- Add
Selectionset.fieldSelection
function to concisely turn a singleField
into aSelectionSet
. Thanks to anagrius for the suggestion!
- Add
mapError
andignoreParsedErrorData
functions to allow you to do more manipulation ofParsedData
within Error data (fixes #52).
- Responses are errors if any data is present in
errors
field in response. Thedata
field from the response is also included inGraphqlError
s now so you can inspect the data upon failure. Here is a summary of how this will effect your code:- Before,
dillonkearns/elm-graphql
always treated responses where it could parse the response as success. - Now, it will treat responses where
errors
are present as an error regardless of whether it is able to parse the responsedata
. - Users will need to add a type variable to their error type as errors may contain parsed data now (so
RemoteData (Graphql.Http.Error) Response
->RemoteData (Graphql.Http.Error Response) Response
) - For more context, here's the Github issue: #48 (comment)
- For an example, see
elm-graphql/examples/src/ErrorHandling.elm
Lines 80 to 107 in 30be357
- Before,
- Add
SelectionSet.succeed
to provide a hardcoded value as the result of a SelectionSet.
- Expose GraphQL response decoder publicly.
- Update model to allow more flexibility based on #32.
- Add functions for transforming
Field
s usingResult
s. These functions are handy for converting values into types likeDateTime
s but can cause your entire response to error when decoding if any incorrect assumptions are made so they should be used with extreme care.
- Remove
AlwaysPost
sinceGraphql.Http.queryRequest
now always uses POST. Added option toGetWhenShortEnough
.
- Add
Graphql.OptionalArgument.fromMaybe
. - Add
SelectionSet.map
.
- Always use POST when sending query requests since some APIs like Github don't support GET (see https://developer.github.com/v4/guides/forming-calls/#communicating-with-graphql).
- Add
Graphql.Http.withQueryParams
.
- Use GET requests by default when sending a query request, unless the resulting
url would be over 2000 characters.
queryParamsForceMethod
allows you to specify a method when needed. - Rename
Graphql.Http
functions frombuildMutationRequest
=>mutationRequest
andbuildQueryRequest
=>queryRequest
to sound more declarative and concise. - Extract Subscription.Protocol module which encapsulates the details about low-level subscription communication for a given framework. The module includes an implementation for Rails and Absinthe/Rhoenix, or custom.
- Add experimental subscriptions module and example.
- Add
Graphql.Http.toTask
. - Expose
Graphql.Http.withCredentials
.
- Rename
FieldDecoder
type and module toField
to match GraphQL domain language more closely.
- Add
hardcoded
function to add arbitrary constants alongsidewith
calls.
- Expose Http.Error constructors.
- Remove unused elm package dependencies.
- Add missing
Encode.float
function. Without this, APIs with float arguments would have compilation errors.
- Modules that are used only by generated code are now under
Graphql.Internal
to make it more clear in the documentation.
- Encode functions to support generated code for input objects. There is now no reason for users to consume the Encode module directly! It's all done under the hood by the generated code.
- Fix bug that excluded arguments when serializing leaves in document.