NAME ScriptX - A plugin-based script framework VERSION This document describes version 0.000004 of ScriptX (from Perl distribution ScriptX), released on 2020-10-01. SYNOPSIS In your script: use ScriptX Rinci => {func => 'MyApp::app'}; ScriptX->run; DESCRIPTION EXPERIMENTAL, EARLY RELEASE. For now, see the included example scripts. Glossary Event A named point in code when plugins have a chance to do stuffs, by registering a handler for it. In other frameworks, an event sometimes this is called a hook. Event handler A coderef that will be called by ScriptX on an event. The event handler will be passed an argument $stash (a hashref) which contains various information (see "Stash"). The event handler is expected to return an enveloped result (see Rinci::function). Plugin A Perl module under the "ScriptX::" namespace that supplies additional behavior/functionality. When you activate a plugin, the plugin registers handler(s) to one or more events. Priority An attribute of event handler. A number between 0 and 100, where smaller number means higher priority. Handlers for an event are executed in order of descending priority (higher priority first, which means smaller number first). CLASS METHODS run Usage: ScriptX->run; This is actually just a shortcut for running the "run" event: run_event(name => 'run'); VARIABLES %Handlers This is where event handlers are registered. Keys are event names. Values are arrayrefs containing list of handler records: [ [$label, $prio, $handler], ... ] @Plugin_Instances An array of activated plugin instances. For reference only. STASH KEYS event Str. The name of current event. handlers Array. Reference to the %Handlers package variable, for convenience. plugin_instances Array. Reference to the @Plugin_Instances package variable, for convenience. plugin_name Str. Current plugin name. Set for "activate_plugin" event. plugin_args Hash. Arguments hashref to instantiate plugin. Set for "activate_plugin" event. EVENT HANDLER RETURN STATUS CODES The following are known event handler return status codes. They roughly follow HTTP semantics. 201 This signifies success with exit ("OK, Skip Rest"), meaning the handler instructs "run_event"() to skip moving to the next handler for the event and use this status as the status of the event. 204 This signifies declination ("Decline"), meaning the handler opts to not do anything for the event. "run_event"() will move to the next handler, regardless of the value of "run_all_handlers". Other 1xx, 2xx, 3xx Including 200 ("OK"), these also signify success. When "run_all_handlers" is set to true, "run_event"() will move to the next handler. When "run_all_handlers" is set to false, run_event will finish the execution of handlers for the event and use the status as the status of the event. 4xx, 5xx This signifies failure. When "stop_after_first_handler_failure" is set to true, "run_event"() will use the status as the last status. Otherwise, it will move to the next handler when "run_all_handlers" is set to true. 601 This signifies event cancellation ("Cancel"), meaning the handler instructs "run_event"() to cancel the event. 602 This signifies repeating of event ("Repeat"), meaning the handler instructs "run_event"() to repeat the event. FUNCTIONS None exported by default, but they are exportable. activate_plugin Usage: activate_plugin($name [, \%args ]); Examples: activate_plugin('CLI::Log'); activate_plugin('Rinci', {func=>'MyPackage::myfunc'}); Load plugin named $name (by loading Perl module "ScriptX::$name"), instantiate it with arguments %$args, then call the object method "activate()". Note: there is a special plugin "DisablePlugin|ScriptX::DisablePlugin" which can block other plugins from being activated. add_handler Usage: add_handler($event, $label, $prio, $handler); Add handler. Usually called by plugins to add handler to events of their choosing. run_event Usage: run_event(%args); Run an event by calling event handlers. If the name of the event (hereby called $name) does not match /^(after|before)_/, first call the "before_$name" event handlers. A handler for "before_$name" event can cancel the $name event by returning 601 status, unless "allow_before_handler_to_cancel_event" argument is set to false. When the $name event is cancelled, "run_event"() ends prematurely: no handlers for the $name as well as "after_$name" events are run, no "on_success" and "on_failure" code will also be called. Then the $name event handlers are run. A handler for $name event can skip the rest of the handlers by returning status 201, unless "allow_handler_to_skip_rest" argument is set to false. A handler for $name event can also repeat the event by returning status 602, unless "allow_handler_to_repeat_event" is set to false. When an event is repeated, the first $name event handler is executed again. The "before_$name" handlers are not re-executed. When the last $name handler returns success (1xx, 2xx, 3xx status) then the "on_success" code is run; otherwise the "on_failure" code is run. After that, the "after_$name" event handlers are run. Unless "allow_after_handler_to_repeat_event" is set to false, the handler for this event can repeat the event by returning 602 status, in which case the routine stops running the "after_$name" handlers and starts running the $name handlers again. The handler which instructs repeat must be careful not to cause an infinite loop. Arguments: * name Str. Required. Name of the event, for example: "get_args". * req_handler Bool. Optional, defaults to 0. When set to true, will die when there is no handler for the event $name. * run_all_handlers Bool. Optional, defaults to 1. When set to false, will stop calling event handlers for the $name event after the first successful handler (success is defined as codes 1xx, 2xx, and 3xx). Otherwise, all handlers are run regardless of success status. * allow_before_handler_to_cancel_event Bool. Optional, defaults to 1. When set to true, an event handler in the "before_$name" event can cancel the event by returning 601 status. When set to false, will die whenever an event handler returns 601. When the $name event is called by the "before_$name" event handler, * allow_before_handler_to_skip_rest Bool. Optional, defaults to 1. When set to true, an event handler can skip the rest of the event handlers in the "before_$name" event by returning 201 status. When set to false, the next event handler will be called anyway even though an event handler returns 201. * allow_handler_to_repeat_event Bool. Optional, defaults to 1. When set to true, an event handler in the $name event can repeat the event by returning 602 status. When set to false, will die whenever an event handler returns 602. * allow_handler_to_skip_rest Bool. Optional, defaults to 1. When set to true, an event handler can skip the rest of the event handlers in the $name event by returning 201 status. When set to false, the next event handler will be called anyway even though an event handler returns 201. * allow_after_handler_to_repeat_event Bool. Optional, defaults to 1. When set to true, an event handler in the "after_$name" event can repeat the event by returning 602 status. When set to false, will die whenever an event handler returns 602. * allow_after_handler_to_skip_rest Bool. Optional, defaults to 1. When set to true, an event handler can skip the rest of the event handlers in the "after_$name" event by returning 201 status. When set to false, the next event handler will be called anyway even though an event handler returns 201. * stop_after_first_handler_failure Bool. Optional, defaults to 1. When set to true, the first failure status (4xx/5xx) from an event is used as the status of the event and the rest of the handlers will be skipped. Otherwise, will ignore the failure status and move on to the next handler. * on_success Coderef. Optional. Will be executed after the last executed $name handler returns 2xx code (including 200, 201, 204). * on_failure Coderef. Optional. Will be executed after the last executed $name handler returns 4xx/5xx code. ENVIRONMENT SCRIPTX_IMPORT String. Additional import, will be added at the first import() before the usual import arguments. Used to add plugins for a running script, e.g. to add debugging plugins. The syntax is: -,,,...,-,... For example, this: use ScriptX 'CLI::Log', 'Rinci::CLI::Debug::DumpStashAfterGetArgs', Exit => {after => 'after_get_args'}; should be written as: SCRIPTX_IMPORT=-CLI::Log,-Rinci::CLI::Debug::DumpStashAfterGetArgs,-Exit,after,after_get_args If your script is: use ScriptX Rinci => {func=>'MyPackage::myfunc'}; then with the injection of the above environment, effectively it will become: use ScriptX 'CLI::Log', 'Rinci::CLI::Debug::DumpStashAfterGetArgs', Exit => {after => 'after_get_args'}, Rinci => {func=>'MyPackage::myfunc'}; Note that PLUGIN_NAME0 is plugin name that can optionally be followed with @EVENT or "@EVENT@PRIO". For example: "Debug::DumpStash@after_run@99" to put the ScriptX::Debug::DumpStash plugin handler in the "after_run" event at priority 99. SCRIPTX_IMPORT_JSON String (JSON-encoded array). This is an alternative to "SCRIPTX_IMPORT" and has a lower precedence (will not be evaluated when SCRIPTX_IMPORT is defined). Useful if a plugin accept data structure instead of plain scalars. Example: SCRIPTX_IMPORT_JSON='["CLI::Log", "Rinci::CLI::Debug::DumpStashAfterGetArgs", "Exit", {"after":"after_get_args"}, "Rinci", {"func":"MyPackage::myfunc"}]' HOMEPAGE Please visit the project's homepage at . SOURCE Source repository is at . 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. SEE ALSO The various plugins under the "ScriptX::" namespace. Older projects: Perinci::CmdLine. AUTHOR perlancar COPYRIGHT AND LICENSE This software is copyright (c) 2020 by 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.