X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fgraphql-client;a=blobdiff_plain;f=bin%2Fgraphql;h=2b5c03b8f1daf353d9ddab51a2a8dafeb075a03f;hp=071cac713fbf6e0c825e3f924b6a8246e6e55f1c;hb=HEAD;hpb=697f37637e11830cac0913e18aa7ebd41e6af508 diff --git a/bin/graphql b/bin/graphql index 071cac7..2b5c03b 100755 --- a/bin/graphql +++ b/bin/graphql @@ -1,168 +1,218 @@ -#!/usr/bin/env perl -# PODNAME: graphql +#! perl # ABSTRACT: Command-line GraphQL client - -use warnings; -use strict; - -use Getopt::Long; -use GraphQL::Client; -use Scalar::Util qw(reftype); - -our $VERSION = '999.999'; # VERSION - -my $url; -my $transport = {}; -my $query = '-'; -my $variables = {}; -my $format = 'json:pretty'; -my $unpack = 0; -my $outfile; -GetOptions( - 'url|u=s' => \$url, - 'transport|t=s%' => \$transport, - 'query|mutation=s' => \$query, - 'variable|var|d=s%' => \$variables, - 'format|f=s' => \$format, - 'unpack!' => \$unpack, - 'output|o=s' => \$outfile, -) or die "Invalid options.\n"; - -$url = shift if !$url; -$query = shift if !$query || $query eq '-'; - -my $client = GraphQL::Client->new( - %$transport, - url => $url, -); -$client->transport; # just make sure we can load the transport - -if (!$query || $query eq '-') { - print STDERR "Interactive mode engaged! Waiting for a query on ...\n" if -t STDIN; - $query = do { local $/; <> }; -} - -my $resp = $client->request($query, $variables); -my $err = $resp->{errors}; -my $data = !$unpack || $err ? $resp : $resp->{data}; - -if ($outfile) { - open(my $out, '>', $outfile) or die "Open $outfile failed: $!"; - *STDOUT = $out; -} - -$format = lc($format); -if ($format eq 'json') { - require JSON::MaybeXS; - print JSON::MaybeXS->new(utf8 => 1)->encode($data); -} -elsif ($format eq 'json:pretty') { - require JSON::MaybeXS; - print JSON::MaybeXS->new(utf8 => 1, pretty => 1)->encode($data); -} -elsif ($format eq 'yaml') { - require YAML; - print YAML::Dump($data); -} -else { - require Data::Dumper; - print Data::Dumper::Dumper($data); -} - -exit($unpack && $err ? 1 : 0); +# PODNAME: graphql =head1 SYNOPSIS - graphql [--var key=value]... [--transport key=value]... - [--[no-]unpack] [--format json|json:pretty|yaml] + graphql [ [--variables JSON] | [--variable KEY=VALUE]... ] + [--operation-name NAME] [--transport KEY=VALUE]... + [--[no-]unpack] [--filter JSONPATH] + [--format json|json:pretty|yaml|perl|csv|tsv|table] [--output FILE] + + graphql --version|--help|--manual =head1 DESCRIPTION C is a command-line program for executing queries and mutations on a L server. +=head1 INSTALL + +There are several ways to install F to your system. + +=head2 from CPAN + +You can install F using L: + + cpanm GraphQL::Client + +=head2 from GitHub + +You can also choose to download F as a self-contained executable: + + curl -OL https://raw.githubusercontent.com/chazmcgarvey/graphql-client/solo/graphql + chmod +x graphql + +To hack on the code, clone the repo instead: + + git clone https://github.com/chazmcgarvey/graphql-client.git + cd graphql-client + make bootstrap # installs dependencies; requires cpanm + =head1 OPTIONS -=head2 --url STR +=head2 C<--url URL> The URL of the GraphQL server endpoint. If no C<--url> option is given, the first argument is assumed to be the URL. +This option is required. + Alias: C<-u> -=head2 --query STR +=head2 C<--query STR> The query or mutation to execute. -If no C<--query> option is given, the first argument (after URL) is assumed to -be the query. +If no C<--query> option is given, the next argument (after URL) is assumed to be the query. -If the value is C<-> (which is the default), the query will be read from -C. +If the value is "-" (which is the default), the query will be read from C. See: L Alias: C<--mutation> -=head2 --variable KEY=VALUE +=head2 C<--variables JSON> + +Provide the variables as a JSON object. + +Aliases: C<--vars>, C<-V> + +=head2 C<--variable KEY=VALUE> + +An alternative way to provide variables one at a time. This option can be repeated to provide +multiple variables. -A key-value pair +If used in combination with L, this option is silently ignored. See: L Aliases: C<--var>, C<-d> -=head2 --transport KEY=VALUE +=head2 C<--operation-name NAME> + +Inform the server which query/mutation to execute. + +Alias: C<-n> + +=head2 C<--output FILE> + +Write the response to a file instead of STDOUT. + +Alias: C<-o> + +=head2 C<--transport KEY=VALUE> Key-value pairs for configuring the transport (usually HTTP). Alias: C<-t> -=head2 --unpack +=head2 C<--format STR> + +Specify the output format to use. See L. + +Alias: C<-f> + +=head2 C<--unpack> + +Enables unpack mode. + +By default, the response structure is printed as-is from the server, and the program exits 0. -Enables C mode. +When unpack mode is enabled, if the response completes with no errors, only the data section of +the response is printed and the program exits 0. If the response has errors, the whole response +structure is printed as-is and the program exits 1. See L to see what this looks like in +practice. -By default, the response structure is printed as-is from the server, and the -program exits 0. +Use C<--no-unpack> to disable if unpack mode was enabled via C. -When C mode is enabled, if the response completes with no errors, only -the data section of the response is printed and the program exits 0. If the -response has errors, the whole response structure is printed as-is and the -program exits 1. +=head2 C<--filter JSONPATH> -=head2 --format STR +Filter the response based on a L expression. -Sets the output format. Possible values include: +Requires L. + +Alias: C<-p> + +=head1 FORMAT + +The argument for L can be one of: =for :list -* C (default) -* C -* C -* C +* C - Comma-separated values (requires L) +* C - Human-readable JSON (default) +* C - JSON +* C - Perl code (requires L) +* C - Table (requires L) +* C - Tab-separated values (requires L) +* C - YAML (requires L) -Alias: C<-f> +The C, C, and C
formats will only work if the response has a particular shape: + + { + "data" : { + "onefield" : [ + { + "key" : "value", + ... + }, + ... + ] + } + } + +or + + { + "data" : { + "onefield" : [ + "value", + ... + ] + } + } + +If the response cannot be formatted, the default format will be used instead, an error message will +be printed to STDERR, and the program will exit 3. + +Table formatting can be done by one of several different modules, each with its own features and +bugs. The default module is L, but this can be overridden using the +C environment variable if desired, like this: + + PERL_TEXT_TABLE=Text::Table::HTML graphql ... -f table + +The list of supported modules is at L. =head1 EXAMPLES -Different ways to provide the query/mutation: +Different ways to provide the query/mutation to execute: - graphql http://localhost:4000/graphql {hello} + graphql http://myserver/graphql {hello} - echo {hello} | graphql http://localhost:4000/graphql + echo {hello} | graphql http://myserver/graphql - graphql http://localhost:4000/graphql < {hello} > END - graphql http://localhost:4000/graphql + graphql http://myserver/graphql Interactive mode engaged! Waiting for a query on ... {hello} ^D -This example shows the effect of L<--unpack>: +Execute a query with variables: - graphql http://localhost:4000/graphql {hello} + graphql http://myserver/graphql < query HeroNameAndFriends($episode: Episode) { + > hero(episode: $episode) { + > name + > friends { + > name + > } + > } + > } + > END + + graphql http://myserver/graphql --vars '{"episode":"JEDI"}' + +Configure the transport: + + graphql http://myserver/graphql {hello} -t headers.authorization='Basic s3cr3t' + +This example shows the effect of L: + + graphql http://myserver/graphql {hello} # Output: { @@ -171,23 +221,47 @@ This example shows the effect of L<--unpack>: } } - graphql --unpack http://localhost:4000/graphql {hello} + graphql http://myserver/graphql {hello} --unpack # Output: { "hello" : "Hello world!" } -Execute a query with variables: +=head1 ENVIRONMENT - graphql unpack http://localhost:4000/graphql < query HeroNameAndFriends($episode: Episode) { - > hero(episode: $episode) { - > name - > friends { - > name - > } - > } - > } - > END +Some environment variables affect the way C behaves: + +=for :list +* C - Set to 1 to print diagnostic messages to STDERR. +* C - Set the HTTP user agent string. +* C - Set the default set of options. +* C - Set table format backend; see L. + +=head1 EXIT STATUS + +Here is a consolidated summary of what exit statuses mean: + +=for :list +* C<0> - Success +* C<1> - Client or server errors +* C<2> - Option usage is wrong +* C<3> - Could not format the response as requested + +=head1 SEE ALSO + +=for :list +* L - Programmatic interface + +=cut + +# FATPACK - Do not remove this line. + +use warnings; +use strict; + +use GraphQL::Client::CLI; + +our $VERSION = '999.999'; # VERSION +GraphQL::Client::CLI->main(@ARGV);