Provided by: libponapi-client-perl_0.002012-2_all 

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.
perl v5.36.0 2022-12-07 PONAPI::Client(3pm)