The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
NAME
    Dist::Zilla::Plugin::Rinci::Wrap - Insert wrapper-generated code

VERSION
    version 0.05

SYNOPSIS
    In dist.ini:

     [Rinci::Wrap]
     ; optional, will be eval'ed as Perl code and passed to wrap_sub()
     wrap_args = { validate_result => 0, convert => {retry=>2} }
     ; optional, will not squish code and add marker comment
     debug=1

    In your module:

     $SPEC{foo} = {
         v => 1.1,
         args => {
             arg1 => { schema => ['int*', default=>3] },
             arg2 => { },
         },
     };
     sub foo {
         my %args = @_;

         ... your code
         return [200, "OK", "some result"];
     }

    output will be something like:

     $SPEC{foo} = {
         v => 1.1,
         args => {
             arg1 => { schema => ['int*', default=>3] },
             arg2 => { },
         },
     };
     require Scalar::Util; require Data::Dumper; { my $meta = $SPEC{foo}; $meta->{args}{arg1}{schema} = ["int", {req=>1, default=>3}, {}]; } # WRAP_PRESUB
     sub foo {
         my %args = @_;

         ... generated preamble code

         ... your code
         return [200, "OK", "some result"];

         ... generated postamble code
     }

DESCRIPTION
    This plugin inserts code generated by Perinci::Sub::Wrapper to your
    source code during building. This lets you add functionalities like
    argument validation, result validation, automatic retries, conversion of
    argument passing style, currying, and so on.

    Code is inserted in three places (see the above example in Synopsis):

    *   The first part (which is the part to load required modules and to
        modify function metadata, e.g. normalize Sah schemas, etc) will be
        inserted right before the opening of the subroutine ("sub NAME {").

    *   The second part (which is the part to validate arguments and do
        stuffs before performing the function) will be inserted at the start
        of subroutine body after the "my %args = @_;" (or "my $args = $_[0]
        // {};" if you accept arguments from a hashref, or "my @args = @_;"
        if you accept arguments from an array, or "my $args = $_[0] // [];"
        if you accept arguments from an arrayref) statement. This should be
        one of the first things you write after your sub declaration before
        you do anything else.

    *   The third part (which is the part to validate function result and do
        stuffs after performing the function) will be inserted right before
        the closing of the subroutine.

    Currently regexes are used to parse the code so things might be rather
    fragile.

RESTRICTIONS
    There are some restrictions (hopefully not actually restricting) when
    writing your code if you want to use this plugin.

    *   Clash of variables

        The generated wrapper code will declare some variables. You need to
        make sure that the variables do not clash. This is rather simple:
        the variables used by the wrapper code will all be prefixed with
        "_w_" (e.g. $_w_res) or "_sahv_" for variables generated by the Sah
        schema compiler (e.g. <$_sahv_dpath>).

    *   Variable used to accept arguments

        Currently the wrapper internally will perform argument validation on
        $args{ARGNAME} variables, even if you accept arguments from a
        hashref/array/arrayref. Thus:

        If you accept arguments from a hash (the default), you need to put
        the arguments to %args, i.e.:

         my %args = @_;

        You can then get the validated arguments e.g.:

         my $name = $args{name};
         my $addr = $args{address};
         ...

        If you accept arguments from a hashref (i.e. "func({ arg1=>1,
        arg2=>2 })"):

         my $args = $_[0] // {};

        If you accept arguments from an array (e.g. "<func(1, 2)">:

         my @args = @_;

        If you accept arguments from an arrayref "<func([1, 2])">:

         my $args = $_[0] // [];

FAQ
  Rationale for this plugin?
    This plugin is an alternative to using Perinci::Sub::Wrapper (PSW)
    dynamically. During build, you generate the wrapper code and insert it
    to the target code. The result is lower startup overhead (no need to
    generate the wrapper code during runtime) and better guarantee that your
    wrapping code (argument validation, etc) is always called when your
    subroutines are called, even if your users do not use PSW and call your
    subroutines directly.

    Another advantage/characteristic using this plugin is that, the wrapper
    code does not introduce extra call level.

  But why use PSW at all?
    In short, adding Rinci metadata to your subroutines allows various tools
    to do useful stuffs, relieving you from coding those stuffs manually.
    Using Sah schema allows you to write validation code succintly, and
    gives you the ability to automatically generate Perl/JavaScript/error
    messages from the schema.

    PSW is one of the ways (currently the only way) to implement those
    behaviours/functionalities.

  But the generated code looks ugly!
    Admittedly, yes. Wrapper-generated code is formatted as a single long
    line to avoid modifying line numbers, which is desirable when debugging
    your modules. An option to not compress everything as a single line
    might be added in the future.

  How do I customize wrapping for my function
    In the future there will be options you can specify in "dist.ini".

    For now, you can put in your Rinci function metadata:

     "x.dist.zilla.plugin.rinci.wrap.wrap_args" => { validate_args => 0 },

    This will be merged and will override "wrap_args" keys specified in
    "dist.ini".

TODO
    *   Use PPI instead of fragile regex.

    *   Option to not compress wrapper code to a single line.

    *   Option to reuse validation code for the same schema.

    *   Option to exclude some subroutines from being wrapped.

    *   Option to specify different wrap_args for different subroutines.

HOMEPAGE
    Please visit the project's homepage at
    <https://metacpan.org/release/Dist-Zilla-Plugin-Rinci-Wrap>.

SOURCE
    Source repository is at
    <https://github.com/sharyanto/perl-Dist-Zilla-Plugin-Rinci-Wrap>.

BUGS
    Please report any bugs or feature requests on the bugtracker website
    <https://rt.cpan.org/Public/Dist/Display.html?Name=Dist-Zilla-Plugin-Rin
    ci-Wrap>

    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.

AUTHOR
    Steven Haryanto <stevenharyanto@gmail.com>

COPYRIGHT AND LICENSE
    This software is copyright (c) 2014 by Steven Haryanto.

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