File Coverage

blib/lib/GraphQL/Type/Scalar.pm
Criterion Covered Total %
statement 83 214 38.7
branch 14 124 11.2
condition n/a
subroutine 25 25 100.0
pod 4 4 100.0
total 126 367 34.3


line stmt bran cond sub pod time code
1              
2             use 5.014;
3 18     18   6324 use strict;
  48         902  
4 48     18   175 use warnings;
  48         86  
  50         900  
5 45     18   495 use Moo;
  20         39  
  20         475  
6 19     18   820 use GraphQL::Type::Library -all;
  19         9392  
  19         993  
7 19     18   7202 use GraphQL::Debug qw(_debug);
  18         49  
  18         133  
8 18     18   210177 use Types::Standard -all;
  18         50  
  18         1080  
9 18     18   103 use JSON::MaybeXS qw(JSON is_bool);
  18         37  
  18         123  
10 18     18   717870 use Exporter 'import';
  18         47  
  18         1415  
11 18     18   1320 extends qw(GraphQL::Type);
  18         34  
  18         856  
12             with qw(
13             GraphQL::Role::Input
14             GraphQL::Role::Output
15             GraphQL::Role::Leaf
16             GraphQL::Role::Nullable
17             GraphQL::Role::Named
18             GraphQL::Role::FieldsEither
19             );
20             use GraphQL::MaybeTypeCheck;
21 18     18   392 use GraphQL::Plugin::Type;
  18         35  
  18         155  
22 18     18   10613  
  18         54  
  18         156  
23             our $VERSION = '0.02';
24             our @EXPORT_OK = qw($Int $Float $String $Boolean $ID);
25              
26             use constant DEBUG => $ENV{GRAPHQL_DEBUG};
27 18     18   138 my $JSON = JSON::MaybeXS->new->allow_nonref->canonical;
  18         36  
  18         2243  
28              
29             =head1 NAME
30              
31             GraphQL::Type::Scalar - GraphQL scalar type
32              
33             =head1 SYNOPSIS
34              
35             use GraphQL::Type::Scalar;
36             my $int_type = GraphQL::Type::Scalar->new(
37             name => 'Int',
38             description =>
39             'The `Int` scalar type represents non-fractional signed whole numeric ' .
40             'values. Int can represent values between -(2^31) and 2^31 - 1. ',
41             serialize => \&coerce_int,
42             parse_value => \&coerce_int,
43             );
44              
45             =head1 ATTRIBUTES
46              
47             Has C<name>, C<description> from L<GraphQL::Role::Named>.
48              
49             =head2 serialize
50              
51             Code-ref. Required.
52              
53             Coerces
54             B<from> a Perl entity of the required type,
55             B<to> a GraphQL entity,
56             or throws an exception.
57              
58             Must throw an exception if passed a defined (i.e. non-null) but invalid
59             Perl object of the relevant type. C<undef> must always be valid.
60              
61             =cut
62              
63             has serialize => (is => 'ro', isa => CodeRef, required => 1);
64              
65             =head2 parse_value
66              
67             Code-ref. Required if is for an input type.
68              
69             Coerces
70             B<from> a GraphQL entity,
71             B<to> a Perl entity of the required type,
72             or throws an exception.
73              
74             =cut
75              
76             has parse_value => (is => 'ro', isa => CodeRef);
77              
78             =head1 METHODS
79              
80             =head2 is_valid
81              
82             True if given Perl entity is valid value for this type. Uses L</serialize>
83             attribute.
84              
85             =cut
86              
87             method is_valid(Any $item) :ReturnType(Bool) {
88 31 50   31 1 91139 return 1 if !defined $item;
  31 50       129  
  31 50       65  
  31 0       92  
  31 0       134  
  19 0       8928  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 100       0  
  0         0  
89 19 50       46 eval { $self->serialize->($item); 1 };
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
    0          
    0          
90 19         89 }
  223         529  
  223         480  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  161         352  
  161         516  
91 18     18   3371  
  18         77  
  18         156  
92             method graphql_to_perl(Any $item) :ReturnType(Any) {
93 222 50   222 1 1271 $self->parse_value->($item);
  222 50       840  
  18 50       6582  
  18         35  
  18         129  
  875         1578  
94 875         1443 }
95 222     18   317  
  222         400  
  222         489  
96             method perl_to_graphql(Any $item) :ReturnType(Any) {
97 875 50   875 1 4598 $self->serialize->($item);
  875 50       2495  
  18 50       9604  
  18         37  
  18         67  
  2         3317  
98 2         8 }
99 875     18   1143  
  875         1309  
  875         1468  
100             method from_ast(
101             HashRef $name2type,
102             HashRef $ast_node,
103             ) :ReturnType(InstanceOf[__PACKAGE__]) {
104 2 50   2 1 907 DEBUG and _debug('Scalar.from_ast', $ast_node);
  2 0       5  
  2 0       17  
  2 0       47  
  180 0       317  
  180 0       1822  
  9 0       25  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
    0          
    50          
105 9         30 $self->new(
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
106             $self->_from_ast_named($ast_node),
107             serialize => sub { require Carp; Carp::croak "Fake serialize called" },
108 0     1   0 parse_value => sub { require Carp; Carp::croak "Fake parse_value called" },
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
109 0     1   0 );
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  957         9630  
  930         3018  
110 0         0 }
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
111 2     18   4  
  2         5  
  2         9  
112             has to_doc => (is => 'lazy', isa => Str);
113             my ($self) = @_;
114             DEBUG and _debug('Scalar.to_doc', $self);
115 0     2   0 join '', map "$_\n",
116 0         0 $self->_description_doc_lines($self->description),
117 0         0 "scalar @{[$self->name]}";
118             }
119 0         0  
120             =head1 EXPORTED VARIABLES
121              
122             =head2 $Int
123              
124             =cut
125              
126             my ($closure) = @_;
127             sub { return undef if !defined $_[0]; goto &$closure; };
128             }
129 0     180   0  
130 0 0   1127   0 our $Int = GraphQL::Type::Scalar->new(
  0         0  
  0         0  
131             name => 'Int',
132             description =>
133             'The `Int` scalar type represents non-fractional signed whole numeric ' .
134             'values. Int can represent values between -(2^31) and 2^31 - 1.',
135             serialize => _leave_undef(sub { !is_Int32Signed($_[0]) and die "Not an Int.\n"; $_[0]+0 }),
136             parse_value => _leave_undef(sub { !is_Int32Signed($_[0]) and die "Not an Int.\n"; $_[0]+0 }),
137             );
138              
139             =head2 $Float
140              
141             =cut
142              
143             our $Float = GraphQL::Type::Scalar->new(
144             name => 'Float',
145             description =>
146             'The `Float` scalar type represents signed double-precision fractional ' .
147             'values as specified by ' .
148             '[IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point).',
149             serialize => _leave_undef(sub { !is_Num($_[0]) and die "Not a Float.\n"; $_[0]+0 }),
150             parse_value => _leave_undef(sub { !is_Num($_[0]) and die "Not a Float.\n"; $_[0]+0 }),
151             );
152              
153             =head2 $String
154              
155             =cut
156              
157             our $String = GraphQL::Type::Scalar->new(
158             name => 'String',
159             description =>
160             'The `String` scalar type represents textual data, represented as UTF-8 ' .
161             'character sequences. The String type is most often used by GraphQL to ' .
162             'represent free-form human-readable text.',
163             serialize => _leave_undef(sub { !is_Str($_[0]) and die "Not a String.\n"; $_[0].'' }),
164             parse_value => _leave_undef(sub { !is_Str($_[0]) and die "Not a String.\n"; $_[0] }),
165             );
166              
167             =head2 $Boolean
168              
169             =cut
170              
171             our $Boolean = GraphQL::Type::Scalar->new(
172             name => 'Boolean',
173             description =>
174             'The `Boolean` scalar type represents `true` or `false`.',
175             serialize => _leave_undef(sub { !is_Bool($_[0]) and !is_bool($_[0]) and die "Not a Boolean.\n"; $_[0] ? JSON->true : JSON->false }),
176             parse_value => _leave_undef(sub { !is_Bool($_[0]) and !is_bool($_[0]) and die "Not a Boolean.\n"; $_[0]+0 }),
177             );
178              
179             =head2 $ID
180              
181             =cut
182              
183             our $ID = GraphQL::Type::Scalar->new(
184             name => 'ID',
185             description =>
186             'The `ID` scalar type represents a unique identifier, often used to ' .
187             'refetch an object or as key for a cache. The ID type appears in a JSON ' .
188             'response as a String; however, it is not intended to be human-readable. ' .
189             'When expected as an input type, any string (such as `"4"`) or integer ' .
190             '(such as `4`) input value will be accepted as an ID.',
191             serialize => _leave_undef(sub { Str->(@_); $_[0].'' }),
192             parse_value => _leave_undef(sub { Str->(@_); $_[0] }),
193             );
194              
195             GraphQL::Plugin::Type->register($_) for ($Int, $Float, $String, $Boolean, $ID);
196              
197             __PACKAGE__->meta->make_immutable();
198              
199             1;