File Coverage

blib/lib/Mojolicious/Plugin/Config/Structured.pm
Criterion Covered Total %
statement 39 39 100.0
branch 8 8 100.0
condition 3 5 60.0
subroutine 8 8 100.0
pod 1 1 100.0
total 59 61 96.7


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::Config::Structured 3.01;
2 3     3   1824668 use v5.26;
  3         14  
3 3     3   22 use warnings;
  3         5  
  3         284  
4              
5             # ABSTRACT: Mojolicious Plugin for Config::Structured: provides Mojo app access to structured configuration data
6              
7             =encoding UTF-8
8              
9             =head1 NAME
10              
11             Mojolicious::Plugin::Config::Structured - provides Mojo app access to structured configuration data
12              
13             =head1 SYNOPSIS
14              
15             # For a full Mojo app
16             $self->plugin('Config::Structured' => {config_file => $filename});
17              
18             ...
19              
20             if ($c->conf->feature->enabled) {
21             ...
22             }
23              
24             say $c->conf->email->recipient->{some_feature};
25              
26             =head1 DESCRIPTION
27              
28             Mojolicious Plugin for L<Config::Structured>: locates and reads config and definition files and loads them into a
29             Config::Structured instance, made available globally via the C<conf> method.
30              
31             =cut
32              
33 3     3   887 use Mojo::Base 'Mojolicious::Plugin';
  3         15364  
  3         26  
34              
35 3     3   4271 use Config::Structured;
  3         1650840  
  3         278  
36 3     3   29 use Readonly;
  3         12  
  3         257  
37              
38 3     3   21 use experimental qw(signatures);
  3         8  
  3         44  
39              
40             Readonly::Scalar our $PERIOD => q{.};
41             Readonly::Scalar our $CONF_FILE_SUFFIX => q{conf};
42             Readonly::Scalar our $DEF_FILE_SUFFIX => q{def};
43              
44             =pod
45              
46             =head1 METHODS
47              
48             L<Mojolicious::Plugin::Config::Structured> inherits all methods from L<Mojolicious::Plugin> and implements the following
49             new ones
50              
51             =head2 register
52              
53             $plugin->register(Mojolicious->new, [structure_file => $struct_fn,] [config_file => $config_file])
54              
55             Register plugin in L<Mojolicious> application. C<structure_file> is the filesystem path of the file that defines the
56             configuration definition. If omitted, a sane default is used (C<./{app}.conf.def>) relative to the mojo app home.
57              
58             C<config_file> is the filesystem path of the file that provides the active configuration. If omitted, a sane default is
59             used (C<./{app}.{mode}.conf> or C<./{app}.conf>)
60              
61             =cut
62              
63 5     5 1 13698 sub register ($self, $app, $params) {
  5         17  
  5         48  
  5         10  
  5         10  
64 5         49 push($app->commands->namespaces->@*, __PACKAGE__ . '::Command');
65              
66             my @search =
67 5         316 ($params->{structure_file}, $app->home->child(join($PERIOD, $app->moniker, $CONF_FILE_SUFFIX, $DEF_FILE_SUFFIX))->to_string);
68 5 100       347 my ($def_file) = grep {defined && -r -f} @search; #get the first existing, readable file
  10         349  
69 5 100 66     89 unless (defined($def_file) && -r -f $def_file) {
70 1   50     9 $app->log->error(sprintf('[Config::Structured] No configuration structure found (tried to read from `%s`)', $def_file // ''));
71 1         637 die("[Config::Structured] Cannot continue without a valid conf structure");
72             }
73              
74             @search = (
75             $params->{config_file},
76 4         26 $app->home->child(join($PERIOD, $app->moniker, $app->mode, $CONF_FILE_SUFFIX))->to_string,
77             $app->home->child(join($PERIOD, $app->moniker, $CONF_FILE_SUFFIX))->to_string
78             );
79 4 100       376 my ($conf_file) = grep {defined && -r -f} @search; #get the first existing, readable file
  12         335  
80 4 100       18 unless (defined($conf_file)) {
81 1         6 $app->log->warn('[Config::Structured] Initializing with empty configuration');
82 1         251 $conf_file = {};
83             }
84              
85             my $conf = Config::Structured->new(
86             config => $conf_file,
87             structure => $def_file,
88             hooks => $params->{hooks},
89 4         41 );
90              
91             =pod
92              
93             =head2 conf
94              
95             This method is used to access the loaded configuration from within the Mojo
96             application. Returns the root C<Config::Structured::Node> instance.
97              
98             =cut
99              
100             $app->helper(
101             conf => sub {
102 11     11   2646 return $conf;
103             }
104 4         43701 );
105              
106 4         3133 return;
107             }
108              
109             =head1 AUTHOR
110              
111             Mark Tyrrell C<< <mark@tyrrminal.dev> >>
112              
113             =head1 LICENSE
114              
115             Copyright (c) 2024 Mark Tyrrell
116              
117             Permission is hereby granted, free of charge, to any person obtaining a copy
118             of this software and associated documentation files (the "Software"), to deal
119             in the Software without restriction, including without limitation the rights
120             to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
121             copies of the Software, and to permit persons to whom the Software is
122             furnished to do so, subject to the following conditions:
123              
124             The above copyright notice and this permission notice shall be included in all
125             copies or substantial portions of the Software.
126              
127             THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
128             IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
129             FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
130             AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
131             LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
132             OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
133             SOFTWARE.
134              
135             =cut
136              
137             1;
138              
139             __END__