File Coverage

lib/APISchema/DSL.pm
Criterion Covered Total %
statement 87 87 100.0
branch 8 8 100.0
condition n/a
subroutine 29 29 100.0
pod 0 6 0.0
total 124 130 95.3


line stmt bran cond sub pod time code
1             package APISchema::DSL;
2 13     13   1636944 use strict;
  13         95  
  13         299  
3 13     13   82 use warnings;
  13         25  
  13         254  
4              
5             # lib
6 10     10   2964 use APISchema::Schema;
  10         27  
  10         284  
7              
8             # core
9 10     10   65 use Carp ();
  10         20  
  10         215  
10              
11             # cpan
12 10     10   56 use Exporter 'import';
  10         20  
  10         293  
13 10     10   55 use Path::Class qw(file);
  10         19  
  10         7155  
14              
15             my %schema_meta = (
16             ( map { $_ => "${_}_resource" } qw(request response) ),
17             ( map { $_ => $_ } qw(title description destination option) ),
18             );
19              
20             our %METHODS = (
21             ( map { $_ => $_ } qw(HEAD GET POST PUT DELETE PATCH) ),
22             FETCH => [qw(GET HEAD)],
23             );
24             our @DIRECTIVES = (qw(include filter resource title description), keys %METHODS);
25             our @EXPORT = @DIRECTIVES;
26              
27             my $_directive = {};
28              
29             sub process (&) {
30 70     70 0 276101 my $dsl = shift;
31              
32 70         417 my $schema = APISchema::Schema->new;
33              
34             local $_directive->{include} = sub {
35 63     63   160 my ($file) = @_;
36 63 100       1849 -r $_[0] or Carp::croak(sprintf 'No such file: %s', $file);
37 62         366 my $content = file($file)->slurp;
38 62         24667 my $with_utf8 = "use utf8;\n" . $content;
39 9     9   4189 eval $with_utf8;
  9     9   252  
  9     7   56  
  9     5   76  
  9     1   18  
  9     1   58  
  7     1   68  
  7     1   17  
  7     1   61  
  5         43  
  5         11  
  5         35  
  62         4255  
  1         2  
  1         6  
  1         8  
  1         2  
  1         6  
  1         9  
  1         2  
  1         6  
  1         9  
  1         3  
  1         6  
  1         8  
  1         2  
  1         8  
  1         9  
  1         3  
  1         6  
40 62 100       687 Carp::croak($@) if $@;
41 70         414 };
42             local $_directive->{title} = sub {
43 60     60   248 $schema->title(@_);
44 70         321 };
45             local $_directive->{description} = sub {
46 58     58   207 $schema->description(@_);
47 70         252 };
48              
49 70         114 my @filters;
50             local $_directive->{filter} = sub {
51 1     1   8 push @filters, $_[0];
52 70         222 };
53             local $_directive->{resource} = sub {
54 126     126   356 $schema->register_resource(@_);
55 70         234 };
56              
57             local @$_directive{keys %METHODS} = map {
58 70         299 my $m = $_;
  484         629  
59             sub {
60 65     65   209 my ($path, @args) = @_;
61 65         175 for my $filter (reverse @filters) {
62 1         8 local $Carp::CarpLevel += 1;
63 1         9 @args = $filter->(@args);
64             }
65 65         148 my ($definition, $option) = @args;
66              
67             $schema->register_route(
68             ( map {
69             defined $definition->{$_} ?
70 385 100       1097 ( $schema_meta{$_} => $definition->{$_} ) : ();
71             } keys %schema_meta ),
72             defined $option ? (option => $option) : (),
73             route => $path,
74 65 100       241 method => $METHODS{$m},
75             );
76 484         1917 };
77             } keys %METHODS;
78              
79 70         293 $dsl->();
80 67         1721 return $schema;
81             }
82              
83             # dispatch directives to the definitions
84 63     63 0 307 sub include ($) { $_directive->{include}->(@_) }
85 61     61 0 662 sub title ($) { $_directive->{title}->(@_) }
86 59     59 0 611 sub description ($) { $_directive->{description}->(@_) }
87 2     2 0 1382 sub filter (&) { $_directive->{filter}->(@_) }
88 127     127 0 707 sub resource ($@) { $_directive->{resource}->(@_) }
89             for my $method (keys %METHODS) {
90 10     10   84 no strict 'refs';
  10         22  
  10         1376  
91 68     68   1806 *$method = sub ($@) { goto \&{ $_directive->{$method} } };
  68         242  
92             }
93              
94             # disable the global definitions
95             @$_directive{@DIRECTIVES} = (sub {
96             Carp::croak(sprintf(
97             q(%s should be called inside 'process {}' block),
98             join '/', @DIRECTIVES
99             ));
100             }) x scalar @DIRECTIVES;
101              
102             1;
103             __END__