File Coverage

lib/APISchema/DSL.pm
Criterion Covered Total %
statement 90 90 100.0
branch 8 8 100.0
condition n/a
subroutine 30 30 100.0
pod 0 6 0.0
total 128 134 95.5


line stmt bran cond sub pod time code
1             package APISchema::DSL;
2 11     11   1269193 use strict;
  11         98  
  11         260  
3 9     9   51 use warnings;
  9         17  
  9         211  
4              
5             # lib
6 9     9   1764 use APISchema::Schema;
  9         34  
  9         314  
7              
8             # core
9 9     9   67 use Carp ();
  9         24  
  9         194  
10              
11             # cpan
12 9     9   55 use Exporter 'import';
  9         20  
  9         339  
13 9     9   56 use Path::Class qw(file);
  9         19  
  9         6222  
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 64     64 0 239492 my $dsl = shift;
31              
32 64         462 my $schema = APISchema::Schema->new;
33              
34             local $_directive->{include} = sub {
35 57     57   135 my ($file) = @_;
36 57 100       2070 -r $_[0] or Carp::croak(sprintf 'No such file: %s', $file);
37 56         308 my $content = file($file)->slurp;
38 56         23381 my $with_utf8 = "use utf8;\n" . $content;
39 9     9   3458 eval $with_utf8;
  9     8   216  
  9     6   70  
  8     4   71  
  8     1   17  
  8     1   65  
  6     1   96  
  6     1   16  
  6     1   45  
  4     1   38  
  4         11  
  4         31  
  56         4904  
  1         2  
  1         7  
  1         9  
  1         2  
  1         6  
  1         9  
  1         2  
  1         6  
  1         11  
  1         2  
  1         9  
  1         8  
  1         2  
  1         6  
  1         13  
  1         2  
  1         9  
  1         10  
  1         2  
  1         6  
40 56 100       709 Carp::croak($@) if $@;
41 64         443 };
42             local $_directive->{title} = sub {
43 55     55   296 $schema->title(@_);
44 64         299 };
45             local $_directive->{description} = sub {
46 54     54   209 $schema->description(@_);
47 64         297 };
48              
49 64         140 my @filters;
50             local $_directive->{filter} = sub {
51 1     1   8 push @filters, $_[0];
52 64         279 };
53             local $_directive->{resource} = sub {
54 116     116   1382 $schema->register_resource(@_);
55 64         247 };
56              
57             local @$_directive{keys %METHODS} = map {
58 64         319 my $m = $_;
  442         612  
59             sub {
60 61     61   205 my ($path, @args) = @_;
61 61         175 for my $filter (reverse @filters) {
62 1         6 local $Carp::CarpLevel += 1;
63 1         8 @args = $filter->(@args);
64             }
65 61         127 my ($definition, $option) = @args;
66              
67             $schema->register_route(
68             ( map {
69             defined $definition->{$_} ?
70 361 100       1229 ( $schema_meta{$_} => $definition->{$_} ) : ();
71             } keys %schema_meta ),
72             defined $option ? (option => $option) : (),
73             route => $path,
74 61 100       261 method => $METHODS{$m},
75             );
76 442         1844 };
77             } keys %METHODS;
78              
79 64         263 $dsl->();
80 61         1578 return $schema;
81             }
82              
83             # dispatch directives to the definitions
84 57     57 0 285 sub include ($) { $_directive->{include}->(@_) }
85 56     56 0 561 sub title ($) { $_directive->{title}->(@_) }
86 55     55 0 466 sub description ($) { $_directive->{description}->(@_) }
87 2     2 0 1243 sub filter (&) { $_directive->{filter}->(@_) }
88 117     117 0 594 sub resource ($@) { $_directive->{resource}->(@_) }
89             for my $method (keys %METHODS) {
90 9     9   81 no strict 'refs';
  9         19  
  9         1110  
91 64     64   1428 *$method = sub ($@) { goto \&{ $_directive->{$method} } };
  64         269  
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__