Plack-App-Catmandu-Bag/lib/Plack/App/Catmandu/Bag.pm
package Plack::App::Catmandu::Bag;
use Catmandu::Sane;
our $VERSION = '0.0102';
use parent 'Plack::Component';
use Catmandu;
use Router::Simple;
use JSON qw(encode_json);
use namespace::clean;
sub bag {
my ($self) = @_;
$self->{_bag} ||= $self->_build_bag;
}
sub router {
my ($self) = @_;
$self->{_router} ||= $self->_build_router;
}
sub _build_bag {
my ($self) = @_;
Catmandu->store($self->{store})->bag($self->{bag});
}
sub _build_router {
my ($self) = @_;
my $router = Router::Simple->new;
if ($self->bag->does('Catmandu::Plugin::Versioning')) {
$router->connect(
'/{id}/versions',
{action => 'version_list'},
{method => ['GET', 'HEAD']},
);
$router->connect(
'/{id}/versions/{version}',
{action => 'version_show'},
{method => ['GET', 'HEAD']},
);
}
$router->connect('/', {action => 'list'}, {method => ['GET', 'HEAD']});
$router->connect('/{id}', {action => 'show'},
{method => ['GET', 'HEAD']});
$router;
}
sub list {
my ($self, $params) = @_;
my $start = $params->{start} // 0;
my $limit = $params->{limit} // 10;
$self->ok($self->bag->slice($start, $limit)->to_array);
}
sub show {
my ($self, $params) = @_;
if (my $data = $self->bag->get($params->{id})) {
$self->ok($data);
}
else {
$self->not_found;
}
}
sub version_list {
my ($self, $params) = @_;
if (my $data = $self->bag->get_history($params->{id})) {
$self->ok($data);
}
else {
$self->not_found;
}
}
sub version_show {
my ($self, $params) = @_;
if (my $data = $self->bag->get_version($params->{id}, $params->{version}))
{
$self->ok($data);
}
else {
$self->not_found;
}
}
sub ok {
my ($self, $data) = @_;
my $res = {data => $data};
[
'200', ['Content-Type' => 'application/vnd.api+json'],
[encode_json($res)],
];
}
sub method_not_allowed {
['405', ['Content-Type' => 'text/plain'], ['Method Not Allowed']];
}
sub not_found {
['404', ['Content-Type' => 'text/plain'], ['Not Found']];
}
sub call {
my ($self, $env) = @_;
my $router = $self->router;
if (my $params = $router->match($env)) {
my $action = $params->{action};
$self->$action($params);
}
elsif ($router->method_not_allowed) {
$self->method_not_allowed;
}
else {
$self->not_found;
}
}
1;
__END__
=encoding utf-8
=head1 NAME
Plack::App::Catmandu::Bag - Wrap a REST API around a Catmandu::Bag
=head1 SYNOPSIS
use Catmandu;
use Plack::Builder;
use Plack::App::Catmandu::Bag;
Catmandu->define_store('library',
MongoDB => (bags => {books => {plugins => ['Versioning']}}));
builder {
mount '/api/books' => Plack::App::Catmandu::Bag->new(
store => 'library',
bag => 'books',
);
};
=head1 DESCRIPTION
This is an early minimal release, look at the tests for usage.
=head1 AUTHOR
Nicolas Steenlant E<lt>nicolas.steenlant@ugent.beE<gt>
=head1 COPYRIGHT
Copyright 2017- Nicolas Steenlant
=head1 LICENSE
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=head1 SEE ALSO
=cut