File Coverage

blib/lib/PAGI/Utils.pm
Criterion Covered Total %
statement 46 46 100.0
branch 27 28 96.4
condition 6 8 75.0
subroutine 10 10 100.0
pod 3 3 100.0
total 92 95 96.8


line stmt bran cond sub pod time code
1             package PAGI::Utils;
2             $PAGI::Utils::VERSION = '0.002001';
3 35     35   463189 use strict;
  35         65  
  35         1231  
4 35     35   169 use warnings;
  35         57  
  35         1446  
5 35     35   138 use Exporter 'import';
  35         48  
  35         1011  
6 35     35   493 use Future::AsyncAwait;
  35         16299  
  35         180  
7 35     35   1599 use Carp qw(croak);
  35         48  
  35         1690  
8 35     35   171 use Scalar::Util qw(blessed);
  35         53  
  35         1373  
9 35     35   13346 use PAGI::Lifespan;
  35         75  
  35         26471  
10              
11             our @EXPORT_OK = qw(handle_lifespan to_app is_response);
12             our %EXPORT_TAGS = (all => \@EXPORT_OK);
13              
14             # True if $x is a PAGI response value: a blessed object that can respond($send).
15             # The single source of truth for the "did the handler return a response?" check
16             # (used by the endpoint and router dispatch paths).
17             sub is_response {
18 53     53 1 88 my ($x) = @_;
19 53 100 100     641 return blessed($x) && $x->can('respond') ? 1 : 0;
20             }
21              
22 6     6 1 210528 async sub handle_lifespan {
23 6         12 my ($scope, $receive, $send, %opts) = @_;
24              
25 6   50     16 my $type = $scope->{type} // '';
26 6 100       177 croak "handle_lifespan called with scope type '$type' (expected 'lifespan'). "
27             . "Check scope type before calling: "
28             . "return await handle_lifespan(...) if \$scope->{type} eq 'lifespan'"
29             unless $type eq 'lifespan';
30              
31 5         33 my $manager = PAGI::Lifespan->for_scope($scope);
32 5 100 66     19 $manager->register(%opts) if $opts{startup} || $opts{shutdown};
33              
34 5         12 return await $manager->handle($scope, $receive, $send);
35             }
36              
37             sub to_app {
38 337     337 1 195081 my ($thing) = @_;
39              
40 337 100       749 croak "to_app() requires an app, component, or class name"
41             unless defined $thing;
42              
43 336 100       1966 return $thing if ref($thing) eq 'CODE';
44              
45 33 100       62 if (blessed($thing)) {
46 20 100       132 return $thing->to_app if $thing->can('to_app');
47 2 100       156 croak ref($thing) . " looks like middleware, not an app"
48             . " - pass it to enable(), or wrap an app with ->wrap(\$app)"
49             if $thing->can('wrap');
50 1         85 croak "Cannot coerce " . ref($thing) . " object to a PAGI app (no to_app method)";
51             }
52              
53 13 100       29 if (!ref($thing)) {
54 12 100       143 croak "Cannot coerce '$thing' to a PAGI app"
55             unless $thing =~ /\A\w+(?:::\w+)*\z/;
56 11 100       107 unless ($thing->can('to_app')) {
57 5         36 local $@;
58 5 100       391 eval "require $thing; 1" or croak "Failed to load '$thing': $@";
59             }
60 9 100       84 return $thing->to_app if $thing->can('to_app');
61 1 50       7 croak "'$thing' looks like middleware, not an app - pass it to enable()"
62             if $thing->can('wrap');
63 1         97 croak "'$thing' does not have a to_app() method";
64             }
65              
66 1         70 croak "Cannot coerce " . ref($thing) . " reference to a PAGI app";
67             }
68              
69             1;
70              
71             __END__