package Catalyst::Plugin::ConfigLoader::Environment;

use warnings;
use strict;
use JSON::Any;
use MRO::Compat;
=head1 NAME

Catalyst::Plugin::ConfigLoader::Environment - Configure your
application with environment variables.

=head1 VERSION

Version 0.05


our $VERSION = '0.07';


Catalyst::Plugin::ConfigLoader::Environment reads environment
variables and sets up the configuration in your application

Here's how you use it:

    package MyApp;
    use Catalyst qw(... ConfigLoader::Environment ...);

Then, before you run your application, set some environment

    export MYAPP_foo='Hello, world!'
    export MYAPP_bar="foobar"
    perl script/

Inside your application, C<< $c->config->{foo} >> will be equal to
C<Hello, world!>, and C<< $c->config->{bar} >> will be equal to

=head2 Compatibility with ConfigLoader

You can use both ConfigLoader and this module in the same application.
If you specify C<ConfigLoader> before C<ConfigLoader::Environment> in
the import list to Catalyst, the environment will override any
configuration files that ConfigLoader may find.  This is the
recommended setup.

You can reverse the order in the import list if you want static config
files to override the environment, but that's not recommended.

=head1 DETAILS

Here's exactly how environment variables are translated into

First, your application's name is converted to ALL CAPS, any colons
are converted to underscores (i.e. C<My::App> is translated to
C<MY_APP>), and a C<_> is appended.  Then, any environment variables
not starting with this prefix are discarded.

The prefix is then stripped, and the remaining variables are then
converted to elements in the C<config> hash as follows.

Variables starting with C<Model::>, C<View::>, or C<Controller::> and
then any character other than C<_> are treated as configuration
options for the corresponding component of your application.  The
prefix is saved as C<prefix> and everything after the first C<_> is
used as a key into the C<< $c->config->{"prefix"} >> hash.

Any other variables not starting with a special prefix are added
directly to the C<< $c->config >> hash.


Let's translate a YAML config file:

    name: MyApp
    title: This is My App!
      EXTENSION: tt
      EVAL_PERL: 1
      root: "/etc"
      connect_info: [ "dbi:Pg:dbname=foo", "username", "password" ]

into environment variables that would setup the same configuration:

    MYAPP_title=This is My App!
    MYAPP_Model__DBIC_connect_info=["dbi:Pg:dbname=foo", "username", "password"]

Double colons are converted into double underscores.  For
compatibility's sake, support for the 0.01-style use of
bourne-incompatible variable names is retained.

Values are JSON-decoded if they look like JSON arrays or objects
(i.e. if they're enclosed in []s or {}s). Taking advantage of that, we
can write the same example this way:

    MYAPP_title=This is My App!
    MYAPP_Model__DBIC={"connect_info":["dbi:Pg:dbname=foo", "username", "password"]}


=head2 setup

Overriding Catalyst' setup routine.


sub setup {
    my $c    = shift;
    my $prefix = Catalyst::Utils::class2env($c);
    my %env;
    for (keys %ENV) { 
        m/^${prefix}[_](.+)$/ and $env{$1} = $ENV{$_}; 

    foreach my $var (keys %env) {
        my $val = $env{$var};

        # Decode JSON array/object 
        if ( $val =~ m{^\[.*\]$|^\{.*\}$} ) {
            $val = JSON::Any->jsonToObj($val);

        # Special syntax Model__Foo is equivalent to Model::Foo
        if($var =~ /(Model|View|Controller)(?:::|__)([^_]+)(?:_(.+))?$/) {
            $var = "${1}::$2";

            # Special syntax Model__Foo_bar (or Model::Foo_bar) will
            # tweak just the 'bar' subparam for Model::Foo's
            # config. We can accomplish this using a hash that
            # specifies just 'bar' ($c->config will merge hashes).
            if ( defined $3 ) {
                $val = { $3 => $val };

        $c->config( $var => $val );
    return $c->maybe::next::method(@_);

=head1 AUTHOR

Jonathan Rockway, C<< <jrockway at> >>



Ryan D Johnson, C<< <ryan at> >>

Devin J. Austin C<< <> >>

=head1 BUGS

Please report any bugs or feature requests to
C<bug-catalyst-plugin-configloader-environment at>, or through the web interface at
I will be notified, and then you'll automatically be notified of progress on
your bug as I make changes.

=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Catalyst::Plugin::ConfigLoader::Environment

You can also look for information at:

=over 4

=item * Catalyst Mailing List


=item * RT: CPAN's request tracker




Copyright 2006 Jonathan Rockway, all rights reserved.

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

If you'd like to use it under a different license, that's probably OK.
Please contact the author.


1; # End of Catalyst::Plugin::ConfigLoader::Environment