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 . SOURCE Source repository is at . 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 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 . 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 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.