NAME
    Sub::Middler - Middleware subroutine chaining

SYNOPSIS
      use strict;
      use warings;
      use Sub::Middler;

  
      my @array;
      my %hash;
      my $scalar;

      # append results in variables
      my $head=linker 
        # Short cut to store (copy/append) in array
        \@array       
        # Short cut to modifiy inputs
        =>\sub { $_*=2 for @{$_[0]}},
        # Short cut to store in hash
        =>\%hash,
        # Short cut to stringyfiy and append to scalar
        =>\$scalar;
  

      $head->([1,2,3,4,], sub {...})
      #         inputs      ready cb


      use strict;
      use warnings;
      use Sub::Middler;

      my $middler=Sub::Middler->new;

      $middler->register(mw1(x=>1));
      $middler->register(mw2(y=>10));

      my $head=$middler->link(
        sub {
          print "Result: $_[0]\n";
        }
      );

      $head->(0); # Call the Chain

      # Middleware 1
      sub mw1 {
        my %options=@_;
        sub {
          my ($next, $index, @optional)=@_;
          sub {
            my $work=$_[0]+$options{x};
            $next->($work);
          }
        }
      }

      # Middleware 2
      sub mw2 {
        my %options=@_;
        sub {
          my ($next, $index, @optional)=@_;
          sub {
            my $work= $_[0]*$options{y};
            $next->( $work);
          }
        }
      }

DESCRIPTION
    A small module, facilitating linking subroutines together, acting as
    middleware ,filters or chains with low runtime overhead.

    To achieve this, the 'complexity' is offloaded to the definition of
    middleware/filters subroutines. They must be wrapped in subroutines
    appropriately to facilitate the lexical binding of linking variables.

    This differs from other 'sub chaining' modules as it does not use a loop
    internally to iterate over a list of subroutines at runtime. As such
    there is no implicit synchronous call to the 'next' item in the chain.
    Each stage can run the following stage synchronously or asynchronously
    or not at all. Each element in the chain is responsible for how and when
    it calls the 'next'.

    Finally the arguments and signatures of each stage of middleware are
    completely user defined and are not interfered with by this module. This
    allows reuse of the @_ array in calling subsequent stages for ultimate
    performance if you know what you're doing.

    As a general guide it's suggested the last argument to a stage be a
    subroutine reference to allow callbacks and asynchronous usage. Instead
    of a flat list of multiple inputs into a stage, it is suggested to also
    contain these in an array

    From v0.4.0, shortcuts can be used to to bypass writing the nestled
    subroutines subroutines for some common use cases. A reference to a
    SCALAR/ARRAY/HASH/CODE can be used instead of custom middleware

API
  Inline linking
      linker mw1, ..., dispatch

    From v0.3.0, the "linker" subroutine is exported and will do an inline
    build and link for a given middleware and dispatch routine

    The return value is the head of the linked chain, and is equivalent to
    created a "Sub::Middler" object, adding middleware, and the calling the
    link method.

  Short Cuts
    Instead of writing custom middleware, references to variables and CODE
    can be used instead.

    If an array reference is used, all elements from the first argument will
    be appended to the array

    If an hash reference is used, the elements from the first argument will
    be treated as key value pairs and set the corresponding elements in the
    target hash

    If a scalar reference is use, the elements from the first argument will
    be converted to strings and appending to the target variable

    If a reference is a CODE reference is used, the underlying subroutine is
    expected to modify the first argument elements in place. The return
    value is not used.

    In all the above cases, the next link in the chain is automatically
    called with the same arguments, making chaining and saving intermediate
    values easy

  Managing a chain
   new
        my $object=Sub::Middler->new;

    Creates a empty middler object ready to accept middleware. The object is
    a blessed array reference which stores the middleware directly.

   register
        $object->register(my_middlware());

    Appends the middleware to the internal list for later linking.

   append, add
    Alias for register

   link
        $object->link($last,[@args]);

    Links together the registered middleware in the sequence of addition.
    Each middleware is intrinsically linked to the next middleware in the
    list. The last middleware being linked to the $last argument, which must
    be a code ref.

    The $last ref MUST be a regular subroutine reference, acting as the
    'kernel' as described in following sections.

    Calls "die" if $last is not a code ref.

    Any optional additional arguments @args are passed to this function are
    passed on to each 'maker' sub after the $next and $index, parameters.
    This gives an alternative approach to distributing configuration data to
    each item in the chain prior to runtime. It is up to each item's maker
    sub to store relevant passed values as they see fit.

  Creating Middleware
    To achieve low over head in linking middleware, functional programming
    techniques (higher order functions) are utilised. This also give the
    greatest flexibility to the middleware, as signatures are completely
    user defined.

    The trade off is that the middleware must be defined in a certain code
    structure. While this isn't difficult, it takes a minute to wrap your
    head around.

   Middlware Definition
    Middleware must be a subroutine (top/name) which returns a anonymous
    subroutine (maker), which also returns a anonymous subroutine to perform
    work (kernel).

    This sounds complicated by this is what is looks like in code:

      sub my_middleware {                 (1) Top/name subroutine
        my %options=@_;                       Store any config
   
        sub {                             (2) maker sub is returned
          my ($next, $index, @optional)=@_;   (3) Must store at least $next

          sub {                           (4) Returns the kernel sub
            # Code here implements your middleware
            # %options are lexically accessable here
            # as are the @optional parameters
        

            # Execute the next item in the chain
            $next->(...);                 (5) Does work and calls the next entry


                                          (6) Post work if applicable 
          }
        }
      }

    Top Subroutine
        The top sub routine (1) can take any arguments you desire and can be
        called what you like. The idea is it represents your
        middleware/filter and stores any setup lexically for the maker sub
        to close over. It returns the maker sub.

    Maker Subroutine
        This anonymous sub (2) closes over the variables stored in Top and
        is the input to this module (via "register"). When being linked
        (called) by this module it is provided at least two arguments: the
        reference to the next item in the chain and the current middleware
        index. These MUST be stored to be useful, but can be called anything
        you like (3).

        Any optional/additional arguments supplied during a call to "link"
        are also used as arguments 'as is' to all maker subroutines in the
        chain.

    Kernel subroutine
        This anonymous subroutine (4) actually performs the work of the
        middleware/filter. After work is done, the next item in the chain
        must be called explicitly (5). This supports synchronous or
        asynchronous middleware. Any extra work can be performed after the
        chain is completed after this call (6).

  LINKING CHAINS
    Multiple chains of middleware can be linked together. This needs to be
    done in reverse order. The last chain after being linked, becomes the
    $last item when linking the preceding chain and so on.

  EXAMPLES
    The synopsis example can be found in the examples directory of this
    distribution.

SEE ALSO
    Sub::Chain and Sub::Pipeline links together subs. They provide other
    features that this module does not.

    These iterate over a list of subroutines at runtime to achieve named
    subs etc. where as this module pre links subroutines together, reducing
    overhead.

AUTHOR
    Ruben Westerberg, <drclaw@mac.com>

REPOSITORTY and BUGS
    Please report any bugs via git hub:
    <https://github.com/drclaw1394/perl-sub-middler>

COPYRIGHT AND LICENSE
    Copyright (C) 2025 by Ruben Westerberg

    This library is free software; you can redistribute it and/or modify it
    under the same terms as Perl or the MIT license.

DISCLAIMER OF WARRANTIES
    THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
    WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

