{"id":27197672,"url":"https://github.com/preaction/beam-wire","last_synced_at":"2025-04-09T20:29:20.989Z","repository":{"id":7354353,"uuid":"8678684","full_name":"preaction/Beam-Wire","owner":"preaction","description":"A simple configuration and dependency injection container","archived":false,"fork":false,"pushed_at":"2024-09-13T14:29:04.000Z","size":390,"stargazers_count":11,"open_issues_count":11,"forks_count":10,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-09-14T04:47:48.839Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/preaction.png","metadata":{"files":{"readme":"README.mkdn","changelog":"CHANGES","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-03-10T00:57:17.000Z","updated_at":"2024-09-13T14:29:07.000Z","dependencies_parsed_at":"2024-06-18T13:54:58.029Z","dependency_job_id":"9b469544-8e8f-4ec2-88e6-487afb1e2408","html_url":"https://github.com/preaction/Beam-Wire","commit_stats":{"total_commits":200,"total_committers":9,"mean_commits":22.22222222222222,"dds":0.12,"last_synced_commit":"f8d629f5749da812a52e99d0b7e0ef92572c2ad1"},"previous_names":[],"tags_count":42,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/preaction%2FBeam-Wire","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/preaction%2FBeam-Wire/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/preaction%2FBeam-Wire/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/preaction%2FBeam-Wire/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/preaction","download_url":"https://codeload.github.com/preaction/Beam-Wire/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248106793,"owners_count":21048797,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-04-09T20:29:20.094Z","updated_at":"2025-04-09T20:29:20.978Z","avatar_url":"https://github.com/preaction.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NAME\n\nBeam::Wire - Lightweight Dependency Injection Container\n\n# VERSION\n\nversion 1.026\n\n# STATUS\n\n\u003ca href=\"https://travis-ci.org/preaction/Beam-Wire\"\u003e\u003cimg src=\"https://travis-ci.org/preaction/Beam-Wire.svg?branch=master\"\u003e\u003c/a\u003e\u003ca href=\"https://coveralls.io/r/preaction/Beam-Wire\"\u003e\u003cimg src=\"https://coveralls.io/repos/preaction/Beam-Wire/badge.png\" alt=\"Coverage Status\" /\u003e\u003c/a\u003e\n\n# SYNOPSIS\n\n    # wire.yml\n    captain:\n        class: Person\n        args:\n            name: Malcolm Reynolds\n            rank: Captain\n    first_officer:\n        $class: Person\n        name: Zoë Alleyne Washburne\n        rank: Commander\n\n    # script.pl\n    use Beam::Wire;\n    my $wire = Beam::Wire-\u003enew( file =\u003e 'wire.yml' );\n    my $captain = $wire-\u003eget( 'captain' );\n    print $captain-\u003ename; # \"Malcolm Reynolds\"\n\n# DESCRIPTION\n\nBeam::Wire is a configuration module and a dependency injection\ncontainer. In addition to complex data structures, Beam::Wire configures\nand creates plain old Perl objects.\n\nA dependency injection (DI) container creates an inversion of control:\nInstead of manually creating all the dependent objects (also called\n\"services\") before creating the main object that we actually want, a DI\ncontainer handles that for us: We describe the relationships between\nobjects, and the objects get built as needed.\n\nDependency injection is sometimes called the opposite of garbage\ncollection. Rather than ensure objects are destroyed in the right order,\ndependency injection makes sure objects are created in the right order.\n\nUsing Beam::Wire in your application brings great flexibility,\nallowing users to easily add their own code to customize how your\nproject behaves.\n\nFor an [introduction to the Beam::Wire service configuration format,\nsee Beam::Wire::Help::Config](https://metacpan.org/pod/Beam::Wire::Help::Config).\n\n# ATTRIBUTES\n\n## file\n\nThe path of the file where services are configured (typically a YAML\nfile). The file's contents should be a single hashref. The keys are\nservice names, and the values are [service\nconfigurations](https://metacpan.org/pod/Beam::Wire::Help::Config).\n\n## dir\n\nThe directory path to use when searching for inner container files.\nDefaults to the directory which contains the file specified by the\n[file attribute](#file).\n\n## config\n\nThe raw configuration data. By default, this data is loaded by\n[Config::Any](https://metacpan.org/pod/Config::Any) using the file specified by the [file attribute](#file).\n\nSee [Beam::Wire::Help::Config for details on what the configuration\ndata structure looks like](https://metacpan.org/pod/Beam::Wire::Help::Config).\n\nIf you don't want to load a file, you can specify this attribute in the\nBeam::Wire constructor.\n\n## services\n\nA hashref of cached services built from the [configuration](#config). If\nyou want to inject a pre-built object for other services to depend on,\nadd it here.\n\n## meta\\_prefix\n\nThe character that begins a meta-property inside of a service's `args`. This\nincludes `$ref`, `$path`, `$method`, and etc...\n\nThe default value is `$`. The empty string is allowed.\n\n# METHODS\n\n## get\n\n    my $service = $wire-\u003eget( $name );\n    my $service = $wire-\u003eget( $name, %overrides )\n\nThe get method resolves and returns the service named `$name`, creating\nit, if necessary, with [the create\\_service method](#create_service).\n\n`%overrides` is an optional list of name-value pairs. If specified,\nget() will create an new, anonymous service that extends the named\nservice with the given config overrides. For example:\n\n    # test.pl\n    use Beam::Wire;\n    my $wire = Beam::Wire-\u003enew(\n        config =\u003e {\n            foo =\u003e {\n                args =\u003e {\n                    text =\u003e 'Hello, World!',\n                },\n            },\n        },\n    );\n\n    my $foo = $wire-\u003eget( 'foo', args =\u003e { text =\u003e 'Hello, Chicago!' } );\n    print $foo; # prints \"Hello, Chicago!\"\n\nThis allows you to create factories out of any service, overriding service\nconfiguration at run-time.\n\nIf `$name` contains a slash (`/`) character (e.g. `foo/bar`), the left\nside (`foo`) will be used as the name of an inner container, and the\nright side (`bar`) is a service inside that container. For example,\nthese two lines are equivalent:\n\n    $bar = $wire-\u003eget( 'foo/bar' );\n    $bar = $wire-\u003eget( 'foo' )-\u003eget( 'bar' );\n\nInner containers can be nested as deeply as desired (`foo/bar/baz/fuzz`).\n\n## set\n\n    $wire-\u003eset( $name =\u003e $service );\n\nThe set method configures and stores the specified `$service` with the\nspecified `$name`. Use this to add or replace built services.\n\nLike [the get() method, above](#get), `$name` can contain a slash (`/`)\ncharacter to traverse through nested containers.\n\n## get\\_config\n\n    my $conf = $wire-\u003eget_config( $name );\n\nGet the config with the given `$name`. Like [the get() method,\nabove](#get), `$name` can contain slash (`/`) characters to traverse\nthrough nested containers.\n\n## normalize\\_config\n\n    my $out_conf = $self-\u003enormalize_config( $in_conf );\n\nNormalize the given `$in_conf` into to hash that [the create\\_service\nmethod](#create_service) expects. This method allows a service to be\ndefined with prefixed meta-names (`$class` instead of `class`) and\nthe arguments specified without prefixes.\n\nFor example, these two services are identical.\n\n    foo:\n        class: Foo\n        args:\n            fizz: buzz\n\n    foo:\n        $class: Foo\n        fizz: buzz\n\nThe `$in_conf` must be a hash, and must already pass [an is\\_meta\ncheck](#is_meta).\n\n## create\\_service\n\n    my $service = $wire-\u003ecreate_service( $name, %config );\n\nCreate the service with the given `$name` and `%config`. Config can\ncontain the following keys:\n\n- class\n\n    The class name of an object to create. Can be combined with `method`,\n    and `args`. An object of any class can be created with Beam::Wire.\n\n- args\n\n    The arguments to the constructor method. Used with `class` and\n    `method`. Can be a simple value, or a reference to an array or\n    hash which will be dereferenced and passed in to the constructor\n    as a list.\n\n    If the `class` consumes the [Beam::Service role](https://metacpan.org/pod/Beam::Service),\n    the service's `name` and `container` will be added to the `args`.\n\n- method\n\n    The method to call to create the object. Only used with `class`.\n    Defaults to `\"new\"`.\n\n    This can also be an array of hashes which describe a list of methods\n    that will be called on the object. The first method should create the\n    object, and each subsequent method can be used to modify the object. The\n    hashes should contain a `method` key, which is a string containing the\n    method to call, and optionally `args` and `return` keys. The `args`\n    key works like the top-level `args` key, above. The optional `return`\n    key can have the special value `\"chain\"`, which will use the return\n    value from the method as the value for the service ([The tutorial shows\n    examples of this](https://metacpan.org/pod/Beam::Wire::Help::Config#Multiple-Constructor-Methods)).\n\n    If an array is used, the top-level `args` key is not used.\n\n- value\n\n    The value of this service. Can be a simple value, or a reference to an\n    array or hash. This value will be simply returned by this method, and is\n    mostly useful when using container files.\n\n    `value` can not be used with `class` or `extends`.\n\n- ref\n\n    A reference to another service.  This may be paired with `call` or `path`.\n\n- config\n\n    The path to a configuration file, relative to [the dir attribute](#dir).\n    The file will be read with [Config::Any](https://metacpan.org/pod/Config::Any), and the resulting data\n    structure returned.\n\n    `value` can not be used with `class` or `extends`.\n\n- extends\n\n    The name of a service to extend. The named service's configuration will\n    be merged with this configuration (via [the merge\\_config\n    method](#merge_config)).\n\n    This can be used in place of the `class` key if the extended configuration\n    contains a class.\n\n- with\n\n    Compose a role into the object's class before creating the object. This\n    can be a single string, or an array reference of strings which are roles\n    to combine.\n\n    This uses [Moo::Role](https://metacpan.org/pod/Moo::Role) and [the create\\_class\\_with\\_roles\n    method](https://metacpan.org/pod/Role::Tiny#create_class_with_roles), which should work with any\n    class (as it uses [the Role::Tiny module](https://metacpan.org/pod/Role::Tiny) under the hood).\n\n    This can be used with the `class` key.\n\n- on\n\n    Attach an event handler to a [Beam::Emitter subclass](https://metacpan.org/pod/Beam::Emitter). This\n    is an array of hashes of event names and handlers. A handler is made from\n    a service reference (`$ref` or an anonymous service), and a subroutine to\n    call on that service (`$sub`).\n\n    For example:\n\n        emitter:\n            class: My::Emitter\n            on:\n                - my_event:\n                    $ref: my_handler\n                    $sub: on_my_event\n\n    This can be used with the `class` key.\n\nThis method uses [the parse\\_args method](#parse_args) to parse the `args` key,\n[resolving references](https://metacpan.org/pod/resolve_ref) as needed.\n\n## merge\\_config\n\n    my %merged = $wire-\u003emerge_config( %config );\n\nIf `%config` contains an `extends` key, merge the extended config together\nwith this one, returning the merged service configuration. This works recursively,\nso a service can extend a service that extends another service just fine.\n\nWhen merging, hashes are combined, with the child configuration taking\nprecedence. The `args` key is handled specially to allow a hash of\nargs to be merged. A single element array of args is merged too, if the\nelement is a hash.\n\nThe configuration returned is a safe copy and can be modified without\neffecting the original config.\n\n## parse\\_args\n\n    my @args = $wire-\u003eparse_args( $for_name, $class, $args );\n\nParse the arguments (`$args`) for the given service (`$for_name`) with\nthe given class (`$class`).\n\n`$args` can be an array reference, a hash reference, or a simple\nscalar. The arguments will be searched for references using [the\nfind\\_refs method](#find_refs), and then a list of arguments will be\nreturned, ready to pass to the object's constructor.\n\nNested containers are handled specially by this method: Their inner\nreferences are not resolved by the parent container. This ensures that\nreferences are always relative to the container they're in.\n\n## find\\_refs\n\n    my @resolved = $wire-\u003efind_refs( $for_name, @args );\n\nGo through the `@args` and recursively resolve any references and\nservices found inside, returning the resolved result. References are\nidentified with [the is\\_meta method](#is_meta).\n\nIf a reference contains a `$ref` key, it will be resolved by [the\nresolve\\_ref method](#resolve_ref). Otherwise, the reference will be\ntreated as an anonymous service, and passed directly to [the\ncreate\\_service method](#create_service).\n\nThis is used when [creating a service](https://metacpan.org/pod/create_service) to ensure all\ndependencies are created first.\n\n## is\\_meta\n\n    my $is_meta = $wire-\u003eis_meta( $ref_hash, $root );\n\nReturns true if the given hash reference describes some kind of\nBeam::Wire service. This is used to identify service configuration\nhashes inside of larger data structures.\n\nA service hash reference must contain at least one key, and must either\ncontain a [prefixed](#meta_prefix) key that could create or reference an\nobject (one of `class`, `extends`, `config`, `value`, or `ref`) or,\nif the `$root` flag exists, be made completely of unprefixed meta keys\n(as returned by [the get\\_meta\\_names method](#get_meta_names)).\n\nThe `$root` flag is used by [the get method](#get) to allow unprefixed\nmeta keys in the top-level hash values.\n\n## get\\_meta\\_names\n\n    my %meta_keys = $wire-\u003eget_meta_names;\n\nGet all the possible service keys with the [meta prefix](#meta_prefix) already\nattached.\n\n## resolve\\_ref\n\n    my @value = $wire-\u003eresolve_ref( $for_name, $ref_hash );\n\nResolves the given dependency from the configuration hash (`$ref_hash`)\nfor the named service (`$for_name`). Reference hashes contain the\nfollowing keys:\n\n- $ref\n\n    The name of a service in the container. Required.\n\n- $path\n\n    A data path to pick some data out of the reference. Useful with `value`\n    and `config` services.\n\n        # container.yml\n        bounties:\n            value:\n                malcolm: 50000\n                zoe: 35000\n                simon: 100000\n\n        captain:\n            class: Person\n            args:\n                name: Malcolm Reynolds\n                bounty:\n                    $ref: bounties\n                    $path: /malcolm\n\n- $call\n\n    Call a method on the referenced object and use the resulting value. This\n    may be a string, which will be the method name to call, or a hash with\n    `$method` and `$args`, which are the method name to call and the\n    arguments to that method, respectively.\n\n        captain:\n            class: Person\n            args:\n                name: Malcolm Reynolds\n                location:\n                    $ref: beacon\n                    $call: get_location\n                bounty:\n                    $ref: news\n                    $call:\n                        $method: get_bounty\n                        $args:\n                            name: mreynolds\n\n## fix\\_refs\n\n    my @fixed = $wire-\u003efix_refs( $for_container_name, @args );\n\nSimilar to [the find\\_refs method](#find_refs). This method searches\nthrough the `@args` and recursively fixes any reference paths to be\nabsolute. References are identified with [the is\\_meta\nmethod](#is_meta).\n\nThis is used by [the get\\_config method](#get_config) to ensure that the\nconfiguration can be passed directly in to [the create\\_service\nmethod](https://metacpan.org/pod/create_service).\n\n## new\n\n    my $wire = Beam::Wire-\u003enew( %attributes );\n\nCreate a new container.\n\n# EXCEPTIONS\n\nIf there is an error internal to Beam::Wire, an exception will be thrown. If there is an\nerror with creating a service or calling a method, the exception thrown will be passed-\nthrough unaltered.\n\n## Beam::Wire::Exception\n\nThe base exception class\n\n## Beam::Wire::Exception::Constructor\n\nAn exception creating a Beam::Wire object\n\n## Beam::Wire::Exception::Config\n\nAn exception loading the configuration file.\n\n## Beam::Wire::Exception::Service\n\nAn exception with service information inside\n\n## Beam::Wire::Exception::NotFound\n\nThe requested service or configuration was not found.\n\n## Beam::Wire::Exception::InvalidConfig\n\nThe configuration is invalid:\n\n- Both \"value\" and \"class\" or \"extends\" are defined. These are mutually-exclusive.\n\n# EVENTS\n\nThe container emits the following events.\n\n## configure\\_service\n\nThis event is emitted when a new service is configured, but before it is\ninstantiated or any classes loaded. This allows altering of the\nconfiguration before the service is built. Already-built services will\nnot fire this event.\n\nEvent handlers get a [Beam::Wire::Event::ConfigService](https://metacpan.org/pod/Beam::Wire::Event::ConfigService) object as their\nonly argument.\n\nThis event will bubble up from child containers.\n\n## build\\_service\n\nThis event is emitted when a new service is built. Cached services will\nnot fire this event.\n\nEvent handlers get a [Beam::Wire::Event::BuildService](https://metacpan.org/pod/Beam::Wire::Event::BuildService) object as their\nonly argument.\n\nThis event will bubble up from child containers.\n\n# ENVIRONMENT VARIABLES\n\n- BEAM\\_WIRE\\_DEBUG\n\n    If set, print a bunch of internal debugging information to STDERR.\n\n# AUTHORS\n\n- Doug Bell \u003cpreaction@cpan.org\u003e\n- Al Newkirk \u003canewkirk@ana.io\u003e\n\n# CONTRIBUTORS\n\n- Al Tom \u003cal-tom.ru@yandex.ru\u003e\n- Ben Moon \u003cguiltydolphin@gmail.com\u003e\n- Bruce Armstrong \u003cbruce@armstronganchor.net\u003e\n- Diab Jerius \u003cdjerius@cfa.harvard.edu\u003e\n- Kent Fredric \u003ckentnl@cpan.org\u003e\n- mauke \u003clukasmai.403@gmail.com\u003e\n- Mohammad S Anwar \u003cmohammad.anwar@yahoo.com\u003e\n- mohawk2 \u003cmohawk2@users.noreply.github.com\u003e\n- Sven Willenbuecher \u003csven.willenbuecher@gmx.de\u003e\n\n# COPYRIGHT AND LICENSE\n\nThis software is copyright (c) 2018-2021 by Doug Bell.\n\nThis is free software; you can redistribute it and/or modify it under\nthe same terms as the Perl 5 programming language system itself.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpreaction%2Fbeam-wire","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpreaction%2Fbeam-wire","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpreaction%2Fbeam-wire/lists"}