forked from loafle/openapi-generator-original
Documentation and automatic documentation
- added POD to Role.pm - added README.md files translated from Role.pm POD - added an autodoc script (based on AutoDoc.pm role). The script prints a listing of the methods built in Role.pm - added class_documentation() and method_documentation() accessors on all object and API classes which return the documentation supplied in the Swagger spec for the API
This commit is contained in:
@@ -69,6 +69,173 @@ sub _build_af {
|
||||
return WWW::SwaggerClient::ApiFactory->new(%args);
|
||||
}
|
||||
|
||||
=head1 NAME
|
||||
|
||||
WWW::SwaggerClient::Role - a Moose role for the Perl Swagger Codegen project
|
||||
|
||||
=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;
|
||||
has [qw(username password)] => ( is => 'ro', required => 1, isa => 'Str' );
|
||||
with 'WWW::SwaggerClient::Role';
|
||||
sub auth_setup_handler {...}
|
||||
|
||||
package main;
|
||||
|
||||
my $api = MyApp->new({username => $username, password => $password});
|
||||
|
||||
my $pet = $api->get_pet_by_id(pet_id => $pet_id);
|
||||
|
||||
Notice that you need to provide the code to accept the parameters passed in to C<new()>
|
||||
(by setting up attributes via the C<has> keyword). They should be used by
|
||||
C<auth_setup_handler()> to configure authentication (see below).
|
||||
|
||||
=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.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 C<auth_setup_handler()>
|
||||
|
||||
This method is NOT provided - you must write it yourself. Its task is to configure
|
||||
authentication for each request.
|
||||
|
||||
The method is called on your C<$api> object and passed the following parameters:
|
||||
|
||||
=over 4
|
||||
|
||||
=item C<header_params>
|
||||
|
||||
A hashref that will become the request headers. You can insert auth
|
||||
parameters.
|
||||
|
||||
=item C<query_params>
|
||||
|
||||
A hashref that will be encoded into the request URL. You can insert auth
|
||||
parameters.
|
||||
|
||||
=item C<auth_settings>
|
||||
|
||||
TODO.
|
||||
|
||||
=item C<api_client>
|
||||
|
||||
A reference to the C<WWW::SwaggerClient::ApiClient> object that is responsible
|
||||
for communicating with the server.
|
||||
|
||||
=back
|
||||
|
||||
For example:
|
||||
|
||||
sub auth_setup_handler {
|
||||
my ($self, %p) = @_;
|
||||
$p{header_params}->{'X-TargetApp-apiKey'} = $api_key;
|
||||
$p{header_params}->{'X-TargetApp-secretKey'} = $secret_key;
|
||||
}
|
||||
|
||||
=head2 base_url
|
||||
|
||||
The generated code has the C<base_url> already set as a default value. This method
|
||||
returns (and optionally sets) the current value of C<base_url>.
|
||||
|
||||
=head2 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 sub-API objects (e.g.
|
||||
Pet API, Store API, User API etc). Where different sub-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)>.
|
||||
|
||||
=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.
|
||||
|
||||
=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 API and class:
|
||||
|
||||
my $cdoc = $api->pet_api->class_documentation;
|
||||
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;
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
package WWW::SwaggerClient::Role::AutoDoc;
|
||||
use List::MoreUtils qw(uniq);
|
||||
|
||||
use Moose::Role;
|
||||
|
||||
sub autodoc {
|
||||
my $self = shift;
|
||||
|
||||
$self->_printisa;
|
||||
$self->_printmethods;
|
||||
$self->_printattrs;
|
||||
print "\n";
|
||||
}
|
||||
|
||||
sub _printisa {
|
||||
my $self = shift;
|
||||
my $meta = $self->meta;
|
||||
|
||||
my $myclass = ref $self;
|
||||
|
||||
my $super = join ', ', $meta->superclasses;
|
||||
my @roles = $meta->calculate_all_roles;
|
||||
shift(@roles); # the first is a composite, the rest are the roles
|
||||
|
||||
my $isa = join ', ', $meta->linearized_isa;
|
||||
my $sub = join ', ', $meta->subclasses;
|
||||
my $dsub = join ', ', $meta->direct_subclasses;
|
||||
|
||||
my ($rolepkg, $role_reqs);
|
||||
|
||||
$~ = 'INHERIT';
|
||||
write;
|
||||
|
||||
foreach my $role (@roles) {
|
||||
$rolepkg = $role->{package};
|
||||
$role_reqs = join ', ', keys %{$role->{required_methods}};
|
||||
$~ = 'ROLES';
|
||||
write;
|
||||
}
|
||||
|
||||
# ----- format specs -----
|
||||
format INHERIT =
|
||||
|
||||
@* -
|
||||
$myclass
|
||||
ISA: @*
|
||||
$isa
|
||||
Direct subclasses: @*
|
||||
$dsub
|
||||
All subclasses: @*
|
||||
$sub
|
||||
.
|
||||
format ROLES =
|
||||
Composes: @*
|
||||
$rolepkg
|
||||
requires: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~
|
||||
$role_reqs
|
||||
.
|
||||
# ----- / format specs -----
|
||||
}
|
||||
|
||||
sub _printmethods {
|
||||
my $self = shift;
|
||||
$~ = 'METHODHEAD';
|
||||
write;
|
||||
$self->_printmethod($_) for uniq sort $self->meta->get_method_list, $self->meta->get_all_method_names;
|
||||
}
|
||||
|
||||
sub _printmethod {
|
||||
my ($self, $methodname) = @_;
|
||||
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 $delegation = '';
|
||||
my $delegate_to = '';
|
||||
my $via = '';
|
||||
my $on = '';
|
||||
if ($method->can('associated_attribute')) {
|
||||
$delegate_to = $method->delegate_to_method;
|
||||
my $aa = $method->associated_attribute;
|
||||
$on = $aa->{isa};
|
||||
$via = $aa->{name};
|
||||
}
|
||||
|
||||
$~ = 'METHOD';
|
||||
write;
|
||||
|
||||
# ----- format specs -----
|
||||
format METHODHEAD =
|
||||
|
||||
METHODS
|
||||
-------
|
||||
Name delegate to on via
|
||||
===================================================================================================================================
|
||||
.
|
||||
format METHOD =
|
||||
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<... @<<<<<<<<<<<<<<<<<<<<<<<<<... @<<<<<<<<<<<<<<<<...
|
||||
$methodname, $delegate_to, $on, $via
|
||||
.
|
||||
# ----- / format specs -----
|
||||
}
|
||||
|
||||
sub _printattrs {
|
||||
my $self = shift;
|
||||
$~ = 'ATTRHEAD';
|
||||
write;
|
||||
$self->_printattr($_) for sort $self->meta->get_attribute_list;
|
||||
}
|
||||
|
||||
sub _printattr {
|
||||
my ($self, $attrname) = @_;
|
||||
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 ? 'reqd' : 'opt';
|
||||
my $lazy = $attr->is_lazy ? 'lazy' : '';
|
||||
my $doc = $attr->has_documentation ? 'yes' : '';
|
||||
my $handles = join ', ', sort @{$attr->handles || []};
|
||||
|
||||
$~ = 'ATTR';
|
||||
write;
|
||||
|
||||
# ----- format specs -----
|
||||
format ATTRHEAD =
|
||||
|
||||
ATTRIBUTES
|
||||
----------
|
||||
Name is isa reqd lazy doc handles
|
||||
==============================================================================================================
|
||||
.
|
||||
format ATTR =
|
||||
@<<<<<<<<<<<<<<<<< @< @<<<<<<<<<<<<<<<<<<<<<<<< @<<< @<<< @<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
$attrname, $is, $tc, $reqd, $lazy, $doc, $handles
|
||||
^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~
|
||||
$handles
|
||||
.
|
||||
# ----- / format specs -----
|
||||
}
|
||||
|
||||
1;
|
||||
Reference in New Issue
Block a user