From 0500659090b2f3412761d871d657c09632ebc865 Mon Sep 17 00:00:00 2001 From: Charles McGarvey Date: Sun, 22 Mar 2020 03:39:37 -0600 Subject: [PATCH] add --filter argument --- bin/graphql | 12 +++++-- dist.ini | 10 +++--- lib/GraphQL/Client/CLI.pm | 70 ++++++++++++++++++++++++++++++--------- t/cli.t | 1 + 4 files changed, 72 insertions(+), 21 deletions(-) diff --git a/bin/graphql b/bin/graphql index 6127922..2b5c03b 100755 --- a/bin/graphql +++ b/bin/graphql @@ -6,8 +6,8 @@ graphql [ [--variables JSON] | [--variable KEY=VALUE]... ] [--operation-name NAME] [--transport KEY=VALUE]... - [--[no-]unpack] [--format json|json:pretty|yaml|perl|csv|tsv|table] - [--output FILE] + [--[no-]unpack] [--filter JSONPATH] + [--format json|json:pretty|yaml|perl|csv|tsv|table] [--output FILE] graphql --version|--help|--manual @@ -117,6 +117,14 @@ practice. Use C<--no-unpack> to disable if unpack mode was enabled via C. +=head2 C<--filter JSONPATH> + +Filter the response based on a L expression. + +Requires L. + +Alias: C<-p> + =head1 FORMAT The argument for L can be one of: diff --git a/dist.ini b/dist.ini index c6f74b2..78e688a 100644 --- a/dist.ini +++ b/dist.ini @@ -22,14 +22,16 @@ remove_runtime = Pod::Usage remove_runtime = Text::CSV remove_runtime = Text::Table::Any remove_runtime = YAML +remove_runtime = JSON::Path::Evaluator [Prereqs / RuntimeRecommends] HTTP::Tiny = 0 Pod::Usage = 0 [Prereqs / RuntimeSuggests] -Data::Dumper = 0 -Text::CSV = 0 -Text::Table::Any = 0 -YAML = 0 +Data::Dumper = 0 +JSON::Path::Evaluator = 0 +Text::CSV = 0 +Text::Table::Any = 0 +YAML = 0 [Prereqs / DevelopRecommends] ; for fatpack.pl App::FatPacker = 0 diff --git a/lib/GraphQL/Client/CLI.pm b/lib/GraphQL/Client/CLI.pm index 66b391c..c23e07f 100644 --- a/lib/GraphQL/Client/CLI.pm +++ b/lib/GraphQL/Client/CLI.pm @@ -84,6 +84,17 @@ sub main { *STDOUT = $out; } + if (my $filter = $options->{filter}) { + eval { require JSON::Path::Evaluator } or die "Missing dependency: JSON::Path\n"; + my @values = JSON::Path::Evaluator::evaluate_jsonpath($data, $filter); + if (@values == 1) { + $data = $values[0]; + } + else { + $data = \@values; + } + } + binmode(STDOUT, 'encoding(UTF-8)'); _print_data($data, $format); @@ -115,6 +126,7 @@ sub _get_options { 'operation-name|n=s' => \$options{operation_name}, 'transport|t=s%' => \$options{transport}, 'format|f=s' => \$options{format}, + 'filter|p=s' => \$options{filter}, 'unpack!' => \$options{unpack}, 'output|o=s' => \$options{outfile}, ) or _pod2usage(2); @@ -167,27 +179,42 @@ sub _print_data { my $unpacked = $data; # $unpacked = $data->{data} if !$unpack && !$err; - $unpacked = $data->{data} if $data && $data->{data}; + $unpacked = $data->{data} if ref $data eq 'HASH' && $data->{data}; # check the response to see if it can be formatted my @columns; my $rows = []; - if (keys %$unpacked == 1) { - my ($val) = values %$unpacked; - if (ref $val eq 'ARRAY') { - my $first = $val->[0]; - if ($first && ref $first eq 'HASH') { - @columns = sort keys %$first; - $rows = [ - map { [map { _stringify($_) } @{$_}{@columns}] } @$val - ]; - } - elsif ($first) { - @columns = keys %$unpacked; - $rows = [map { [map { _stringify($_) } $_] } @$val]; + if (ref $unpacked eq 'HASH') { + if (keys %$unpacked == 1) { + my ($val) = values %$unpacked; + if (ref $val eq 'ARRAY') { + my $first = $val->[0]; + if ($first && ref $first eq 'HASH') { + @columns = sort keys %$first; + $rows = [ + map { [map { _stringify($_) } @{$_}{@columns}] } @$val + ]; + } + elsif ($first) { + @columns = keys %$unpacked; + $rows = [map { [map { _stringify($_) } $_] } @$val]; + } } } } + elsif (ref $unpacked eq 'ARRAY') { + my $first = $unpacked->[0]; + if ($first && ref $first eq 'HASH') { + @columns = sort keys %$first; + $rows = [ + map { [map { _stringify($_) } @{$_}{@columns}] } @$unpacked + ]; + } + elsif ($first) { + @columns = qw(column); + $rows = [map { [map { _stringify($_) } $_] } @$unpacked]; + } + } if (@columns) { if ($format eq 'table') { @@ -214,13 +241,26 @@ sub _print_data { exit 3; } } + elsif ($format eq 'string') { + if (!ref $data) { + print $data, "\n"; + } + elsif (ref $data eq 'ARRAY') { + print join("\n", @$data); + } + else { + _print_data($data); + print STDERR sprintf("Error: Response could not be formatted as %s.\n", $format); + exit 3; + } + } elsif ($format eq 'perl') { eval { require Data::Dumper } or die "Missing dependency: Data::Dumper\n"; print Data::Dumper::Dumper($data); } else { - print STDERR "Error: Format not supported: $format\n"; _print_data($data); + print STDERR "Error: Format not supported: $format\n"; exit 3; } } diff --git a/t/cli.t b/t/cli.t index 2fa501c..a32af83 100755 --- a/t/cli.t +++ b/t/cli.t @@ -13,6 +13,7 @@ delete $ENV{GRAPHQL_CLIENT_OPTIONS}; subtest 'get_options' => sub { my $expected = { format => 'json:pretty', + filter => undef, help => undef, manual => undef, operation_name => undef, -- 2.45.2