NAME
    Plugin::System - A plugin system for your Perl framework or application

VERSION
    This document describes version 0.000001 of Plugin::System (from Perl
    distribution Plugin-System), released on 2024-03-02.

SYNOPSIS
  Use in framework
    In your lib/Your/Framework.pm:

     package Your::Framework;
     use Plugin::System;

     use Plugin::System (
         # optional, default to caller package (i.e. in this case, Your::Framework)
         #app => 'Your::Framework',

         # optional, namespace to search for the plugins, default to ${app}::Plugin.
         # can also be an arrayref to search in multiple namespaces.
         plugin_ns => 'Your::FrameworkX',

         # required, list of known hooks along with their specification
         hooks => {
             check_input => { ... },
             output => { ... },
             ...
         },
         ...

     );

     # after this, Plugin::System will install hook_XXX(;&@) routines for each
     # defined hook so you can use them:

     sub run {
         my %args = @_;

         my $res = hook_check_input {
             # the code block for a hook. plugins can run before and/or after this
             # block. a "before" plugin can ask to skip this block. an "after"
             # plugin can ask to repeat this block.
             check_args(%args);
         };
         # the hook will return the result of the code block or, if configured, the
         # result of the first handler that returns result.

         # this hook does not provide the main call block. the hook might require
         # that there is at least one plugin that installs a handler for this hook.
         hook_output;
     }

     1;

  Plugin code
    In your lib/Your/FrameworkX/Foo.pm:

     package Your::FrameworkX::Foo;

     sub meta {
         # must return a DefHash, see DefHash specification
         return +{
             # optional, default priority for all handlers (0-100), defaults to 50
             #prio => ...,

             # optional, define arguments/configuration parameters that your plugin
             # recognizes
             args => {
                 # a DefHash
                 arg1 => {
                     # a DefHash
                     summary => 'Blah blah ...',
                     schema => 'str*', # a Sah schema
                     req => 0,
                     ...
                 },
             },
         };
     }

     sub new {
         my ($self, %args) = @_;
         ...
     }

     # required handler if we want to handle the 'check_input' hook
     sub on_check_input {
         ...

         # plugin can signal success by returning 200 or error by returning 4xx or
         # 5xx status. it can also return 201 to instruct to skip calling the rest
         # of the handlers for the hook. it can also return 204 to "decline".

         # a handler can be configured to return (replace) the result of the
     }

     # metadata for the 'check_input' handler. required.
     sub meta_on_check_input {
         return +{ prio => ..., ... };
     }

     # a before_ handler is optional
     sub before_check_input {
         my ($self, $r) = @_;
         ...

         # plugin can instruct to cancel the hook by returning 601.
     }

     # required if before_check_input is defined
     sub meta_before_check_input { ... }

     # an after_ handler is optional
     sub after_check_input {
         my ($self, $r) = @_;
         ...
         # plugin can instruct to repeat an hook by returning 602.
     }

     # required if after_check_input is defined
     sub meta_after_check_input { ... }

     1;

  Using plugins for users
    You can use Plugin::System::Exporter, e.g. in lib/Your/Framework.pm:

     package Your::Framework;
     ...
     use Plugin::System::Exporter (
         # optional, see Synopsis/Use in framework
         # app => 'Your::Framework',

         # optional, see Synopsis/Use in framework
         plugin_ns => 'Your::FrameworkX',
     );

    so your users can activate plugins this way:

     use Your::Framework 'Foo' => {arg1=>..., arg2 => ..., ...};

DESCRIPTION
    A plugin approach offers flexibility. Users can enable or disable
    plugins which they need, in the order that they want. Each plugin can
    supply behavior at various code points (hooks) in an application. More
    than one plugin (also multiple instances of the same plugin) can supply
    behavior for a single hook.

    This module, Plugin::System, offers a fast, highly flexible plugin
    system with a (hopefully) nice syntax. A plugin can modify the flow of
    the application by skipping (aborting) or repeating a hook. For all
    features of this plugin system, see Plugin::System::_ModuleFeatures.

GLOSSARY
  Hook
    A named point in code. Plugins can define handlers to add behaviors for
    a hook. A hook can also contain the main code block. When no handlers
    are registered for a hook, only the main code block will be executed and
    the result returned. When there are handlers, the handler can add
    behavior before and/or after the main code block, and can also replace
    or remove the execution of the main code block.

  Main code block
    The code to be executed by default during an hook. See "Hook".

  Handler
    Code to execute for an hook. Handlers are supplied by plugins.

  Plugin
    A module defining a class which provides methods to generate handlers
    for hooks. In Plugin::System, the user can also register plugin from
    another application/framework (as long as it also uses Plugin::System).
    The user can also customize the target hook and priority of handlers
    from the plugin.

  Priority
    A number between 0 and 100 to specify order of execution of handlers for
    a hook. Smaller number means higher priority (earlier execution). If two
    handlers have the same priority, then handlers registered first will be
    executed first.

  Target package
    The package which "use"s "Plugin::System" and defines the hooks it wants
    to have. Plugin::System will install the hook subroutines (by default
    "hook_NAME"s) to this package.

  Registration
    The act of loading a plugin then adding the handlers it provides to a
    target package.

  Initialization
    The process of generating the hook subroutines for a target package.

IMPORT ARGUMENTS
    Plugin::System accepts a key-value pairs of arguments. Known arguments:

  hooks
    Define known hooks.

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

SOURCE
    Source repository is at
    <https://github.com/perlancar/perl-Plugin-System>.

SEE ALSO
    Other plugin systems: Module::Pluggable and its variants like
    Module::Pluggable::Fast. See comparison and benchmarks at
    Acme::CPANModules::PluginSystems.

    Examples of frameworks using Plugin::System: Require::HookPlugin,
    ScriptX, Data::DumpX.

AUTHOR
    perlancar <perlancar@cpan.org>

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 Dist::Zilla,
    Dist::Zilla::PluginBundle::Author::PERLANCAR,
    Pod::Weaver::PluginBundle::Author::PERLANCAR, and sometimes one or two
    other Dist::Zilla- and/or Pod::Weaver plugins. Any additional steps
    required beyond that are considered a bug and can be reported to me.

COPYRIGHT AND LICENSE
    This software is copyright (c) 2024, 2023 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.

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

    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.