APISchema
view release on metacpan or search on metacpan
controller => 'BMI',
action => 'calculate',
},
request => 'figure',
response => 'bmi',
};
# main.pl
use APISchema::DSL;
my $schema = APISchema::DSL::process {
include 'bmi.def';
};
# Routing
use APISchema::Generator::Router::Simple;
my $router = do {
my $generator = APISchema::Generator::Router::Simple->new;
$generator->generate_router($schema);
};
eg/bmi.psgi view on Meta::CPAN
use Plack::Builder;
use Plack::Request;
use APISchema::DSL;
use APISchema::Generator::Router::Simple;
use Plack::App::APISchema::Document;
use Plack::App::APISchema::MockServer;
use APISchema::Generator::Markdown;
use JSON qw(decode_json encode_json);
my $schema = APISchema::DSL::process {
include '../t/fixtures/bmi.def';
};
my $router = do {
my $generator = APISchema::Generator::Router::Simple->new;
$generator->generate_router($schema);
};
my $app = sub {
my $env = shift;
lib/APISchema.pm view on Meta::CPAN
controller => 'BMI',
action => 'calculate',
},
request => 'figure',
response => 'bmi',
};
# main.pl
use APISchema::DSL;
my $schema = APISchema::DSL::process {
include 'bmi.def';
};
# Routing
use APISchema::Generator::Router::Simple;
my $router = do {
my $generator = APISchema::Generator::Router::Simple->new;
$generator->generate_router($schema);
};
lib/APISchema/DSL.pm view on Meta::CPAN
our %METHODS = (
( map { $_ => $_ } qw(HEAD GET POST PUT DELETE PATCH) ),
FETCH => [qw(GET HEAD)],
);
our @DIRECTIVES = (qw(include filter resource title description), keys %METHODS);
our @EXPORT = @DIRECTIVES;
my $_directive = {};
sub process (&) {
my $dsl = shift;
my $schema = APISchema::Schema->new;
local $_directive->{include} = sub {
my ($file) = @_;
-r $_[0] or Carp::croak(sprintf 'No such file: %s', $file);
my $content = file($file)->slurp;
my $with_utf8 = "use utf8;\n" . $content;
eval $with_utf8;
lib/APISchema/DSL.pm view on Meta::CPAN
sub filter (&) { $_directive->{filter}->(@_) }
sub resource ($@) { $_directive->{resource}->(@_) }
for my $method (keys %METHODS) {
no strict 'refs';
*$method = sub ($@) { goto \&{ $_directive->{$method} } };
}
# disable the global definitions
@$_directive{@DIRECTIVES} = (sub {
Carp::croak(sprintf(
q(%s should be called inside 'process {}' block),
join '/', @DIRECTIVES
));
}) x scalar @DIRECTIVES;
1;
__END__
script/generate_markdown_document.pl view on Meta::CPAN
unless ($ARGV[0]) {
print <<EOM;
Usage: $0 <file>
Options:
<file> API definition file.
EOM
exit;
}
my $schema = APISchema::DSL::process {
include $ARGV[0];
};
my $generator = APISchema::Generator::Markdown->new;
print encode_utf8 $generator->format_schema($schema);
t/APISchema-DSL.t view on Meta::CPAN
dies_ok {
GET '/' => ();
};
dies_ok {
POST '/' => ();
};
}
sub process : Tests {
lives_ok {
my $schema = APISchema::DSL::process {};
isa_ok $schema, 'APISchema::Schema';
};
dies_ok {
GET '/' => ();
};
subtest 'title, description' => sub {
lives_ok {
my $schema = APISchema::DSL::process {
title 'BMI API';
description 'The API to calculate BMI';
};
isa_ok $schema, 'APISchema::Schema';
is $schema->title, 'BMI API';
is $schema->description, 'The API to calculate BMI';
};
};
subtest 'Simple GET' => sub {
lives_ok {
my $schema = APISchema::DSL::process {
GET '/' => {
title => 'Simple GET',
destination => { some => 'property' },
};
};
isa_ok $schema, 'APISchema::Schema';
my $routes = $schema->get_routes;
is scalar @$routes, 1;
is $routes->[0]->route, '/';
is $routes->[0]->title, 'Simple GET';
is_deeply $routes->[0]->destination, { some => 'property' };
};
};
subtest 'Support PATCH' => sub {
lives_ok {
my $schema = APISchema::DSL::process {
PATCH '/my' => {
title => 'Update My BMI',
destination => {
controller => 'BMI',
action => 'update',
},
};
};
isa_ok $schema, 'APISchema::Schema';
t/APISchema-DSL.t view on Meta::CPAN
is $routes->[0]->method, 'PATCH';
is_deeply $routes->[0]->destination, {
controller => 'BMI',
action => 'update',
};
};
};
subtest 'Validation should be returned' => sub {
lives_ok {
my $schema = APISchema::DSL::process {
title 'BMI API';
description 'The API to calculate BMI';
resource figure => {
type => 'object',
description => 'Figure, which includes weight and height',
properties => {
weight => {
type => 'number',
description => 'Weight(kg)',
t/APISchema-DSL.t view on Meta::CPAN
};
cmp_deeply $routes->[0]->option, { on_match => code(sub { 1 }) };
is $routes->[0]->request_resource, 'figure';
is $routes->[0]->response_resource, 'bmi';
};
};
}
sub from_file : Tests {
lives_ok {
my $schema = APISchema::DSL::process {
include 't/fixtures/bmi.def';
};
isa_ok $schema, 'APISchema::Schema';
is $schema->title, 'BMI API';
is $schema->description, 'The API to calculate BMI';
is_deeply [ sort {
$a->title cmp $b->title;
t/APISchema-DSL.t view on Meta::CPAN
is_deeply $routes->[0]->destination, {
controller => 'BMI',
action => 'calculate',
};
cmp_deeply $routes->[0]->option, { on_match => code(sub { 1 }) };
is $routes->[0]->request_resource, 'figure';
is $routes->[0]->response_resource, 'bmi';
};
dies_ok {
my $schema = APISchema::DSL::process {
include 'not-such-file';
};
};
dies_ok {
my $schema = APISchema::DSL::process {
include 't/fixtures/syntax-error.def';
};
};
dies_ok {
my $schema = APISchema::DSL::process {
include 't/fixtures/runtime-error.def';
};
};
}
sub with_unicode : Tests {
my $schema = APISchema::DSL::process {
include 't/fixtures/user.def';
};
isa_ok $schema, 'APISchema::Schema';
is $schema->title, decode_utf8('ã¦ã¼ã¶ã¼');
is $schema->description, decode_utf8('ã¦ã¼ã¶ã¼ã®å®ç¾©');
cmp_deeply $schema->get_resource_by_name('user')->{definition}, {
type => 'object',
t/APISchema-Generator-Markdown.t view on Meta::CPAN
my $schema = t::test::fixtures::prepare_status;
my $generator = APISchema::Generator::Markdown->new;
my $markdown = $generator->format_schema($schema);
like $markdown, qr{#### Response `200 OK`};
like $markdown, qr{\nHTTP/1.1 200 OK\nSucceeded!\n};
like $markdown, qr{#### Response `400 Bad Request`};
};
subtest 'example with no containers' => sub {
my $schema = APISchema::DSL::process {
resource gender => {
enum => ['male', 'female', 'other'],
example => 'other',
};
};
my $generator = APISchema::Generator::Markdown->new;
my $markdown = $generator->format_schema($schema);
like $markdown, qr/^"other"$/m;
};
subtest 'FETCH endpoint' => sub {
my $schema = APISchema::DSL::process {
FETCH '/' => {
title => 'Fetch',
destination => {},
};
};
my $generator = APISchema::Generator::Markdown->new;
my $markdown = $generator->format_schema($schema);
like $markdown, qr{\Q- [Fetch](#route-Fetch) - `GET`, `HEAD` /\E}, 'FETCH expanded to GET and HEAD';
t/test/fixtures.pm view on Meta::CPAN
package t::test::fixtures;
use strict;
use warnings;
use APISchema::DSL;
sub prepare_bmi {
APISchema::DSL::process {
include 't/fixtures/bmi.def';
};
}
sub prepare_family {
APISchema::DSL::process {
include 't/fixtures/family.def';
};
}
sub prepare_user {
APISchema::DSL::process {
include 't/fixtures/user.def';
};
}
sub prepare_author {
APISchema::DSL::process {
include 't/fixtures/author.def';
};
}
sub prepare_status {
APISchema::DSL::process {
include 't/fixtures/status.def';
};
}
sub prepare_boolean {
APISchema::DSL::process {
include 't/fixtures/boolean.def';
};
}
sub prepare_example_null {
APISchema::DSL::process {
include 't/fixtures/example-null.def';
};
}
1;
( run in 0.292 second using v1.01-cache-2.11-cpan-8d75d55dd25 )