package Rinci::resmeta; # just to make PodWeaver happy

# AUTHORITY
# DATE
our $DIST = 'Rinci'; # DIST
# VERSION

1;
# ABSTRACT: Function/method result metadata

__END__

=pod

=encoding UTF-8

=head1 NAME

Rinci::resmeta - Function/method result metadata

=head1 SPECIFICATION VERSION

 1.1

=head1 VERSION

This document describes version 1.1.100 of Rinci::resmeta (from Perl distribution Rinci), released on 2022-01-23.

=head1 INTRODUCTION

This document describes metadata for function/method result. This specification
is part of L<Rinci>. Please do a read up on it first, if you have not already
done so.

=head1 SPECIFICATION

There are currently several properties being used:

=head2 cmdline.*

Interpreted by L<Perinci::CmdLine>. See its documentation for more detail.

=head2 content_type

Value: str* (MIME content type)

Can be used to describe the MIME content type of result. Example enveloped
result (in Perl):

 [200, "OK", "...", {content_type => "image/jpeg"}]

See also L</"Properties: func_content_type.*">.

Note: borrowed from HTTP.

=head2 func.*

Value: any.

These properties allow function to return extra results. Usually done to avoid
breaking format of existing result (to maintain API compatibility). The
attributes after C<func.> is up to the respective function. An example is the
C<get_args_from_argv()> function in the L<Perinci::Sub::GetArgs::Argv> Perl
module. The function returns C<$args> but from v0.26 it also wants to give hints
about whether or not there are missing arguments. It can do this via
C<func.missing_arg> result metadata. Some other examples (in Perl):

 # result from check_user()
 [200, "OK", 1,         # 1 means valie
 {
     "func.detail" => { # detailed check result
         last_login      => '2021-01-21T01:55:40Z',
         password_secure => 1,
         quota_exceeded  => 0,
     },
 }]

=head2 func_content_type.*

Value: str* (MIME content type)

Can be used to describe the MIME content type of each extra result. Example (in
Perl):

 func.attachment => '...',
 func_content_type.attachment => 'image/jpeg',

See also L</"Property: content_type">.

=head2 len

Value: int*

The C<len>, C<part_start> and C<part_len> properties specifies the range of data
when function sends partial result. Suppose your function is returning a partial
content of a large file where total file size is 24500000 bytes and the returned
content is from bytes 10000000 to 15000000, then C<len> is 24500000, C<part_len>
is 5000000, and C<part_start> is 10000000. When returning partial content,
status will be 206.

=head2 location

Value: str* (URL)

Can be used to specify that the content is elsewhere. Used in combination with
301 or 302 result status. Example (in Perl):

 # result from a function that generates a chart
 [301, "Moved", undef, {content_type => "image/jpeg", location=>"file:/tmp/asd9uxzw.png"}]

Note: borrowed from HTTP.

=head2 logs

Value: array[hash]

Store log of events happening to this result, stored chronologically (older
first). Each log should be a hash which should have at least the following keys:
C<time> (Unix timestamp), C<type> (string).

Normally, the first element of the log will contain information about who
produced the result and where/when. It has the C<type> key with the value of
C<create>. It should be a hash with the following keys:

=over

=item * package

Package (namespace) where this result is produced.

=item * file

File name where the result is created. Might be a relative or absolute path.

=item * line

Line number where the result is created.

=item * func

Function name where this result is produced.

=item * stack_trace

Optional, a stack trace. In Perl this can be produced by using << [caller(1),
caller(2), ...] >>.

=back

=head2 part_len

Value: int*

See L</"Property: len">

=head2 part_start

Value: int*

See L</"Property: len">.

=head2 perm_err

Value: bool

Indicate that error is permanent (instead of temporary/transient). This is to
provide a feature like that found in SMTP/POP protocol, where 4xx codes indicate
transient errors and 5xx permanent ones.

=head2 prev

Value: any

Store "previous result". Result MUST be enveloped. Usually useful when tracing
errors, especially in conjunction with C<logs>: when reporting error that
results from a call to another function, the original result can be set here, to
preserve information. See L<Perinci::Sub::Util>'s C<err()> for a convenience
function for this, and L<Perinci::CmdLine>'s way of displaying it.

Example:

 sub f1 {
     ...
     if (error) { return [500, "Can't f1: blah"] }
     ...
 }

 sub f2 {
     ...
     my $res = f1(...);
     if ($res is error) { return [500, "Can't f2", undef, {prev=>$res}] }
     ...
 }

 sub f3 {
     ...
     my $res = f1(...);
     if ($res is error) { return [500, "Can't f3", undef, {prev=>$res}] }
 }

=head2 results

Value: array*

When a function returns an error response (in particular status 207, but other
statuses can also use this), it can put detailed errors here. For example, a
function which processed 5 items wanted to report that 2 items were successfully
processed but the rest 3 failed:

 [207, "Multistatus", undef, {
      results => [
          {status=>200, message=>"OK", item_id=>1},
          {status=>403, message=>"Forbidden", item_id=>2},
          {status=>404, message=>"Not found", item_id=>3},
          {status=>500, message=>"Failed", item_id=>4},
          {status=>200, message=>"OK", item_id=>5},
      ],
  }]

Each result is a hash to be able to store C<status>, C<message>, as well as
additional data like C<item_id> or whatever the function wants.

Another example, a function wants to give information on what arguments fail
validation:

 [400, "Some arguments fail validation", undef, {
      results => [
          {status=>400, arg=>"name", message=>"Missing"},
          {status=>400, arg=>"location/street", message=>"Missing"},
          {status=>400, arg=>"age", message=>"Must be numbers only"},
          {status=>400, arg=>"password", is_warning=>1,
           message=>"Should be longer than 4 characters"}, # warning only
      ],
 }]

=head2 schema

Value: sah::schema

Describe result's schema. Has lower precedence than schema from function
metadata's result property.

=head2 stream

Value: bool*

If set to true, signify that result is an output stream. Usually in
implementations the result will be a filehandle or an object with C<getline> or
C<getitem> methods, where caller can then fetch data from it.

=head2 caption

Value: str*

Optional.

=head2 undo_data

Value: any

(DEPRECATED) Explained in C<undo> feature section in L<Rinci::function>.

=head1 FAQ

=head1 HOMEPAGE

Please visit the project's homepage at L<https://metacpan.org/release/Rinci>.

=head1 SOURCE

Source repository is at L<https://github.com/perlancar/perl-Rinci>.

=head1 SEE ALSO

L<Rinci>

=head1 AUTHOR

perlancar <perlancar@cpan.org>

=head1 CONTRIBUTING


To contribute, you can send patches by email/via RT, or send pull requests on
GitHub.

Most of the time, you don't need to build the distribution yourself. You can
simply modify the code, then test via:

 % prove -l

If you want to build the distribution (e.g. to try to install it locally on your
system), you can install L<Dist::Zilla>,
L<Dist::Zilla::PluginBundle::Author::PERLANCAR>, and sometimes one or two other
Dist::Zilla plugin and/or Pod::Weaver::Plugin. Any additional steps required
beyond that are considered a bug and can be reported to me.

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2022, 2020, 2019, 2018, 2017, 2016, 2015, 2014, 2013, 2012 by perlancar <perlancar@cpan.org>.

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

=head1 BUGS

Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Rinci>

When submitting a bug or request, please include a test-file or a
patch to an existing test-file that illustrates the bug or desired
feature.

=cut
