Merge pull request #1543 from dvz5/master

Moose role, docs, and automatic docs
This commit is contained in:
wing328
2015-11-14 18:26:49 +08:00
33 changed files with 3218 additions and 114 deletions

6
.gitignore vendored
View File

@@ -55,3 +55,9 @@ samples/client/petstore/python/.projectile
samples/client/petstore/python/.venv/
*/.settings
*.mustache~
*.java~
*.pm~
*.xml~
*.t~

View File

@@ -99,6 +99,9 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("Configuration.mustache", ("lib/WWW/" + moduleName).replace('/', File.separatorChar), "Configuration.pm"));
supportingFiles.add(new SupportingFile("BaseObject.mustache", ("lib/WWW/" + moduleName).replace('/', File.separatorChar), "Object/BaseObject.pm"));
supportingFiles.add(new SupportingFile("ApiFactory.mustache", ("lib/WWW/" + moduleName).replace('/', File.separatorChar), "ApiFactory.pm"));
supportingFiles.add(new SupportingFile("Role.mustache", ("lib/WWW/" + moduleName).replace('/', File.separatorChar), "Role.pm"));
supportingFiles.add(new SupportingFile("AutoDoc.mustache", ("lib/WWW/" + moduleName + "/Role").replace('/', File.separatorChar), "AutoDoc.pm"));
supportingFiles.add(new SupportingFile("autodoc.script.mustache", ("bin/").replace('/', File.separatorChar), "autodoc"));
}
public CodegenType getTag() {

View File

@@ -20,7 +20,9 @@ use Module::Runtime qw(use_module);
use WWW::{{moduleName}}::Configuration;
sub new
use base 'Class::Singleton';
sub _new_instance
{
my $class = shift;
my (%args) = (
@@ -32,6 +34,8 @@ sub new
return bless \%args, $class;
}
sub _cfg {'WWW::{{moduleName}}::Configuration'}
# Set the user agent of the API client
#
# @param string $user_agent The user agent of the API client
@@ -288,13 +292,15 @@ sub select_header_content_type
# @return string API key with the prefix
sub get_api_key_with_prefix
{
my ($self, $api_key) = @_;
if ($WWW::{{moduleName}}::Configuration::api_key_prefix->{$api_key}) {
return $WWW::{{moduleName}}::Configuration::api_key_prefix->{$api_key}." ".$WWW::{{moduleName}}::Configuration::api_key->{$api_key};
} else {
return $WWW::{{moduleName}}::Configuration::api_key->{$api_key};
}
}
my ($self, $key_name) = @_;
my $api_key = $WWW::{{moduleName}}::Configuration::api_key->{$key_name};
return unless $api_key;
my $prefix = $WWW::{{moduleName}}::Configuration::api_key_prefix->{$key_name};
return $prefix ? "$prefix $api_key" : $api_key;
}
# update header and query param based on authentication setting
#
@@ -304,17 +310,8 @@ sub get_api_key_with_prefix
sub update_params_for_auth {
my ($self, $header_params, $query_params, $auth_settings) = @_;
# we can defer to the application
if ($self->{auth_setup_handler} && ref($self->{auth_setup_handler}) eq 'CODE') {
$self->{auth_setup_handler}->( api_client => $self,
header_params => $header_params,
query_params => $query_params,
auth_settings => $auth_settings, # presumably this won't be defined if we're doing it this way
);
return;
}
return if (!defined($auth_settings) || scalar(@$auth_settings) == 0);
return $self->_global_auth_setup($header_params, $query_params)
unless $auth_settings && @$auth_settings;
# one endpoint can have more than 1 auth settings
foreach my $auth (@$auth_settings) {
@@ -327,10 +324,47 @@ sub update_params_for_auth {
}
{{/authMethods}}
else {
# TODO show warning about security definition not found
# TODO show warning about security definition not found
}
}
}
# The endpoint API class has not found any settings for auth. This may be deliberate,
# in which case update_params_for_auth() will be a no-op. But it may also be that the
# swagger spec does not describe the intended authorization. So we check in the config for any
# auth tokens and if we find any, we use them for all endpoints;
sub _global_auth_setup {
my ($self, $header_params, $query_params) = @_;
my $tokens = $self->_cfg->get_tokens;
return unless keys %$tokens;
# basic
if (my $uname = delete $tokens->{username}) {
my $pword = delete $tokens->{password};
$header_params->{'Authorization'} = 'Basic '.encode_base64($uname.":".$pword);
}
# oauth
if (my $access_token = delete $tokens->{access_token}) {
$header_params->{'Authorization'} = 'Bearer ' . $access_token;
}
# other keys
foreach my $token_name (keys %$tokens) {
my $in = $tokens->{$token_name}->{in};
my $token = $self->get_api_key_with_prefix($token_name);
if ($in eq 'head') {
$header_params->{$token_name} = $token;
}
elsif ($in eq 'query') {
$query_params->{$token_name} = $token;
}
else {
die "Don't know where to put token '$token_name' ('$in' is not 'head' or 'query')";
}
}
}
1;

View File

@@ -21,9 +21,7 @@ use WWW::{{moduleName}}::ApiClient;
use WWW::{{moduleName}}::ApiFactory;
my $api_factory = WWW::{{moduleName}}::ApiFactory->new( base_url => 'http://petstore.swagger.io/v2',
..., # other args for ApiClient constructor
);
my $api_factory = WWW::{{moduleName}}::ApiFactory->new( ... ); # any args for ApiClient constructor
# later...
my $pet_api = $api_factory->get_api('Pet');
@@ -47,26 +45,16 @@ my %_apis = map { $_ =~ /^WWW::{{moduleName}}::(.*)$/; $1 => $_ }
=head1 new()
All parameters are optional, and are passed to and stored on the api_client object.
Any parameters are optional, and are passed to and stored on the api_client object.
base_url: supply this to change the default base URL taken from the Swagger definition.
base_url: (optional)
supply this to change the default base URL taken from the Swagger definition.
auth_setup_handler: a coderef you can supply to set up authentication.
The coderef receives a hashref with keys: api_client, query_params, header_params, auth_settings.
my $api_factory = WWW::{{moduleName}}::ApiFactory->new( auth_setup_handler => \&setup_auth ); );
sub setup_auth {
my %p = @_;
$p{header_params}->{'X-SomeApp-FunkyKeyName'} = 'aaaaabbbbbcccccddddd';
}
=cut
sub new {
my ($class, %p) = (shift, @_);
$p{api_client} = WWW::{{moduleName}}::ApiClient->new(%p);
$p{api_client} = WWW::{{moduleName}}::ApiClient->instance(%p);
return bless \%p, $class;
}
@@ -95,4 +83,18 @@ sub get_api {
sub api_client { $_[0]->{api_client} }
=head1 apis_available()
=cut
sub apis_available { return map { $_ =~ s/Api$//; $_ } sort keys %_apis }
=head1 classname_for()
=cut
sub classname_for {
my ($self, $api_name) = @_;
return $_apis{"${api_name}Api"};
}
1;

View File

@@ -0,0 +1,427 @@
package WWW::{{moduleName}}::Role::AutoDoc;
use List::MoreUtils qw(uniq);
use Moose::Role;
sub autodoc {
my ($self, $how) = @_;
die "Unknown format '$how'" unless $how =~ /^(pod|wide|narrow)$/;
$self->_printisa($how);
$self->_printmethods($how);
$self->_printattrs($how);
print "\n";
}
sub _printisa {
my ($self, $how) = @_;
my $meta = $self->meta;
my $myclass = ref $self;
my $super = join ', ', $meta->superclasses;
my @roles = $meta->calculate_all_roles;
#shift(@roles) if @roles > 1; # if > 1, the first is a composite, the rest are the roles
my $isa = join ', ', grep {$_ ne $myclass} $meta->linearized_isa;
my $sub = join ', ', $meta->subclasses;
my $dsub = join ', ', $meta->direct_subclasses;
my $app_name = $self->version_info->{app_name};
my $app_version = $self->version_info->{app_version};
my $generated_date = $self->version_info->{generated_date};
my $generator_class = $self->version_info->{generator_class};
$~ = $how eq 'pod' ? 'INHERIT_POD' : 'INHERIT';
write;
my ($rolepkg, $role_reqs);
foreach my $role (@roles) {
$rolepkg = $role->{package} || next; # some are anonymous, or something
next if $rolepkg eq 'WWW::{{moduleName}}::Role::AutoDoc';
$role_reqs = join ', ', keys %{$role->{required_methods}};
$role_reqs ||= '';
$~ = $how eq 'pod' ? 'ROLES_POD' : 'ROLES';
write;
}
if ($how eq 'pod') {
$~ = 'ROLES_POD_CLOSE';
write;
}
# ----- format specs -----
format INHERIT =
@* -
$myclass
ISA: @*
$isa
Direct subclasses: @*
$dsub
All subclasses: @*
$sub
Target API: @* @*
$app_name, $app_version
Generated on: @*
$generated_date
Generator class: @*
$generator_class
.
format ROLES =
Composes: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~
$rolepkg
requires: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~
$role_reqs
^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~
$role_reqs
.
format INHERIT_POD =
=head1 NAME
@*
$myclass
=head1 VERSION
=head2 @* version: @*
$app_name, $app_version
Automatically generated by the Perl Swagger Codegen project:
=over 4
=item Build date: @*
$generated_date
=item Build package: @*
$generator_class
=item Codegen version:
=back
=head1 INHERITANCE
=head2 Base class(es)
@*
$isa
=head2 Direct subclasses
@*
$dsub
=head2 All subclasses
@*
$sub
=head1 COMPOSITION
@* composes the following roles:
$myclass
.
format ROLES_POD =
=head2 C<@*>
$rolepkg
Requires:
@*
$role_reqs
.
format ROLES_POD_CLOSE =
.
# ----- / format specs -----
}
sub _printmethods {
my ($self, $how) = @_;
if ($how eq 'narrow') {
print <<HEAD;
METHODS
-------
HEAD
}
elsif ($how eq 'wide') {
$~ = 'METHODHEAD';
write;
}
elsif ($how eq 'pod') {
$~ = 'METHODHEAD_POD';
write;
}
else {
die "Don't know how to print '$how'";
}
$self->_printmethod($_, $how) for uniq sort $self->meta->get_all_method_names; #$self->meta->get_method_list,
if ($how eq 'pod') {
$~ = 'METHOD_POD_CLOSE';
write;
}
}
sub _printmethod {
my ($self, $methodname, $how) = @_;
return if $methodname =~ /^_/;
return if $self->meta->has_attribute($methodname);
my %internal = map {$_ => 1} qw(BUILD BUILDARGS meta can new DEMOLISHALL DESTROY
DOES isa BUILDALL does VERSION dump
);
return if $internal{$methodname};
my $method = $self->meta->get_method($methodname) or return; # symbols imported into namespaces i.e. not known by Moose
return if $method->original_package_name eq __PACKAGE__;
my $delegate_to = '';
my $via = '';
my $on = '';
my $doc = '';
my $original_pkg = $method->original_package_name;
if ($method->can('associated_attribute')) {
$delegate_to = $method->delegate_to_method;
my $aa = $method->associated_attribute;
$on = $aa->{isa};
$via = $aa->{name};
$original_pkg = $on;
$doc = $original_pkg->method_documentation->{$delegate_to}->{summary};
}
else {
$doc = $method->documentation;
}
if ($how eq 'narrow') {
$~ = 'METHOD_NARROW';
write;
}
elsif ($how eq 'pod' and $delegate_to) {
$~ = 'METHOD_POD_DELEGATED';
write;
}
elsif ($how eq 'pod') {
$~ = 'METHOD_POD';
write;
}
else {
$~ = 'METHOD';
write;
}
# ----- format specs -----
format METHODHEAD =
METHODS
-------
Name delegates to on via
===========================================================================================================================================================================
.
format METHOD =
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<... @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<... @<<<<<<<<<<<<<<<<...
$methodname, $delegate_to, $on, $via
.
format METHOD_NARROW =
@*
$methodname
original pkg: @*
$original_pkg
delegates to: @*
$delegate_to
on: @*
$on
via: @*
$via
.
format METHODHEAD_POD =
=head1 METHODS
.
format METHOD_POD =
=head2 C<@*()>
$methodname
Defined in: @*
$original_pkg
.
format METHOD_POD_DELEGATED =
=head2 C<@*()>
$methodname
Defined in: @*
$original_pkg
Delegates to: @*()
$delegate_to
On: @*
$on
Via: @*()
$via
Doc: @*
$doc
Same as: $self->@*->@*()
$via, $delegate_to
.
format METHOD_POD_CLOSE =
.
# ----- / format specs -----
}
sub _printattrs {
my ($self, $how) = @_;
if ($how eq 'narrow') {
print <<HEAD;
ATTRIBUTES
----------
HEAD
}
elsif ($how eq 'wide') {
$~ = 'ATTRHEAD';
write;
}
elsif ($how eq 'pod') {
$~ = 'ATTRHEAD_POD';
write;
}
else {
die "Don't know how to print attributes '$how'";
}
$self->_printattr($_, $how) for sort $self->meta->get_attribute_list;
if ($how eq 'pod') {
$~ = 'ATTR_POD_CLOSE';
write;
}
}
sub _printattr {
my ($self, $attrname, $how) = @_;
return if $attrname =~ /^_/;
my $attr = $self->meta->get_attribute($attrname) or die "No attr for $attrname";
my $is;
$is = 'rw' if $attr->get_read_method && $attr->get_write_method;
$is = 'ro' if $attr->get_read_method && ! $attr->get_write_method;
$is = 'wo' if $attr->get_write_method && ! $attr->get_read_method;
$is = '--' if ! $attr->get_write_method && ! $attr->get_read_method;
$is or die "No \$is for $attrname";
my $tc = $attr->type_constraint || '';
my $from = $attr->associated_class->name || '';
my $reqd = $attr->is_required ? 'yes' : 'no';
my $lazy = $attr->is_lazy ? 'yes' : 'no';
my $has_doc = $attr->has_documentation ? 'yes' : 'no'; # *_api attributes will never have doc, but other attributes might have
my $doc = $attr->documentation || '';
my $handles = join ', ', sort @{$attr->handles || []};
$handles ||= '';
if ($how eq 'narrow') {
$~ = 'ATTR_NARROW';
}
elsif ($how eq 'pod') {
$~ = 'ATTR_POD';
}
else {
$~ = 'ATTR';
}
write;
# ----- format specs -----
format ATTRHEAD =
ATTRIBUTES
----------
Name is isa reqd lazy doc handles
==============================================================================================================
.
format ATTR =
@<<<<<<<<<<<<<<<<< @< @<<<<<<<<<<<<<<<<<<<<<<<< @<<< @<<< @<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$attrname, $is, $tc, $reqd, $lazy, $has_doc, $handles
^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~
$handles
.
format ATTR_NARROW =
@*
$attrname
is: @*
$is
isa: @*
$tc
reqd: @*
$reqd
lazy: @*
$lazy
doc: @*
$doc
handles: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$handles
^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~
$handles
.
format ATTRHEAD_POD =
=head1 ATTRIBUTES
.
format ATTR_POD =
=head2 C<@*>
$attrname
is: @*
$is
isa: @*
$tc
reqd: @*
$reqd
lazy: @*
$lazy
doc: @*
$doc
handles: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$handles
^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~
$handles
.
format ATTR_POD_CLOSE =
.
# ----- / format specs -----
}
1;

View File

@@ -20,8 +20,10 @@ use base ("Class::Accessor", "Class::Data::Inheritable");
#NOTE: This class is auto generated by the swagger code generator program. Do not edit the class manually.
#
__PACKAGE__->mk_classdata('attribute_map');
__PACKAGE__->mk_classdata('swagger_types');
__PACKAGE__->mk_classdata('attribute_map' => {});
__PACKAGE__->mk_classdata('swagger_types' => {});
__PACKAGE__->mk_classdata('method_documentation' => {});
__PACKAGE__->mk_classdata('class_documentation' => {});
# new object
sub new {

View File

@@ -10,13 +10,13 @@ use Carp;
use constant VERSION => '{{moduleVersion}}';
# class/static variables
our $api_client;
our $http_timeout = 180;
our $http_user_agent = 'Perl-Swagger';
# authenticaiton setting
our $api_key = {};
our $api_key_prefix = {};
our $api_key_in = {};
# username and password for HTTP basic authentication
our $username = '';
@@ -25,4 +25,56 @@ our $password = '';
# access token for OAuth
our $access_token = '';
sub get_tokens {
my $class = shift;
my $tokens = {};
$tokens->{username} = $username if $username;
$tokens->{password} = $password if $password;
$tokens->{access_token} = $access_token if $access_token;
foreach my $token_name (keys %{ $api_key }) {
$tokens->{$token_name}->{token} = $api_key->{$token_name};
$tokens->{$token_name}->{prefix} = $api_key_prefix->{$token_name};
$tokens->{$token_name}->{in} = $api_key_in->{$token_name};
}
return $tokens;
}
sub clear_tokens {
my $class = shift;
my %tokens = %{$class->get_tokens}; # copy
$username = undef;
$password = undef;
$access_token = undef;
$api_key = {};
$api_key_prefix = {};
$api_key_in = {};
return \%tokens;
}
sub accept_tokens {
my ($class, $tokens) = @_;
foreach my $known_name (qw(username password access_token)) {
next unless $tokens->{$known_name};
eval "\$$known_name = delete \$tokens->{\$known_name}";
die $@ if $@;
}
foreach my $token_name (keys %$tokens) {
$api_key->{$token_name} = $tokens->{$token_name}->{token};
if ($tokens->{$token_name}->{prefix}) {
$api_key_prefix->{$token_name} = $tokens->{$token_name}->{prefix};
}
my $in = $tokens->{$token_name}->{in} || 'head';
croak "Tokens can only go in 'head' or 'query' (not in '$in')" unless $in =~ /^(?:head|query)$/;
$api_key_in->{$token_name} = $in;
}
}
1;

View File

@@ -0,0 +1,219 @@
# NAME
WWW::{{moduleName}}::Role - a Moose role for the {{appName}}
## {{appName}} version: {{appVersion}}
# VERSION
Automatically generated by the Perl Swagger Codegen project:
- Build date: {{generatedDate}}
- Build package: {{generatorClass}}
- Codegen version:
## A note on Moose
This role is the only component of the library that uses Moose. See
WWW::{{moduleName}}::ApiFactory for non-Moosey usage.
# SYNOPSIS
The Perl Swagger Codegen project builds a library of Perl modules to interact with
a web service defined by a Swagger specification. See below for how to build the
library.
This module provides an interface to the generated library. All the classes,
objects, and methods (well, not quite \*all\*, see below) are flattened into this
role.
package MyApp;
use Moose;
with 'WWW::{{moduleName}}::Role';
package main;
my $api = MyApp->new({ tokens => $tokens });
my $pet = $api->get_pet_by_id(pet_id => $pet_id);
## Structure of the library
The library consists of a set of API classes, one for each endpoint. These APIs
implement the method calls available on each endpoint.
Additionally, there is a set of "object" classes, which represent the objects
returned by and sent to the methods on the endpoints.
An API factory class is provided, which builds instances of each endpoint API.
This Moose role flattens all the methods from the endpoint APIs onto the consuming
class. It also provides methods to retrieve the endpoint API objects, and the API
factory object, should you need it.
For documentation of all these methods, see AUTOMATIC DOCUMENTATION below.
## Configuring authentication
In the normal case, the Swagger spec will describe what parameters are
required and where to put them. You just need to supply the tokens.
my $tokens = {
# basic
username => $username,
password => $password,
# oauth
access_token => $oauth_token,
# keys
$some_key => { token => $token,
prefix => $prefix,
in => $in, # 'head||query',
},
$another => { token => $token,
prefix => $prefix,
in => $in, # 'head||query',
},
...,
};
my $api = MyApp->new({ tokens => $tokens });
Note these are all optional, as are `prefix` and `in`, and depend on the API
you are accessing. Usually `prefix` and `in` will be determined by the code generator from
the spec and you will not need to set them at run time. If not, `in` will
default to 'head' and `prefix` to the empty string.
The tokens will be placed in the `WWW::{{moduleName}}::Configuration` namespace
as follows, but you don't need to know about this.
- `$WWW::{{moduleName}}::Configuration::username`
String. The username for basic auth.
- `$WWW::{{moduleName}}::Configuration::password`
String. The password for basic auth.
- `$WWW::{{moduleName}}::Configuration::api_key`
Hashref. Keyed on the name of each key (there can be multiple tokens).
$WWW::{{moduleName}}::Configuration::api_key = {
secretKey => 'aaaabbbbccccdddd',
anotherKey => '1111222233334444',
};
- `$WWW::{{moduleName}}::Configuration::api_key_prefix`
Hashref. Keyed on the name of each key (there can be multiple tokens). Note not
all api keys require a prefix.
$WWW::{{moduleName}}::Configuration::api_key_prefix = {
secretKey => 'string',
anotherKey => 'same or some other string',
};
- `$WWW::{{moduleName}}::Configuration::access_token`
String. The OAuth access token.
# METHODS
## `base_url`
The generated code has the `base_url` already set as a default value. This method
returns (and optionally sets, but only if the API client has not been
created yet) the current value of `base_url`.
## `api_factory`
Returns an API factory object. You probably won't need to call this directly.
$self->api_factory('Pet'); # returns a WWW::{{moduleName}}::PetApi instance
$self->pet_api; # the same
# MISSING METHODS
Most of the methods on the API are delegated to individual endpoint API objects
(e.g. Pet API, Store API, User API etc). Where different endpoint APIs use the
same method name (e.g. `new()`), these methods can't be delegated. So you need
to call `$api->pet_api->new()`.
In principle, every API is susceptible to the presence of a few, random, undelegatable
method names. In practice, because of the way method names are constructed, it's
unlikely in general that any methods will be undelegatable, except for:
new()
class_documentation()
method_documentation()
To call these methods, you need to get a handle on the relevant object, either
by calling `$api->foo_api` or by retrieving an object, e.g.
`$api->get_pet_by_id(pet_id => $pet_id)`. They are class methods, so
you could also call them on class names.
# BUILDING YOUR LIBRARY
See the homepage `https://github.com/swagger-api/swagger-codegen` for full details.
But briefly, clone the git repository, build the codegen codebase, set up your build
config file, then run the API build script. You will need git, Java 7 and Apache
maven 3.0.3 or better already installed.
The config file should specify the project name for the generated library:
{"moduleName":"MyProjectName"}
Your library files will be built under `WWW::MyProjectName`.
$ git clone https://github.com/swagger-api/swagger-codegen.git
$ cd swagger-codegen
$ mvn package
$ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-i [URL or file path to JSON swagger API spec] \
-l perl \
-c /path/to/config/file.json \
-o /path/to/output/folder
Bang, all done. Run the `autodoc` script in the `bin` directory to see the API
you just built.
# AUTOMATIC DOCUMENTATION
You can print out a summary of the generated API by running the included
`autodoc` script in the `bin` directory of your generated library. A few
output formats are supported:
Usage: autodoc [OPTION]
-w wide format (default)
-n narrow format
-p POD format
-H HTML format
-m Markdown format
-h print this help message
-c your application class
The `-c` option allows you to load and inspect your own application. A dummy
namespace is used if you don't supply your own class.
# DOCUMENTATION FROM THE SWAGGER SPEC
Additional documentation for each class and method may be provided by the Swagger
spec. If so, this is available via the `class_documentation()` and
`method_documentation()` methods on each generated object class, and the
`method_documentation()` method on the endpoint API classes:
my $cmdoc = $api->pet_api->method_documentation->{$method_name};
my $odoc = $api->get_pet_by_id->(pet_id => $pet_id)->class_documentation;
my $omdoc = $api->get_pet_by_id->(pet_id => $pet_id)->method_documentation->{method_name};
Each of these calls returns a hashref with various useful pieces of information.

View File

@@ -0,0 +1,323 @@
package WWW::{{moduleName}}::Role;
use utf8;
use Moose::Role;
use namespace::autoclean;
use Class::Inspector;
use Log::Any qw($log);
use WWW::{{moduleName}}::ApiFactory;
has base_url => ( is => 'ro',
required => 0,
isa => 'Str',
documentation => 'Root of the server that requests are sent to',
);
has api_factory => ( is => 'ro',
isa => 'WWW::{{moduleName}}::ApiFactory',
builder => '_build_af',
lazy => 1,
documentation => 'Builds an instance of the endpoint API class',
);
has tokens => ( is => 'ro',
isa => 'HashRef',
required => 0,
default => sub { {} },
documentation => 'The auth tokens required by the application - basic, OAuth and/or API key(s)',
);
has _cfg => ( is => 'ro',
isa => 'Str',
default => 'WWW::{{moduleName}}::Configuration',
);
has version_info => ( is => 'ro',
isa => 'HashRef',
default => sub { {
app_name => '{{appName}}',
app_version => '{{appVersion}}',
generated_date => '{{generatedDate}}',
generator_class => '{{generatorClass}}',
} },
documentation => 'Information about the application version and the codegen codebase version'
);
sub BUILD {
my $self = shift;
$self->_cfg->accept_tokens( $self->tokens ) if keys %{$self->tokens};
# ignore these symbols imported into API namespaces
my %outsiders = map {$_ => 1} qw( croak );
my %delegates;
# collect the methods callable on each API
foreach my $api_name ($self->api_factory->apis_available) {
my $api_class = $self->api_factory->classname_for($api_name);
my $methods = Class::Inspector->methods($api_class, 'expanded'); # not Moose, so use CI instead
my @local_methods = grep {! /^_/} grep {! $outsiders{$_}} map {$_->[2]} grep {$_->[1] eq $api_class} @$methods;
push( @{$delegates{$_}}, {api_name => $api_name, api_class => $api_class} ) for @local_methods;
}
# remove clashes
foreach my $method (keys %delegates) {
if ( @{$delegates{$method}} > 1 ) {
my ($apis) = delete $delegates{$method};
}
}
# build the flattened API
foreach my $api_name ($self->api_factory->apis_available) {
my $att_name = sprintf "%s_api", lc($api_name);
my $api_class = $self->api_factory->classname_for($api_name);
my @delegated = grep { $delegates{$_}->[0]->{api_name} eq $api_name } keys %delegates;
$log->debugf("Adding API: '%s' handles %s", $att_name, join ', ', @delegated);
$self->meta->add_attribute( $att_name => (
is => 'ro',
isa => $api_class,
default => sub {$self->api_factory->get_api($api_name)},
lazy => 1,
handles => \@delegated,
) );
}
}
sub _build_af {
my $self = shift;
my %args;
$args{base_url} = $self->base_url if $self->base_url;
return WWW::{{moduleName}}::ApiFactory->new(%args);
}
=head1 NAME
WWW::{{moduleName}}::Role - a Moose role for the {{appName}}
=head2 {{appName}} version: {{appVersion}}
=head1 VERSION
Automatically generated by the Perl Swagger Codegen project:
=over 4
=item Build date: {{generatedDate}}
=item Build package: {{generatorClass}}
=item Codegen version:
=back
=head2 A note on Moose
This role is the only component of the library that uses Moose. See
WWW::{{moduleName}}::ApiFactory for non-Moosey usage.
=head1 SYNOPSIS
The Perl Swagger Codegen project builds a library of Perl modules to interact with
a web service defined by a Swagger specification. See below for how to build the
library.
This module provides an interface to the generated library. All the classes,
objects, and methods (well, not quite *all*, see below) are flattened into this
role.
package MyApp;
use Moose;
with 'WWW::{{moduleName}}::Role';
package main;
my $api = MyApp->new({ tokens => $tokens });
my $pet = $api->get_pet_by_id(pet_id => $pet_id);
=head2 Structure of the library
The library consists of a set of API classes, one for each endpoint. These APIs
implement the method calls available on each endpoint.
Additionally, there is a set of "object" classes, which represent the objects
returned by and sent to the methods on the endpoints.
An API factory class is provided, which builds instances of each endpoint API.
This Moose role flattens all the methods from the endpoint APIs onto the consuming
class. It also provides methods to retrieve the endpoint API objects, and the API
factory object, should you need it.
For documentation of all these methods, see AUTOMATIC DOCUMENTATION below.
=head2 Configuring authentication
In the normal case, the Swagger spec will describe what parameters are
required and where to put them. You just need to supply the tokens.
my $tokens = {
# basic
username => $username,
password => $password,
# oauth
access_token => $oauth_token,
# keys
$some_key => { token => $token,
prefix => $prefix,
in => $in, # 'head||query',
},
$another => { token => $token,
prefix => $prefix,
in => $in, # 'head||query',
},
...,
};
my $api = MyApp->new({ tokens => $tokens });
Note these are all optional, as are C<prefix> and C<in>, and depend on the API
you are accessing. Usually C<prefix> and C<in> will be determined by the code generator from
the spec and you will not need to set them at run time. If not, C<in> will
default to 'head' and C<prefix> to the empty string.
The tokens will be placed in the C<WWW::{{moduleName}}::Configuration> namespace
as follows, but you don't need to know about this.
=over 4
=item C<$WWW::{{moduleName}}::Configuration::username>
String. The username for basic auth.
=item C<$WWW::{{moduleName}}::Configuration::password>
String. The password for basic auth.
=item C<$WWW::{{moduleName}}::Configuration::api_key>
Hashref. Keyed on the name of each key (there can be multiple tokens).
$WWW::{{moduleName}}::Configuration::api_key = {
secretKey => 'aaaabbbbccccdddd',
anotherKey => '1111222233334444',
};
=item C<$WWW::{{moduleName}}::Configuration::api_key_prefix>
Hashref. Keyed on the name of each key (there can be multiple tokens). Note not
all api keys require a prefix.
$WWW::{{moduleName}}::Configuration::api_key_prefix = {
secretKey => 'string',
anotherKey => 'same or some other string',
};
=item C<$WWW::{{moduleName}}::Configuration::access_token>
String. The OAuth access token.
=back
=head1 METHODS
=head2 C<base_url>
The generated code has the C<base_url> already set as a default value. This method
returns (and optionally sets, but only if the API client has not been
created yet) the current value of C<base_url>.
=head2 C<api_factory>
Returns an API factory object. You probably won't need to call this directly.
$self->api_factory('Pet'); # returns a WWW::{{moduleName}}::PetApi instance
$self->pet_api; # the same
=head1 MISSING METHODS
Most of the methods on the API are delegated to individual endpoint API objects
(e.g. Pet API, Store API, User API etc). Where different endpoint APIs use the
same method name (e.g. C<new()>), these methods can't be delegated. So you need
to call C<$api-E<gt>pet_api-E<gt>new()>.
In principle, every API is susceptible to the presence of a few, random, undelegatable
method names. In practice, because of the way method names are constructed, it's
unlikely in general that any methods will be undelegatable, except for:
new()
class_documentation()
method_documentation()
To call these methods, you need to get a handle on the relevant object, either
by calling C<$api-E<gt>foo_api> or by retrieving an object, e.g.
C<$api-E<gt>get_pet_by_id(pet_id =E<gt> $pet_id)>. They are class methods, so
you could also call them on class names.
=head1 BUILDING YOUR LIBRARY
See the homepage C<https://github.com/swagger-api/swagger-codegen> for full details.
But briefly, clone the git repository, build the codegen codebase, set up your build
config file, then run the API build script. You will need git, Java 7 and Apache
maven 3.0.3 or better already installed.
The config file should specify the project name for the generated library:
{"moduleName":"MyProjectName"}
Your library files will be built under C<WWW::MyProjectName>.
$ git clone https://github.com/swagger-api/swagger-codegen.git
$ cd swagger-codegen
$ mvn package
$ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-i [URL or file path to JSON swagger API spec] \
-l perl \
-c /path/to/config/file.json \
-o /path/to/output/folder
Bang, all done. Run the C<autodoc> script in the C<bin> directory to see the API
you just built.
=head1 AUTOMATIC DOCUMENTATION
You can print out a summary of the generated API by running the included
C<autodoc> script in the C<bin> directory of your generated library. A few
output formats are supported:
Usage: autodoc [OPTION]
-w wide format (default)
-n narrow format
-p POD format
-H HTML format
-m Markdown format
-h print this help message
-c your application class
The C<-c> option allows you to load and inspect your own application. A dummy
namespace is used if you don't supply your own class.
=head1 DOCUMENTATION FROM THE SWAGGER SPEC
Additional documentation for each class and method may be provided by the Swagger
spec. If so, this is available via the C<class_documentation()> and
C<method_documentation()> methods on each generated object class, and the
C<method_documentation()> method on the endpoint API classes:
my $cmdoc = $api->pet_api->method_documentation->{$method_name};
my $odoc = $api->get_pet_by_id->(pet_id => $pet_id)->class_documentation;
my $omdoc = $api->get_pet_by_id->(pet_id => $pet_id)->method_documentation->{method_name};
Each of these calls returns a hashref with various useful pieces of information.
=cut
1;

View File

@@ -30,11 +30,14 @@ use Log::Any qw($log);
use WWW::{{moduleName}}::ApiClient;
use WWW::{{moduleName}}::Configuration;
use base "Class::Data::Inheritable";
__PACKAGE__->mk_classdata('method_documentation' => {});
sub new {
my $class = shift;
my $default_api_client = $WWW::{{moduleName}}::Configuration::api_client ? $WWW::{{moduleName}}::Configuration::api_client : WWW::{{moduleName}}::ApiClient->new;
my (%self) = (
'api_client' => $default_api_client,
'api_client' => WWW::{{moduleName}}::ApiClient->instance,
@_
);
@@ -49,13 +52,31 @@ sub new {
{{#operations}}
{{#operation}}
#
# {{{nickname}}}
#
# {{{summary}}}
#
{{#allParams}}# @param {{dataType}} ${{paramName}} {{description}} {{#required}}(required){{/required}}{{^required}}(optional){{/required}}
{{/allParams}}# @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
{{/allParams}}
{
my $params = {
{{#allParams}}
'{{paramName}}' => {
data_type => '{{dataType}}',
description => '{{description}}',
required => {{#required}}'1'{{/required}}{{^required}}'0'{{/required}},
},
{{/allParams}}
};
__PACKAGE__->method_documentation->{ {{nickname}} } = {
summary => '{{summary}}',
params => $params,
returns => {{#returnType}}'{{{returnType}}}'{{/returnType}}{{^returnType}}undef{{/returnType}},
};
}
# @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
#
sub {{nickname}} {
my ($self, %args) = @_;
@@ -112,7 +133,7 @@ sub {{nickname}} {
}{{/bodyParams}}
# authentication setting, if any
my $auth_settings = [{{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}];
my $auth_settings = [qw({{#authMethods}}{{name}} {{/authMethods}})];
# make the API Call
{{#returnType}}my $response = $self->{api_client}->call_api($_resource_path, $_method,

View File

@@ -0,0 +1,77 @@
#!/usr/bin/perl
use FindBin;
use File::Spec;
use lib File::Spec->catdir($FindBin::Bin, '..', 'lib');
use Moose::Util qw(apply_all_roles);
use Getopt::Std;
my %options=();
getopts("wnphmHc:", \%options);
help if $options{h};
my $my_app = $options{c} || 'My::App';
if ($options{c}) {
eval <<LOAD;
use $my_app;
apply_all_roles($my_app, "WWW::{{moduleName}}::Role::AutoDoc");
LOAD
die $@ if $@;
}
else {
package My::App;
use Moose;
with ('WWW::{{moduleName}}::Role', 'WWW::{{moduleName}}::Role::AutoDoc');
}
package main;
my $opt;
$opt = 'wide' if $options{w};
$opt = 'narrow' if $options{n};
$opt = 'pod' if $options{p};
$opt = 'pod' if $options{H};
$opt = 'pod' if $options{m};
$opt ||= 'wide';
my $api = $my_app->new;
if ($options{H}) {
my $pod2html = "pod2html --backlink --css http://st.pimg.net/tucs/style.css?3";
open STDOUT, "| $pod2html" or die "Can't fork: $!";
$api->autodoc($opt);
close STDOUT or die "Can't close: $!";
}
elsif ($options{m}) {
my $pod2markdown = "pod2markdown --html-encode-chars 1";
open STDOUT, "| $pod2markdown" or die "Can't fork: $!";
$api->autodoc($opt);
close STDOUT or die "Can't close: $!";
}
else {
$api->autodoc($opt);
}
exit(0);
# --------------------
sub help {
print <<HELP;
Usage: autodoc [OPTION] [-c My::App::Class]
-w wide format (default)
-n narrow format
-p POD format
-H HTML format
-m Markdown format
-h print this help message
-c your application class
HELP
exit(0);
}

View File

@@ -21,6 +21,22 @@ use base "WWW::{{moduleName}}::Object::BaseObject";
#NOTE: This class is auto generated by the swagger code generator program. Do not edit the class manually.
#
__PACKAGE__->class_documentation({description => '{{description}}',
class => '{{classname}}',
required => [], # TODO
} );
__PACKAGE__->method_documentation({
{{#vars}}'{{name}}' => {
datatype => '{{datatype}}',
base_name => '{{baseName}}',
description => '{{description}}',
format => '{{format}}',
read_only => '{{readOnly}}',
},
{{/vars}}
});
__PACKAGE__->swagger_types( {
{{#vars}}'{{name}}' => '{{{datatype}}}'{{#hasMore}},
{{/hasMore}}{{/vars}}

View File

@@ -0,0 +1,281 @@
# NAME
My::App
# VERSION
## Swagger Petstore version: 1.0.0
Automatically generated by the Perl Swagger Codegen project:
- Build date: 2015-11-13T20:46:43.271Z
- Build package: class io.swagger.codegen.languages.PerlClientCodegen
- Codegen version:
# INHERITANCE
## Base class(es)
Moose::Object
## Direct subclasses
## All subclasses
# COMPOSITION
My::App composes the following roles:
## `WWW::SwaggerClient::Role`
Requires:
# METHODS
## `add_pet()`
Defined in: WWW::SwaggerClient::PetApi
Delegates to: add_pet()
On: WWW::SwaggerClient::PetApi
Via: pet_api()
Doc: Add a new pet to the store
Same as: $self->pet_api->add_pet()
## `create_user()`
Defined in: WWW::SwaggerClient::UserApi
Delegates to: create_user()
On: WWW::SwaggerClient::UserApi
Via: user_api()
Doc: Create user
Same as: $self->user_api->create_user()
## `create_users_with_array_input()`
Defined in: WWW::SwaggerClient::UserApi
Delegates to: create_users_with_array_input()
On: WWW::SwaggerClient::UserApi
Via: user_api()
Doc: Creates list of users with given input array
Same as: $self->user_api->create_users_with_array_input()
## `create_users_with_list_input()`
Defined in: WWW::SwaggerClient::UserApi
Delegates to: create_users_with_list_input()
On: WWW::SwaggerClient::UserApi
Via: user_api()
Doc: Creates list of users with given input array
Same as: $self->user_api->create_users_with_list_input()
## `delete_order()`
Defined in: WWW::SwaggerClient::StoreApi
Delegates to: delete_order()
On: WWW::SwaggerClient::StoreApi
Via: store_api()
Doc: Delete purchase order by ID
Same as: $self->store_api->delete_order()
## `delete_pet()`
Defined in: WWW::SwaggerClient::PetApi
Delegates to: delete_pet()
On: WWW::SwaggerClient::PetApi
Via: pet_api()
Doc: Deletes a pet
Same as: $self->pet_api->delete_pet()
## `delete_user()`
Defined in: WWW::SwaggerClient::UserApi
Delegates to: delete_user()
On: WWW::SwaggerClient::UserApi
Via: user_api()
Doc: Delete user
Same as: $self->user_api->delete_user()
## `find_pets_by_status()`
Defined in: WWW::SwaggerClient::PetApi
Delegates to: find_pets_by_status()
On: WWW::SwaggerClient::PetApi
Via: pet_api()
Doc: Finds Pets by status
Same as: $self->pet_api->find_pets_by_status()
## `find_pets_by_tags()`
Defined in: WWW::SwaggerClient::PetApi
Delegates to: find_pets_by_tags()
On: WWW::SwaggerClient::PetApi
Via: pet_api()
Doc: Finds Pets by tags
Same as: $self->pet_api->find_pets_by_tags()
## `get_inventory()`
Defined in: WWW::SwaggerClient::StoreApi
Delegates to: get_inventory()
On: WWW::SwaggerClient::StoreApi
Via: store_api()
Doc: Returns pet inventories by status
Same as: $self->store_api->get_inventory()
## `get_order_by_id()`
Defined in: WWW::SwaggerClient::StoreApi
Delegates to: get_order_by_id()
On: WWW::SwaggerClient::StoreApi
Via: store_api()
Doc: Find purchase order by ID
Same as: $self->store_api->get_order_by_id()
## `get_pet_by_id()`
Defined in: WWW::SwaggerClient::PetApi
Delegates to: get_pet_by_id()
On: WWW::SwaggerClient::PetApi
Via: pet_api()
Doc: Find pet by ID
Same as: $self->pet_api->get_pet_by_id()
## `get_user_by_name()`
Defined in: WWW::SwaggerClient::UserApi
Delegates to: get_user_by_name()
On: WWW::SwaggerClient::UserApi
Via: user_api()
Doc: Get user by user name
Same as: $self->user_api->get_user_by_name()
## `login_user()`
Defined in: WWW::SwaggerClient::UserApi
Delegates to: login_user()
On: WWW::SwaggerClient::UserApi
Via: user_api()
Doc: Logs user into the system
Same as: $self->user_api->login_user()
## `logout_user()`
Defined in: WWW::SwaggerClient::UserApi
Delegates to: logout_user()
On: WWW::SwaggerClient::UserApi
Via: user_api()
Doc: Logs out current logged in user session
Same as: $self->user_api->logout_user()
## `place_order()`
Defined in: WWW::SwaggerClient::StoreApi
Delegates to: place_order()
On: WWW::SwaggerClient::StoreApi
Via: store_api()
Doc: Place an order for a pet
Same as: $self->store_api->place_order()
## `update_pet()`
Defined in: WWW::SwaggerClient::PetApi
Delegates to: update_pet()
On: WWW::SwaggerClient::PetApi
Via: pet_api()
Doc: Update an existing pet
Same as: $self->pet_api->update_pet()
## `update_pet_with_form()`
Defined in: WWW::SwaggerClient::PetApi
Delegates to: update_pet_with_form()
On: WWW::SwaggerClient::PetApi
Via: pet_api()
Doc: Updates a pet in the store with form data
Same as: $self->pet_api->update_pet_with_form()
## `update_user()`
Defined in: WWW::SwaggerClient::UserApi
Delegates to: update_user()
On: WWW::SwaggerClient::UserApi
Via: user_api()
Doc: Updated user
Same as: $self->user_api->update_user()
## `upload_file()`
Defined in: WWW::SwaggerClient::PetApi
Delegates to: upload_file()
On: WWW::SwaggerClient::PetApi
Via: pet_api()
Doc: uploads an image
Same as: $self->pet_api->upload_file()
# ATTRIBUTES
## `api_factory`
is: ro
isa: WWW::SwaggerClient::ApiFactory
reqd: no
lazy: yes
doc: Builds an instance of the endpoint API class
handles:
## `base_url`
is: ro
isa: Str
reqd: no
lazy: no
doc: Root of the server that requests are sent to
handles:
## `pet_api`
is: ro
isa: WWW::SwaggerClient::PetApi
reqd: no
lazy: yes
doc:
handles: add_pet, delete_pet, find_pets_by_status, find_pets_by_tags,
get_pet_by_id, update_pet, update_pet_with_form, upload_file
## `store_api`
is: ro
isa: WWW::SwaggerClient::StoreApi
reqd: no
lazy: yes
doc:
handles: delete_order, get_inventory, get_order_by_id, place_order
## `tokens`
is: ro
isa: HashRef
reqd: no
lazy: no
doc: The auth tokens required by the application - basic, OAuth and/or API key(s)
handles:
## `user_api`
is: ro
isa: WWW::SwaggerClient::UserApi
reqd: no
lazy: yes
doc:
handles: create_user, create_users_with_array_input,
create_users_with_list_input, delete_user, get_user_by_name,
login_user, logout_user, update_user
## `version_info`
is: ro
isa: HashRef
reqd: no
lazy: no
doc: Information about the application version and the codegen codebase version
handles:

View File

@@ -0,0 +1,77 @@
#!/usr/bin/perl
use FindBin;
use File::Spec;
use lib File::Spec->catdir($FindBin::Bin, '..', 'lib');
use Moose::Util qw(apply_all_roles);
use Getopt::Std;
my %options=();
getopts("wnphmHc:", \%options);
help if $options{h};
my $my_app = $options{c} || 'My::App';
if ($options{c}) {
eval <<LOAD;
use $my_app;
apply_all_roles($my_app, "WWW::SwaggerClient::Role::AutoDoc");
LOAD
die $@ if $@;
}
else {
package My::App;
use Moose;
with ('WWW::SwaggerClient::Role', 'WWW::SwaggerClient::Role::AutoDoc');
}
package main;
my $opt;
$opt = 'wide' if $options{w};
$opt = 'narrow' if $options{n};
$opt = 'pod' if $options{p};
$opt = 'pod' if $options{H};
$opt = 'pod' if $options{m};
$opt ||= 'wide';
my $api = $my_app->new;
if ($options{H}) {
my $pod2html = "pod2html --backlink --css http://st.pimg.net/tucs/style.css?3";
open STDOUT, "| $pod2html" or die "Can't fork: $!";
$api->autodoc($opt);
close STDOUT or die "Can't close: $!";
}
elsif ($options{m}) {
my $pod2markdown = "pod2markdown --html-encode-chars 1";
open STDOUT, "| $pod2markdown" or die "Can't fork: $!";
$api->autodoc($opt);
close STDOUT or die "Can't close: $!";
}
else {
$api->autodoc($opt);
}
exit(0);
# --------------------
sub help {
print <<HELP;
Usage: autodoc [OPTION] [-c My::App::Class]
-w wide format (default)
-n narrow format
-p POD format
-H HTML format
-m Markdown format
-h print this help message
-c your application class
HELP
exit(0);
}

View File

@@ -20,7 +20,9 @@ use Module::Runtime qw(use_module);
use WWW::SwaggerClient::Configuration;
sub new
use base 'Class::Singleton';
sub _new_instance
{
my $class = shift;
my (%args) = (
@@ -32,6 +34,8 @@ sub new
return bless \%args, $class;
}
sub _cfg {'WWW::SwaggerClient::Configuration'}
# Set the user agent of the API client
#
# @param string $user_agent The user agent of the API client
@@ -288,13 +292,15 @@ sub select_header_content_type
# @return string API key with the prefix
sub get_api_key_with_prefix
{
my ($self, $api_key) = @_;
if ($WWW::SwaggerClient::Configuration::api_key_prefix->{$api_key}) {
return $WWW::SwaggerClient::Configuration::api_key_prefix->{$api_key}." ".$WWW::SwaggerClient::Configuration::api_key->{$api_key};
} else {
return $WWW::SwaggerClient::Configuration::api_key->{$api_key};
}
}
my ($self, $key_name) = @_;
my $api_key = $WWW::SwaggerClient::Configuration::api_key->{$key_name};
return unless $api_key;
my $prefix = $WWW::SwaggerClient::Configuration::api_key_prefix->{$key_name};
return $prefix ? "$prefix $api_key" : $api_key;
}
# update header and query param based on authentication setting
#
@@ -304,17 +310,8 @@ sub get_api_key_with_prefix
sub update_params_for_auth {
my ($self, $header_params, $query_params, $auth_settings) = @_;
# we can defer to the application
if ($self->{auth_setup_handler} && ref($self->{auth_setup_handler}) eq 'CODE') {
$self->{auth_setup_handler}->( api_client => $self,
header_params => $header_params,
query_params => $query_params,
auth_settings => $auth_settings, # presumably this won't be defined if we're doing it this way
);
return;
}
return if (!defined($auth_settings) || scalar(@$auth_settings) == 0);
return $self->_global_auth_setup($header_params, $query_params)
unless $auth_settings && @$auth_settings;
# one endpoint can have more than 1 auth settings
foreach my $auth (@$auth_settings) {
@@ -331,10 +328,47 @@ sub update_params_for_auth {
}
else {
# TODO show warning about security definition not found
# TODO show warning about security definition not found
}
}
}
# The endpoint API class has not found any settings for auth. This may be deliberate,
# in which case update_params_for_auth() will be a no-op. But it may also be that the
# swagger spec does not describe the intended authorization. So we check in the config for any
# auth tokens and if we find any, we use them for all endpoints;
sub _global_auth_setup {
my ($self, $header_params, $query_params) = @_;
my $tokens = $self->_cfg->get_tokens;
return unless keys %$tokens;
# basic
if (my $uname = delete $tokens->{username}) {
my $pword = delete $tokens->{password};
$header_params->{'Authorization'} = 'Basic '.encode_base64($uname.":".$pword);
}
# oauth
if (my $access_token = delete $tokens->{access_token}) {
$header_params->{'Authorization'} = 'Bearer ' . $access_token;
}
# other keys
foreach my $token_name (keys %$tokens) {
my $in = $tokens->{$token_name}->{in};
my $token = $self->get_api_key_with_prefix($token_name);
if ($in eq 'head') {
$header_params->{$token_name} = $token;
}
elsif ($in eq 'query') {
$query_params->{$token_name} = $token;
}
else {
die "Don't know where to put token '$token_name' ('$in' is not 'head' or 'query')";
}
}
}
1;

View File

@@ -21,9 +21,7 @@ use WWW::SwaggerClient::ApiClient;
use WWW::SwaggerClient::ApiFactory;
my $api_factory = WWW::SwaggerClient::ApiFactory->new( base_url => 'http://petstore.swagger.io/v2',
..., # other args for ApiClient constructor
);
my $api_factory = WWW::SwaggerClient::ApiFactory->new( ... ); # any args for ApiClient constructor
# later...
my $pet_api = $api_factory->get_api('Pet');
@@ -47,26 +45,16 @@ my %_apis = map { $_ =~ /^WWW::SwaggerClient::(.*)$/; $1 => $_ }
=head1 new()
All parameters are optional, and are passed to and stored on the api_client object.
Any parameters are optional, and are passed to and stored on the api_client object.
base_url: supply this to change the default base URL taken from the Swagger definition.
base_url: (optional)
supply this to change the default base URL taken from the Swagger definition.
auth_setup_handler: a coderef you can supply to set up authentication.
The coderef receives a hashref with keys: api_client, query_params, header_params, auth_settings.
my $api_factory = WWW::SwaggerClient::ApiFactory->new( auth_setup_handler => \&setup_auth ); );
sub setup_auth {
my %p = @_;
$p{header_params}->{'X-SomeApp-FunkyKeyName'} = 'aaaaabbbbbcccccddddd';
}
=cut
sub new {
my ($class, %p) = (shift, @_);
$p{api_client} = WWW::SwaggerClient::ApiClient->new(%p);
$p{api_client} = WWW::SwaggerClient::ApiClient->instance(%p);
return bless \%p, $class;
}
@@ -95,4 +83,18 @@ sub get_api {
sub api_client { $_[0]->{api_client} }
=head1 apis_available()
=cut
sub apis_available { return map { $_ =~ s/Api$//; $_ } sort keys %_apis }
=head1 classname_for()
=cut
sub classname_for {
my ($self, $api_name) = @_;
return $_apis{"${api_name}Api"};
}
1;

View File

@@ -10,13 +10,13 @@ use Carp;
use constant VERSION => '1.0.0';
# class/static variables
our $api_client;
our $http_timeout = 180;
our $http_user_agent = 'Perl-Swagger';
# authenticaiton setting
our $api_key = {};
our $api_key_prefix = {};
our $api_key_in = {};
# username and password for HTTP basic authentication
our $username = '';
@@ -25,4 +25,56 @@ our $password = '';
# access token for OAuth
our $access_token = '';
sub get_tokens {
my $class = shift;
my $tokens = {};
$tokens->{username} = $username if $username;
$tokens->{password} = $password if $password;
$tokens->{access_token} = $access_token if $access_token;
foreach my $token_name (keys %{ $api_key }) {
$tokens->{$token_name}->{token} = $api_key->{$token_name};
$tokens->{$token_name}->{prefix} = $api_key_prefix->{$token_name};
$tokens->{$token_name}->{in} = $api_key_in->{$token_name};
}
return $tokens;
}
sub clear_tokens {
my $class = shift;
my %tokens = %{$class->get_tokens}; # copy
$username = undef;
$password = undef;
$access_token = undef;
$api_key = {};
$api_key_prefix = {};
$api_key_in = {};
return \%tokens;
}
sub accept_tokens {
my ($class, $tokens) = @_;
foreach my $known_name (qw(username password access_token)) {
next unless $tokens->{$known_name};
eval "\$$known_name = delete \$tokens->{\$known_name}";
die $@ if $@;
}
foreach my $token_name (keys %$tokens) {
$api_key->{$token_name} = $tokens->{$token_name}->{token};
if ($tokens->{$token_name}->{prefix}) {
$api_key_prefix->{$token_name} = $tokens->{$token_name}->{prefix};
}
my $in = $tokens->{$token_name}->{in} || 'head';
croak "Tokens can only go in 'head' or 'query' (not in '$in')" unless $in =~ /^(?:head|query)$/;
$api_key_in->{$token_name} = $in;
}
}
1;

View File

@@ -20,8 +20,10 @@ use base ("Class::Accessor", "Class::Data::Inheritable");
#NOTE: This class is auto generated by the swagger code generator program. Do not edit the class manually.
#
__PACKAGE__->mk_classdata('attribute_map');
__PACKAGE__->mk_classdata('swagger_types');
__PACKAGE__->mk_classdata('attribute_map' => {});
__PACKAGE__->mk_classdata('swagger_types' => {});
__PACKAGE__->mk_classdata('method_documentation' => {});
__PACKAGE__->mk_classdata('class_documentation' => {});
# new object
sub new {

View File

@@ -19,6 +19,29 @@ use base "WWW::SwaggerClient::Object::BaseObject";
#NOTE: This class is auto generated by the swagger code generator program. Do not edit the class manually.
#
__PACKAGE__->class_documentation({description => '',
class => 'Category',
required => [], # TODO
} );
__PACKAGE__->method_documentation({
'id' => {
datatype => 'int',
base_name => 'id',
description => '',
format => '',
read_only => '',
},
'name' => {
datatype => 'string',
base_name => 'name',
description => '',
format => '',
read_only => '',
},
});
__PACKAGE__->swagger_types( {
'id' => 'int',
'name' => 'string'

View File

@@ -19,6 +19,57 @@ use base "WWW::SwaggerClient::Object::BaseObject";
#NOTE: This class is auto generated by the swagger code generator program. Do not edit the class manually.
#
__PACKAGE__->class_documentation({description => '',
class => 'Order',
required => [], # TODO
} );
__PACKAGE__->method_documentation({
'id' => {
datatype => 'int',
base_name => 'id',
description => '',
format => '',
read_only => '',
},
'pet_id' => {
datatype => 'int',
base_name => 'petId',
description => '',
format => '',
read_only => '',
},
'quantity' => {
datatype => 'int',
base_name => 'quantity',
description => '',
format => '',
read_only => '',
},
'ship_date' => {
datatype => 'DateTime',
base_name => 'shipDate',
description => '',
format => '',
read_only => '',
},
'status' => {
datatype => 'string',
base_name => 'status',
description => 'Order Status',
format => '',
read_only => '',
},
'complete' => {
datatype => 'boolean',
base_name => 'complete',
description => '',
format => '',
read_only => '',
},
});
__PACKAGE__->swagger_types( {
'id' => 'int',
'pet_id' => 'int',

View File

@@ -19,6 +19,57 @@ use base "WWW::SwaggerClient::Object::BaseObject";
#NOTE: This class is auto generated by the swagger code generator program. Do not edit the class manually.
#
__PACKAGE__->class_documentation({description => '',
class => 'Pet',
required => [], # TODO
} );
__PACKAGE__->method_documentation({
'id' => {
datatype => 'int',
base_name => 'id',
description => '',
format => '',
read_only => '',
},
'category' => {
datatype => 'Category',
base_name => 'category',
description => '',
format => '',
read_only => '',
},
'name' => {
datatype => 'string',
base_name => 'name',
description => '',
format => '',
read_only => '',
},
'photo_urls' => {
datatype => 'ARRAY[string]',
base_name => 'photoUrls',
description => '',
format => '',
read_only => '',
},
'tags' => {
datatype => 'ARRAY[Tag]',
base_name => 'tags',
description => '',
format => '',
read_only => '',
},
'status' => {
datatype => 'string',
base_name => 'status',
description => 'pet status in the store',
format => '',
read_only => '',
},
});
__PACKAGE__->swagger_types( {
'id' => 'int',
'category' => 'Category',

View File

@@ -19,6 +19,29 @@ use base "WWW::SwaggerClient::Object::BaseObject";
#NOTE: This class is auto generated by the swagger code generator program. Do not edit the class manually.
#
__PACKAGE__->class_documentation({description => '',
class => 'Tag',
required => [], # TODO
} );
__PACKAGE__->method_documentation({
'id' => {
datatype => 'int',
base_name => 'id',
description => '',
format => '',
read_only => '',
},
'name' => {
datatype => 'string',
base_name => 'name',
description => '',
format => '',
read_only => '',
},
});
__PACKAGE__->swagger_types( {
'id' => 'int',
'name' => 'string'

View File

@@ -19,6 +19,71 @@ use base "WWW::SwaggerClient::Object::BaseObject";
#NOTE: This class is auto generated by the swagger code generator program. Do not edit the class manually.
#
__PACKAGE__->class_documentation({description => '',
class => 'User',
required => [], # TODO
} );
__PACKAGE__->method_documentation({
'id' => {
datatype => 'int',
base_name => 'id',
description => '',
format => '',
read_only => '',
},
'username' => {
datatype => 'string',
base_name => 'username',
description => '',
format => '',
read_only => '',
},
'first_name' => {
datatype => 'string',
base_name => 'firstName',
description => '',
format => '',
read_only => '',
},
'last_name' => {
datatype => 'string',
base_name => 'lastName',
description => '',
format => '',
read_only => '',
},
'email' => {
datatype => 'string',
base_name => 'email',
description => '',
format => '',
read_only => '',
},
'password' => {
datatype => 'string',
base_name => 'password',
description => '',
format => '',
read_only => '',
},
'phone' => {
datatype => 'string',
base_name => 'phone',
description => '',
format => '',
read_only => '',
},
'user_status' => {
datatype => 'int',
base_name => 'userStatus',
description => 'User Status',
format => '',
read_only => '',
},
});
__PACKAGE__->swagger_types( {
'id' => 'int',
'username' => 'string',

View File

@@ -30,11 +30,14 @@ use Log::Any qw($log);
use WWW::SwaggerClient::ApiClient;
use WWW::SwaggerClient::Configuration;
use base "Class::Data::Inheritable";
__PACKAGE__->mk_classdata('method_documentation' => {});
sub new {
my $class = shift;
my $default_api_client = $WWW::SwaggerClient::Configuration::api_client ? $WWW::SwaggerClient::Configuration::api_client : WWW::SwaggerClient::ApiClient->new;
my (%self) = (
'api_client' => $default_api_client,
'api_client' => WWW::SwaggerClient::ApiClient->instance,
@_
);
@@ -47,12 +50,27 @@ sub new {
}
#
# update_pet
#
# Update an existing pet
#
# @param Pet $body Pet object that needs to be added to the store (optional)
{
my $params = {
'body' => {
data_type => 'Pet',
description => 'Pet object that needs to be added to the store',
required => '0',
},
};
__PACKAGE__->method_documentation->{ update_pet } = {
summary => 'Update an existing pet',
params => $params,
returns => undef,
};
}
# @return void
#
sub update_pet {
@@ -87,7 +105,7 @@ sub update_pet {
}
# authentication setting, if any
my $auth_settings = ['petstore_auth'];
my $auth_settings = [qw(petstore_auth )];
# make the API Call
@@ -97,12 +115,27 @@ sub update_pet {
return;
}
#
# add_pet
#
# Add a new pet to the store
#
# @param Pet $body Pet object that needs to be added to the store (optional)
{
my $params = {
'body' => {
data_type => 'Pet',
description => 'Pet object that needs to be added to the store',
required => '0',
},
};
__PACKAGE__->method_documentation->{ add_pet } = {
summary => 'Add a new pet to the store',
params => $params,
returns => undef,
};
}
# @return void
#
sub add_pet {
@@ -137,7 +170,7 @@ sub add_pet {
}
# authentication setting, if any
my $auth_settings = ['petstore_auth'];
my $auth_settings = [qw(petstore_auth )];
# make the API Call
@@ -147,12 +180,27 @@ sub add_pet {
return;
}
#
# find_pets_by_status
#
# Finds Pets by status
#
# @param ARRAY[string] $status Status values that need to be considered for filter (optional)
{
my $params = {
'status' => {
data_type => 'ARRAY[string]',
description => 'Status values that need to be considered for filter',
required => '0',
},
};
__PACKAGE__->method_documentation->{ find_pets_by_status } = {
summary => 'Finds Pets by status',
params => $params,
returns => 'ARRAY[Pet]',
};
}
# @return ARRAY[Pet]
#
sub find_pets_by_status {
@@ -187,7 +235,7 @@ sub find_pets_by_status {
# authentication setting, if any
my $auth_settings = ['petstore_auth'];
my $auth_settings = [qw(petstore_auth )];
# make the API Call
my $response = $self->{api_client}->call_api($_resource_path, $_method,
@@ -200,12 +248,27 @@ sub find_pets_by_status {
return $_response_object;
}
#
# find_pets_by_tags
#
# Finds Pets by tags
#
# @param ARRAY[string] $tags Tags to filter by (optional)
{
my $params = {
'tags' => {
data_type => 'ARRAY[string]',
description => 'Tags to filter by',
required => '0',
},
};
__PACKAGE__->method_documentation->{ find_pets_by_tags } = {
summary => 'Finds Pets by tags',
params => $params,
returns => 'ARRAY[Pet]',
};
}
# @return ARRAY[Pet]
#
sub find_pets_by_tags {
@@ -240,7 +303,7 @@ sub find_pets_by_tags {
# authentication setting, if any
my $auth_settings = ['petstore_auth'];
my $auth_settings = [qw(petstore_auth )];
# make the API Call
my $response = $self->{api_client}->call_api($_resource_path, $_method,
@@ -253,12 +316,27 @@ sub find_pets_by_tags {
return $_response_object;
}
#
# get_pet_by_id
#
# Find pet by ID
#
# @param int $pet_id ID of pet that needs to be fetched (required)
{
my $params = {
'pet_id' => {
data_type => 'int',
description => 'ID of pet that needs to be fetched',
required => '1',
},
};
__PACKAGE__->method_documentation->{ get_pet_by_id } = {
summary => 'Find pet by ID',
params => $params,
returns => 'Pet',
};
}
# @return Pet
#
sub get_pet_by_id {
@@ -300,7 +378,7 @@ sub get_pet_by_id {
# authentication setting, if any
my $auth_settings = ['api_key'];
my $auth_settings = [qw(api_key )];
# make the API Call
my $response = $self->{api_client}->call_api($_resource_path, $_method,
@@ -313,6 +391,7 @@ sub get_pet_by_id {
return $_response_object;
}
#
# update_pet_with_form
#
@@ -321,6 +400,30 @@ sub get_pet_by_id {
# @param string $pet_id ID of pet that needs to be updated (required)
# @param string $name Updated name of the pet (optional)
# @param string $status Updated status of the pet (optional)
{
my $params = {
'pet_id' => {
data_type => 'string',
description => 'ID of pet that needs to be updated',
required => '1',
},
'name' => {
data_type => 'string',
description => 'Updated name of the pet',
required => '0',
},
'status' => {
data_type => 'string',
description => 'Updated status of the pet',
required => '0',
},
};
__PACKAGE__->method_documentation->{ update_pet_with_form } = {
summary => 'Updates a pet in the store with form data',
params => $params,
returns => undef,
};
}
# @return void
#
sub update_pet_with_form {
@@ -372,7 +475,7 @@ sub update_pet_with_form {
# authentication setting, if any
my $auth_settings = ['petstore_auth'];
my $auth_settings = [qw(petstore_auth )];
# make the API Call
@@ -382,6 +485,7 @@ sub update_pet_with_form {
return;
}
#
# delete_pet
#
@@ -389,6 +493,25 @@ sub update_pet_with_form {
#
# @param int $pet_id Pet id to delete (required)
# @param string $api_key (optional)
{
my $params = {
'pet_id' => {
data_type => 'int',
description => 'Pet id to delete',
required => '1',
},
'api_key' => {
data_type => 'string',
description => '',
required => '0',
},
};
__PACKAGE__->method_documentation->{ delete_pet } = {
summary => 'Deletes a pet',
params => $params,
returns => undef,
};
}
# @return void
#
sub delete_pet {
@@ -433,7 +556,7 @@ sub delete_pet {
# authentication setting, if any
my $auth_settings = ['petstore_auth'];
my $auth_settings = [qw(petstore_auth )];
# make the API Call
@@ -443,6 +566,7 @@ sub delete_pet {
return;
}
#
# upload_file
#
@@ -451,6 +575,30 @@ sub delete_pet {
# @param int $pet_id ID of pet to update (required)
# @param string $additional_metadata Additional data to pass to server (optional)
# @param file $file file to upload (optional)
{
my $params = {
'pet_id' => {
data_type => 'int',
description => 'ID of pet to update',
required => '1',
},
'additional_metadata' => {
data_type => 'string',
description => 'Additional data to pass to server',
required => '0',
},
'file' => {
data_type => 'file',
description => 'file to upload',
required => '0',
},
};
__PACKAGE__->method_documentation->{ upload_file } = {
summary => 'uploads an image',
params => $params,
returns => undef,
};
}
# @return void
#
sub upload_file {
@@ -503,7 +651,7 @@ sub upload_file {
# authentication setting, if any
my $auth_settings = ['petstore_auth'];
my $auth_settings = [qw(petstore_auth )];
# make the API Call

View File

@@ -0,0 +1,323 @@
package WWW::SwaggerClient::Role;
use utf8;
use Moose::Role;
use namespace::autoclean;
use Class::Inspector;
use Log::Any qw($log);
use WWW::SwaggerClient::ApiFactory;
has base_url => ( is => 'ro',
required => 0,
isa => 'Str',
documentation => 'Root of the server that requests are sent to',
);
has api_factory => ( is => 'ro',
isa => 'WWW::SwaggerClient::ApiFactory',
builder => '_build_af',
lazy => 1,
documentation => 'Builds an instance of the endpoint API class',
);
has tokens => ( is => 'ro',
isa => 'HashRef',
required => 0,
default => sub { {} },
documentation => 'The auth tokens required by the application - basic, OAuth and/or API key(s)',
);
has _cfg => ( is => 'ro',
isa => 'Str',
default => 'WWW::SwaggerClient::Configuration',
);
has version_info => ( is => 'ro',
isa => 'HashRef',
default => sub { {
app_name => 'Swagger Petstore',
app_version => '1.0.0',
generated_date => '2015-11-13T20:46:43.271Z',
generator_class => 'class io.swagger.codegen.languages.PerlClientCodegen',
} },
documentation => 'Information about the application version and the codegen codebase version'
);
sub BUILD {
my $self = shift;
$self->_cfg->accept_tokens( $self->tokens ) if keys %{$self->tokens};
# ignore these symbols imported into API namespaces
my %outsiders = map {$_ => 1} qw( croak );
my %delegates;
# collect the methods callable on each API
foreach my $api_name ($self->api_factory->apis_available) {
my $api_class = $self->api_factory->classname_for($api_name);
my $methods = Class::Inspector->methods($api_class, 'expanded'); # not Moose, so use CI instead
my @local_methods = grep {! /^_/} grep {! $outsiders{$_}} map {$_->[2]} grep {$_->[1] eq $api_class} @$methods;
push( @{$delegates{$_}}, {api_name => $api_name, api_class => $api_class} ) for @local_methods;
}
# remove clashes
foreach my $method (keys %delegates) {
if ( @{$delegates{$method}} > 1 ) {
my ($apis) = delete $delegates{$method};
}
}
# build the flattened API
foreach my $api_name ($self->api_factory->apis_available) {
my $att_name = sprintf "%s_api", lc($api_name);
my $api_class = $self->api_factory->classname_for($api_name);
my @delegated = grep { $delegates{$_}->[0]->{api_name} eq $api_name } keys %delegates;
$log->debugf("Adding API: '%s' handles %s", $att_name, join ', ', @delegated);
$self->meta->add_attribute( $att_name => (
is => 'ro',
isa => $api_class,
default => sub {$self->api_factory->get_api($api_name)},
lazy => 1,
handles => \@delegated,
) );
}
}
sub _build_af {
my $self = shift;
my %args;
$args{base_url} = $self->base_url if $self->base_url;
return WWW::SwaggerClient::ApiFactory->new(%args);
}
=head1 NAME
WWW::SwaggerClient::Role - a Moose role for the Swagger Petstore
=head2 Swagger Petstore version: 1.0.0
=head1 VERSION
Automatically generated by the Perl Swagger Codegen project:
=over 4
=item Build date: 2015-11-13T20:46:43.271Z
=item Build package: class io.swagger.codegen.languages.PerlClientCodegen
=item Codegen version:
=back
=head2 A note on Moose
This role is the only component of the library that uses Moose. See
WWW::SwaggerClient::ApiFactory for non-Moosey usage.
=head1 SYNOPSIS
The Perl Swagger Codegen project builds a library of Perl modules to interact with
a web service defined by a Swagger specification. See below for how to build the
library.
This module provides an interface to the generated library. All the classes,
objects, and methods (well, not quite *all*, see below) are flattened into this
role.
package MyApp;
use Moose;
with 'WWW::SwaggerClient::Role';
package main;
my $api = MyApp->new({ tokens => $tokens });
my $pet = $api->get_pet_by_id(pet_id => $pet_id);
=head2 Structure of the library
The library consists of a set of API classes, one for each endpoint. These APIs
implement the method calls available on each endpoint.
Additionally, there is a set of "object" classes, which represent the objects
returned by and sent to the methods on the endpoints.
An API factory class is provided, which builds instances of each endpoint API.
This Moose role flattens all the methods from the endpoint APIs onto the consuming
class. It also provides methods to retrieve the endpoint API objects, and the API
factory object, should you need it.
For documentation of all these methods, see AUTOMATIC DOCUMENTATION below.
=head2 Configuring authentication
In the normal case, the Swagger spec will describe what parameters are
required and where to put them. You just need to supply the tokens.
my $tokens = {
# basic
username => $username,
password => $password,
# oauth
access_token => $oauth_token,
# keys
$some_key => { token => $token,
prefix => $prefix,
in => $in, # 'head||query',
},
$another => { token => $token,
prefix => $prefix,
in => $in, # 'head||query',
},
...,
};
my $api = MyApp->new({ tokens => $tokens });
Note these are all optional, as are C<prefix> and C<in>, and depend on the API
you are accessing. Usually C<prefix> and C<in> will be determined by the code generator from
the spec and you will not need to set them at run time. If not, C<in> will
default to 'head' and C<prefix> to the empty string.
The tokens will be placed in the C<WWW::SwaggerClient::Configuration> namespace
as follows, but you don't need to know about this.
=over 4
=item C<$WWW::SwaggerClient::Configuration::username>
String. The username for basic auth.
=item C<$WWW::SwaggerClient::Configuration::password>
String. The password for basic auth.
=item C<$WWW::SwaggerClient::Configuration::api_key>
Hashref. Keyed on the name of each key (there can be multiple tokens).
$WWW::SwaggerClient::Configuration::api_key = {
secretKey => 'aaaabbbbccccdddd',
anotherKey => '1111222233334444',
};
=item C<$WWW::SwaggerClient::Configuration::api_key_prefix>
Hashref. Keyed on the name of each key (there can be multiple tokens). Note not
all api keys require a prefix.
$WWW::SwaggerClient::Configuration::api_key_prefix = {
secretKey => 'string',
anotherKey => 'same or some other string',
};
=item C<$WWW::SwaggerClient::Configuration::access_token>
String. The OAuth access token.
=back
=head1 METHODS
=head2 C<base_url>
The generated code has the C<base_url> already set as a default value. This method
returns (and optionally sets, but only if the API client has not been
created yet) the current value of C<base_url>.
=head2 C<api_factory>
Returns an API factory object. You probably won't need to call this directly.
$self->api_factory('Pet'); # returns a WWW::SwaggerClient::PetApi instance
$self->pet_api; # the same
=head1 MISSING METHODS
Most of the methods on the API are delegated to individual endpoint API objects
(e.g. Pet API, Store API, User API etc). Where different endpoint APIs use the
same method name (e.g. C<new()>), these methods can't be delegated. So you need
to call C<$api-E<gt>pet_api-E<gt>new()>.
In principle, every API is susceptible to the presence of a few, random, undelegatable
method names. In practice, because of the way method names are constructed, it's
unlikely in general that any methods will be undelegatable, except for:
new()
class_documentation()
method_documentation()
To call these methods, you need to get a handle on the relevant object, either
by calling C<$api-E<gt>foo_api> or by retrieving an object, e.g.
C<$api-E<gt>get_pet_by_id(pet_id =E<gt> $pet_id)>. They are class methods, so
you could also call them on class names.
=head1 BUILDING YOUR LIBRARY
See the homepage C<https://github.com/swagger-api/swagger-codegen> for full details.
But briefly, clone the git repository, build the codegen codebase, set up your build
config file, then run the API build script. You will need git, Java 7 and Apache
maven 3.0.3 or better already installed.
The config file should specify the project name for the generated library:
{"moduleName":"MyProjectName"}
Your library files will be built under C<WWW::MyProjectName>.
$ git clone https://github.com/swagger-api/swagger-codegen.git
$ cd swagger-codegen
$ mvn package
$ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-i [URL or file path to JSON swagger API spec] \
-l perl \
-c /path/to/config/file.json \
-o /path/to/output/folder
Bang, all done. Run the C<autodoc> script in the C<bin> directory to see the API
you just built.
=head1 AUTOMATIC DOCUMENTATION
You can print out a summary of the generated API by running the included
C<autodoc> script in the C<bin> directory of your generated library. A few
output formats are supported:
Usage: autodoc [OPTION]
-w wide format (default)
-n narrow format
-p POD format
-H HTML format
-m Markdown format
-h print this help message
-c your application class
The C<-c> option allows you to load and inspect your own application. A dummy
namespace is used if you don't supply your own class.
=head1 DOCUMENTATION FROM THE SWAGGER SPEC
Additional documentation for each class and method may be provided by the Swagger
spec. If so, this is available via the C<class_documentation()> and
C<method_documentation()> methods on each generated object class, and the
C<method_documentation()> method on the endpoint API classes:
my $cmdoc = $api->pet_api->method_documentation->{$method_name};
my $odoc = $api->get_pet_by_id->(pet_id => $pet_id)->class_documentation;
my $omdoc = $api->get_pet_by_id->(pet_id => $pet_id)->method_documentation->{method_name};
Each of these calls returns a hashref with various useful pieces of information.
=cut
1;

View File

@@ -0,0 +1,427 @@
package WWW::SwaggerClient::Role::AutoDoc;
use List::MoreUtils qw(uniq);
use Moose::Role;
sub autodoc {
my ($self, $how) = @_;
die "Unknown format '$how'" unless $how =~ /^(pod|wide|narrow)$/;
$self->_printisa($how);
$self->_printmethods($how);
$self->_printattrs($how);
print "\n";
}
sub _printisa {
my ($self, $how) = @_;
my $meta = $self->meta;
my $myclass = ref $self;
my $super = join ', ', $meta->superclasses;
my @roles = $meta->calculate_all_roles;
#shift(@roles) if @roles > 1; # if > 1, the first is a composite, the rest are the roles
my $isa = join ', ', grep {$_ ne $myclass} $meta->linearized_isa;
my $sub = join ', ', $meta->subclasses;
my $dsub = join ', ', $meta->direct_subclasses;
my $app_name = $self->version_info->{app_name};
my $app_version = $self->version_info->{app_version};
my $generated_date = $self->version_info->{generated_date};
my $generator_class = $self->version_info->{generator_class};
$~ = $how eq 'pod' ? 'INHERIT_POD' : 'INHERIT';
write;
my ($rolepkg, $role_reqs);
foreach my $role (@roles) {
$rolepkg = $role->{package} || next; # some are anonymous, or something
next if $rolepkg eq 'WWW::SwaggerClient::Role::AutoDoc';
$role_reqs = join ', ', keys %{$role->{required_methods}};
$role_reqs ||= '';
$~ = $how eq 'pod' ? 'ROLES_POD' : 'ROLES';
write;
}
if ($how eq 'pod') {
$~ = 'ROLES_POD_CLOSE';
write;
}
# ----- format specs -----
format INHERIT =
@* -
$myclass
ISA: @*
$isa
Direct subclasses: @*
$dsub
All subclasses: @*
$sub
Target API: @* @*
$app_name, $app_version
Generated on: @*
$generated_date
Generator class: @*
$generator_class
.
format ROLES =
Composes: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~
$rolepkg
requires: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~
$role_reqs
^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~
$role_reqs
.
format INHERIT_POD =
=head1 NAME
@*
$myclass
=head1 VERSION
=head2 @* version: @*
$app_name, $app_version
Automatically generated by the Perl Swagger Codegen project:
=over 4
=item Build date: @*
$generated_date
=item Build package: @*
$generator_class
=item Codegen version:
=back
=head1 INHERITANCE
=head2 Base class(es)
@*
$isa
=head2 Direct subclasses
@*
$dsub
=head2 All subclasses
@*
$sub
=head1 COMPOSITION
@* composes the following roles:
$myclass
.
format ROLES_POD =
=head2 C<@*>
$rolepkg
Requires:
@*
$role_reqs
.
format ROLES_POD_CLOSE =
.
# ----- / format specs -----
}
sub _printmethods {
my ($self, $how) = @_;
if ($how eq 'narrow') {
print <<HEAD;
METHODS
-------
HEAD
}
elsif ($how eq 'wide') {
$~ = 'METHODHEAD';
write;
}
elsif ($how eq 'pod') {
$~ = 'METHODHEAD_POD';
write;
}
else {
die "Don't know how to print '$how'";
}
$self->_printmethod($_, $how) for uniq sort $self->meta->get_all_method_names; #$self->meta->get_method_list,
if ($how eq 'pod') {
$~ = 'METHOD_POD_CLOSE';
write;
}
}
sub _printmethod {
my ($self, $methodname, $how) = @_;
return if $methodname =~ /^_/;
return if $self->meta->has_attribute($methodname);
my %internal = map {$_ => 1} qw(BUILD BUILDARGS meta can new DEMOLISHALL DESTROY
DOES isa BUILDALL does VERSION dump
);
return if $internal{$methodname};
my $method = $self->meta->get_method($methodname) or return; # symbols imported into namespaces i.e. not known by Moose
return if $method->original_package_name eq __PACKAGE__;
my $delegate_to = '';
my $via = '';
my $on = '';
my $doc = '';
my $original_pkg = $method->original_package_name;
if ($method->can('associated_attribute')) {
$delegate_to = $method->delegate_to_method;
my $aa = $method->associated_attribute;
$on = $aa->{isa};
$via = $aa->{name};
$original_pkg = $on;
$doc = $original_pkg->method_documentation->{$delegate_to}->{summary};
}
else {
$doc = $method->documentation;
}
if ($how eq 'narrow') {
$~ = 'METHOD_NARROW';
write;
}
elsif ($how eq 'pod' and $delegate_to) {
$~ = 'METHOD_POD_DELEGATED';
write;
}
elsif ($how eq 'pod') {
$~ = 'METHOD_POD';
write;
}
else {
$~ = 'METHOD';
write;
}
# ----- format specs -----
format METHODHEAD =
METHODS
-------
Name delegates to on via
===========================================================================================================================================================================
.
format METHOD =
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<... @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<... @<<<<<<<<<<<<<<<<...
$methodname, $delegate_to, $on, $via
.
format METHOD_NARROW =
@*
$methodname
original pkg: @*
$original_pkg
delegates to: @*
$delegate_to
on: @*
$on
via: @*
$via
.
format METHODHEAD_POD =
=head1 METHODS
.
format METHOD_POD =
=head2 C<@*()>
$methodname
Defined in: @*
$original_pkg
.
format METHOD_POD_DELEGATED =
=head2 C<@*()>
$methodname
Defined in: @*
$original_pkg
Delegates to: @*()
$delegate_to
On: @*
$on
Via: @*()
$via
Doc: @*
$doc
Same as: $self->@*->@*()
$via, $delegate_to
.
format METHOD_POD_CLOSE =
.
# ----- / format specs -----
}
sub _printattrs {
my ($self, $how) = @_;
if ($how eq 'narrow') {
print <<HEAD;
ATTRIBUTES
----------
HEAD
}
elsif ($how eq 'wide') {
$~ = 'ATTRHEAD';
write;
}
elsif ($how eq 'pod') {
$~ = 'ATTRHEAD_POD';
write;
}
else {
die "Don't know how to print attributes '$how'";
}
$self->_printattr($_, $how) for sort $self->meta->get_attribute_list;
if ($how eq 'pod') {
$~ = 'ATTR_POD_CLOSE';
write;
}
}
sub _printattr {
my ($self, $attrname, $how) = @_;
return if $attrname =~ /^_/;
my $attr = $self->meta->get_attribute($attrname) or die "No attr for $attrname";
my $is;
$is = 'rw' if $attr->get_read_method && $attr->get_write_method;
$is = 'ro' if $attr->get_read_method && ! $attr->get_write_method;
$is = 'wo' if $attr->get_write_method && ! $attr->get_read_method;
$is = '--' if ! $attr->get_write_method && ! $attr->get_read_method;
$is or die "No \$is for $attrname";
my $tc = $attr->type_constraint || '';
my $from = $attr->associated_class->name || '';
my $reqd = $attr->is_required ? 'yes' : 'no';
my $lazy = $attr->is_lazy ? 'yes' : 'no';
my $has_doc = $attr->has_documentation ? 'yes' : 'no'; # *_api attributes will never have doc, but other attributes might have
my $doc = $attr->documentation || '';
my $handles = join ', ', sort @{$attr->handles || []};
$handles ||= '';
if ($how eq 'narrow') {
$~ = 'ATTR_NARROW';
}
elsif ($how eq 'pod') {
$~ = 'ATTR_POD';
}
else {
$~ = 'ATTR';
}
write;
# ----- format specs -----
format ATTRHEAD =
ATTRIBUTES
----------
Name is isa reqd lazy doc handles
==============================================================================================================
.
format ATTR =
@<<<<<<<<<<<<<<<<< @< @<<<<<<<<<<<<<<<<<<<<<<<< @<<< @<<< @<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$attrname, $is, $tc, $reqd, $lazy, $has_doc, $handles
^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~
$handles
.
format ATTR_NARROW =
@*
$attrname
is: @*
$is
isa: @*
$tc
reqd: @*
$reqd
lazy: @*
$lazy
doc: @*
$doc
handles: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$handles
^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~
$handles
.
format ATTRHEAD_POD =
=head1 ATTRIBUTES
.
format ATTR_POD =
=head2 C<@*>
$attrname
is: @*
$is
isa: @*
$tc
reqd: @*
$reqd
lazy: @*
$lazy
doc: @*
$doc
handles: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$handles
^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~
$handles
.
format ATTR_POD_CLOSE =
.
# ----- / format specs -----
}
1;

View File

@@ -30,11 +30,14 @@ use Log::Any qw($log);
use WWW::SwaggerClient::ApiClient;
use WWW::SwaggerClient::Configuration;
use base "Class::Data::Inheritable";
__PACKAGE__->mk_classdata('method_documentation' => {});
sub new {
my $class = shift;
my $default_api_client = $WWW::SwaggerClient::Configuration::api_client ? $WWW::SwaggerClient::Configuration::api_client : WWW::SwaggerClient::ApiClient->new;
my (%self) = (
'api_client' => $default_api_client,
'api_client' => WWW::SwaggerClient::ApiClient->instance,
@_
);
@@ -47,11 +50,21 @@ sub new {
}
#
# get_inventory
#
# Returns pet inventories by status
#
{
my $params = {
};
__PACKAGE__->method_documentation->{ get_inventory } = {
summary => 'Returns pet inventories by status',
params => $params,
returns => 'HASH[string,int]',
};
}
# @return HASH[string,int]
#
sub get_inventory {
@@ -83,7 +96,7 @@ sub get_inventory {
# authentication setting, if any
my $auth_settings = ['api_key'];
my $auth_settings = [qw(api_key )];
# make the API Call
my $response = $self->{api_client}->call_api($_resource_path, $_method,
@@ -96,12 +109,27 @@ sub get_inventory {
return $_response_object;
}
#
# place_order
#
# Place an order for a pet
#
# @param Order $body order placed for purchasing the pet (optional)
{
my $params = {
'body' => {
data_type => 'Order',
description => 'order placed for purchasing the pet',
required => '0',
},
};
__PACKAGE__->method_documentation->{ place_order } = {
summary => 'Place an order for a pet',
params => $params,
returns => 'Order',
};
}
# @return Order
#
sub place_order {
@@ -136,7 +164,7 @@ sub place_order {
}
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call
my $response = $self->{api_client}->call_api($_resource_path, $_method,
@@ -149,12 +177,27 @@ sub place_order {
return $_response_object;
}
#
# get_order_by_id
#
# Find purchase order by ID
#
# @param string $order_id ID of pet that needs to be fetched (required)
{
my $params = {
'order_id' => {
data_type => 'string',
description => 'ID of pet that needs to be fetched',
required => '1',
},
};
__PACKAGE__->method_documentation->{ get_order_by_id } = {
summary => 'Find purchase order by ID',
params => $params,
returns => 'Order',
};
}
# @return Order
#
sub get_order_by_id {
@@ -196,7 +239,7 @@ sub get_order_by_id {
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call
my $response = $self->{api_client}->call_api($_resource_path, $_method,
@@ -209,12 +252,27 @@ sub get_order_by_id {
return $_response_object;
}
#
# delete_order
#
# Delete purchase order by ID
#
# @param string $order_id ID of the order that needs to be deleted (required)
{
my $params = {
'order_id' => {
data_type => 'string',
description => 'ID of the order that needs to be deleted',
required => '1',
},
};
__PACKAGE__->method_documentation->{ delete_order } = {
summary => 'Delete purchase order by ID',
params => $params,
returns => undef,
};
}
# @return void
#
sub delete_order {
@@ -256,7 +314,7 @@ sub delete_order {
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call

View File

@@ -30,11 +30,14 @@ use Log::Any qw($log);
use WWW::SwaggerClient::ApiClient;
use WWW::SwaggerClient::Configuration;
use base "Class::Data::Inheritable";
__PACKAGE__->mk_classdata('method_documentation' => {});
sub new {
my $class = shift;
my $default_api_client = $WWW::SwaggerClient::Configuration::api_client ? $WWW::SwaggerClient::Configuration::api_client : WWW::SwaggerClient::ApiClient->new;
my (%self) = (
'api_client' => $default_api_client,
'api_client' => WWW::SwaggerClient::ApiClient->instance,
@_
);
@@ -47,12 +50,27 @@ sub new {
}
#
# create_user
#
# Create user
#
# @param User $body Created user object (optional)
{
my $params = {
'body' => {
data_type => 'User',
description => 'Created user object',
required => '0',
},
};
__PACKAGE__->method_documentation->{ create_user } = {
summary => 'Create user',
params => $params,
returns => undef,
};
}
# @return void
#
sub create_user {
@@ -87,7 +105,7 @@ sub create_user {
}
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call
@@ -97,12 +115,27 @@ sub create_user {
return;
}
#
# create_users_with_array_input
#
# Creates list of users with given input array
#
# @param ARRAY[User] $body List of user object (optional)
{
my $params = {
'body' => {
data_type => 'ARRAY[User]',
description => 'List of user object',
required => '0',
},
};
__PACKAGE__->method_documentation->{ create_users_with_array_input } = {
summary => 'Creates list of users with given input array',
params => $params,
returns => undef,
};
}
# @return void
#
sub create_users_with_array_input {
@@ -137,7 +170,7 @@ sub create_users_with_array_input {
}
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call
@@ -147,12 +180,27 @@ sub create_users_with_array_input {
return;
}
#
# create_users_with_list_input
#
# Creates list of users with given input array
#
# @param ARRAY[User] $body List of user object (optional)
{
my $params = {
'body' => {
data_type => 'ARRAY[User]',
description => 'List of user object',
required => '0',
},
};
__PACKAGE__->method_documentation->{ create_users_with_list_input } = {
summary => 'Creates list of users with given input array',
params => $params,
returns => undef,
};
}
# @return void
#
sub create_users_with_list_input {
@@ -187,7 +235,7 @@ sub create_users_with_list_input {
}
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call
@@ -197,6 +245,7 @@ sub create_users_with_list_input {
return;
}
#
# login_user
#
@@ -204,6 +253,25 @@ sub create_users_with_list_input {
#
# @param string $username The user name for login (optional)
# @param string $password The password for login in clear text (optional)
{
my $params = {
'username' => {
data_type => 'string',
description => 'The user name for login',
required => '0',
},
'password' => {
data_type => 'string',
description => 'The password for login in clear text',
required => '0',
},
};
__PACKAGE__->method_documentation->{ login_user } = {
summary => 'Logs user into the system',
params => $params,
returns => 'string',
};
}
# @return string
#
sub login_user {
@@ -241,7 +309,7 @@ sub login_user {
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call
my $response = $self->{api_client}->call_api($_resource_path, $_method,
@@ -254,11 +322,21 @@ sub login_user {
return $_response_object;
}
#
# logout_user
#
# Logs out current logged in user session
#
{
my $params = {
};
__PACKAGE__->method_documentation->{ logout_user } = {
summary => 'Logs out current logged in user session',
params => $params,
returns => undef,
};
}
# @return void
#
sub logout_user {
@@ -290,7 +368,7 @@ sub logout_user {
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call
@@ -300,12 +378,27 @@ sub logout_user {
return;
}
#
# get_user_by_name
#
# Get user by user name
#
# @param string $username The name that needs to be fetched. Use user1 for testing. (required)
{
my $params = {
'username' => {
data_type => 'string',
description => 'The name that needs to be fetched. Use user1 for testing.',
required => '1',
},
};
__PACKAGE__->method_documentation->{ get_user_by_name } = {
summary => 'Get user by user name',
params => $params,
returns => 'User',
};
}
# @return User
#
sub get_user_by_name {
@@ -347,7 +440,7 @@ sub get_user_by_name {
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call
my $response = $self->{api_client}->call_api($_resource_path, $_method,
@@ -360,6 +453,7 @@ sub get_user_by_name {
return $_response_object;
}
#
# update_user
#
@@ -367,6 +461,25 @@ sub get_user_by_name {
#
# @param string $username name that need to be deleted (required)
# @param User $body Updated user object (optional)
{
my $params = {
'username' => {
data_type => 'string',
description => 'name that need to be deleted',
required => '1',
},
'body' => {
data_type => 'User',
description => 'Updated user object',
required => '0',
},
};
__PACKAGE__->method_documentation->{ update_user } = {
summary => 'Updated user',
params => $params,
returns => undef,
};
}
# @return void
#
sub update_user {
@@ -411,7 +524,7 @@ sub update_user {
}
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call
@@ -421,12 +534,27 @@ sub update_user {
return;
}
#
# delete_user
#
# Delete user
#
# @param string $username The name that needs to be deleted (required)
{
my $params = {
'username' => {
data_type => 'string',
description => 'The name that needs to be deleted',
required => '1',
},
};
__PACKAGE__->method_documentation->{ delete_user } = {
summary => 'Delete user',
params => $params,
returns => undef,
};
}
# @return void
#
sub delete_user {
@@ -468,7 +596,7 @@ sub delete_user {
# authentication setting, if any
my $auth_settings = [];
my $auth_settings = [qw()];
# make the API Call

View File

@@ -65,6 +65,19 @@
</arguments>
</configuration>
</execution>
<execution>
<id>Test::More for Role</id>
<phase>integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>perl</executable>
<arguments>
<argument>t/04_role.t</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>

View File

@@ -1,4 +1,4 @@
use Test::More tests => 37;
use Test::More tests => 38;
use Test::Exception;
use lib 'lib';
@@ -11,12 +11,18 @@ use_ok('WWW::SwaggerClient::Object::Pet');
use_ok('WWW::SwaggerClient::Object::Tag');
use_ok('WWW::SwaggerClient::Object::Category');
my $api_client = WWW::SwaggerClient::ApiClient->new('base_url' => 'http://testing');
my $api_client = WWW::SwaggerClient::ApiClient->instance('base_url' => 'http://testing');
my $pet_api = WWW::SwaggerClient::PetApi->new('api_client' => $api_client);
is $pet_api->{api_client}->{base_url}, 'http://testing', 'get the proper base URL from api client';
my $api = WWW::SwaggerClient::PetApi->new();
is $api->{api_client}->{base_url}, 'http://testing', 'we still get the original base URL from api client, because it\'s a singleton';
# reset the base_url - no direct access because an application shouldn't be changing
# its base URL halfway through
$api->{api_client}->{base_url} = 'http://petstore.swagger.io/v2';
is $api->{api_client}->{base_url}, 'http://petstore.swagger.io/v2', 'get the default base URL from api client';
# test select_header_content_type

View File

@@ -15,7 +15,7 @@ use_ok('WWW::SwaggerClient::Object::Category');
use_ok('WWW::SwaggerClient::Object::User');
my $api_client = WWW::SwaggerClient::ApiClient->new();
my $api_client = WWW::SwaggerClient::ApiClient->instance();
my $store_api = WWW::SwaggerClient::StoreApi->new('api_client' => $api_client);
is $store_api->{api_client}->{base_url}, 'http://petstore.swagger.io/v2', 'get the default base URL from api client';

View File

@@ -1,4 +1,4 @@
use Test::More tests => 13;
use Test::More tests => 19;
use Test::Exception;
use lib 'lib';
@@ -15,6 +15,9 @@ is $pet_api->{api_client}->{base_url}, 'http://testing', 'get the proper base UR
$api_factory = WWW::SwaggerClient::ApiFactory->new;
$pet_api = $api_factory->get_api('Pet');
# reset the base_url - no direct access because an application shouldn't be changing
# its base URL halfway through
$pet_api->{api_client}->{base_url} = 'http://petstore.swagger.io/v2';
is $pet_api->{api_client}->{base_url}, 'http://petstore.swagger.io/v2', 'get the default base URL from api client';
# test accessor methods
@@ -32,3 +35,15 @@ is $pet->category->id, '22', 'got the proper category id';
is $pet->category->name, 'perl', 'got the proper category name';
is $pet->tags->[0]->name, 'just kidding', 'got the proper tag name';
is $pet->tags->[0]->id, '11', 'got the proper tag id';
my $add_pet = $pet_api->add_pet(body => $pet);
my $get_pet = $pet_api->get_pet_by_id(pet_id => $pet_id);
is $get_pet->id, '10008', 'stored and retrieved: got the proper pet id';
is $get_pet->name, 'perl test', 'stored and retrieved: got the proper pet name';
is $get_pet->category->id, '22', 'stored and retrieved: got the proper category id';
is $get_pet->category->name, 'perl', 'stored and retrieved: got the proper category name';
is $get_pet->tags->[0]->name, 'just kidding', 'stored and retrieved: got the proper tag name';
is $get_pet->tags->[0]->id, '11', 'stored and retrieved: got the proper tag id';

View File

@@ -0,0 +1,143 @@
use Test::More tests => 37;
use Test::Exception;
use Test::Warnings 'warnings';
use Test::Deep;
use lib 'lib';
use strict;
use warnings;
SKIP: {
eval "
package MyApp;
use Moose;
with 'WWW::SwaggerClient::Role';
sub auth_setup_handler {}
";
# die $@ if $@;
skip 'Moose not installed', 37 if $@;
my $api = MyApp->new;
my $pet_id = 10008;
# note - we don't need to 'use' these modules because they've already been loaded by ApiFactory
my ($category, $tag, $pet);
lives_ok { $category = WWW::SwaggerClient::Object::Category->new('id' => '22', 'name' => 'perl') } 'Category.pm loaded OK';
lives_ok { $tag = WWW::SwaggerClient::Object::Tag->new('id' => '11', 'name' => 'just kidding') } 'Tag.pm loaded OK';
lives_ok { $pet = WWW::SwaggerClient::Object::Pet->new('id' => $pet_id, 'name' => 'perl test',
"photoUrls" => ['123', 'oop'], 'tags' => [$tag], 'status' => 'pending', 'category' => $category) } 'Pet.pm loaded OK';
is $pet->id, '10008', 'got the proper pet id';
is $pet->name, 'perl test', 'got the proper pet name';
is $pet->category->id, '22', 'got the proper category id';
is $pet->category->name, 'perl', 'got the proper category name';
is $pet->tags->[0]->name, 'just kidding', 'got the proper tag name';
is $pet->tags->[0]->id, '11', 'got the proper tag id';
my $add_pet = $api->add_pet(body => $pet);
my $get_pet = $api->get_pet_by_id(pet_id => $pet_id);
is $get_pet->id, '10008', 'stored and retrieved: got the proper pet id';
is $get_pet->name, 'perl test', 'stored and retrieved: got the proper pet name';
is $get_pet->category->id, '22', 'stored and retrieved: got the proper category id';
is $get_pet->category->name, 'perl', 'stored and retrieved: got the proper category name';
is $get_pet->tags->[0]->name, 'just kidding', 'stored and retrieved: got the proper tag name';
is $get_pet->tags->[0]->id, '11', 'stored and retrieved: got the proper tag id';
# documentation tests
# API method docs
is_deeply( [sort keys %{$api->pet_api->method_documentation}],
[ 'add_pet', 'delete_pet', 'find_pets_by_status', 'find_pets_by_tags', 'get_pet_by_id', 'update_pet', 'update_pet_with_form', 'upload_file'],
"Pet API method_documentation has the correct keys");
is $api->pet_api->method_documentation->{get_pet_by_id}->{params}->{pet_id}->{description},
'ID of pet that needs to be fetched', 'get_pet_by_id parameter pet_id description is correct';
is $api->pet_api->method_documentation->{get_pet_by_id}->{params}->{pet_id}->{required},
1, 'get_pet_by_id parameter pet_id is required';
is $api->pet_api->method_documentation->{get_pet_by_id}->{params}->{pet_id}->{data_type},
'int', 'get_pet_by_id parameter pet_id is an int';
is $api->pet_api->method_documentation->{get_pet_by_id}->{returns},
'Pet', 'get_pet_by_id returns a Pet';
is $api->pet_api->method_documentation->{get_pet_by_id}->{summary},
'Find pet by ID', 'get_pet_by_id summary is correct';
# object class docs
my $pet_class_doco = { 'description' => '', required => [], class => 'Pet' };
is_deeply($get_pet->class_documentation, $pet_class_doco, 'Pet object class_documentation is available');
is $get_pet->class_documentation->{description}, '', 'Pet object class_documentation is correct'; # right now it's blank
is $get_pet->class_documentation->{class}, 'Pet', 'Pet object class_documentation returns correct class name';
# object method docs
is $get_pet->method_documentation->{status}->{description}, 'pet status in the store', 'Pet object method_documentation for status() - description is correct';
is $get_pet->method_documentation->{status}->{format}, '', 'Pet object method_documentation for status() - format is correct';
is $get_pet->method_documentation->{status}->{base_name}, 'status', 'Pet object method_documentation for status() - base_name is correct';
is $get_pet->method_documentation->{status}->{datatype}, 'string', 'Pet object method_documentation for status() - datatype is correct';
# / documentation tests
my $tokens = {
username => 'UserName',
password => 'PassWord',
access_token => 'OAuth_token',
someKey => { token => 'some_key_token',
prefix => 'some_key_prefix',
in => 'query',
},
anotherKey => { token => 'another_key_token',
},
};
$api->_cfg->accept_tokens({%$tokens}); # pass a copy
no warnings 'once';
is $WWW::SwaggerClient::Configuration::username, 'UserName', 'accept_tokens() correctly set the username';
is $WWW::SwaggerClient::Configuration::password, 'PassWord', 'accept_tokens() correctly set the password';
is $WWW::SwaggerClient::Configuration::access_token, 'OAuth_token', 'accept_tokens() correctly set the oauth';
my $api_key_href = {
'anotherKey' => 'another_key_token',
'someKey' => 'some_key_token'
};
cmp_deeply( $WWW::SwaggerClient::Configuration::api_key, $api_key_href, 'accept_tokens() correctly set api_key' );
my $api_key_prefix_href = {
'someKey' => 'some_key_prefix'
};
cmp_deeply( $WWW::SwaggerClient::Configuration::api_key_prefix, $api_key_prefix_href, 'accept_tokens() correctly set api_key_prefix' );
my $api_key_in = {
'someKey' => 'query',
'anotherKey' => 'head'
};
cmp_deeply( $WWW::SwaggerClient::Configuration::api_key_in, $api_key_in, 'accept_tokens() correctly set api_key_in' );
use warnings 'once';
my $cleared_tokens_cmp = {
'anotherKey' => {
'in' => 'head',
'token' => 'another_key_token',
'prefix' => undef
},
'access_token' => 'OAuth_token',
'someKey' => {
'token' => 'some_key_token',
'in' => 'query',
'prefix' => 'some_key_prefix'
},
'username' => 'UserName',
'password' => 'PassWord'
};
cmp_deeply( $api->_cfg->clear_tokens, $cleared_tokens_cmp, 'clear_tokens() returns the correct data structure' );
my $bad_token = { bad_token_name => 'bad token value' }; # value should should be hashref
dies_ok { $api->_cfg->accept_tokens($bad_token) } "bad token causes exception";
} # / SKIP