File Coverage

blib/lib/Modern/OpenAPI/Generator/CLI.pm
Criterion Covered Total %
statement 47 75 62.6
branch 18 36 50.0
condition 0 15 0.0
subroutine 8 10 80.0
pod 1 1 100.0
total 74 137 54.0


line stmt bran cond sub pod time code
1             package Modern::OpenAPI::Generator::CLI;
2              
3 2     2   81761 use v5.26;
  2         6  
4 2     2   7 use strict;
  2         2  
  2         32  
5 2     2   7 use warnings;
  2         3  
  2         89  
6 2     2   8 use Carp qw(croak);
  2         3  
  2         134  
7 2     2   1197 use Getopt::Long qw(GetOptionsFromArray);
  2         20541  
  2         8  
8 2     2   1006 use Path::Tiny qw(path);
  2         11474  
  2         86  
9 2     2   438 use Modern::OpenAPI::Generator ();
  2         5  
  2         1222  
10              
11             # Resolves --client / --server / --ui and --no-* from raw argv (before Getopt mutates it).
12             #
13             # No such flags -> (1,1,1) full stack.
14             # Only --no-* -> start from (1,1,1), turn off each mentioned flag.
15             # Any --client / --server / --ui (positive) appears -> start (0,0,0), apply all flags in order
16             # (--client --server does NOT imply --ui; add --ui explicitly if you want Swagger UI).
17             sub _resolve_feature_flags {
18 8     8   139533 my ($argv) = @_;
19 8         14 my @tokens = grep { /^--(no-)?(client|server|ui)$/ } @$argv;
  29         87  
20 8 100       22 return ( 1, 1, 1 ) unless @tokens;
21              
22 7         10 my $has_positive = grep { /^--(client|server|ui)$/ } @tokens;
  13         27  
23              
24 7 100       15 if ( !$has_positive ) {
25 3         6 my ( $c, $s, $u ) = ( 1, 1, 1 );
26 3         6 for (@tokens) {
27 4 100       10 /^--no-client$/ && do { $c = 0; next };
  1         3  
  1         4  
28 3 100       7 /^--no-server$/ && do { $s = 0; next };
  1         1  
  1         2  
29 2 50       7 /^--no-ui$/ && do { $u = 0; next };
  2         2  
  2         4  
30             }
31 3         16 return ( $c, $s, $u );
32             }
33              
34 4         8 my ( $c, $s, $u ) = ( 0, 0, 0 );
35 4         6 for (@tokens) {
36 9 100       29 if (/^--client$/) { $c = 1 }
  4 50       7  
    100          
    50          
    100          
    50          
37 0         0 elsif (/^--no-client$/) { $c = 0 }
38 3         4 elsif (/^--server$/) { $s = 1 }
39 0         0 elsif (/^--no-server$/) { $s = 0 }
40 1         2 elsif (/^--ui$/) { $u = 1 }
41 1         24 elsif (/^--no-ui$/) { $u = 0 }
42             }
43 4         23 return ( $c, $s, $u );
44             }
45              
46             sub run {
47 0     0 1   my ( $class, @argv ) = @_;
48 0           my @orig_argv = @argv;
49 0           my $spec;
50 0           my $output = '.';
51 0           my $name;
52 0           my ( $sync, $async ) = ( 1, 1 );
53 0           my $skeleton = 0;
54 0           my $local_test = 0;
55 0           my $force = 0;
56 0           my $merge = 0;
57 0           my @signatures;
58              
59 0 0         GetOptionsFromArray(
60             \@argv,
61             'spec=s' => \$spec,
62             'output|o=s' => \$output,
63             'name|n=s' => \$name,
64             'sync!' => \$sync,
65             'async!' => \$async,
66             'skeleton' => \$skeleton,
67             'local-test' => \$local_test,
68             'force' => \$force,
69             'merge' => \$merge,
70             'signature=s@' => \@signatures,
71             'help|h' => \my $help,
72             ) or _usage();
73              
74 0 0         _usage() if $help;
75              
76 0           my ( $client, $server, $ui ) = _resolve_feature_flags( \@orig_argv );
77              
78 0   0       $spec //= $argv[0];
79 0 0 0       $output = '.' if !defined $output || !length $output;
80 0 0         croak "Usage: oapi-perl-gen --name MyApp::API [--spec openapi.yaml] [--output DIR]\n" unless $spec;
81 0 0         croak "--name is required (Perl package prefix)\n" unless $name;
82              
83 0 0 0       croak "At least one of --client, --server, or --ui must stay enabled "
      0        
84             . "(use defaults or omit all --no-* flags).\n"
85             if !$client && !$server && !$ui;
86              
87 0 0 0       if ( @signatures == 1 && $signatures[0] =~ /,/ ) {
88 0           @signatures = split /,/, $signatures[0];
89             }
90              
91             Modern::OpenAPI::Generator->new(
92 0           spec_path => $spec,
93             output_dir => $output,
94             name => $name,
95             client => $client,
96             server => $server,
97             ui => $ui,
98             sync => $sync,
99             async => $async,
100             skeleton => $skeleton,
101             force => $force,
102             merge => $merge,
103             signatures => \@signatures,
104             local_test => $local_test,
105             )->run;
106              
107 0           print "Generated under $output (package $name)\n";
108 0           return 0;
109             }
110              
111             sub _usage {
112 0     0     print <<'USAGE';
113             oapi-perl-gen -- OpenAPI generator (Modern::OpenAPI::Generator)
114              
115             --name, -n Root Perl package (required), e.g. MyApp::API
116             --spec FILE OpenAPI 3.x YAML/JSON (positional arg also accepted)
117             --output, -o Output directory (default: .)
118              
119             Feature selection (client / server / Swagger UI):
120              
121             If you pass none of: --client, --no-client, --server, --no-server, --ui, --no-ui,
122             all three are generated (default "full" mode).
123              
124             If you pass only --no-* flags, each turns that feature off; the rest stay on
125             (example: --no-ui => client + server, no embedded Swagger UI).
126              
127             If you pass at least one of --client, --server, or --ui (positive), only the
128             features you set explicitly are generated (--client --server does not add UI).
129              
130             Examples:
131             --client => client only
132             --client --server => client + server, no UI
133             --client --server --ui => client + server + Swagger UI
134             --client --server --no-ui => client + server, no UI
135             --no-ui => client + server, no UI
136             --no-server --no-ui => client only
137              
138             Swagger UI: when server and UI are generated, GET /openapi.yaml prepends the
139             current request origin (scheme/host/port from your daemon -l URL) to `servers`
140             so "Try it out" targets the running app.
141              
142             --sync / --no-sync Emit Client::Sync (default: on)
143             --async / --no-async Emit Client::Async (default: on)
144              
145             --skeleton Server controller stubs without TODO comments
146              
147             --local-test With --server: controllers use ::StubData + ::Model::* (random
148             payload, from_json) instead of 501. Also emits ::Model::* when
149             --no-client (models are required for local stubs).
150              
151             --signature hmac Emit Auth::Plugin::Hmac (repeat or comma-separated)
152             --signature bearer Emit Auth::Plugin::Bearer
153              
154             --force Overwrite existing files
155             --merge Skip files that already exist
156              
157             --help, -h
158              
159             USAGE
160 0           exit 0;
161             }
162              
163             1;
164              
165             __END__