1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
package GraphQL::Type::Union;
use 5.014;
use strict;
use warnings;
use Moo;
use MooX::Thunking;
use Types::Standard -all;
use GraphQL::Type::Library -all;
use GraphQL::MaybeTypeCheck;
use GraphQL::Debug qw(_debug);
extends qw(GraphQL::Type);
with qw(
GraphQL::Role::Output
GraphQL::Role::Composite
GraphQL::Role::Abstract
GraphQL::Role::Nullable
GraphQL::Role::Named
);
use constant DEBUG => $ENV{GRAPHQL_DEBUG};
our $VERSION = '0.02';
=head1 NAME
GraphQL::Type::Union - GraphQL union type
=head1 SYNOPSIS
use GraphQL::Type::Union;
my $union_type = GraphQL::Type::Union->new(
name => 'Union',
types => [ $type1, $type2 ],
resolve_type => sub {
return $type1 if ref $_[0] eq 'Type1';
return $type2 if ref $_[0] eq 'Type2';
},
);
=head1 ATTRIBUTES
Inherits C<name>, C<description> from L<GraphQL::Type>.
=head2 types
Thunked array-ref of L<GraphQL::Type::Object> objects.
=cut
has types => (
is => 'thunked',
isa => UniqueByProperty['name'] & ArrayRefNonEmpty[InstanceOf['GraphQL::Type::Object']],
required => 1,
);
=head2 resolve_type
Optional code-ref. Input is a value, returns a GraphQL type object for
it. If not given, relies on its possible type objects having a provided
C<is_type_of>.
=cut
has resolve_type => (is => 'ro', isa => CodeRef);
=head1 METHODS
=head2 get_types
Returns list of L<GraphQL::Type::Object>s of which the object is a union,
performing validation.
=cut
has _types_validated => (is => 'rw', isa => Bool);
method get_types() :ReturnType(ArrayRefNonEmpty[InstanceOf['GraphQL::Type::Object']]) {
my @types = @{ $self->types };
DEBUG and _debug('Union.get_types', $self->name, \@types);
return \@types if $self->_types_validated; # only do once
$self->_types_validated(1);
if (!$self->resolve_type) {
my @bad = map $_->name, grep !$_->is_type_of, @types;
die $self->name." no resolve_type and no is_type_of for @bad" if @bad;
}
\@types;
}
method from_ast(
HashRef $name2type,
HashRef $ast_node,
) :ReturnType(InstanceOf[__PACKAGE__]) {
DEBUG and _debug('Union.from_ast', $ast_node);
$self->new(
$self->_from_ast_named($ast_node),
resolve_type => sub {}, # fake
$self->_from_ast_maptype($name2type, $ast_node, 'types'),
);
}
has to_doc => (is => 'lazy', isa => Str);
sub _build_to_doc {
my ($self) = @_;
DEBUG and _debug('Union.to_doc', $self);
join '', map "$_\n",
($self->description ? (map "# $_", split /\n/, $self->description) : ()),
"union @{[$self->name]} = " . join(' | ', map $_->name, @{$self->{types}});
}
__PACKAGE__->meta->make_immutable();
1;
|