File Coverage

blib/lib/RPC/ExtDirect/Client/API.pm
Criterion Covered Total %
statement 55 55 100.0
branch 7 10 70.0
condition 1 3 33.3
subroutine 12 12 100.0
pod 1 2 50.0
total 76 82 92.6


line stmt bran cond sub pod time code
1             package RPC::ExtDirect::Client::API;
2              
3 10     10   40215 use strict;
  10         26  
  10         445  
4 10     10   42 use warnings;
  10         11  
  10         293  
5 10     10   41 no warnings 'uninitialized'; ## no critic
  10         19  
  10         441  
6              
7 10     10   40 use JSON;
  10         245  
  10         265  
8              
9 10     10   2016 use RPC::ExtDirect::Util::Accessor;
  10         14  
  10         218  
10 10     10   40 use RPC::ExtDirect::Config;
  10         13  
  10         210  
11 10     10   470 use RPC::ExtDirect::API;
  10         4279  
  10         206  
12              
13 10     10   314 use base 'RPC::ExtDirect::API';
  10         14  
  10         6496  
14              
15             ### PUBLIC CLASS METHOD (CONSTRUCTOR) ###
16             #
17             # Instantiate a new API declaration from JavaScript code
18             #
19              
20             sub new_from_js {
21 21     21 0 1248 my ($class, %params) = @_;
22            
23 21   33     144 my $config = delete $params{config} || RPC::ExtDirect::Config->new();
24 21         46 my $js = delete $params{js};
25            
26 21         74 my $api_href = _decode_api($js);
27            
28 21         288 my $self = $class->SUPER::new_from_hashref(
29             config => $config,
30             api_href => $api_href->{actions},
31             type => $api_href->{type},
32             url => $api_href->{url},
33             %params,
34             );
35            
36 21         27698 return $self;
37             }
38              
39             ### PUBLIC INSTANCE METHOD ###
40             #
41             # Return an Action object or a list of Action objects, depending on context
42             #
43              
44             sub actions {
45 3     3 1 26588 my ($self, @actions) = @_;
46              
47 3 100       8 if ( wantarray ) {
48 1         5 my @set = @actions ? @actions
49 2 100       4 : keys %{ $self->{actions} }
50             ;
51            
52 2         6 my @result = map { $self->get_action_by_name($_) } @set;
  5         21  
53              
54 2         17 return @result;
55             }
56             else {
57 1         2 my $action_name = shift @actions;
58            
59 1         4 return $self->get_action_by_name($action_name);
60             };
61             }
62              
63             ### PUBLIC INSTANCE METHODS ###
64             #
65             # Read-write accessors
66             #
67              
68             RPC::ExtDirect::Util::Accessor->mk_accessors(
69             simple => [qw/ type url /],
70             );
71              
72             ############## PRIVATE METHODS BELOW ##############
73              
74             ### PRIVATE PACKAGE SUBROUTINE ###
75             #
76             # Decode API declaration and check basic constraints
77             #
78              
79             sub _decode_api {
80 21     21   36 my ($js) = @_;
81              
82 21         104 $js =~ s/^[^{]+//;
83            
84 21         46 my ($api_js) = eval { JSON->new->utf8(1)->decode_prefix($js) };
  21         722  
85              
86 21 50       167 die "Can't decode API declaration: $@\n" if $@;
87              
88 21 50       82 die "Empty API declaration\n"
89             unless 'HASH' eq ref $api_js;
90              
91 21 50       240 die "Unsupported API type\n"
92             unless $api_js->{type} =~ /remoting|polling/i;
93            
94             # Convert the JavaScript API definition to the format
95             # API::new_from_hashref expects
96 21         45 my $actions = $api_js->{actions};
97            
98 13         50 my %remote_actions
99 21         81 = map { $_ => _convert_action($actions->{$_}) } keys %$actions;
100            
101 21         62 $api_js->{actions} = \%remote_actions;
102            
103 21         140 return $api_js;
104             }
105              
106             ### PRIVATE PACKAGE SUBROUTINE ###
107             #
108             # Convert JavaScript Action definition to remote Action definition
109             #
110              
111             sub _convert_action {
112 13     13   18 my ($action_def) = @_;
113            
114 13         25 my %methods = map { delete $_->{name} => $_ } @$action_def;
  87         230  
115            
116             return {
117 13         121 remote => 1,
118             methods => \%methods,
119             };
120             }
121              
122             1;