File Coverage

blib/lib/GraphQL/Directive.pm
Criterion Covered Total %
statement 68 68 100.0
branch 15 24 62.5
condition n/a
subroutine 15 15 100.0
pod 1 1 100.0
total 99 108 91.6


line stmt bran cond sub pod time code
1             package GraphQL::Directive;
2              
3 17     17   462 use 5.014;
  17         77  
4 17     17   91 use strict;
  17         35  
  17         397  
5 17     17   82 use warnings;
  17         37  
  17         476  
6 17     17   88 use Moo;
  17         35  
  17         139  
7 17     17   11839 use MooX::Thunking;
  17         211621  
  17         123  
8 17     17   2573 use GraphQL::MaybeTypeCheck;
  17         36  
  17         115  
9 17     17   98 use GraphQL::Debug qw(_debug);
  17         35  
  17         851  
10 17     17   104 use Types::Standard -all;
  17         34  
  17         135  
11 17     17   752019 use GraphQL::Type::Library -all;
  17         50  
  17         165  
12 17     17   233205 use GraphQL::Type::Scalar qw($Boolean $String);
  17         65  
  17         3234  
13             with qw(
14             GraphQL::Role::Named
15             GraphQL::Role::FieldsEither
16             );
17              
18             our $VERSION = '0.02';
19 17     17   145 use constant DEBUG => $ENV{GRAPHQL_DEBUG};
  17         37  
  17         2589  
20              
21             my @LOCATIONS = qw(
22             QUERY
23             MUTATION
24             SUBSCRIPTION
25             FIELD
26             FRAGMENT_DEFINITION
27             FRAGMENT_SPREAD
28             INLINE_FRAGMENT
29             SCHEMA
30             SCALAR
31             OBJECT
32             FIELD_DEFINITION
33             ARGUMENT_DEFINITION
34             INTERFACE
35             UNION
36             ENUM
37             ENUM_VALUE
38             INPUT_OBJECT
39             INPUT_FIELD_DEFINITION
40             );
41              
42             =head1 NAME
43              
44             GraphQL::Directive - GraphQL directive
45              
46             =head1 SYNOPSIS
47              
48             use GraphQL::Directive;
49             my $directive = GraphQL::Directive->new(
50             name => 'Object',
51             interfaces => [ $interfaceType ],
52             fields => { field_name => { type => $scalar_type, resolve => sub { '' } }},
53             );
54              
55             =head1 ATTRIBUTES
56              
57             Has C<name>, C<description> from L<GraphQL::Role::Named>.
58              
59             =head2 locations
60              
61             Array-ref of locations where the directive can occur. Must be one of
62             these strings:
63              
64             QUERY
65             MUTATION
66             SUBSCRIPTION
67             FIELD
68             FRAGMENT_DEFINITION
69             FRAGMENT_SPREAD
70             INLINE_FRAGMENT
71             SCHEMA
72             SCALAR
73             OBJECT
74             FIELD_DEFINITION
75             ARGUMENT_DEFINITION
76             INTERFACE
77             UNION
78             ENUM
79             ENUM_VALUE
80             INPUT_OBJECT
81             INPUT_FIELD_DEFINITION
82              
83             =cut
84              
85             has locations => (is => 'ro', isa => ArrayRef[Enum[@LOCATIONS]], required => 1);
86              
87             =head2 args
88              
89             Hash-ref of arguments. See L<GraphQL::Type::Library/FieldMapInput>.
90              
91             =cut
92              
93             has args => (is => 'thunked', isa => FieldMapInput, required => 1);
94              
95             =head1 METHODS
96              
97             =head2 from_ast
98              
99             See L<GraphQL::Type/from_ast>.
100              
101             =cut
102              
103             method from_ast(
104             HashRef $name2type,
105             HashRef $ast_node,
106 9 50   9 1 441 ) :ReturnType(InstanceOf[__PACKAGE__]) {
  9 50       72  
  9 50       23  
  9 50       29  
  9         44  
  9         102  
  9         68  
107 9         17 DEBUG and _debug('Directive.from_ast', $ast_node);
108             $self->new(
109             $self->_from_ast_named($ast_node),
110             locations => $ast_node->{locations},
111 9         42 $self->_from_ast_fields($name2type, $ast_node, 'args'),
112             );
113 17     17   5336 }
  17         45  
  17         147  
114              
115             has to_doc => (is => 'lazy', isa => Str);
116             sub _build_to_doc {
117 3     3   57 my ($self) = @_;
118 3         7 DEBUG and _debug('Directive.to_doc', $self);
119 3         31 my @start = (
120             $self->_description_doc_lines($self->description),
121 3         29 "directive \@@{[$self->name]}(",
122             );
123 3         81 my @argtuples = $self->_make_fieldtuples($self->args);
124 3         9 DEBUG and _debug('Directive.to_doc(args)', \@argtuples);
125 3         10 my $end = ") on " . join(' | ', @{$self->locations});
  3         22  
126 3 100       65 return join("\n", @start).join(
127             ', ', map $_->[0], @argtuples
128             ).$end."\n" if !grep $_->[1], @argtuples; # no descriptions
129             # if descriptions
130             join '', map "$_\n",
131             @start,
132             (map {
133 1         4 my ($main, @description) = @$_;
  1         5  
134             (
135 1 50       34 map length() ? " $_" : "", @description, $main,
136             )
137             } @argtuples),
138             $end;
139             }
140              
141             =head1 PACKAGE VARIABLES
142              
143             =head2 $GraphQL::Directive::DEPRECATED
144              
145             =cut
146              
147             $GraphQL::Directive::DEPRECATED = GraphQL::Directive->new(
148             name => 'deprecated',
149             description => 'Marks an element of a GraphQL schema as no longer supported.',
150             locations => [ qw(FIELD_DEFINITION ENUM_VALUE) ],
151             args => {
152             reason => {
153             type => $String,
154             description =>
155             'Explains why this element was deprecated, usually also including ' .
156             'a suggestion for how to access supported similar data. Formatted ' .
157             'in [Markdown](https://daringfireball.net/projects/markdown/).',
158             default_value => 'No longer supported',
159             },
160             },
161             );
162              
163             =head2 $GraphQL::Directive::INCLUDE
164              
165             =cut
166              
167             $GraphQL::Directive::INCLUDE = GraphQL::Directive->new(
168             name => 'include',
169             description => 'Directs the executor to include this field or fragment only when the `if` argument is true.',
170             locations => [ qw(FIELD FRAGMENT_SPREAD INLINE_FRAGMENT) ],
171             args => {
172             if => {
173             type => $Boolean->non_null,
174             description => 'Included when true.',
175             },
176             },
177             );
178              
179             =head2 $GraphQL::Directive::SKIP
180              
181             =cut
182              
183             $GraphQL::Directive::SKIP = GraphQL::Directive->new(
184             name => 'skip',
185             description => 'Directs the executor to skip this field or fragment when the `if` argument is true.',
186             locations => [ qw(FIELD FRAGMENT_SPREAD INLINE_FRAGMENT) ],
187             args => {
188             if => {
189             type => $Boolean->non_null,
190             description => 'Skipped when true.',
191             },
192             },
193             );
194              
195             =head2 @GraphQL::Directive::SPECIFIED_DIRECTIVES
196              
197             Not exported. Contains the three GraphQL-specified directives: C<@skip>,
198             C<@include>, C<@deprecated>, each of which are available with the
199             variables above. Use if you want to have these plus your own directives
200             in your schema:
201              
202             my $schema = GraphQL::Schema->new(
203             # ...
204             directives => [ @GraphQL::Directive::SPECIFIED_DIRECTIVES, $my_directive ],
205             );
206              
207             =cut
208              
209             @GraphQL::Directive::SPECIFIED_DIRECTIVES = (
210             $GraphQL::Directive::INCLUDE,
211             $GraphQL::Directive::SKIP,
212             $GraphQL::Directive::DEPRECATED,
213             );
214              
215             method _get_directive_values(
216             HashRef $node,
217             HashRef $variables,
218 4723 50   4723   7463 ) {
  4723 50       6957  
  4723 50       5351  
  4723 50       5941  
  4723         7253  
  4723         26018  
  4723         23271  
219 4723         5055 DEBUG and _debug('_get_directive_values', $self->name, $node, $variables);
220 4723 100       4970 my ($d) = grep $_->{name} eq $self->name, @{$node->{directives} || []};
  4723         13486  
221 4723 100       10062 return if !$d;
222 21         50 GraphQL::Execution::_get_argument_values($self, $d, $variables);
223             }
224              
225             __PACKAGE__->meta->make_immutable();
226              
227             1;