Provided by: libponapi-client-perl_0.002012-1_all bug

NAME

       PONAPI::Client - Client to a {JSON:API} service (http://jsonapi.org/) v1.0

VERSION

       version 0.002012

SYNOPSIS

           use PONAPI::Client;
           my $client = PONAPI::Client->new(
               host => $host,
               port => $port,
           );

           $client->retrieve_all( type => $type );

           $client->retrieve(
               type => $type,
               id   => $id,
           );

           $client->retrieve_relationships(
               type     => $type,
               id       => $id,
               rel_type => $rel_type,
           );

           $client->retrieve_by_relationship(
               type     => $type,
               id       => $id,
               rel_type => $rel_type,
           );

           $client->create(
               type => $type,
               data => {
                   attributes    => { ... },
                   relationships => { ... },
               },
           );

           $client->delete(
               type => $type,
               id   => $id,
           );

           $client->update(
               type => $type,
               id   => $id,
               data => {
                   type => $type,
                   id   => $id,
                   attributes    => { ... },
                   relationships => { ... },
               }
           );

           $client->delete_relationships(
               type => $type,
               id   => $id,
               rel_type => $rel_type,
               data => [
                   { type => $rel_type, id => $rel_id },
                   ...
               ],
           );

           $client->create_relationships(
               type => $type,
               id   => $id,
               rel_type => $rel_type,
               data => [
                   { type => $rel_type, id => $rel_id },
                   ...
               ],
           );

           $client->update_relationships(
               type => $type,
               id   => $id,
               rel_type => $rel_type,
               # for a one-to-one:
               data => { type => $rel_type, id => $rel_id },
               # or for a one-to-many:
               data => [
                   { type => $rel_type, id => $rel_id },
                   ...
               ],
           );

           # If the endpoint uses an uncommon url format:
           $client->retrieve(
               type => 'foo',
               id   => 43,
               # Will generate a request to
               # host:port/type_foo_id_43
               uri_template => "type_{type}_id_{id}",
           );

DESCRIPTION

       "PONAPI::Client" is a {JSON:API} <http://jsonapi.org/> compliant client; it should be able
       to communicate with any API-compliant service.

       The client does a handful of checks required by the spec, then uses Hijk to communicate
       with the service.

       In most cases, all API methods return a response document:

           my $response = $client->retrieve(...);

       In list context however, all api methods will return the request status and the document:

           my ($status, $response) = $client->retrieve(...)

       Response documents will look something like these:

           # Successful retrieve(type => 'articles', id => 2)
           {
               jsonapi  => { version => "1.0"         },
               links    => { self    => "/articles/2" },
               data     => { ... },
               meta     => { ... }, # May not be there
               included => [ ... ], # May not be there, see C<include>
           }

           # Successful retrieve_all( type => 'articles' )
           {
               jsonapi => { version => "1.0"       },
               links   => { self    => "/articles" }, # May include pagination links
               data    => [
                   { ... },
                   { ... },
                   ...
               ],
               meta     => { ... }, # May not be there
               included => [ ... ], # May not be there, see C<include>
           }

           # Successful create(type => 'foo', data => { ... })
           {
               jsonapi => { version => "1.0"                 },
               links   => { self => "/foo/$created_id"       },
               data    => { type => 'foo', id => $created_id },
           }

           # Successful update(type => 'foo', id => 2, data => { ... })
           {
               jsonapi => { version => "1.0" },
               links   => { self => "/foo/2" }, # may not be there
               meta    => { ...              }, # may not be there
           }

           # Error, see http://jsonapi.org/format/#error-objects
           {
               jsonapi => { version => "1.0" },
               errors  => [
                   { ... }, # error 1
                   ...      # potentially others
               ],
           }

       However, there are situations where the server may respond with a "204 No Content" and no
       response document; depending on the situation, it might be worth checking the status.

METHODS

   new
       Creates a new "PONAPI::Client" object.  Takes a couple of attributes:

       host
           The hostname (or IP address) of the service.  Defaults to localhost.

       port
           Port of the service.  Defaults to 5000.

       send_version_header
           Sends a "X-PONAPI-Client-Version" header set to the {JSON:API} version the client
           supports.  Defaults to true.

   retrieve_all
           retrieve_all( type => $type, %optional_arguments )

       Retrieves all resources of the given type.  In SQL, this is similar to "SELECT * FROM
       $type".

       This handles several arguments:

       fields
           Spec <http://jsonapi.org/format/#fetching-sparse-fieldsets>.

           Instead of returning every attribute and relationship from a given resource, "fields"
           can be used to specify exactly what is returned.

           This excepts a hashref of arrayrefs, where the keys are types, and the values are
           either attribute names, or relationship names.

               $client->retrieve_all(
                   type   => 'people',
                   fields => { people => [ 'name', 'age' ] }
               )

           Note that an attribute not being in fields means the opposite to an attribute having
           empty fields:

               # No attributes or relationships for both people and comments
               $client->retrieve_all(
                   type   => 'people',
                   fields => { people => [], comments => [] },
               );

               # No attributes or relationships for comments, but
               # ALL attributes and relationships for people
               $client->retrieve_all(
                   type   => 'people',
                   fields => { comments => [] },
               );

       include
           Spec <http://jsonapi.org/format/#fetching-includes>.

           "include" can be used to fetch related resources.  The example below is fetching both
           all the people, and all comments made by those people:

               my $response = $client->retrieve_all(
                   type   => 'people',
                   include => ['comments']
               );

           "include" expects an arrayref of relationship names.  In the response, the resources
           fetched will be in an arrayref under the top-level "included" key:

               say $_->{attributes}{body} for @{ $response->{included} }

       page
           Spec <http://jsonapi.org/format/#fetching-pagination>.

           Requests that the server paginate the results.  Each endpoint may have different
           pagination rules.

       sort
           Spec <http://jsonapi.org/format/#fetching-sorting>.

           Requests that the server sort the results in a given way:

               $client->retrieve_all(
                   type => 'people',
                   sort => [qw/ age  /], # sort by age, ascending
               );

               $client->retrieve_all(
                   type => 'people',
                   sort => [qw/ -age /], # sort by age, descending
               );

           Although not all endpoints will support this, it may be possible to sort by a
           relationship's attribute:

               $client->retrieve_all(
                   type => 'people',
                   sort => [qw/ -comments.created_date /],
               );

       filter
           Spec <http://jsonapi.org/format/#fetching-filtering>.

           This one is entirely dependent on the endpoint.  It's usually employed to act as a
           "WHERE" clause:

               $client->retrieve_all(
                   type   => 'people',
                   filter => {
                       id  => [ 1, 2, 3, 4, 6 ], # IN ( 1, 2, ... )
                       age => 34,                # age = 34
                   },
               );

           Sadly, more complex filters are currently not available.

   retrieve
           retrieve( type => $type, id => $id, %optional_arguments )

       Similar to "retrieve_all", but retrieves a single resource.

   retrieve_relationships
           retrieve_relationships( type => $type, id => $id, rel_type => $rel_type, %optional_arguments )

       Retrieves all of $id's relationships to $rel_type as resource identifiers; that is, as
       hashrefs that contain only "type" and "id":

           # retrieve_relationships(type=>'people', id=>2, rel_type=>'comments')
           {
               jsonapi => { version => "1.0" },
               data    => [
                   { type => 'comments', id => 4  },
                   { type => 'comments', id => 9  },
                   { type => 'comments', id => 14 },
               ]
           }

       These two do roughly the same thing:

           my $response      = $client->retrieve( type => $type, id => $id );
           my $relationships = $response->{data}{relationships}{$rel_type};
           say join ", ", map $_->{id}, @$relationships;

           my $response = $client->retrieve_relationships(
               type     => $type,
               id       => $id,
               rel_type => $rel_type,
           );
           my $relationships = $response->{data};
           say join ", ", map $_->{id}, @$relationships;

       However, "retrieve_relationships" also allows you to page those relationships, which may
       be quite useful.

       Keep in mind that "retrieve_relationships" will return an arrayref for one-to-many
       relationships, and a hashref for one-to-ones.

   retrieve_by_relationship
           retrieve_by_relationship( type => $type, id => $id, rel_type => $rel_type, %optional_arguments )

       "retrieve_relationships" on steroids.  It behaves the same way, but will retrieve full
       resources, not just resource identifiers; because of this, you can also potentially apply
       more complex filters and sorts.

   create
           create( type => $type, data => { ... }, id => $optional )

       Create a resource of type $type using $data to populate it.  Data must include the type,
       and may include two other keys: "attributes" and "relationships":

           $client->create(
               type => 'comments',
               data => {
                   type          => 'comments',
                   attributes    => { body => 'abc' },
                   relationships => {
                       author   => { type => 'people', id => 55 },
                       liked_by => [
                           { type => 'people', id => 55  },
                           { type => 'people', id => 577 },
                       ],
                   }
               }
           }

       An optional "id" may be provided, in which case the server may choose to use it when
       creating the new resource.

   update
           update( type => $type, id => $id, data => { ... } )

       Can be used to update the resource.  Data must have "type" and "id" keys:

           $client->create(
               type => 'comments',
               id   => 5,
               data => {
                   type          => 'comments',
                   id            => 5,
                   attributes    => { body => 'new body!' },
                   relationships => {
                       author   => undef, # no author
                       liked_by => [
                           { type => 'people', id => 79 },
                       ],
                   }
               }
           }

       An empty arrayref ("[]") can be used to clear one-to-many relationships, and "undef" to
       clear one-to-one relationships.

       A successful "update" will always return a response document; see the spec for more
       details.

       Spec <http://jsonapi.org/format/#crud-updating>.

   delete
           delete( type => $type, id => $id )

       Deletes the resource.

   update_relationships
          update_relationships( type => $type, id => $id, rel_type => $rel_type, data => $data )

       Update a resource's relationships.  Basically a shortcut to using "update".

       For one-to-one relationships, "data" can be either a single hashref, or undef.  For one-
       to-many relationships, "data" can be an arrayref; an empty arrayref means 'clear the
       relationship'.

   create_relationships
          create_relationships( type => $type, id => $id, rel_type => $rel_type, data => [{ ... }] )

       Adds to the specified one-to-many relationship.

   delete_relationships
          delete_relationships( type => $type, id => $id, rel_type => $rel_type, data => [{ ... }] )

       Deletes from the specified one-to-many relationship.

Endpoint URI format

       By default, "PONAPI::Client" assumes urls on the endpoint are in this format:

           retrieve_all:               /$type
           retrieve:                   /$type/$id
           retrieve_by_relationships:  /$type/$id/$rel_type
           retrieve_relationships:     /$type/$id/relationships/$rel_type

           create:                     /$type or /$type/$id
           delete:                     /$type/$id
           update:                     /$type/$id

           update_relationships:       /$type/$id/relationships/$rel_type
           create_relationships:       /$type/$id/relationships/$rel_type
           delete_relationships:       /$type/$id/relationships/$rel_type

           # Will generate a request to /foo/99
           $client->retrieve(
               type => 'foo',
               id   => 99,
           );

       However, if another format is needed, two approaches are possible:

   URI paths have a common prefix
       If all the endpoint urls have a common prefix, ala "/v1/articles" instead of simply
       "/articles", then you can just set "uri_base" as needed:

           $client->retrieve(
               type     => 'foo',
               id       => 99,
               uri_base => '/v1'
           );

       We can also set this when creating the client; if done this way, all requests generated
       from this client will include the base:

           my $new_client = PONAPI::Client->new(
               uri_base => '/v1',
               ...
           );

           # This will generate a request to /v1/foo/99
           $new_client->retrieve(
               type => 'foo',
               id   => 99,
           );

   Completely different uris
       If the endpoint's expected formats are wildly different, you can specify "uri_template"
       with your request:

           # Will generate a request to id_here_99_and_type_there/foo
           $client->retrieve(
               type => 'foo',
               id   => 99,
               uri_template => 'id_here_{id}_and_type_there/{type}'
           );

       These placeholders are recognized:

       •   type

       •   id

       •   rel_type

       This can only be done on a per-request basis.

AUTHORS

       •   Mickey Nasriachi <mickey@cpan.org>

       •   Stevan Little <stevan@cpan.org>

       •   Brian Fraser <hugmeir@cpan.org>

COPYRIGHT AND LICENSE

       This software is copyright (c) 2019 by Mickey Nasriachi, Stevan Little, Brian Fraser.

       This is free software; you can redistribute it and/or modify it under the same terms as
       the Perl 5 programming language system itself.