]>
Dogcows Code - chaz/graphql-client/blob - lib/GraphQL/Client.pm
1 package GraphQL
::Client
;
2 # ABSTRACT: A GraphQL client
7 use Module
::Load
qw(load);
10 our $VERSION = '999.999'; # VERSION
12 sub _croak
{ use Carp
; goto &Carp
::croak
}
21 my ($query, $variables, $options) = @_;
23 my $transport_opts = {%{$options || {}}};
24 my $operation_name = delete($transport_opts->{operation_name
}) // delete($transport_opts->{operationName
});
28 $variables ? (variables
=> $variables) : (),
29 $operation_name ? (operationName
=> $operation_name) : (),
32 my $resp = $self->transport->request($request, $transport_opts);
33 return $self->_handle_response($resp);
36 sub _handle_response
{
40 if (eval { $resp->isa('Future') }) {
41 return $resp->followed_by(sub {
43 if (my $exception = $f->failure) {
44 if ($self->unpack || !$exception->{errors
}) {
45 return Future-
>fail($exception);
47 return Future-
>done($exception);
52 if ($resp->{errors
}) {
53 return Future-
>fail($resp);
55 return Future-
>done($resp->{data
});
57 return Future-
>done($resp);
63 if ($resp->{errors
}) {
64 throw
'The GraphQL server returned errors', {
87 $self->{transport
} //= do {
88 my $class = $self->_transport_class;
91 warn $err if $ENV{GRAPHQL_CLIENT_DEBUG
};
92 _croak
"Failed to load transport for \"${class}\"";
100 $self->{unpack} //= 0;
106 my $url = $self->url;
107 my ($protocol) = $url =~ /^([^+:]+)/;
112 sub _transport_class
{
115 return _expand_class
($self->{class}) if $self->{class};
117 my $protocol = $self->_url_protocol;
118 _croak
'Failed to determine transport from URL' if !$protocol;
120 my $class = lc($protocol);
121 $class =~ s/[^a-z]/_/g;
123 return _expand_class
($class);
128 $class = "GraphQL::Client::$class" unless $class =~ s/^\+//;
137 my $client = GraphQL::Client->new();
139 my $data = $client->request(q[
141 human(id: $human_id) {
154 $client = GraphQL::Client->new(%attributes);
156 Construct a new client.
160 $response = $client->request($query);
161 $response = $client->request($query, \%variables);
162 $response = $client->request($query, \%variables, \%transport_options);
164 Get a response from the GraphQL server.
166 By default, the response will either be a hashref with the following structure or a L<Future> that
167 resolves to such a hashref, depending on the transport and how it is configured.
171 field1 => {...}, # or [...]
175 { message => 'some error message blah blah blah' },
180 Note: Setting the L</unpack> attribute affects the response shape.
184 The URL of a GraphQL endpoint, e.g. C<"http://myapiserver/graphql">.
190 The package name of a transport.
192 By default this is automatically determined from the protocol portion of the L</url>.
196 The transport object.
198 By default this is automatically constructed based on the L</class>.
202 Whether or not to "unpack" the response, which enables a different style for error-handling.
206 See L</ERROR HANDLING>.
208 =head1 ERROR HANDLING
210 There are two different styles for handling errors.
212 If L</unpack> is 0 (off), every response -- whether success or failure -- is enveloped like this:
219 where C<data> might be missing or undef if errors occurred (though not necessarily) and C<errors>
220 will be missing if the response completed without error.
222 It is up to you to check for errors in the response, so your code might look like this:
224 my $response = $client->request(...);
225 if (my $errors = $response->{errors}) {
228 my $data = $response->{data};
229 # do something with $data
231 If C<unpack> is 1 (on), then L</request> will return just the data if there were no errors,
232 otherwise it will throw an exception. So your code would look like this:
234 my $data = eval { $client->request(...) };
235 if (my $error = $@) {
238 # do something with $data
240 Or if you want to handle errors in a different stack frame, your code is simply this:
242 my $data = $client->request(...);
243 # do something with $data
245 Both styles map to L<Future> responses intuitively. If C<unpack> is 0, the response always resolves
246 to the envelope structure. If C<unpack> is 1, successful responses will resolve to just the data and
247 errors will fail/reject.
This page took 0.047275 seconds and 5 git commands to generate.