GraphQL Networking
Make sure to read the documentation for eit_networking, as this package reuses its entire functionality.
Main purpose of this package is to abstract the configuration needed for using GraphQL. Selected package is graphql. There are three types of operations in GraphQL - Queries, Mutations and Subscriptions. Queries and Mutations are always served over HTTP. Subscription, in most cases, uses websockets, but other implementaitons are possibly.
For HTTP communication we use dio client, configured via eit_networking interfaces. To work with dio and graphql, we need a Link. Links are similar to interceptors in Dio. We have a custom implementation of DioLink, which is heavily inspired by gql_dio_link.
For websocket communication we use standard WebSocketLink from graphql.
Installation
dart pub add eit_networking_gql --hosted-url=https://gitea.whitelabel.mobile.embedit.dev/api/packages/platform/pub/
!IMPORTANT You need access token for fetching from private pub repository. ELI add token automatically
Usage
Before you will run first http request you must init GqlApiClient.
await GqlApiClient.initialize(config, store: store);
Configuration
Default configuration set from eit_networking
Attribute | Default value | Description |
---|---|---|
baseUrl | none required | Base url of your api server |
connectionTimeout | 5s | |
receiveTimeout | 15s | |
useIsolate | false | jsonDecode in isolate |
useNative | true | Use native if possible |
debug | false | log to console |
validateStatuses | 200, 201, 203, 205, 302 | status codes as validation |
useConnectivity | true | Network change listener |
checkInterval | 5s | periodic check connectivity |
interceptors | empty | dio client interceptors |
Default configuration set for additional graphql parameters
Attribute | Default value | Description |
---|---|---|
graphQlEndpointUrl | none required | URL of the graphql endpoint, usually '/graphql' |
baseLink | none | If present, will be connected to created link with baseLink.concat(link) |
websocketUrl | none | If present, the client will be configured to use Websockets for subscriptions |
Store
Cache store is a required parameter of the GraphQL client. Two main implementations are InMemoryCacheStore and HiveStore. For HiveStore, check eit_storage and its Boxes. There is also an implementation of AlwaysEmptyStore, in case you want to forcefully disable the cache on the store level.
Simple configuration of the client may look like this:
final box = getEitBox(); // use your own implementation
final config = const GqlApiConfig(
'http://127.0.0.1:3000',
'graphql',
websocketUrl: 'ws://localhost:3000',
);
final store = HiveStore(box);
final gqlApiClient = await GqlApiClient.initialize(config, store: store);
Api request
Extensions
Used extensions are same as with eit_networking.
FutureResponse.request
// original
final result = await waitTask();
result.tryResult(onFailure, onSuccess)
// shorthand
final result = await waitTask().request(converter);
FutureResponse.run
- equivalent to
/// original
waitTask().then((result)=> result.tryResult(onFailure, onSuccess));
/// shorthand
waitTask().run(onFailure, onSuccess);
Api query
Standard call on GraphQLClient with generated extensions
returns standard response with DTO or throw exception, so you have to use try/catch
final GraphQLClient apiClient = gqlApiClient.gql; // we initialised the gqlApiClient above
try{
// this is a real code example of getting detail by id
final result = apiClient
.query$ReadCharacterDetail(
Options$Query$ReadCharacterDetail(
variables: Variables$Query$ReadCharacterDetail(id: id),
),
);
} catch (e, s){
logger.e(e, s);
rethrow;
}
Use request
shorthand to convert Dto to Entity and error handler
return Future<Result<ApiFailure, MyEntity>>
final GraphQLClient apiClient = gqlApiClient.gql; // we initialised the gqlApiClient above
final result = apiClient
.query$ReadCharacterDetail( // generated extension method
Options$Query$ReadCharacterDetail( // generated class
variables: Variables$Query$ReadCharacterDetail(id: id), // generated class
),
)
.request((data) => MyEntity(data)); // use custom mapper from generated response (data is typed)
result.tryResult(onSuccess:(data){
...
}, onFailure: (exception){
...
})
Api Failure
There are two more exceptions added on top of ApiFailure from eit_networking. GraphQlErrorsException, which gets fired when the response contains errors (all the errors are part of the exception data for further processing) and GraphQlLinkParserException, which gets fired when the DioLink could not parse the query or response.
How to use in Bloc
The interface of repositories remains the same as in eit_networking.
/// Simple result mapper
on<FetchEvent>((event, emit){
repository.get(event.id).request<MyEntity>(MyEntityX.fromDto).run(
onSuccess: SuccessState.new,
onFailure: FailureState.new,
);
})