Modern-OpenAPI-Generator

 view release on metacpan or  search on metacpan

lib/Modern/OpenAPI/Generator/CodeGen/Client.pm  view on Meta::CPAN

}

sub request_sync {
  my ( \$self, \$meta, \$args ) = \@_;
  \$self->ua->blocking(1);
  my \$tx = \$self->build_tx( \$meta, \$args );
  \$self->_apply_auth(\$tx, \$meta);
  if ( my \$err = \$self->_request_validation_error( \$meta, \$tx ) ) {
    croak \$err;
  }
  \$self->ua->start(\$tx);
  return \$self->_result_from_tx( \$tx, \$meta );
}

sub request_p {
  my ( \$self, \$meta, \$args ) = \@_;
  \$self->ua->blocking(0);
  my \$tx = \$self->build_tx( \$meta, \$args );
  \$self->_apply_auth(\$tx, \$meta );
  if ( my \$err = \$self->_request_validation_error( \$meta, \$tx ) ) {
    return Mojo::Promise->reject(\$err);
  }
  return \$self->ua->start_p(\$tx)->then(
    sub (\$tx) {
      return \$self->_result_from_tx( \$tx, \$meta );
    }
  );
}

sub _result_from_tx {
  my ( \$self, \$tx, \$meta ) = \@_;
  if ( my \$err = \$self->_response_validation_error( \$meta, \$tx ) ) {
    croak \$err;
  }
  my \$data = \$self->_inflate_response( \$tx, \$meta );
  return ${rc}->new( tx => \$tx, data => \$data );
}

sub _inflate_response {
  my ( \$self, \$tx, \$meta ) = \@_;
  my \$code = \$tx->res->code // 0;
  return undef unless \$code >= 200 && \$code < 300;
  my \$ct = \$tx->res->headers->content_type // '';
  return undef unless \$ct =~ m{json}i;
  my \$json = \$tx->res->json;
  return undef unless defined \$json;
  my \$pkg = \$meta->{response_model} // '';
  return \$json if !length \$pkg;
  my \$ok = eval { require \$pkg; 1 };
  return \$json if !\$ok || !\$pkg->can('from_json');
  my \$out = eval { \$pkg->from_json( \$json, \$meta->{response_is_array} // 0 ) };
  return defined \$out ? \$out : \$json;
}

MID

    return <<"HEAD" . $mid . <<'CORE';
package $pkg;

use v5.26;
use Modern::Perl::Prelude -class;

use Moo;
use Types::Standard qw(Str ArrayRef InstanceOf);
use OpenAPI::Modern;
use Mojo::UserAgent;
use Mojo::URL;
use Mojo::JSON qw(encode_json);
use Mojo::Promise;
use Carp qw(croak);
use ${base}::Client::Result;
$extra_use

has base_url => (
  is       => 'ro',
  isa      => Str,
  required => 1,
);

has openapi_schema_file => (
  is  => 'ro',
  isa => Str,
);

has openapi => (
  is       => 'lazy',
  isa      => InstanceOf ['OpenAPI::Modern'],
  init_arg => undef,
);

has ua => (
  is      => 'lazy',
  isa     => InstanceOf ['Mojo::UserAgent'],
  default => sub { Mojo::UserAgent->new },
);

has auth_plugins => (
  is      => 'ro',
  isa     => ArrayRef,
  default => sub { $auth_default },
);

HEAD

sub build_tx {
  my ( $self, $meta, $args ) = @_;
  $args //= {};

  my $path = $meta->{path_template};
  for my $name ( @{ $meta->{path_params} // [] } ) {
    croak "missing path param '$name'" unless exists $args->{$name};
    my $v = $args->{$name};
    $path =~ s/\{\Q$name\E\}/$v/g;
  }

  my $url = Mojo::URL->new( $self->base_url . $path );
  my %q;
  for my $q ( @{ $meta->{query_params} // [] } ) {
    $q{$q} = $args->{$q} if exists $args->{$q};
  }
  $url->query( \%q ) if keys %q;

  my $headers = { Accept => 'application/json' };
  for my $h ( @{ $meta->{header_params} // [] } ) {
    $headers->{$h} = $args->{$h} if exists $args->{$h};
  }

  my $body;
  if ( $meta->{has_body} ) {
    my $payload = $args->{body} // croak 'body required';
    $headers->{'Content-Type'} //= 'application/json';
    $body = ref($payload) ? encode_json($payload) : $payload;
  }

  my $method = $meta->{method};
  return $self->ua->build_tx( $method => $url => $headers => $body );
}

sub _apply_auth {
  my ( $self, $tx, $meta ) = @_;
  for my $p ( @{ $self->auth_plugins } ) {
    $p->apply( $tx, $meta );
  }
}

1;
CORE
}

sub _ops_pm {
    my ( $pkg, $core_pkg, $ops, $sync, $async, $spec, $base ) = @_;
    my @methods;
    for my $op (@$ops) {
        my $sub = _sanitize_sub( $op->{operation_id} );
        my $meta = _meta_literal( $spec, $base, $op );
        push @methods, <<"SUB";
sub $sub {
  my ( \$self, \%args ) = \@_;
  my \$meta = $meta;
  return \$self->core->request_sync( \$meta, \\\%args ) if \$self->sync_mode;
  return \$self->core->request_p( \$meta, \\\%args );
}
SUB
    }

    my $body = join "\n", @methods;
    return <<"PM";
package $pkg;

use v5.26;
use Modern::Perl::Prelude -class;

use Moo::Role;
use Types::Standard qw(Bool InstanceOf);

requires 'core';

has sync_mode => (
  is       => 'ro',
  isa      => Bool,
  required => 1,
);

$body

1;
PM
}

sub _sync_pm {
    my ( $pkg, $ops_pkg, $core_pkg ) = @_;
    return <<"PM";
package $pkg;

use v5.26;
use Modern::Perl::Prelude -class;

use Moo;
use Types::Standard qw(InstanceOf);

has core => (
  is       => 'ro',
  isa      => InstanceOf ['$core_pkg'],
  required => 1,
);

with '$ops_pkg';

sub sync_mode { 1 }

1;
PM
}

sub _async_pm {
    my ( $pkg, $ops_pkg, $core_pkg ) = @_;
    return <<"PM";
package $pkg;

use v5.26;
use Modern::Perl::Prelude -class;

use Moo;
use Types::Standard qw(InstanceOf);

has core => (
  is       => 'ro',
  isa      => InstanceOf ['$core_pkg'],
  required => 1,
);

with '$ops_pkg';

sub sync_mode { 0 }

1;
PM
}

1;

__END__

=encoding utf8

=head1 NAME

Modern::OpenAPI::Generator::CodeGen::Client - Generate C<::Client::*> modules

=head1 DESCRIPTION

Emits C<Client::Core>, C<Client::Ops>, and optional C<Client::Sync> /
C<Client::Async> from the spec.

=head2 generate

Class method. Arguments include C<writer>, C<spec>, C<base>, C<sync>, C<async>,
C<signatures>.

=cut



( run in 2.807 seconds using v1.01-cache-2.11-cpan-d8267643d1d )