]>
Dogcows Code - chaz/graphql-client/blob - lib/GraphQL/Client.pm
faa5edaf59dc3d823b119a474cd873ba4f6904cd
1 package GraphQL
::Client
;
2 # ABSTRACT: A GraphQL client
7 use Module
::Load
qw(load);
8 use Scalar
::Util
qw(reftype);
11 our $VERSION = '999.999'; # VERSION
13 sub _croak
{ use Carp
; goto &Carp
::croak
}
22 my ($query, $variables, $operation_name, $options) = @_;
24 if ((reftype
($operation_name) || '') eq 'HASH') {
25 $options = $operation_name;
26 $operation_name = undef;
31 ($variables && %$variables) ? (variables
=> $variables) : (),
32 $operation_name ? (operationName
=> $operation_name) : (),
35 my $resp = $self->transport->request($request, $options);
36 return $self->_handle_response($resp);
39 my $ERROR_MESSAGE = 'The GraphQL server returned errors';
40 sub _handle_response
{
44 if (eval { $resp->isa('Future') }) {
45 return $resp->followed_by(sub {
47 if (my ($exception, $category, @details) = $f->failure) {
48 if (!$exception->{errors
}) {
49 return Future-
>fail($exception, $category, @details);
52 return Future-
>fail($ERROR_MESSAGE, 'graphql', $exception, @details);
54 return Future-
>done($exception);
57 my ($resp, @other) = $f->get;
59 if ($resp->{errors
}) {
60 return Future-
>fail($ERROR_MESSAGE, 'graphql', $resp, @other);
62 return Future-
>done($resp->{data
});
64 return Future-
>done($resp);
70 if ($resp->{errors
}) {
71 throw
$ERROR_MESSAGE, {
94 $self->{transport
} //= do {
95 my $class = $self->_transport_class;
97 if ((my $err = $@) || !$class->can('request')) {
98 $err ||= "Loaded $class, but it doesn't look like a proper transport.\n";
99 warn $err if $ENV{GRAPHQL_CLIENT_DEBUG
};
100 _croak
"Failed to load transport for \"${class}\"";
108 $self->{unpack} //= 0;
114 my $url = $self->url;
115 my ($protocol) = $url =~ /^([^+:]+)/;
120 sub _transport_class
{
123 return _expand_class
($self->{class}) if $self->{class};
125 my $protocol = $self->_url_protocol;
126 _croak
'Failed to determine transport from URL' if !$protocol;
128 my $class = lc($protocol);
129 $class =~ s/[^a-z]/_/g;
131 return _expand_class
($class);
136 $class = "GraphQL::Client::$class" unless $class =~ s/^\+//;
145 my $client = GraphQL::Client->new();
147 my $data = $client->request(q[
149 human(id: $human_id) {
162 $client = GraphQL::Client->new(%attributes);
164 Construct a new client.
168 $response = $client->request($query);
169 $response = $client->request($query, \%variables);
170 $response = $client->request($query, \%variables, $operation_name);
171 $response = $client->request($query, \%variables, $operation_name, \%transport_options);
172 $response = $client->request($query, \%variables, \%transport_options);
174 Get a response from the GraphQL server.
176 By default, the response will either be a hashref with the following structure or a L<Future> that
177 resolves to such a hashref, depending on the transport and how it is configured.
181 field1 => {...}, # or [...]
185 { message => 'some error message blah blah blah' },
190 Note: Setting the L</unpack> attribute affects the response shape.
194 The URL of a GraphQL endpoint, e.g. C<"http://myapiserver/graphql">.
200 The package name of a transport.
202 By default this is automatically determined from the protocol portion of the L</url>.
206 The transport object.
208 By default this is automatically constructed based on the L</class>.
212 Whether or not to "unpack" the response, which enables a different style for error-handling.
216 See L</ERROR HANDLING>.
218 =head1 ERROR HANDLING
220 There are two different styles for handling errors.
222 If L</unpack> is 0 (off), every response -- whether success or failure -- is enveloped like this:
229 where C<data> might be missing or undef if errors occurred (though not necessarily) and C<errors>
230 will be missing if the response completed without error.
232 It is up to you to check for errors in the response, so your code might look like this:
234 my $response = $client->request(...);
235 if (my $errors = $response->{errors}) {
238 my $data = $response->{data};
239 # do something with $data
241 If C<unpack> is 1 (on), then L</request> will return just the data if there were no errors,
242 otherwise it will throw an exception. So your code would look like this:
244 my $data = eval { $client->request(...) };
245 if (my $error = $@) {
248 # do something with $data
250 Or if you want to handle errors in a different stack frame, your code is simply this:
252 my $data = $client->request(...);
253 # do something with $data
255 Both styles map to L<Future> responses intuitively. If C<unpack> is 0, the response always resolves
256 to the envelope structure. If C<unpack> is 1, successful responses will resolve to just the data and
257 errors will fail/reject.
This page took 0.0511 seconds and 3 git commands to generate.