<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">package Mojolicious::Che;
use Mojo::Base  'Mojolicious';#::Che
use Mojo::Log::Che;
use Mojo::Loader qw(load_class);

sub new {
  my ($class, %args) = @_;
  my $config = delete($args{config}) || 'Config.pm';
  my $app = $class-&gt;SUPER::new(%args);
  
  $app-&gt;plugin(Config =&gt;{file =&gt; $config});
  my $conf = $app-&gt;config;
  
  my $defaults = $conf-&gt;{'mojo_defaults'} || $conf-&gt;{'mojo'}{'defaults'}  || $conf-&gt;{'mojo.defaults'};
  $app-&gt;defaults($defaults)
    if $defaults;
  
  my $secret = $conf-&gt;{'mojo_secret'} || $conf-&gt;{'mojo_secrets'} || $conf-&gt;{'mojo'}{'secret'} || $conf-&gt;{'mojo'}{'secrets'} || $conf-&gt;{'С€РёС„СЂС‹'} || [rand];
  $app-&gt;secrets($secret);
  
  my $mode = $conf-&gt;{'mojo_mode'} || $conf-&gt;{'mojo'}{'mode'} || $conf-&gt;{'mojo.mode'};
  $app-&gt;mode($mode) # Р¤Р°Р№Р» Р»РѕРіР° СѓР¶Рµ РЅРµ РїРµСЂРµРєР»СЋС‡РёС€СЊ
    if $mode;
  #~ $app-&gt;log-&gt;level( $conf-&gt;{'mojo_log_level'} || $conf-&gt;{'mojo'}{'log_level'} || 'debug');
  my $log = $conf-&gt;{'mojo_log'} || $conf-&gt;{'mojo.log'} || $conf-&gt;{'mojo'}{'log'};
  $app-&gt;log(Mojo::Log::Che-&gt;new(%$log))
    if $log;
  #~ warn "Mode: ", $app-&gt;mode, "; log level: ", $app-&gt;log-&gt;level;
  
  my $home = $app-&gt;home;
  my $statics = $conf-&gt;{'mojo_static_paths'} || $conf-&gt;{'mojo.static.paths'} || $conf-&gt;{mojo}{static}{paths} || [];
   #~ push @{$app-&gt;static-&gt;paths}, @{$paths} if $paths;
  push @{$app-&gt;static-&gt;paths},  $home-&gt;rel_file($_) for @$statics;
  
  my $templates_paths = $conf-&gt;{'mojo_renderer_paths'} || $conf-&gt;{'mojo.renderer.paths'} || $conf-&gt;{mojo}{renderer}{paths} || [];
  push @{$app-&gt;renderer-&gt;paths}, $home-&gt;rel_dir($_) for @$templates_paths;
  
  my $renderer_classes = $conf-&gt;{'mojo_renderer_classes'} || $conf-&gt;{'mojo.renderer.classes'} || $conf-&gt;{mojo}{renderer}{classes} || [];
  push @{$app-&gt;renderer-&gt;classes}, $_ for grep ! load_class($_), @$renderer_classes;
  
  
  $app-&gt;СЃРµСЃСЃРёСЏ();
  $app-&gt;С…Р°Р·С‹();
  #~ $app-&gt;Р±Р°Р·С‹();
  #~ $app-&gt;Р·Р°РїСЂРѕСЃС‹();
  $app-&gt;РїР»СѓРіРёРЅС‹();
  $app-&gt;С…СѓРєРё();
  $app-&gt;СЃРїРµР№СЃС‹();
  $app-&gt;РјР°СЂС€СЂСѓС‚С‹();
  
  return $app;

}

sub С…Р°Р·С‹ { # РҐР°Р·С‹ РёР· РєРѕРЅС„РёРіР°
  my $app = shift;
  my $conf = $app-&gt;config;
  my $h = $conf-&gt;{'mojo_has'} || $conf-&gt;{'mojo'}{'has'} || $conf-&gt;{'С…Р°Р·С‹'};
  map {
    $app-&gt;log-&gt;debug("Make the app-&gt;has('$_')");
    has $_ =&gt; $h-&gt;{$_};
  } keys %$h;
}

sub РїР»СѓРіРёРЅС‹ {# РџР»СѓРіРёРЅС‹ РёР· РєРѕРЅС„РёРіР°
  my $app = shift;
  my $conf = $app-&gt;config;
  my $plugins = $conf-&gt;{'mojo_plugins'} || $conf-&gt;{'mojo'}{'plugins'} || $conf-&gt;{'РїР»СѓРіРёРЅС‹'}
    || return;
  map {
    ref $_-&gt;[1] eq 'CODE' ? $app-&gt;plugin($_-&gt;[0] =&gt; $app-&gt;${ \$_-&gt;[1] }) : $app-&gt;plugin(@$_);
    $app-&gt;log-&gt;debug("Enable plugin [$_-&gt;[0]]");
  } @$plugins;
}

has dbh =&gt; sub {
#~ sub Р±Р°Р·С‹ {# РѕР±СЂР°Р±Р°С‚С‹РІР°РµС‚ dbh РєРѕРЅС„РёРіР°
  my $app = shift;
  my $conf = $app-&gt;config;
  my $c_dbh = $conf-&gt;{dbh} || $conf-&gt;{'Р±Р°Р·С‹'};
  return unless $c_dbh &amp;&amp; ref($c_dbh) eq 'HASH' &amp;&amp; keys %$c_dbh;
  #~ has dbh =&gt; sub {{};}
    #~ unless $app-&gt;can('dbh');
  
  my $dbh = {};
  
  my $req_dbi;
  while (my ($db, $opt) = each %$c_dbh) {
    if ($opt-&gt;{dbh}) {# &amp;&amp; ref $opt eq 'DBI::db'
      $dbh-&gt;{$db} ||= $opt-&gt;{dbh};
    } else {
      ++$req_dbi
        and require DBI
        unless $req_dbi;
      $dbh-&gt;{$db} ||= DBI-&gt;connect(@{$opt-&gt;{connect}});
      $app-&gt;log-&gt;debug("РЎРѕРµРґРёРЅРёР»СЃСЏ СЃ Р±Р°Р·РѕР№ $opt-&gt;{connect}[0] app-&gt;dbh-&gt;{'$db'}");
    }
    
    map {
      $dbh-&gt;{$db}-&gt;do($_);
    } @{$opt-&gt;{do}} if $opt-&gt;{do};
    

  }
  return $dbh;
  
};

has sth =&gt; sub {

#~ sub Р·Р°РїСЂРѕСЃС‹ {# РѕР±СЂР°Р±Р°С‚С‹РІР°РµС‚ sth РєРѕРЅС„РёРіР°
  my $app = shift;
  my $dbh = eval { $app-&gt;dbh }
    or return;
  #~ my %arg = @_;
  my $conf = $app-&gt;config;
  
  my $c_dbh = $conf-&gt;{dbh} || $conf-&gt;{'Р±Р°Р·С‹'};
  my $c_sth = $conf-&gt;{sth} || $conf-&gt;{'Р·Р°РїСЂРѕСЃС‹'} || {};
  #~ my $c_pos = $conf-&gt;{pos} || $conf-&gt;{'РїРѕСЃС‹'} || {};
    
  return
    unless ($c_sth &amp;&amp; ref($c_sth) eq 'HASH' &amp;&amp; keys %$c_sth);
    #~ || ($c_pos &amp;&amp; ref($c_pos) eq 'HASH' &amp;&amp; keys %$c_pos);

  my $sth = {};
  
  while (my ($db, $opt) = each %$c_dbh) {
    while (my ($st, $sql) = each %{$opt-&gt;{sth}}) {
      $sth-&gt;{$db}{$st} = $dbh-&gt;{$db}-&gt;prepare($sql);# $app-&gt;sth-&gt;{main}{...}
      $app-&gt;log-&gt;debug("РџРѕРґРіРѕС‚РѕРІРёР»СЃСЏ Р·Р°РїСЂРѕСЃ [app-&gt;sth-&gt;{$db}{$st}]");
    }
  }
  
  while (my ($db, $h) = each %$c_sth) {
    while (my ($st, $sql) = each %$h) {
      $sth-&gt;{$db}{$st} = $dbh-&gt;{$db}-&gt;prepare($sql);# $app-&gt;sth-&gt;{main}{...}
      $app-&gt;log-&gt;debug("РџРѕРґРіРѕС‚РѕРІРёР»СЃСЏ Р·Р°РїСЂРѕСЃ [app-&gt;sth-&gt;{$db}{$st}]");
    }
  }
  
   $sth;
};

  
sub С…СѓРєРё {# РҐСѓРєРё РёР· РєРѕРЅС„РёРіР°
  my $app = shift;
  my $conf = $app-&gt;config;
  my $hooks = $conf-&gt;{'mojo_hooks'} || $conf-&gt;{'mojo'}{'hooks'} || $conf-&gt;{'С…СѓРєРё'}
     || return;
  while (my ($name, $sub) = each %$hooks) {
    if (ref $sub eq 'ARRAY') {
      $app-&gt;hook($name =&gt; $_)
        for @$sub;
    } else {
      $app-&gt;hook($name =&gt; $sub);
    }
    
    $app-&gt;log-&gt;debug(sprintf("Applied hook%s [%s] from config", ref $sub eq 'ARRAY' ? "s (@{[ scalar @$sub]})" : '', $name));
  }

}

sub СЃРµСЃСЃРёСЏ {
  my $app = shift;
  my $conf = $app-&gt;config;
  my $session = $conf-&gt;{'mojo_session'} || $conf-&gt;{'mojo.session'} || $conf-&gt;{'mojo'}{'session'} || $conf-&gt;{'СЃРµСЃСЃРёСЏ'}
    || return;
  
  #~ $app-&gt;sessions-&gt;cookie_name($session-&gt;{'cookie_name'})
    #~ if $session-&gt;{'cookie_name'};
  
  #~ $app-&gt;sessions-&gt;default_expiration($session-&gt;{'default_expiration'}) # set expiry
    #~ if defined $session-&gt;{'default_expiration'};
  
  while (my ($meth, $val) = each %$session) {
    next
      unless $app-&gt;sessions-&gt;can($meth);
    $app-&gt;sessions-&gt;$meth($val);
  }
}

sub РјР°СЂС€СЂСѓС‚С‹ {
  my $app = shift;
  my $conf = $app-&gt;config;
  my $routes = $conf-&gt;{'routes'} || $conf-&gt;{'РјР°СЂС€СЂСѓС‚С‹'}
    or return;
  my $app_routes = $app-&gt;routes;
  my $apply_route = sub {
    my $r = shift || $app_routes;
    my ($meth, $arg) = @_;
    my $nr;
    if (my $m = $r-&gt;can($meth)) {
      $nr = $r-&gt;$m($arg) unless ref($arg);
      $nr = $r-&gt;$m(cb =&gt; $arg) if ref($arg) eq 'CODE';
      $nr = $r-&gt;$m(@$arg) if ref($arg) eq 'ARRAY';
      $nr = $r-&gt;$m(%$arg) if ref($arg) eq 'HASH';
      
    }  else {
      $app-&gt;log-&gt;warn("Can't method [$meth] for route",);
    }
    return $nr;
  };
  
  for my $r (@$routes) {
    my $nr = $apply_route-&gt;($app_routes, @$r[0,1])
      or next;
    $app-&gt;log-&gt;debug("Apply route [$r-&gt;[0] $r-&gt;[1]]");
    for( my $i = 2; $i &lt; @$r; $i += 2 ) {
      $nr = $apply_route-&gt;($nr, @$r[$i, $i+1])
        or next;
    }
  }
}

sub СЃРїРµР№СЃС‹ {
  my $app = shift;
  my $conf = $app-&gt;config;
  my $ns = $conf-&gt;{'namespaces'} || $conf-&gt;{'ns'} || $conf-&gt;{'СЃРїРµР№СЃС‹'}
    || return;
  push @{$app-&gt;routes-&gt;namespaces}, @$ns;
}

our $VERSION = '0.033';

=pod

=encoding utf8

=head1 Mojolicious::Che

Р”РѕР±СЂРѕРіРѕ РІСЃРµРј

ВЎ ВЎ ВЎ ALL GLORY TO GLORIA ! ! !

=head1 VERSION

0.033

=head1 NAME

Mojolicious::Che - РњРѕР№ Р±Р°Р·РѕРІС‹Р№ РјРѕРґСѓР»СЊ РґР»СЏ РїСЂРёР»РѕР¶РµРЅРёР№ Mojolicious. РќСѓР¶РµРЅ С‚РѕР»СЊРєРѕ СЂР°Р·РІРµСЂРЅСѓС‚С‹Р№ РєРѕРЅС„РёРі.

=head1 SYNOPSIS

  use Mojo::Base::Che 'Mojolicious::Che' -lib, 'lib';
  
  __PACKAGE__-&gt;new(config =&gt; 'lib/Config.pm')-&gt;start();


=head1 Config file

РџРѕСЂСЏРґРѕРє СЃС‚СЂРѕРє РІ СЌС‚РѕРј РєРѕРЅС„РёРіРµ СЃРѕРѕС‚РІРµС‚СЃС‚РІСѓРµС‚ РёСЃРїРѕР»РЅРµРЅРёСЋ РІ РјРѕРґСѓР»Рµ!

  {
  'РџСЂРѕРµРєС‚'=&gt;'РўРµСЃС‚-РїСЂРѕРµРєС‚',
  # mojo =&gt; {
    # defaults =&gt;
    # secrets =&gt;
    # mode=&gt;
    # log =&gt; {level=&gt;...}
    # static =&gt; {paths =&gt; [...]},
    # renderer =&gt; {paths =&gt; [...], classes =&gt; [...], },
    # session =&gt;
    # has =&gt;
    # plugins=&gt;
    # hooks =&gt;
  # },
  # Default values for "stash" in Mojolicious::Controller, assigned for every new request.
  mojo_defaults =&gt; {layout=&gt;'default',},
  # 'С€РёС„СЂС‹' =&gt; [
  mojo_secrets =&gt; ['true 123 my app',],
  mojo_mode=&gt; 'development',
  mojo_log=&gt;{level =&gt; 'error'},
  mojo_static_paths =&gt; ["static"],
  mojo_renderer_classes =&gt; ["Mojolicious::Foo::Fun"],
  # 'СЃРµСЃСЃРёСЏ' =&gt; 
  mojo_session =&gt; {cookie_name =&gt; 'EXX', default_expiration =&gt; 86400},
  
  # 'С…Р°Р·С‹' =&gt; 'Р›РµС‚ 500-700 РЅР°Р·Р°Рґ Р±С‹Р» С‚Р°РєРѕР№ РґРёРєРёР№ СЃС‚РµРїРЅРѕР№ С‚РѕСЂРіРѕРІС‹Р№ Р¶Р°РґРЅС‹Р№ РЅР°СЂРѕРґ РҐРђР—РђР&nbsp;Р«. РЎС‚РѕР»РёС†РµР№ РёС… "РіРѕСЃСѓРґР°СЂСЃС‚РІР°" Р±С‹Р» РіРѕСЂРѕРґ РўСЊРјСѓС‚Р°СЂР°РєР°РЅСЊ, РіРґРµ-С‚Рѕ РЅР° Р±РµСЂРµРіСѓ РјРѕСЂСЏ РљР°СЃРїРёСЏ. РџРѕС‚РѕРјРєРё СЌС‚РёС… Р»СЋРґРµР№ СЂР°СЃСЃС‹РїР°РЅС‹ РїРѕ СЃС‚СЂР°РЅР°Рј Р&nbsp;РѕСЃСЃРёРё, РЎСЂРµРґРЅРµР№ РђР·РёРё, Р•РІСЂРѕРїС‹. Р•СЃС‚СЊ РјРЅРµРЅРёРµ, С‡С‚Рѕ С…Р°Р·Р°СЂС‹ РїСЂРёСЃРІРѕРёР»Рё СЃРµР±Рµ РЅР°Р·РІР°РЅРёРµ Р•Р’Р&nbsp;Р•Р, РЅРѕ СЌС‚Рѕ РЅРµ С‚Рµ Р±РёР±Р»РµР№СЃРєРёРµ РєСЂРѕС‚РєРёРµ РµРІСЂРµРё, Р° Р¶Р°РґРЅС‹Рµ РїРѕС‚РѕРјРєРё РєСЂРѕРјР°РЅСЊРѕРЅС†РµРІ'
  mojo_has =&gt; {
    foo =&gt; sub {my $app = shift; return 'is a bar';},
  },
  
  # 'Р±Р°Р·С‹' =&gt; 
  # will be as has!
  dbh=&gt;{
    'main' =&gt; {
      # DBI-&gt;connect(dsn, user, passwd, $attrs)
      connect =&gt; ["DBI:Pg:dbname=test;", "postgres", undef, {
        ShowErrorStatement =&gt; 1,
        AutoCommit =&gt; 1,
        RaiseError =&gt; 1,
        PrintError =&gt; 1, 
        pg_enable_utf8 =&gt; 1,
        #mysql_enable_utf8 =&gt; 1,
        #mysql_auto_reconnect=&gt;1,
      }],
      # or use Foo::Dbh; external defined dbh
      # dbh =&gt; Dbh-&gt;dbh,
      # will do on connect
      do =&gt; ['set datestyle to "ISO, DMY";',],
      # prepared sth will be as has $app-&gt;sth-&gt;{&lt;dbh name&gt;}{&lt;sth name&gt;}
      sth =&gt; {
        foo =&gt; &lt;&lt;SQL,
  select * 
  from foo
  where
    bar = ?;
  SQL
      },
    }
  },
  # 'Р·Р°РїСЂРѕСЃС‹' =&gt; 
  # prepared sth will be as has $app-&gt;sth-&gt;{&lt;dbh name&gt;}{&lt;sth name&gt;}
  sth =&gt; {
    main =&gt; {
      now =&gt; "select now();"
    },
  },
  
  # 'РїР»СѓРіРёРЅС‹'=&gt; [
  mojo_plugins=&gt;[ 
      ['Foo::Bar'],
      [Foo::Bar::Plugin =&gt; opt1 =&gt; ..., opt2 =&gt; ...],
      ['Foo::Plugin' =&gt; sub {&lt;...returns config data list...&gt;}],
  ],
  # 'С…СѓРєРё' =&gt; 
  mojo_hooks=&gt;{
    #~ before_dispatch =&gt; sub {1;},
  },
  # 'СЃРїРµР№СЃС‹' =&gt; 
  namespaces =&gt; ['Space::Shattle'],
  # 'РјР°СЂС€СЂСѓС‚С‹' =&gt; 
  routes =&gt; [
    [get=&gt;'/', to=&gt; {cb=&gt;sub{shift-&gt;render(format=&gt;'txt', text=&gt;'Hello friend!');},}],
  ]
  };

=head1 ATTRIBUTES

B&lt;Mojolicious::Che&gt; inherits all attributes from L&lt;Mojolicious&gt; and implements the
following new ones.

=head2 dbh

Set DBI handlers from config B&lt;dbh&gt; (РёР»Рё B&lt;Р±Р°Р·С‹&gt;)

  my $dbh = $app-&gt;dbh-&gt;{main};

=head2 sth

Set prepared stattements from config B&lt;sth&gt; (РёР»Рё B&lt;Р·Р°РїСЂРѕСЃС‹&gt;).

  my $sth = $app-&gt;sth-&gt;{main}{foo};

=head1 METHODS

B&lt;Mojolicious::Che&gt; inherits all methods from L&lt;Mojolicious&gt; and implements the following new ones.

=head2 СЃРµСЃСЃРёСЏ()

Session object config apply

=head2 С…Р°Р·С‹()

Apply has's

=head2 РїР»СѓРіРёРЅС‹()

Apply plugins

=head2 С…СѓРєРё()

Apply hooks

=head2 СЃРїРµР№СЃС‹()

Apply namespases

=head2 РјР°СЂС€СЂСѓС‚С‹()

Apply routes

=head1 SEE ALSO

L&lt;Mojolicious&gt;

L&lt;Ado&gt;

=head1 AUTHOR

РњРёС…Р°РёР» Р§Рµ (Mikhail Che), C&lt;&lt; &lt;mche[-at-]cpan.org&gt; &gt;&gt;

=head1 BUGS / CONTRIBUTING

Please report any bugs or feature requests at L&lt;https://github.com/mche/Mojolicious-Che/issues&gt;. Pull requests also welcome.

=head1 COPYRIGHT

Copyright 2016-2017 Mikhail Che.

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut

1;</pre></body></html>