Initial Commit

This commit is contained in:
Riley Schneider
2025-12-03 16:38:10 +01:00
parent c5e26bf594
commit b732d8d4b5
17680 changed files with 5977495 additions and 2 deletions

View File

@@ -0,0 +1,102 @@
package Mojolicious::Command::Author::cpanify;
use Mojo::Base 'Mojolicious::Command';
use Mojo::File qw(path);
use Mojo::Util qw(getopt);
has description => 'Upload distribution to CPAN';
has usage => sub { shift->extract_usage };
sub run {
my ($self, @args) = @_;
die $self->usage unless getopt \@args,
'p|password=s' => \(my $password = ''),
'u|user=s' => \(my $user = '');
die $self->usage unless my $file = shift @args;
my $tx = $self->app->ua->tap(sub { $_->proxy->detect })->post(
"https://$user:$password\@pause.perl.org/pause/authenquery" => form => {
HIDDENNAME => $user,
CAN_MULTIPART => 1,
pause99_add_uri_upload => path($file)->basename,
SUBMIT_pause99_add_uri_httpupload => ' Upload this file from my disk ',
pause99_add_uri_uri => '',
pause99_add_uri_httpupload => {file => $file},
}
);
if (my $err = $tx->error) {
my $code = $tx->res->code // 0;
my $msg = $err->{message};
if ($code == 401) { $msg = 'Wrong username or password.' }
elsif ($code == 409) { $msg = 'File already exists on CPAN.' }
die qq{Problem uploading file "$file": $msg\n};
}
say 'Upload successful!';
}
1;
=encoding utf8
=head1 NAME
Mojolicious::Command::Author::cpanify - CPAN-ify command
=head1 SYNOPSIS
Usage: APPLICATION cpanify [OPTIONS] [FILE]
mojo cpanify -u sri -p secr3t Mojolicious-Plugin-MyPlugin-0.01.tar.gz
Options:
-h, --help Show this summary of available options
-p, --password <password> PAUSE password
-u, --user <name> PAUSE username
=head1 DESCRIPTION
L<Mojolicious::Command::Author::cpanify> uploads files to CPAN.
This is a core command, that means it is always enabled and its code a good example for learning to build new commands,
you're welcome to fork it.
See L<Mojolicious::Commands/"COMMANDS"> for a list of commands that are available by default.
=head1 ATTRIBUTES
L<Mojolicious::Command::Author::cpanify> inherits all attributes from L<Mojolicious::Command> and implements the
following new ones.
=head2 description
my $description = $cpanify->description;
$cpanify = $cpanify->description('Foo');
Short description of this command, used for the command list.
=head2 usage
my $usage = $cpanify->usage;
$cpanify = $cpanify->usage('Foo');
Usage information for this command, used for the help screen.
=head1 METHODS
L<Mojolicious::Command::Author::cpanify> inherits all methods from L<Mojolicious::Command> and implements the following
new ones.
=head2 run
$cpanify->run(@ARGV);
Run this command.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
=cut

View File

@@ -0,0 +1,87 @@
package Mojolicious::Command::Author::generate;
use Mojo::Base 'Mojolicious::Commands';
has description => 'Generate files and directories from templates';
has hint => <<EOF;
See 'APPLICATION generate help GENERATOR' for more information on a specific
generator.
EOF
has message => sub { shift->extract_usage . "\nGenerators:\n" };
has namespaces => sub { ['Mojolicious::Command::Author::generate'] };
sub help { shift->run(@_) }
1;
=encoding utf8
=head1 NAME
Mojolicious::Command::Author::generate - Generator command
=head1 SYNOPSIS
Usage: APPLICATION generate GENERATOR [OPTIONS]
mojo generate app
mojo generate lite-app
=head1 DESCRIPTION
L<Mojolicious::Command::Author::generate> lists available generators.
This is a core command, that means it is always enabled and its code a good example for learning to build new commands,
you're welcome to fork it.
See L<Mojolicious::Commands/"COMMANDS"> for a list of commands that are available by default.
=head1 ATTRIBUTES
L<Mojolicious::Command::Author::generate> inherits all attributes from L<Mojolicious::Commands> and implements the
following new ones.
=head2 description
my $description = $generator->description;
$generator = $generator->description('Foo');
Short description of this command, used for the command list.
=head2 hint
my $hint = $generator->hint;
$generator = $generator->hint('Foo');
Short hint shown after listing available generator commands.
=head2 message
my $msg = $generator->message;
$generator = $generator->message('Bar');
Short usage message shown before listing available generator commands.
=head2 namespaces
my $namespaces = $generator->namespaces;
$generator = $generator->namespaces(['MyApp::Command::generate']);
Namespaces to search for available generator commands, defaults to L<Mojolicious::Command::Author::generate>.
=head1 METHODS
L<Mojolicious::Command::Author::generate> inherits all methods from L<Mojolicious::Commands> and implements the
following new ones.
=head2 help
$generator->help('app');
Print usage information for generator command.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
=cut

View File

@@ -0,0 +1,200 @@
package Mojolicious::Command::Author::generate::app;
use Mojo::Base 'Mojolicious::Command';
use Mojo::Util qw(class_to_file class_to_path decamelize);
has description => 'Generate Mojolicious application directory structure';
has usage => sub { shift->extract_usage };
sub run {
my ($self, $class) = (shift, shift || 'MyApp');
# Script
my $name = class_to_file $class;
$self->render_to_rel_file('mojo', "$name/script/$name", {class => $class});
$self->chmod_rel_file("$name/script/$name", 0744);
# Application class
my $app = class_to_path $class;
$self->render_to_rel_file('appclass', "$name/lib/$app", {class => $class});
# Config file (using the default moniker)
$self->render_to_rel_file('config', "$name/@{[decamelize $class]}.yml");
# Controller
my $controller = "${class}::Controller::Example";
my $path = class_to_path $controller;
$self->render_to_rel_file('controller', "$name/lib/$path", {class => $controller});
# Test
$self->render_to_rel_file('test', "$name/t/basic.t", {class => $class});
# Static file
$self->render_to_rel_file('static', "$name/public/index.html");
# Templates
$self->render_to_rel_file('layout', "$name/templates/layouts/default.html.ep");
$self->render_to_rel_file('welcome', "$name/templates/example/welcome.html.ep");
}
1;
=encoding utf8
=head1 NAME
Mojolicious::Command::Author::generate::app - App generator command
=head1 SYNOPSIS
Usage: APPLICATION generate app [OPTIONS] [NAME]
mojo generate app
mojo generate app TestApp
Options:
-h, --help Show this summary of available options
=head1 DESCRIPTION
L<Mojolicious::Command::Author::generate::app> generates application directory structures for fully functional
L<Mojolicious> applications.
This is a core command, that means it is always enabled and its code a good example for learning to build new commands,
you're welcome to fork it.
See L<Mojolicious::Commands/"COMMANDS"> for a list of commands that are available by default.
=head1 ATTRIBUTES
L<Mojolicious::Command::Author::generate::app> inherits all attributes from L<Mojolicious::Command> and implements the
following new ones.
=head2 description
my $description = $app->description;
$app = $app->description('Foo');
Short description of this command, used for the command list.
=head2 usage
my $usage = $app->usage;
$app = $app->usage('Foo');
Usage information for this command, used for the help screen.
=head1 METHODS
L<Mojolicious::Command::Author::generate::app> inherits all methods from L<Mojolicious::Command> and implements the
following new ones.
=head2 run
$app->run(@ARGV);
Run this command.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
=cut
__DATA__
@@ mojo
#!/usr/bin/env perl
use strict;
use warnings;
use Mojo::File qw(curfile);
use lib curfile->dirname->sibling('lib')->to_string;
use Mojolicious::Commands;
# Start command line interface for application
Mojolicious::Commands->start_app('<%= $class %>');
@@ appclass
package <%= $class %>;
use Mojo::Base 'Mojolicious', -signatures;
# This method will run once at server start
sub startup ($self) {
# Load configuration from config file
my $config = $self->plugin('NotYAMLConfig');
# Configure the application
$self->secrets($config->{secrets});
# Router
my $r = $self->routes;
# Normal route to controller
$r->get('/')->to('example#welcome');
}
1;
@@ controller
package <%= $class %>;
use Mojo::Base 'Mojolicious::Controller', -signatures;
# This action will render a template
sub welcome ($self) {
# Render template "example/welcome.html.ep" with message
$self->render(msg => 'Welcome to the Mojolicious real-time web framework!');
}
1;
@@ static
<!DOCTYPE html>
<html>
<head>
<title>Welcome to the Mojolicious real-time web framework!</title>
</head>
<body>
<h2>Welcome to the Mojolicious real-time web framework!</h2>
This is the static document "public/index.html",
<a href="/">click here</a> to get back to the start.
</body>
</html>
@@ test
use Mojo::Base -strict;
use Test::More;
use Test::Mojo;
my $t = Test::Mojo->new('<%= $class %>');
$t->get_ok('/')->status_is(200)->content_like(qr/Mojolicious/i);
done_testing();
@@ layout
<!DOCTYPE html>
<html>
<head><title><%%= title %></title></head>
<body><%%= content %></body>
</html>
@@ welcome
%% layout 'default';
%% title 'Welcome';
<h2><%%= $msg %></h2>
<p>
This page was generated from the template "templates/example/welcome.html.ep"
and the layout "templates/layouts/default.html.ep",
<%%= link_to 'click here' => url_for %> to reload the page or
<%%= link_to 'here' => '/index.html' %> to move forward to a static page.
</p>
@@ config
% use Mojo::Util qw(sha1_sum steady_time);
---
secrets:
- <%= sha1_sum $$ . steady_time . rand %>

View File

@@ -0,0 +1,87 @@
package Mojolicious::Command::Author::generate::dockerfile;
use Mojo::Base 'Mojolicious::Command';
use Mojo::File qw(path);
has description => 'Generate "Dockerfile"';
has usage => sub { shift->extract_usage };
sub run {
my $self = shift;
my $name = $self->app->moniker;
my $exe = $ENV{MOJO_EXE} ? path($ENV{MOJO_EXE})->to_rel($self->app->home)->to_string : "script/$name";
$self->render_to_rel_file('dockerfile', 'Dockerfile', {name => $name, cmd => "./$exe prefork"});
}
1;
=encoding utf8
=head1 NAME
Mojolicious::Command::Author::generate::dockerfile - Dockerfile generator command
=head1 SYNOPSIS
Usage: APPLICATION generate dockerfile [OPTIONS]
./myapp.pl generate dockerfile
./script/my_app generate dockerfile
Options:
-h, --help Show this summary of available options
=head1 DESCRIPTION
L<Mojolicious::Command::Author::generate::dockerfile> generates C<Dockerfile> for applications.
This is a core command, that means it is always enabled and its code a good example for learning to build new commands,
you're welcome to fork it.
See L<Mojolicious::Commands/"COMMANDS"> for a list of commands that are available by default.
=head1 ATTRIBUTES
L<Mojolicious::Command::Author::generate::dockerfile> inherits all attributes from L<Mojolicious::Command> and
implements the following new ones.
=head2 description
my $description = $dockerfile->description;
$dockerfile = $dockerfile->description('Foo');
Short description of this command, used for the command list.
=head2 usage
my $usage = $dockerfile->usage;
$dockerfile = $dockerfile->usage('Foo');
Usage information for this command, used for the help screen.
=head1 METHODS
L<Mojolicious::Command::Author::generate::dockerfile> inherits all methods from L<Mojolicious::Command> and implements
the following new ones.
=head2 run
$dockerfile->run(@ARGV);
Run this command.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
=cut
__DATA__
@@ dockerfile
FROM perl
WORKDIR /opt/<%= $name %>
COPY . .
RUN cpanm --installdeps -n .
EXPOSE 3000
CMD <%= $cmd %>

View File

@@ -0,0 +1,99 @@
package Mojolicious::Command::Author::generate::lite_app;
use Mojo::Base 'Mojolicious::Command';
has description => 'Generate Mojolicious::Lite application';
has usage => sub { shift->extract_usage };
sub run {
my ($self, $name) = (shift, shift || 'myapp.pl');
$self->render_to_rel_file('liteapp', $name);
$self->chmod_rel_file($name, 0744);
}
1;
=encoding utf8
=head1 NAME
Mojolicious::Command::Author::generate::lite_app - Lite app generator command
=head1 SYNOPSIS
Usage: APPLICATION generate lite-app [OPTIONS] [NAME]
mojo generate lite-app
mojo generate lite-app foo.pl
Options:
-h, --help Show this summary of available options
=head1 DESCRIPTION
L<Mojolicious::Command::Author::generate::lite_app> generate fully functional L<Mojolicious::Lite> applications.
This is a core command, that means it is always enabled and its code a good example for learning to build new commands,
you're welcome to fork it.
See L<Mojolicious::Commands/"COMMANDS"> for a list of commands that are available by default.
=head1 ATTRIBUTES
L<Mojolicious::Command::Author::generate::lite_app> inherits all attributes from L<Mojolicious::Command> and implements
the following new ones.
=head2 description
my $description = $app->description;
$app = $app->description('Foo');
Short description of this command, used for the command list.
=head2 usage
my $usage = $app->usage;
$app = $app->usage('Foo');
Usage information for this command, used for the help screen.
=head1 METHODS
L<Mojolicious::Command::Author::generate::lite_app> inherits all methods from L<Mojolicious::Command> and implements
the following new ones.
=head2 run
$app->run(@ARGV);
Run this command.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
=cut
__DATA__
@@ liteapp
#!/usr/bin/env perl
use Mojolicious::Lite -signatures;
get '/' => sub ($c) {
$c->render(template => 'index');
};
app->start;
<% %>__DATA__
<% %>@@ index.html.ep
%% layout 'default';
%% title 'Welcome';
<h1>Welcome to the Mojolicious real-time web framework!</h1>
<% %>@@ layouts/default.html.ep
<!DOCTYPE html>
<html>
<head><title><%%= title %></title></head>
<body><%%= content %></body>
</html>

View File

@@ -0,0 +1,86 @@
package Mojolicious::Command::Author::generate::makefile;
use Mojo::Base 'Mojolicious::Command';
has description => 'Generate "Makefile.PL"';
has usage => sub { shift->extract_usage };
sub run { shift->render_to_rel_file('makefile', 'Makefile.PL') }
1;
=encoding utf8
=head1 NAME
Mojolicious::Command::Author::generate::makefile - Makefile generator command
=head1 SYNOPSIS
Usage: APPLICATION generate makefile [OPTIONS]
./myapp.pl generate makefile
mojo generate makefile
Options:
-h, --help Show this summary of available options
=head1 DESCRIPTION
L<Mojolicious::Command::Author::generate::makefile> generates C<Makefile.PL> files for applications.
This is a core command, that means it is always enabled and its code a good example for learning to build new commands,
you're welcome to fork it.
See L<Mojolicious::Commands/"COMMANDS"> for a list of commands that are available by default.
=head1 ATTRIBUTES
L<Mojolicious::Command::Author::generate::makefile> inherits all attributes from L<Mojolicious::Command> and implements
the following new ones.
=head2 description
my $description = $makefile->description;
$makefile = $makefile->description('Foo');
Short description of this command, used for the command list.
=head2 usage
my $usage = $makefile->usage;
$makefile = $makefile->usage('Foo');
Usage information for this command, used for the help screen.
=head1 METHODS
L<Mojolicious::Command::Author::generate::makefile> inherits all methods from L<Mojolicious::Command> and implements
the following new ones.
=head2 run
$makefile->run(@ARGV);
Run this command.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
=cut
__DATA__
@@ makefile
use strict;
use warnings;
use ExtUtils::MakeMaker;
WriteMakefile(
VERSION => '0.01',
PREREQ_PM => {
'Mojolicious' => '<%= $Mojolicious::VERSION %>'
},
test => {TESTS => 't/*.t'}
);

View File

@@ -0,0 +1,174 @@
package Mojolicious::Command::Author::generate::plugin;
use Mojo::Base 'Mojolicious::Command';
use Mojo::Util qw(camelize class_to_path getopt);
has description => 'Generate Mojolicious plugin directory structure';
has usage => sub { shift->extract_usage };
sub run {
my ($self, @args) = @_;
die $self->usage unless getopt \@args, 'f|full' => \(my $full);
# Class
my $name = $args[0] // 'MyPlugin';
my $class = $full ? $name : "Mojolicious::Plugin::$name";
my $dir = join '-', split(/::/, $class);
my $app = class_to_path $class;
$self->render_to_rel_file('class', "$dir/lib/$app", {class => $class, name => $name});
# Test
$self->render_to_rel_file('test', "$dir/t/basic.t", {name => $name});
# Makefile
$self->render_to_rel_file('makefile', "$dir/Makefile.PL", {class => $class, path => $app});
}
1;
=encoding utf8
=head1 NAME
Mojolicious::Command::Author::generate::plugin - Plugin generator command
=head1 SYNOPSIS
Usage: APPLICATION generate plugin [OPTIONS] [NAME]
mojo generate plugin
mojo generate plugin TestPlugin
mojo generate plugin -f MyApp::Plugin::AwesomeFeature
Options:
-f, --full Do not prepend "Mojolicious::Plugin::" to the plugin name
-h, --help Show this summary of available options
=head1 DESCRIPTION
L<Mojolicious::Command::Author::generate::plugin> generates directory structures for fully functional L<Mojolicious>
plugins.
This is a core command, that means it is always enabled and its code a good example for learning to build new commands,
you're welcome to fork it.
See L<Mojolicious::Commands/"COMMANDS"> for a list of commands that are available by default.
=head1 ATTRIBUTES
L<Mojolicious::Command::Author::generate::plugin> inherits all attributes from L<Mojolicious::Command> and implements
the following new ones.
=head2 description
my $description = $plugin->description;
$plugin = $plugin->description('Foo');
Short description of this command, used for the command list.
=head2 usage
my $usage = $plugin->usage;
$plugin = $plugin->usage('Foo');
Usage information for this command, used for the help screen.
=head1 METHODS
L<Mojolicious::Command::Author::generate::plugin> inherits all methods from L<Mojolicious::Command> and implements the
following new ones.
=head2 run
$plugin->run(@ARGV);
Run this command.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
=cut
__DATA__
@@ class
package <%= $class %>;
use Mojo::Base 'Mojolicious::Plugin';
our $VERSION = '0.01';
sub register {
my ($self, $app) = @_;
}
1;
<% %>=encoding utf8
<% %>=head1 NAME
<%= $class %> - Mojolicious Plugin
<% %>=head1 SYNOPSIS
# Mojolicious
$self->plugin('<%= $name %>');
# Mojolicious::Lite
plugin '<%= $name %>';
<% %>=head1 DESCRIPTION
L<<%= $class %>> is a L<Mojolicious> plugin.
<% %>=head1 METHODS
L<<%= $class %>> inherits all methods from
L<Mojolicious::Plugin> and implements the following new ones.
<% %>=head2 register
$plugin->register(Mojolicious->new);
Register plugin in L<Mojolicious> application.
<% %>=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
<% %>=cut
@@ test
use Mojo::Base -strict;
use Test::More;
use Mojolicious::Lite;
use Test::Mojo;
plugin '<%= $name %>';
get '/' => sub {
my $c = shift;
$c->render(text => 'Hello Mojo!');
};
my $t = Test::Mojo->new;
$t->get_ok('/')->status_is(200)->content_is('Hello Mojo!');
done_testing();
@@ makefile
use strict;
use warnings;
use ExtUtils::MakeMaker;
WriteMakefile(
NAME => '<%= $class %>',
VERSION_FROM => 'lib/<%= $path %>',
AUTHOR => 'A Good Programmer <nospam@cpan.org>',
PREREQ_PM => {'Mojolicious' => '<%= $Mojolicious::VERSION %>'},
test => {TESTS => 't/*.t'}
);

View File

@@ -0,0 +1,96 @@
package Mojolicious::Command::Author::inflate;
use Mojo::Base 'Mojolicious::Command';
use Mojo::Loader qw(data_section file_is_binary);
use Mojo::Util qw(encode);
has description => 'Inflate embedded files to real files';
has usage => sub { shift->extract_usage };
sub run {
my $self = shift;
# Find all embedded files
my %all;
my $app = $self->app;
for my $class (@{$app->renderer->classes}, @{$app->static->classes}) {
for my $name (keys %{data_section $class}) {
my $data = data_section $class, $name;
$data = encode 'UTF-8', $data unless file_is_binary $class, $name;
$all{$name} = $data;
}
}
# Turn them into real files
for my $name (grep {/\.\w+$/} keys %all) {
my $prefix = $name =~ /\.\w+\.\w+$/ ? 'templates' : 'public';
$self->write_file($self->rel_file("$prefix/$name"), $all{$name});
}
}
1;
=encoding utf8
=head1 NAME
Mojolicious::Command::Author::inflate - Inflate command
=head1 SYNOPSIS
Usage: APPLICATION inflate [OPTIONS]
./myapp.pl inflate
Options:
-h, --help Show this summary of available options
--home <path> Path to home directory of your application, defaults to
the value of MOJO_HOME or auto-detection
-m, --mode <name> Operating mode for your application, defaults to the
value of MOJO_MODE/PLACK_ENV or "development"
=head1 DESCRIPTION
L<Mojolicious::Command::Author::inflate> turns templates and static files embedded in the C<DATA> sections of your
application into real files.
This is a core command, that means it is always enabled and its code a good example for learning to build new commands,
you're welcome to fork it.
See L<Mojolicious::Commands/"COMMANDS"> for a list of commands that are available by default.
=head1 ATTRIBUTES
L<Mojolicious::Command::Author::inflate> inherits all attributes from L<Mojolicious::Command> and implements the
following new ones.
=head2 description
my $description = $inflate->description;
$inflate = $inflate->description('Foo');
Short description of this command, used for the command list.
=head2 usage
my $usage = $inflate->usage;
$inflate = $inflate->usage('Foo');
Usage information for this command, used for the help screen.
=head1 METHODS
L<Mojolicious::Command::Author::inflate> inherits all methods from L<Mojolicious::Command> and implements the following
new ones.
=head2 run
$inflate->run(@ARGV);
Run this command.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
=cut

View File

@@ -0,0 +1,80 @@
package Mojolicious::Command::cgi;
use Mojo::Base 'Mojolicious::Command';
use Mojo::Server::CGI;
use Mojo::Util qw(getopt);
has description => 'Start application with CGI';
has usage => sub { shift->extract_usage };
sub run {
my ($self, @args) = @_;
die $self->usage unless getopt \@args, nph => \(my $nph = 0);
Mojo::Server::CGI->new(app => $self->app, nph => $nph)->run;
}
1;
=encoding utf8
=head1 NAME
Mojolicious::Command::cgi - CGI command
=head1 SYNOPSIS
Usage: APPLICATION cgi [OPTIONS]
./myapp.pl cgi
Options:
-h, --help Show this summary of available options
--home <path> Path to home directory of your application, defaults to
the value of MOJO_HOME or auto-detection
-m, --mode <name> Operating mode for your application, defaults to the
value of MOJO_MODE/PLACK_ENV or "development"
--nph Enable non-parsed-header mode
=head1 DESCRIPTION
L<Mojolicious::Command::cgi> starts applications with the L<Mojo::Server::CGI> backend.
This is a core command, that means it is always enabled and its code a good example for learning to build new commands,
you're welcome to fork it.
See L<Mojolicious::Commands/"COMMANDS"> for a list of commands that are available by default.
=head1 ATTRIBUTES
L<Mojolicious::Command::cgi> inherits all attributes from L<Mojolicious::Command> and implements the following new
ones.
=head2 description
my $description = $cgi->description;
$cgi = $cgi->description('Foo');
Short description of this command, used for the command list.
=head2 usage
my $usage = $cgi->usage;
$cgi = $cgi->usage('Foo');
Usage information for this command, used for the help screen.
=head1 METHODS
L<Mojolicious::Command::cgi> inherits all methods from L<Mojolicious::Command> and implements the following new ones.
=head2 run
$cgi->run(@ARGV);
Run this command.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
=cut

View File

@@ -0,0 +1,114 @@
package Mojolicious::Command::daemon;
use Mojo::Base 'Mojolicious::Command';
use Mojo::Server::Daemon;
use Mojo::Util qw(getopt);
has description => 'Start application with HTTP and WebSocket server';
has usage => sub { shift->extract_usage };
sub run {
my ($self, @args) = @_;
my $daemon = Mojo::Server::Daemon->new(app => $self->app);
die $self->usage
unless getopt \@args,
'b|backlog=i' => sub { $daemon->backlog($_[1]) },
'c|clients=i' => sub { $daemon->max_clients($_[1]) },
'i|inactivity-timeout=i' => sub { $daemon->inactivity_timeout($_[1]) },
'k|keep-alive-timeout=i' => sub { $daemon->keep_alive_timeout($_[1]) },
'l|listen=s' => \my @listen,
'p|proxy' => sub { $daemon->reverse_proxy(1) },
'r|requests=i' => sub { $daemon->max_requests($_[1]) };
$daemon->listen(\@listen) if @listen;
$daemon->run;
}
1;
=encoding utf8
=head1 NAME
Mojolicious::Command::daemon - Daemon command
=head1 SYNOPSIS
Usage: APPLICATION daemon [OPTIONS]
./myapp.pl daemon
./myapp.pl daemon -m production -l http://*:8080
./myapp.pl daemon -l http://127.0.0.1:8080 -l https://[::]:8081
./myapp.pl daemon -l 'https://*:443?cert=./server.crt&key=./server.key'
./myapp.pl daemon -l http+unix://%2Ftmp%2Fmyapp.sock
Options:
-b, --backlog <size> Listen backlog size, defaults to
SOMAXCONN
-c, --clients <number> Maximum number of concurrent
connections, defaults to 1000
-h, --help Show this summary of available options
--home <path> Path to home directory of your
application, defaults to the value of
MOJO_HOME or auto-detection
-i, --inactivity-timeout <seconds> Inactivity timeout, defaults to the
value of MOJO_INACTIVITY_TIMEOUT or 30
-k, --keep-alive-timeout <seconds> Keep-alive timeout, defaults to the
value of MOJO_KEEP_ALIVE_TIMEOUT or 5
-l, --listen <location> One or more locations you want to
listen on, defaults to the value of
MOJO_LISTEN or "http://*:3000"
-m, --mode <name> Operating mode for your application,
defaults to the value of
MOJO_MODE/PLACK_ENV or "development"
-p, --proxy Activate reverse proxy support,
defaults to the value of
MOJO_REVERSE_PROXY
-r, --requests <number> Maximum number of requests per
keep-alive connection, defaults to 100
=head1 DESCRIPTION
L<Mojolicious::Command::daemon> starts applications with the L<Mojo::Server::Daemon> backend.
This is a core command, that means it is always enabled and its code a good example for learning to build new commands,
you're welcome to fork it.
See L<Mojolicious::Commands/"COMMANDS"> for a list of commands that are available by default.
=head1 ATTRIBUTES
L<Mojolicious::Command::daemon> inherits all attributes from L<Mojolicious::Command> and implements the following new
ones.
=head2 description
my $description = $daemon->description;
$daemon = $daemon->description('Foo');
Short description of this command, used for the command list.
=head2 usage
my $usage = $daemon->usage;
$daemon = $daemon->usage('Foo');
Usage information for this command, used for the help screen.
=head1 METHODS
L<Mojolicious::Command::daemon> inherits all methods from L<Mojolicious::Command> and implements the following new
ones.
=head2 run
$daemon->run(@ARGV);
Run this command.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
=cut

View File

@@ -0,0 +1,99 @@
package Mojolicious::Command::eval;
use Mojo::Base 'Mojolicious::Command';
use Mojo::Promise;
use Mojo::Util qw(getopt);
has description => 'Run code against application';
has usage => sub { shift->extract_usage };
sub run {
my ($self, @args) = @_;
die $self->usage unless getopt \@args, 'v|verbose' => \my $v1, 'V' => \my $v2;
my $code = shift @args || '';
# Run code against application
my $app = $self->app;
my $result = eval "package main; no warnings 'redefine'; sub app; local *app = sub { \$app }; $code";
die $@ if $@;
# Handle promises
my $err;
Mojo::Promise->resolve($result)->then(sub { $result = shift }, sub { $err = shift })->wait;
die $err if $err;
return $result unless defined $result && ($v1 || $v2);
$v2 ? print($app->dumper($result)) : say $result;
}
1;
=encoding utf8
=head1 NAME
Mojolicious::Command::eval - Eval command
=head1 SYNOPSIS
Usage: APPLICATION eval [OPTIONS] CODE
./myapp.pl eval 'say app->ua->get("/")->result->body'
./myapp.pl eval 'say for sort keys %{app->renderer->helpers}'
./myapp.pl eval -v 'app->home'
./myapp.pl eval -V 'app->renderer->paths'
Options:
-h, --help Show this summary of available options
--home <path> Path to home directory of your application, defaults to
the value of MOJO_HOME or auto-detection
-m, --mode <name> Operating mode for your application, defaults to the
value of MOJO_MODE/PLACK_ENV or "development"
-v, --verbose Print return value to STDOUT
-V Print returned data structure to STDOUT
=head1 DESCRIPTION
L<Mojolicious::Command::eval> runs code against applications. If the result is a promise (then-able), it will wait
until the promise is fulfilled or rejected and the result is returned.
This is a core command, that means it is always enabled and its code a good example for learning to build new commands,
you're welcome to fork it.
See L<Mojolicious::Commands/"COMMANDS"> for a list of commands that are available by default.
=head1 ATTRIBUTES
L<Mojolicious::Command::eval> inherits all attributes from L<Mojolicious::Command> and implements the following new
ones.
=head2 description
my $description = $eval->description;
$eval = $eval->description('Foo');
Short description of this command, used for the command list.
=head2 usage
my $usage = $eval->usage;
$eval = $eval->usage('Foo');
Usage information for this command, used for the help screen.
=head1 METHODS
L<Mojolicious::Command::eval> inherits all methods from L<Mojolicious::Command> and implements the following new ones.
=head2 run
$eval->run(@ARGV);
Run this command.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
=cut

View File

@@ -0,0 +1,231 @@
package Mojolicious::Command::get;
use Mojo::Base 'Mojolicious::Command';
use Mojo::Collection qw(c);
use Mojo::DOM;
use Mojo::IOLoop;
use Mojo::JSON qw(to_json j);
use Mojo::JSON::Pointer;
use Mojo::URL;
use Mojo::UserAgent;
use Mojo::Util qw(decode encode getopt);
use Scalar::Util qw(weaken);
has description => 'Perform HTTP request';
has usage => sub { shift->extract_usage };
sub run {
my ($self, @args) = @_;
# Data from STDIN
vec(my $r = '', fileno(STDIN), 1) = 1;
my $in = !-t STDIN && select($r, undef, undef, 0) ? join '', <STDIN> : undef;
my $ua = Mojo::UserAgent->new(ioloop => Mojo::IOLoop->singleton);
my %form;
die $self->usage
unless getopt \@args,
'C|charset=s' => \my $charset,
'c|content=s' => \$in,
'f|form=s' => sub { _form(\%form) if $_[1] =~ /^(.+)=(\@?)(.+)$/ },
'H|header=s' => \my @headers,
'i|inactivity-timeout=i' => sub { $ua->inactivity_timeout($_[1]) },
'k|insecure' => sub { $ua->insecure(1) },
'M|method=s' => \(my $method = 'GET'),
'o|connect-timeout=i' => sub { $ua->connect_timeout($_[1]) },
'r|redirect' => \my $redirect,
'S|response-size=i' => sub { $ua->max_response_size($_[1]) },
'u|user=s' => \my $user,
'v|verbose' => \my $verbose;
@args = map { decode 'UTF-8', $_ } @args;
die $self->usage unless my $url = shift @args;
my $selector = shift @args;
# Parse header pairs
my %headers = map { /^\s*([^:]+)\s*:\s*(.*+)$/ ? ($1, $2) : () } @headers;
# Detect proxy for absolute URLs
$url !~ m!^/! ? $ua->proxy->detect : $ua->server->app($self->app);
$url = Mojo::URL->new($url)->userinfo($user) if $user;
$ua->max_redirects(10) if $redirect;
my $buffer = '';
$ua->on(
start => sub {
my ($ua, $tx) = @_;
# Verbose
weaken $tx;
$tx->res->content->on(body => sub { warn _header($tx->req), _header($tx->res) }) if $verbose;
# Stream content (ignore redirects)
$tx->res->content->unsubscribe('read')->on(
read => sub {
return if $redirect && $tx->res->is_redirect;
defined $selector ? ($buffer .= pop) : print pop;
}
);
}
);
# Switch to verbose for HEAD requests
$verbose = 1 if $method eq 'HEAD';
STDOUT->autoflush(1);
my @content = %form ? (form => \%form) : defined $in ? ($in) : ();
my $tx = $ua->start($ua->build_tx($method, $url, \%headers, @content));
my $res = $tx->result;
# JSON Pointer
return undef unless defined $selector;
return _json($buffer, $selector) if !length $selector || $selector =~ m!^/!;
# Selector
$charset //= $res->content->charset || $res->default_charset;
_select($buffer, $selector, $charset, @args);
}
sub _form { push @{$_[0]{$1}}, $2 ? {file => $3} : $3 }
sub _header { $_[0]->build_start_line, $_[0]->headers->to_string, "\n\n" }
sub _json {
return unless my $data = j(shift);
return unless defined($data = Mojo::JSON::Pointer->new($data)->get(shift));
_say(ref $data eq 'HASH' || ref $data eq 'ARRAY' ? to_json($data) : $data);
}
sub _say { length && say encode('UTF-8', $_) for @_ }
sub _select {
my ($buffer, $selector, $charset, @args) = @_;
# Keep a strong reference to the root
$buffer = decode($charset, $buffer) // $buffer if $charset;
my $dom = Mojo::DOM->new($buffer);
my $results = $dom->find($selector);
while (defined(my $command = shift @args)) {
# Number
($results = c($results->[$command])) and next if $command =~ /^\d+$/;
# Text
return _say($results->map('text')->each) if $command eq 'text';
# All text
return _say($results->map('all_text')->each) if $command eq 'all';
# Attribute
return _say($results->map(attr => $args[0] // '')->each) if $command eq 'attr';
# Unknown
die qq{Unknown command "$command".\n};
}
_say($results->each);
}
1;
=encoding utf8
=head1 NAME
Mojolicious::Command::get - Get command
=head1 SYNOPSIS
Usage: APPLICATION get [OPTIONS] URL [SELECTOR|JSON-POINTER] [COMMANDS]
./myapp.pl get /
./myapp.pl get -H 'Accept: text/html' /hello.html 'head > title' text
./myapp.pl get //sri:secr3t@/secrets.json /1/content
mojo get mojolicious.org
mojo get -v -r -o 25 -i 50 google.com
mojo get -v -H 'Host: mojolicious.org' -H 'Accept: */*' mojolicious.org
mojo get -u 'sri:s3cret' https://mojolicious.org
mojo get mojolicious.org > example.html
mojo get -M PUT mojolicious.org < example.html
mojo get -f 'q=Mojolicious' -f 'size=5' https://metacpan.org/search
mojo get -M POST -f 'upload=@example.html' mojolicious.org
mojo get mojolicious.org 'head > title' text
mojo get mojolicious.org .footer all
mojo get mojolicious.org a attr href
mojo get mojolicious.org '*' attr id
mojo get mojolicious.org 'h1, h2, h3' 3 text
mojo get https://fastapi.metacpan.org/v1/author/SRI /name
mojo get -H 'Host: example.com' http+unix://%2Ftmp%2Fmyapp.sock/index.html
Options:
-C, --charset <charset> Charset of HTML/XML content, defaults
to auto-detection
-c, --content <content> Content to send with request
-f, --form <name=value> One or more form values and file
uploads
-H, --header <name:value> One or more additional HTTP headers
-h, --help Show this summary of available options
--home <path> Path to home directory of your
application, defaults to the value of
MOJO_HOME or auto-detection
-i, --inactivity-timeout <seconds> Inactivity timeout, defaults to the
value of MOJO_INACTIVITY_TIMEOUT or 40
-k, --insecure Do not require a valid TLS certificate
to access HTTPS sites
-M, --method <method> HTTP method to use, defaults to "GET"
-m, --mode <name> Operating mode for your application,
defaults to the value of
MOJO_MODE/PLACK_ENV or "development"
-o, --connect-timeout <seconds> Connect timeout, defaults to the value
of MOJO_CONNECT_TIMEOUT or 10
-r, --redirect Follow up to 10 redirects
-S, --response-size <size> Maximum response size in bytes,
defaults to 2147483648 (2GiB)
-u, --user <userinfo> Alternate mechanism for specifying
colon-separated username and password
-v, --verbose Print request and response headers to
STDERR
=head1 DESCRIPTION
L<Mojolicious::Command::get> performs requests to remote hosts or local applications.
This is a core command, that means it is always enabled and its code a good example for learning to build new commands,
you're welcome to fork it.
See L<Mojolicious::Commands/"COMMANDS"> for a list of commands that are available by default.
=head1 ATTRIBUTES
L<Mojolicious::Command::get> inherits all attributes from L<Mojolicious::Command> and implements the following new
ones.
=head2 description
my $description = $get->description;
$get = $get->description('Foo');
Short description of this command, used for the command list.
=head2 usage
my $usage = $get->usage;
$get = $get->usage('Foo');
Usage information for this command, used for the help screen.
=head1 METHODS
L<Mojolicious::Command::get> inherits all methods from L<Mojolicious::Command> and implements the following new ones.
=head2 run
$get->run(@ARGV);
Run this command.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
=cut

View File

@@ -0,0 +1,131 @@
package Mojolicious::Command::prefork;
use Mojo::Base 'Mojolicious::Command';
use Mojo::Server::Prefork;
use Mojo::Util qw(getopt);
has description => 'Start application with pre-forking HTTP and WebSocket server';
has usage => sub { shift->extract_usage };
sub run {
my ($self, @args) = @_;
my $prefork = Mojo::Server::Prefork->new(app => $self->app);
die $self->usage
unless getopt \@args,
'a|accepts=i' => sub { $prefork->accepts($_[1]) },
'b|backlog=i' => sub { $prefork->backlog($_[1]) },
'c|clients=i' => sub { $prefork->max_clients($_[1]) },
'G|graceful-timeout=i' => sub { $prefork->graceful_timeout($_[1]) },
'I|heartbeat-interval=i' => sub { $prefork->heartbeat_interval($_[1]) },
'H|heartbeat-timeout=i' => sub { $prefork->heartbeat_timeout($_[1]) },
'i|inactivity-timeout=i' => sub { $prefork->inactivity_timeout($_[1]) },
'k|keep-alive-timeout=i' => sub { $prefork->keep_alive_timeout($_[1]) },
'l|listen=s' => \my @listen,
'P|pid-file=s' => sub { $prefork->pid_file($_[1]) },
'p|proxy' => sub { $prefork->reverse_proxy(1) },
'r|requests=i' => sub { $prefork->max_requests($_[1]) },
's|spare=i' => sub { $prefork->spare($_[1]) },
'w|workers=i' => sub { $prefork->workers($_[1]) };
$prefork->listen(\@listen) if @listen;
$prefork->run;
}
1;
=encoding utf8
=head1 NAME
Mojolicious::Command::prefork - Pre-fork command
=head1 SYNOPSIS
Usage: APPLICATION prefork [OPTIONS]
./myapp.pl prefork
./myapp.pl prefork -m production -l http://*:8080
./myapp.pl prefork -l http://127.0.0.1:8080 -l https://[::]:8081
./myapp.pl prefork -l 'https://*:443?cert=./server.crt&key=./server.key'
./myapp.pl prefork -l http+unix://%2Ftmp%2Fmyapp.sock -w 12
Options:
-a, --accepts <number> Number of connections for workers to
accept, defaults to 10000
-b, --backlog <size> Listen backlog size, defaults to
SOMAXCONN
-c, --clients <number> Maximum number of concurrent
connections, defaults to 1000
-G, --graceful-timeout <seconds> Graceful timeout, defaults to 120.
-I, --heartbeat-interval <seconds> Heartbeat interval, defaults to 5
-H, --heartbeat-timeout <seconds> Heartbeat timeout, defaults to 50
-h, --help Show this summary of available options
--home <path> Path to home directory of your
application, defaults to the value of
MOJO_HOME or auto-detection
-i, --inactivity-timeout <seconds> Inactivity timeout, defaults to the
value of MOJO_INACTIVITY_TIMEOUT or 30
-k, --keep-alive-timeout <seconds> Keep-alive timeout, defaults to the
value of MOJO_KEEP_ALIVE_TIMEOUT or 5
-l, --listen <location> One or more locations you want to
listen on, defaults to the value of
MOJO_LISTEN or "http://*:3000"
-m, --mode <name> Operating mode for your application,
defaults to the value of
MOJO_MODE/PLACK_ENV or "development"
-P, --pid-file <path> Path to process id file, defaults to
"prefork.pid" in a temporary directory
-p, --proxy Activate reverse proxy support,
defaults to the value of
MOJO_REVERSE_PROXY
-r, --requests <number> Maximum number of requests per
keep-alive connection, defaults to 100
-s, --spare <number> Temporarily spawn up to this number of
additional workers, defaults to 2
-w, --workers <number> Number of workers, defaults to 4
=head1 DESCRIPTION
L<Mojolicious::Command::prefork> starts applications with the L<Mojo::Server::Prefork> backend.
This is a core command, that means it is always enabled and its code a good example for learning to build new commands,
you're welcome to fork it.
See L<Mojolicious::Commands/"COMMANDS"> for a list of commands that are available by default.
=head1 ATTRIBUTES
L<Mojolicious::Command::prefork> inherits all attributes from L<Mojolicious::Command> and implements the following new
ones.
=head2 description
my $description = $prefork->description;
$prefork = $prefork->description('Foo');
Short description of this command, used for the command list.
=head2 usage
my $usage = $prefork->usage;
$prefork = $prefork->usage('Foo');
Usage information for this command, used for the help screen.
=head1 METHODS
L<Mojolicious::Command::prefork> inherits all methods from L<Mojolicious::Command> and implements the following new
ones.
=head2 run
$prefork->run(@ARGV);
Run this command.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
=cut

View File

@@ -0,0 +1,74 @@
package Mojolicious::Command::psgi;
use Mojo::Base 'Mojolicious::Command';
use Mojo::Server::PSGI;
has description => 'Start application with PSGI';
has usage => sub { shift->extract_usage };
sub run { Mojo::Server::PSGI->new(app => shift->app)->to_psgi_app }
1;
=encoding utf8
=head1 NAME
Mojolicious::Command::psgi - PSGI command
=head1 SYNOPSIS
Usage: APPLICATION psgi [OPTIONS]
./myapp.pl psgi
Options:
-h, --help Show this summary of available options
--home <path> Path to home directory of your application, defaults to
the value of MOJO_HOME or auto-detection
-m, --mode <name> Operating mode for your application, defaults to the
value of MOJO_MODE/PLACK_ENV or "development"
=head1 DESCRIPTION
L<Mojolicious::Command::psgi> starts applications with the L<Mojo::Server::PSGI> backend.
This is a core command, that means it is always enabled and its code a good example for learning to build new commands,
you're welcome to fork it.
See L<Mojolicious::Commands/"COMMANDS"> for a list of commands that are available by default.
=head1 ATTRIBUTES
L<Mojolicious::Command::psgi> inherits all attributes from L<Mojolicious::Command> and implements the following new
ones.
=head2 description
my $description = $psgi->description;
$psgi = $psgi->description('Foo');
Short description of this command, used for the command list.
=head2 usage
my $usage = $psgi->usage;
$psgi = $psgi->usage('Foo');
Usage information for this command, used for the help screen.
=head1 METHODS
L<Mojolicious::Command::psgi> inherits all methods from L<Mojolicious::Command> and implements the following new ones.
=head2 run
my $app = $psgi->run;
Run this command.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
=cut

View File

@@ -0,0 +1,121 @@
package Mojolicious::Command::routes;
use Mojo::Base 'Mojolicious::Command';
use re qw(regexp_pattern);
use Mojo::Util qw(encode getopt tablify);
has description => 'Show available routes';
has usage => sub { shift->extract_usage };
sub run {
my ($self, @args) = @_;
die $self->usage unless getopt \@args, 'v|verbose' => \my $verbose;
my $rows = [];
_walk($_, 0, $rows, $verbose) for @{$self->app->routes->children};
print encode('UTF-8', tablify($rows));
}
sub _walk {
my ($route, $depth, $rows, $verbose) = @_;
# Pattern
my $prefix = '';
if (my $i = $depth * 2) { $prefix .= ' ' x $i . '+' }
push @$rows, my $row = [$prefix . ($route->pattern->unparsed || '/')];
# Flags
my @flags;
push @flags, @{$route->requires // []} ? 'C' : '.';
push @flags, (my $partial = $route->partial) ? 'P' : '.';
push @flags, $route->inline ? 'U' : '.';
push @flags, $route->is_websocket ? 'W' : '.';
push @$row, join('', @flags) if $verbose;
# Methods
my $methods = $route->methods;
push @$row, !$methods ? '*' : uc join ',', @$methods;
# Name
my $name = $route->name;
push @$row, $route->has_custom_name ? qq{"$name"} : $name;
# Regex (verbose)
my $pattern = $route->pattern;
$pattern->match('/', $route->is_endpoint && !$partial);
push @$row, (regexp_pattern $pattern->regex)[0] if $verbose;
$depth++;
_walk($_, $depth, $rows, $verbose) for @{$route->children};
$depth--;
}
1;
=encoding utf8
=head1 NAME
Mojolicious::Command::routes - Routes command
=head1 SYNOPSIS
Usage: APPLICATION routes [OPTIONS]
./myapp.pl routes
./myapp.pl routes -v
Options:
-h, --help Show this summary of available options
--home <path> Path to home directory of your application, defaults to
the value of MOJO_HOME or auto-detection
-m, --mode <name> Operating mode for your application, defaults to the
value of MOJO_MODE/PLACK_ENV or "development"
-v, --verbose Print additional details about routes, flags indicate
C=Conditions, P=Partial, U=Under and W=WebSocket
=head1 DESCRIPTION
L<Mojolicious::Command::routes> lists all your application routes.
This is a core command, that means it is always enabled and its code a good example for learning to build new commands,
you're welcome to fork it.
See L<Mojolicious::Commands/"COMMANDS"> for a list of commands that are available by default.
=head1 ATTRIBUTES
L<Mojolicious::Command::routes> inherits all attributes from L<Mojolicious::Command> and implements the following new
ones.
=head2 description
my $description = $routes->description;
$routes = $routes->description('Foo');
Short description of this command, used for the command list.
=head2 usage
my $usage = $routes->usage;
$routes = $routes->usage('Foo');
Usage information for this command, used for the help screen.
=head1 METHODS
L<Mojolicious::Command::routes> inherits all methods from L<Mojolicious::Command> and implements the following new
ones.
=head2 run
$routes->run(@ARGV);
Run this command.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
=cut

View File

@@ -0,0 +1,111 @@
package Mojolicious::Command::version;
use Mojo::Base 'Mojolicious::Command';
use Mojo::IOLoop::Client;
use Mojo::IOLoop::TLS;
use Mojo::JSON;
use Mojolicious;
has description => 'Show versions of available modules';
has usage => sub { shift->extract_usage };
sub run {
my $self = shift;
my $json = Mojo::JSON->JSON_XS ? $Cpanel::JSON::XS::VERSION : 'n/a';
my $ev = eval { require Mojo::Reactor::EV; 1 } ? $EV::VERSION : 'n/a';
my $socks = Mojo::IOLoop::Client->can_socks ? $IO::Socket::Socks::VERSION : 'n/a';
my $tls = Mojo::IOLoop::TLS->can_tls ? $IO::Socket::SSL::VERSION : 'n/a';
my $nnr = Mojo::IOLoop::Client->can_nnr ? $Net::DNS::Native::VERSION : 'n/a';
my $roles = Mojo::Base->ROLES ? $Role::Tiny::VERSION : 'n/a';
my $async = Mojo::Base->ASYNC ? $Future::AsyncAwait::VERSION : 'n/a';
print <<EOF;
CORE
Perl ($^V, $^O)
Mojolicious ($Mojolicious::VERSION, $Mojolicious::CODENAME)
OPTIONAL
Cpanel::JSON::XS 4.09+ ($json)
EV 4.32+ ($ev)
IO::Socket::Socks 0.64+ ($socks)
IO::Socket::SSL 2.009+ ($tls)
Net::DNS::Native 0.15+ ($nnr)
Role::Tiny 2.000001+ ($roles)
Future::AsyncAwait 0.36+ ($async)
EOF
# Check latest version on CPAN
my $latest = eval {
$self->app->ua->max_redirects(10)->tap(sub { $_->proxy->detect })
->get('fastapi.metacpan.org/v1/release/Mojolicious')->result->json->{version};
} or return;
my $msg = 'This version is up to date, have fun!';
$msg = 'Thanks for testing a development release, you are awesome!' if $latest < $Mojolicious::VERSION;
$msg = "You might want to update your Mojolicious to $latest!" if $latest > $Mojolicious::VERSION;
say $msg;
}
1;
=encoding utf8
=head1 NAME
Mojolicious::Command::version - Version command
=head1 SYNOPSIS
Usage: APPLICATION version [OPTIONS]
mojo version
Options:
-h, --help Show this summary of available options
=head1 DESCRIPTION
L<Mojolicious::Command::version> shows version information for available core and optional modules.
This is a core command, that means it is always enabled and its code a good example for learning to build new commands,
you're welcome to fork it.
See L<Mojolicious::Commands/"COMMANDS"> for a list of commands that are available by default.
=head1 ATTRIBUTES
L<Mojolicious::Command::version> inherits all attributes from L<Mojolicious::Command> and implements the following new
ones.
=head2 description
my $description = $v->description;
$v = $v->description('Foo');
Short description of this command, used for the command list.
=head2 usage
my $usage = $v->usage;
$v = $v->usage('Foo');
Usage information for this command, used for the help screen.
=head1 METHODS
L<Mojolicious::Command::version> inherits all methods from L<Mojolicious::Command> and implements the following new
ones.
=head2 run
$v->run(@ARGV);
Run this command.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
=cut