dry-rb/dry-system

View on GitHub
changelog.yml

Summary

Maintainability
Test Coverage
---
- version: 0.22.0
  summary:
  date: 2022-01-06
  fixed:
  added:
  - 'Expanded public interfaces for `Dry::System::Config::ComponentDirs` and `Dry::System::Config::Namespaces` to better support programmatic construction and inspection of these configs (@timriley in #195)'
  changed:
  - 'Deprecated `Dry::System::Config::Namespaces#root` as the way to add and configure a root namespace. Use `#add_root` instead (@timriley in #195)'
  - 'Allow bootsnap plugin to use bootsnap on Ruby versions up to 3.0 (pusewicz in #196)'
- version: 0.21.0
  summary: 
  date: 2021-11-01
  fixed:
  added:
  - 'Added **component dir namespaces** as a way to specify multiple, ordered, independent
    namespace rules within a given component dir. This replaces and expands upon the
    namespace support we previously provided via the singular `default_namespace`
    component dir setting (@timriley in #181)'
  changed:
  - |-
    `default_namespace` setting on component dirs has been deprecated. Add a component dir namespace instead, e.g. instead of:

      ```ruby
      # Inside Dry::System::Container.configure
      config.component_dirs.add "lib" do |dir|
        dir.default_namespace = "admin"
      end
      ```

      Add this:

      ```ruby
      config.component_dirs.add "lib" do |dir|
        dir.namespaces.add "admin", key: nil
      end
      ```

      (@timriley in #181)
  - "`Dry::System::Component#path` has been removed and replaced by `Component#require_path`
    and `Component#const_path` (@timriley in #181)"
  - 'Unused `Dry::System::FileNotFoundError` and `Dry::System::InvalidComponentIdentifierTypeError`
    errors have been removed (@timriley in #194)'
  - 'Allow bootsnap for Rubies up to 3.0.x (via #196) (@pusewicz)'
- version: 0.20.0
  summary: 
  date: '2021-09-12'
  fixed:
  - 'Fixed dependency graph plugin to work with internal changes introduced in 0.19.0
    (@wuarmin in #173)'
  - 'Fixed behavior of `Dry::System::Identifier#start_with?` for components identified
    by a single segment, or if all matching segments are provided (@wuarmin in #177)'
  - 'Fixed compatibility of `finalize!` signature provided in `Container::Stubs` (@mpokrywka
    in #178)'
  added: 
  changed:
  - "[internal] Upgraded to new `setting` API provided in dry-configurable 0.13.0
    (@timriley in #179)"
- version: 0.19.2
  date: '2021-08-30'
  changed:
  - "[internal] Improved compatibility with upcoming dry-configurable 0.13.0 release
    (@timriley in #186)"
- version: 0.18.2
  date: '2021-08-30'
  changed:
  - "[internal] Improved compatibility with upcoming dry-configurable 0.13.0 release
    (@timriley in #187)"
- version: 0.19.1
  date: 2021-07-11
  fixed:
  - 'Check for registered components (@timriley in #175)'
- version: 0.19.0
  date: 2021-04-22
  summary: This release marks a huge step forward for dry-system, bringing support
    for Zeitwerk and other autoloaders, plus clearer configuration and improved consistency
    around component resolution for both finalized and lazy loading containers. [Read
    the announcement post](https://dry-rb.org/news/2021/04/22/dry-system-0-19-released-with-zeitwerk-support-and-more-leading-the-way-for-hanami-2-0/)
    for a high-level tour of the new features.
  added:
  - |-
    New `component_dirs` setting on `Dry::System::Container`, which must be used for specifying the directories which dry-system will search for component source files.

      Each added component dir is relative to the container's `root`, and can have its own set of settings configured:

      ```ruby
      class MyApp::Container < Dry::System::Container
        configure do |config|
          config.root = __dir__

          # Defaults for all component dirs can be configured separately
          config.component_dirs.auto_register = true # default is already true

          # Component dirs can be added and configured independently
          config.component_dirs.add "lib" do |dir|
            dir.add_to_load_path = true # defaults to true
            dir.default_namespace = "my_app"
          end

          # All component dir settings are optional. Component dirs relying on default
          # settings can be added like so:
          config.component_dirs.add "custom_components"
        end
      end
      ```

      The following settings are available for configuring added `component_dirs`:

      - `auto_register`, a boolean, or a proc accepting a `Dry::System::Component` instance and returning a truthy or falsey value. Providing a proc allows an auto-registration policy to apply on a per-component basis
      - `add_to_load_path`, a boolean
      - `default_namespace`, a string representing the leading namespace segments to be stripped from the component's identifier (given the identifier is derived from the component's fully qualified class name)
      - `loader`, a custom replacement for the default `Dry::System::Loader` to be used for the component dir
      - `memoize`, a boolean, to enable/disable memoizing all components in the directory, or a proc accepting a `Dry::System::Component` instance and returning a truthy or falsey value. Providing a proc allows a memoization policy to apply on a per-component basis

      _All component dir settings are optional._

      (@timriley in #155, #157, and #162)
  - "A new autoloading-friendly `Dry::System::Loader::Autoloading` is available, which
    is tested to work with [Zeitwerk](https://github.com/fxn/zeitwerk) \U0001F389\n\n
    \ Configure this on the container (via a component dir `loader` setting), and
    the loader will no longer `require` any components, instead allowing missing constant
    resolution to trigger the loading of the required file.\n\n  This loader presumes
    an autoloading system like Zeitwerk has already been enabled and appropriately
    configured.\n\n  A recommended setup is as follows:\n\n  ```ruby\n  require \"dry/system/container\"\n
    \ require \"dry/system/loader/autoloading\"\n  require \"zeitwerk\"\n\n  class
    MyApp::Container < Dry::System::Container\n    configure do |config|\n      config.root
    = __dir__\n\n      config.component_dirs.loader = Dry::System::Loader::Autoloading\n
    \     config.component_dirs.add_to_load_path = false\n\n      config.component_dirs.add
    \"lib\" do |dir|\n        # ...\n      end\n    end\n  end\n\n  loader = Zeitwerk::Loader.new\n
    \ loader.push_dir MyApp::Container.config.root.join(\"lib\").realpath\n  loader.setup\n
    \ ```\n\n  (@timriley in #153)"
  - "[BREAKING] `Dry::System::Component` instances (which users of dry-system will
    interact with via custom loaders, as well as via the `auto_register` and `memoize`
    component dir settings described above) now return a `Dry::System::Identifier`
    from their `#identifier` method. The raw identifier string may be accessed via
    the identifier's own `#key` or `#to_s` methods. `Identifier` also provides a helpful
    namespace-aware `#start_with?` method for returning whether the identifier begins
    with the provided namespace(s) (@timriley in #158)"
  changed:
  - 'Components with `# auto_register: false` magic comments in their source files
    are now properly ignored when lazy loading (@timriley in #155)'
  - "`# memoize: true` and `# memoize: false` magic comments at top of component files
    are now respected (@timriley in #155)"
  - "[BREAKING] `Dry::System::Container.load_paths!` has been renamed to `.add_to_load_path!`.
    This method now exists as a mere convenience only. Calling this method is no longer
    required for any configured `component_dirs`; these are now added to the load
    path automatically (@timriley in #153 and #155)"
  - "[BREAKING] `auto_register` container setting has been removed. Configured directories
    to be auto-registered by adding `component_dirs` instead (@timriley in #155)"
  - "[BREAKING] `default_namespace` container setting has been removed. Set it when
    adding `component_dirs` instead (@timriley in #155)"
  - "[BREAKING] `loader` container setting has been nested under `component_dirs`,
    now available as `component_dirs.loader` to configure a default loader for all
    component dirs, as well as on individual component dirs when being added (@timriley
    in #162)"
  - "[BREAKING] `Dry::System::ComponentLoadError` is no longer raised when a component
    could not be lazy loaded; this was only raised in a single specific failure condition.
    Instead, a `Dry::Container::Error` is raised in all cases of components failing
    to load (@timriley in #155)"
  - "[BREAKING] `Dry::System::Container.auto_register!` has been removed. Configure
    `component_dirs` instead. (@timriley in #157)"
  - "[BREAKING] The `Dry::System::Loader` interface has changed. It is now a static
    interface, no longer initialized with a component. The component is instead passed
    to each method as an argument: `.require!(component)`, `.call(component, *args)`,
    `.constant(component)` (@timriley in #157)"
  - "[BREAKING] `Dry::System::Container.require_path` has been removed. Provide custom
    require behavior by configuring your own `loader` (@timriley in #153)"
- version: 0.18.1
  summary: 
  date: '2020-08-26'
  fixed:
  - Made `Booter#boot_files` a public method again, since it was required by dry-rails
    (@timriley)
  added: 
  changed: 
- version: 0.18.0
  summary: 
  date: '2020-08-24'
  fixed: 
  added:
  - |-
    New `bootable_dirs` setting on `Dry::System::Container`, which accepts paths to multiple directories for looking up bootable component files. (@timriley in PR #151)

      For each entry in the `bootable_dirs` array, relative directories will be appended to the container's `root`, and absolute directories will be left unchanged.

      When searching for bootable files, the first match will win, and any subsequent same-named files will not be loaded. In this way, the `bootable_dirs` act similarly to the `$PATH` in a shell environment.
  changed: 
- version: 0.17.0
  summary: 
  date: '2020-02-19'
  fixed:
  - 'Works with the latest dry-configurable version (issue #141) (@solnic)'
  added: 
  changed:
  - Depends on dry-configurable `=> 0.11.1` now (@solnic)
- version: 0.16.0
  summary: 
  date: '2020-02-15'
  changed:
  - Plugins can now define their own settings which are available in the `before(:configure)`
    hook (@solnic)
  - Dependency on dry-configurable was bumped to `~> 0.11` (@solnic)
- version: 0.15.0
  summary: 
  date: '2020-01-30'
  fixed: 
  added: |
    New hook - `before(:configure)` which a plugin should use if it needs to declare new settings (@solnic)

    ```ruby
    # in your plugin code
    before(:configure) { setting :my_new_setting }

    after(:configure) { config.my_new_setting = "awesome" }
    ```
  changed:
  - Centralize error definitions in `lib/dry/system/errors.rb` (@cgeorgii)
  - All built-in plugins use `before(:configure)` now to declare their settings (@solnic)
- version: 0.14.1
  summary: 
  date: '2020-01-22'
  fixed: 
  added: 
  changed:
  - Use `Kernel.require` explicitly to avoid issues with monkey-patched `require`
    from ActiveSupport (@solnic)
- version: 0.14.0
  date: '2020-01-21'
  fixed:
  - 'Misspelled plugin name raises meaningful error (issue #132) (@cgeorgii)'
  - Fail fast if auto_registrar config contains incorrect path (@cutalion)
- version: 0.13.2
  date: '2019-12-28'
  fixed:
  - More keyword warnings (flash-gordon)
- version: 0.13.1
  date: '2019-11-07'
  fixed:
  - Fixed keyword warnings reported by Ruby 2.7 (flash-gordon)
  - Duplicates in `Dry::System::Plugins.loaded_dependencies` (AMHOL)
- version: 0.13.0
  date: '2019-10-13'
  changed:
  - "[BREAKING] `Container.key?` triggers lazy-loading for not finalized containers.
    If component wasn't found it returns `false` without raising an error. This is
    a breaking change, if you seek the previous behavior, use `Container.registered?`
    (flash-gordon)"
  added:
  - |-
    `Container.resolve` accepts and optional block parameter which will be called if component cannot be found. This makes dry-system consistent with dry-container 0.7.2 (flash-gordon)
      ```ruby
      App.resolve('missing.dep') { :fallback } # => :fallback
      ```
- version: 0.12.0
  date: '2019-04-24'
  changed:
  - Compatibility with dry-struct 1.0 and dry-types 1.0 (flash-gordon)
- version: 0.11.0
  date: '2019-03-22'
  changed:
  - "[BREAKING] `:decorate` plugin was moved from dry-system to dry-container (available
    in 0.7.0+). To upgrade remove `use :decorate` and change `decorate` calls from
    `decorate(key, decorator: something)` to `decorate(key, with: something)` (flash-gordon)"
  - "[internal] Compatibility with dry-struct 0.7.0 and dry-types 0.15.0"
- version: 0.10.1
  date: '2018-07-05'
  added:
  - Support for stopping bootable components with `Container.stop(component_name)`
    (GustavoCaso)
  fixed:
  - When using a non-finalized container, you can now resolve multiple different container
    objects registered using the same root key as a bootable component (timriley)
- version: 0.10.0
  date: '2018-06-07'
  added:
  - |-
    You can now set a custom inflector on the container level. As a result, the `Loader`'s constructor accepts two arguments: `path` and `inflector`, update your custom loaders accordingly (flash-gordon)

      ```ruby
      class MyContainer < Dry::System::Container
        configure do |config|
          config.inflector = Dry::Inflector.new do |inflections|
            inflections.acronym('API')
          end
        end
      end
      ```
  changed:
  - A helpful error will be raised if an invalid setting value is provided (GustavoCaso)
  - When using setting plugin, will use default values from types (GustavoCaso)
  - Minimal supported ruby version was bumped to `2.3` (flash-gordon)
  - "`dry-struct` was updated to `~> 0.5` (flash-gordon)"
- version: 0.9.2
  date: '2018-02-08'
  fixed:
  - Default namespace no longer breaks resolving dependencies with identifier that
    includes part of the namespace (ie `mail.mailer`) (GustavoCaso)
- version: 0.9.1
  date: '2018-01-03'
  fixed:
  - Plugin dependencies are now auto-required and a meaningful error is raised when
    a dep failed to load (solnic)
- version: 0.9.0
  date: '2018-01-02'
  added:
  - Plugin API (solnic)
  - "`:env` plugin which adds support for setting `env` config value (solnic)"
  - "`:logging` plugin which adds a default logger (solnic)"
  - "`:decorate` plugin for decorating registered objects (solnic)"
  - "`:notifications` plugin adding pub/sub bus to containers (solnic)"
  - "`:monitoring` plugin which adds `monitor` method for monitoring object method
    calls (solnic)"
  - "`:bootsnap` plugin which adds support for bootsnap (solnic)"
  changed:
  - "[BREAKING] renamed `Container.{require=>require_from_root}` (GustavoCaso)"
- version: 0.8.1
  date: '2017-10-17'
  fixed:
  - Aliasing an external component works correctly (solnic)
  - Manually calling `:init` will also finalize a component (solnic)
- version: 0.8.0
  date: '2017-10-16'
  added:
  - Support for external bootable components (solnic)
  - Built-in `:system` components including `:settings` component (solnic)
  fixed:
  - Lazy-loading components work when a container has `default_namespace` configured
    (GustavoCaso)
  changed:
  - "[BREAKING] Improved boot DSL with support for namespacing and lifecycle before/after
    callbacks (solnic)"
- version: 0.7.3
  date: '2017-08-02'
  fixed:
  - "`Container.enable_stubs!` calls super too, which actually adds `stub` API (solnic)"
  - Issues with lazy-loading and import in stub mode are gone (solnic)
- version: 0.7.2
  date: '2017-08-02'
  added:
  - "`Container.enable_stubs!` for test environments which enables stubbing components
    (GustavoCaso)"
  changed:
  - Component identifiers can now include same name more than once ie `foo.stuff.foo`
    (GustavoCaso)
  - "`Container#boot!` was renamed to `Container#start` (davydovanton)"
  - "`Container#boot` was renamed to `Container#init` (davydovanton)"
- version: 0.7.1
  date: '2017-06-16'
  changed:
  - Accept string values for Container's `root` config (timriley)
- version: 0.7.0
  date: '2017-06-15'
  added:
  - Added `manual_registrar` container setting (along with default `ManualRegistrar`
    implementation), and `registrations_dir` setting. These provide support for a
    well-established place for keeping files with manual container registrations (timriley)
  - 'AutoRegistrar parses initial lines of Ruby source files for "magic comments"
    when auto-registering components. An `# auto_register: false` magic comment will
    prevent a Ruby file from being auto-registered (timriley)'
  - |-
    `Container.auto_register!`, when called with a block, yields a configuration object to control the auto-registration behavior for that path, with support for configuring 2 different aspects of auto-registration behavior (both optional):

      ```ruby
      class MyContainer < Dry::System::Container
        auto_register!('lib') do |config|
          config.instance do |component|
            # custom logic for initializing a component
          end

          config.exclude do |component|
            # return true to skip auto-registration of the component, e.g.
            # component.path =~ /entities/
          end
        end
      end
      ```
  - A helpful error will be raised if a bootable component's finalize block name doesn't
    match its boot file name (GustavoCaso)
  changed:
  - The `default_namespace` container setting now supports multi-level namespaces
    (GustavoCaso)
  - "`Container.auto_register!` yields a configuration block instead of a block for
    returning a custom instance (see above) (GustavoCaso)"
  - "`Container.import` now requires an explicit local name for the imported container
    (e.g. `import(local_name: AnotherContainer)`) (timriley)"
- version: 0.6.0
  date: '2016-02-02'
  changed:
  - Lazy load components as they are resolved, rather than on injection (timriley)
  - Perform registration even though component already required (blelump)
- version: 0.5.1
  date: '2016-08-23'
  fixed:
  - Undefined locals or method calls will raise proper exceptions in Lifecycle DSL
    (aradunovic)
- version: 0.5.0
  date: '2016-08-15'
  summary: for multi-container setups. As part of this release `dry-system` has been
    renamed to `dry-system`.
  added:
  - |-
    Boot DSL with:
      - Lifecycle triggers: `init`, `start` and `stop` (solnic)
      - `use` method which auto-boots a dependency and makes it available in the booting context (solnic)
  - When a component relies on a bootable component, and is being loaded in isolation,
    the component will be booted automatically (solnic)
  changed:
  - "[BREAKING] `Dry::Component::Container` is now `Dry::System::Container` (solnic)"
  - "[BREAKING] Configurable `loader` is now a class that accepts container's config
    and responds to `#constant` and `#instance` (solnic)"
  - "[BREAKING] `core_dir` renameda to `system_dir` and defaults to `system` (solnic)"
  - "[BREAKING] `auto_register!` yields `Component` objects (solnic)"
- version: 0.4.3
  date: '2016-08-01'
  fixed:
  - Return immediately from `Container.load_component` if the requested component
    key already exists in the container. This fixes a crash when requesting to load
    a manually registered component with a name that doesn't map to a filename (timriley
    in [#24](https://github.com/dry-rb/dry-system/pull/24))
- version: 0.4.2
  date: '2016-07-26'
  fixed:
  - Ensure file components can be loaded when they're requested for the first time
    using their shorthand container identifier (i.e. with the container's default
    namespace removed) (timriley)
- version: 0.4.1
  date: '2016-07-26'
  fixed:
  - Require the 0.4.0 release of dry-auto_inject for the features below (in 0.4.0)
    to work properly (timriley)
- version: 0.4.0
  date: '2016-07-26'
  added:
  - |-
    Support for supplying a default namespace to a container, which is passed to the container's injector to allow for convenient shorthand access to registered objects in the same namespace (timriley in [#20](https://github.com/dry-rb/dry-system/pull/20))

      ```ruby
      # Set up container with default namespace
      module Admin
        class Container < Dry::Component::Container
          configure do |config|
            config.root = Pathname.new(__dir__).join("../..")
            config.default_namespace = "admin"
          end
        end

        Import = Container.injector
      end

      module Admin
        class CreateUser
          # "users.repository" will resolve an Admin::Users::Repository instance,
          # where previously you had to identify it as "admin.users.repository"
          include Admin::Import["users.repository"]
        end
      end
      ```
  - Support for supplying to options directly to dry-auto_inject's `Builder` via `Dry::Component::Container#injector(options)`.
    This allows you to provide dry-auto_inject customizations like your own container
    of injection strategies (timriley in [#20](https://github.com/dry-rb/dry-system/pull/20))
  - Support for accessing all available injector strategies, not just the defaults
    (e.g. `MyContainer.injector.some_custom_strategy`) (timriley in [#19](https://github.com/dry-rb/dry-system/pull/19))
  changed:
  - Subclasses of `Dry::Component::Container` no longer have an `Injector` constant
    automatically defined within them. The recommended approach is to save your own
    injector object to a constant, which allows you to pass options to it at the same
    time, e.g. `MyApp::Import = MyApp::Container.injector(my_options)` (timriley in
    [#19](https://github.com/dry-rb/dry-system/pull/19))
- version: 0.3.0
  date: '2016-06-18'
  changed:
  - 'Removed two pieces that are moving to dry-web:'
  - Removed `env` setting from `Container` (timriley)
  - Removed `Dry::Component::Config` and `options` setting from `Container` (timriley)
  - Changed `Component#configure` behavior so it can be run multiple times for configuration
    to be applied in multiple passes (timriley)
  summary: 'Removed two pieces that are moving to dry-web:'
- version: 0.2.0
  date: '2016-06-13'
  changed:
  - Component core directory is now `component/` by default (timriley)
  - Injector default stragegy is now whatever dry-auto_inject's default is (rather
    than hard-coding a particular default strategy for dry-system) (timriley)
  fixed:
  - Fixed bug where specified auto-inject strategies were not respected (timriley)
- version: 0.1.0
  date: '2016-06-07'
  added:
  - Provide a dependency injector as an `Inject` constant inside any subclass of `Dry::Component::Container`.
    This injector supports all of `dry-auto_inject`'s default injection strategies,
    and will lazily load any dependencies as they are injected. It also supports arbitrarily
    switching strategies, so they can be used in different classes as required (e.g.
    `include MyComponent::Inject.args["dep"]`) (timriley)
  - 'Support aliased dependency names when calling the injector object (e.g. `MyComponent::Inject[foo:
    "my_app.foo", bar: "another.thing"]`) (timriley)'
  - |-
    Allow a custom dependency loader to be set on a container via its config (AMHOL)

      ```ruby
      class MyContainer < Dry::Component::Container
        configure do |config|
          # other config
          config.loader = MyLoader
        end
      end
      ```
  changed:
  - "`Container.boot` now only makes a simple `require` for the boot file (solnic)"
  - Container object is passed to `Container.finalize` blocks (solnic)
  - Allow `Pathname` objects passed to `Container.require` (solnic)
  - Support lazily loading missing dependencies from imported containers (solnic)
  - "`Container.import_module` renamed to `.injector` (timriley)"
  - Default injection strategy is now `kwargs`, courtesy of the new dry-auto_inject
    default (timriley)
- version: 0.0.2
  date: '2015-12-24'
  added:
  - Containers have a `name` setting (solnic)
  - Containers can be imported into one another (solnic)
  changed:
  - Container name is used to determine the name of its config file (solnic)
- version: 0.0.1
  date: '2015-12-24'
  summary: First public release, extracted from rodakase project