Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [[v0.1.1](https://github.com/The-FireHub-Project/Module/compare/v0.1.0...v0.1.1)] – 2026-10-26

### Added
* Add a method to check for service registrations in modules by @dieselxxx

## [v0.1.0] – 2026-10-21

### Added
Expand Down
101 changes: 63 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
/></a>
<a href="#">
<img
src="https://img.shields.io/badge/Version-0.1.0-d50000?style=flat&labelColor=30363d&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMzMuNjUxIDM4Ny4wOSI+CiAgICA8dGl0bGU+RmlyZWh1YiBJY29uPC90aXRsZT4KICAgIDxzdHlsZT4KICAgICAgICAuY29sb3Ige2ZpbGw6ICNkNTAwMDA7fQogICAgPC9zdHlsZT4KICAgIDxnPgogICAgICAgIDxwYXRoIGNsYXNzPSJjb2xvciIgZD0iTTI2Ny4xMDYsMjYyLjU2MWMxMC41LTE3LjYzMSwxOS42My0zNi45MzEsMjAuMTItNTcuNDUxYzAuNDktMjAuNTItOS42LTQyLjQxOS0yOC40Ni01MC41MmM1LjcxLDkuNjcsMTAuMjUsMjAuNjIsOS4yOCwzMS44MWMtMC45NywxMS4xOS04Ljg2LDIyLjM3LTIwLDI0Yy0xMC40OSwxLjUyOS0yMC43Ny01Ljg1MS0yNS41MS0xNS4zNGMtNC43NC05LjQ5MS00LjYyLTIwLjU2MS00LTMxLjE1QzIyNC4zOTYsNTYuMTcsMTQyLjA0Niw1Ljk0LDEyNy4yODYsMGMwLDAsMTEuNDksMTIuMzksMTMuODgsMzAuNTNjMS45LDE0LjQ0LDAuMTcsMjkuMjItMy4zNCw0My4yNGMtMTAuODgsNDMuMzUtMzYuODYsNzcuODItNTguNTksMTE2Yy0xNC41OCwyNS41OC0yNCw1NC4wNS0yMy4zMiw4My42OWMwLjc2LDM0LDE2LDY3LjksNDIuNzMsODguODdjMTMuMDUsMTAuMjI5LDI4LjMyLDE3LjY1LDQzLjg0LDIzLjI5Yy0yLjE5LTIuNjItNC44NS01LjYyLTctOC42MDFjLTE4LjY4LTI1LjkzOS0zMi4yNi01MS41LTMzLjE3LTg0LjEwOWMtMC43Ny0yOC4yMyw3LjQtNTMuOTMsMTUuMTQtODAuNjFjLTAuOTEsMy4xNCwxLjgzLDEwLjcsMi4xLDE0LjIxYzAuNDEsNS40LDAuNDYsMTAuODIsMC41LDE2LjIyMWMwLjA4LDExLjQ3LTAuMTQsMjMsMS4zMiwzNC4zNzljMy40MiwyNi43NCwxOC4yOCw0OS43MTEsNDMuMjYsNjEuMjAxYy04LjQ3LTE5LjY5LTkuMzEtMzYuMzAxLTEuMjgtNTYuNzIxYzYuMDUtMTUuMzY5LDE0LjcxLTI5Ljc3OSwxOC45NC00NS43NWM4LjYzLTMyLjU2LTIuNDItNjcuNjQtMjAuNzUtOTUuODljMTcuMzIsMTUuMzEsMzIsMzQuNDUsMzguMyw1Ni43YzcuMzYsMjYsMi44Niw1My41NiwwLDgwLjM5Yy0yLjUxLDIzLjIxLTMuNzEsNDgsNS40Miw3MC4wNWM4LDE5LjIzLDIyLjQsMjkuNTIxLDM5LjUxLDQwYy0zLjY0NC0zLjAxMS02LjU2Ni02LjgtOC41NS0xMS4wOWMtOS4xNi0xOC4zNy02LjczLTQwLjY2LDAuNzktNTkuNzZTMjU2LjYxNiwyODAuMiwyNjcuMTA2LDI2Mi41NjF6Ii8+CiAgICAgICAgPHBhdGggY2xhc3M9ImNvbG9yIiBkPSJNMTczLjEzNiwyMi40M2M1LjA3OCw0Ljk5MSw5Ljg3MiwxMC4yNjIsMTQuMzYsMTUuNzljMS43NzMsMi4xODcsMy40ODMsNC40LDUuMTMsNi42NGM3OS42NzQsMTQuMjQ0LDEzMi43MTYsOTAuMzgsMTE4LjQ3MiwxNzAuMDU0Yy02Ljk0NywzOC44NTctMjkuMjc2LDczLjI3LTYxLjkzMiw5NS40NDZjLTEuNDMsMy0yLjc3LDYtNCw5Yy0yLjUyOCw2LjM3Ny00LjMzLDEzLjAxOS01LjM3LDE5LjhjODIuODQ5LTQwLjMyOSwxMTcuMzE4LTE0MC4xODUsNzYuOTg5LTIyMy4wMzNDMjg5Ljg0OSw2MC43OSwyMzQuNjM1LDI0Ljc3NywxNzMuMTM2LDIyLjQzeiIvPgogICAgICAgIDxwYXRoIGNsYXNzPSJjb2xvciIgZD0iTTQ3LjA0NiwyNzMuNjA5di0wLjA4QzAuNDM1LDIwNy4zNTQsMTYuMjk2LDExNS45MjMsODIuNDcxLDY5LjMxM2MxNS4yNTQtMTAuNzQ0LDMyLjQyLTE4LjQ3Nyw1MC41NzUtMjIuNzgzYzAuMjEyLTQuOTYyLDAuMDA1LTkuOTMzLTAuNjItMTQuODZjLTAuMjUzLTEuODc1LTAuNjI0LTMuNzMxLTEuMTEtNS41NkM0MS4yOTksNDUuNzM4LTE1Ljc2MywxMzQuNjIzLDMuODY1LDIyNC42NGM3LjI4LDMzLjM5LDI0LjY0LDYzLjczOCw0OS43MzEsODYuOTRDNDkuNTU5LDI5OS4zMTQsNDcuMzUyLDI4Ni41Miw0Ny4wNDYsMjczLjYwOXoiLz4KICAgIDwvZz4KPC9zdmc+"
src="https://img.shields.io/badge/Version-0.1.1-d50000?style=flat&labelColor=30363d&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMzMuNjUxIDM4Ny4wOSI+CiAgICA8dGl0bGU+RmlyZWh1YiBJY29uPC90aXRsZT4KICAgIDxzdHlsZT4KICAgICAgICAuY29sb3Ige2ZpbGw6ICNkNTAwMDA7fQogICAgPC9zdHlsZT4KICAgIDxnPgogICAgICAgIDxwYXRoIGNsYXNzPSJjb2xvciIgZD0iTTI2Ny4xMDYsMjYyLjU2MWMxMC41LTE3LjYzMSwxOS42My0zNi45MzEsMjAuMTItNTcuNDUxYzAuNDktMjAuNTItOS42LTQyLjQxOS0yOC40Ni01MC41MmM1LjcxLDkuNjcsMTAuMjUsMjAuNjIsOS4yOCwzMS44MWMtMC45NywxMS4xOS04Ljg2LDIyLjM3LTIwLDI0Yy0xMC40OSwxLjUyOS0yMC43Ny01Ljg1MS0yNS41MS0xNS4zNGMtNC43NC05LjQ5MS00LjYyLTIwLjU2MS00LTMxLjE1QzIyNC4zOTYsNTYuMTcsMTQyLjA0Niw1Ljk0LDEyNy4yODYsMGMwLDAsMTEuNDksMTIuMzksMTMuODgsMzAuNTNjMS45LDE0LjQ0LDAuMTcsMjkuMjItMy4zNCw0My4yNGMtMTAuODgsNDMuMzUtMzYuODYsNzcuODItNTguNTksMTE2Yy0xNC41OCwyNS41OC0yNCw1NC4wNS0yMy4zMiw4My42OWMwLjc2LDM0LDE2LDY3LjksNDIuNzMsODguODdjMTMuMDUsMTAuMjI5LDI4LjMyLDE3LjY1LDQzLjg0LDIzLjI5Yy0yLjE5LTIuNjItNC44NS01LjYyLTctOC42MDFjLTE4LjY4LTI1LjkzOS0zMi4yNi01MS41LTMzLjE3LTg0LjEwOWMtMC43Ny0yOC4yMyw3LjQtNTMuOTMsMTUuMTQtODAuNjFjLTAuOTEsMy4xNCwxLjgzLDEwLjcsMi4xLDE0LjIxYzAuNDEsNS40LDAuNDYsMTAuODIsMC41LDE2LjIyMWMwLjA4LDExLjQ3LTAuMTQsMjMsMS4zMiwzNC4zNzljMy40MiwyNi43NCwxOC4yOCw0OS43MTEsNDMuMjYsNjEuMjAxYy04LjQ3LTE5LjY5LTkuMzEtMzYuMzAxLTEuMjgtNTYuNzIxYzYuMDUtMTUuMzY5LDE0LjcxLTI5Ljc3OSwxOC45NC00NS43NWM4LjYzLTMyLjU2LTIuNDItNjcuNjQtMjAuNzUtOTUuODljMTcuMzIsMTUuMzEsMzIsMzQuNDUsMzguMyw1Ni43YzcuMzYsMjYsMi44Niw1My41NiwwLDgwLjM5Yy0yLjUxLDIzLjIxLTMuNzEsNDgsNS40Miw3MC4wNWM4LDE5LjIzLDIyLjQsMjkuNTIxLDM5LjUxLDQwYy0zLjY0NC0zLjAxMS02LjU2Ni02LjgtOC41NS0xMS4wOWMtOS4xNi0xOC4zNy02LjczLTQwLjY2LDAuNzktNTkuNzZTMjU2LjYxNiwyODAuMiwyNjcuMTA2LDI2Mi41NjF6Ii8+CiAgICAgICAgPHBhdGggY2xhc3M9ImNvbG9yIiBkPSJNMTczLjEzNiwyMi40M2M1LjA3OCw0Ljk5MSw5Ljg3MiwxMC4yNjIsMTQuMzYsMTUuNzljMS43NzMsMi4xODcsMy40ODMsNC40LDUuMTMsNi42NGM3OS42NzQsMTQuMjQ0LDEzMi43MTYsOTAuMzgsMTE4LjQ3MiwxNzAuMDU0Yy02Ljk0NywzOC44NTctMjkuMjc2LDczLjI3LTYxLjkzMiw5NS40NDZjLTEuNDMsMy0yLjc3LDYtNCw5Yy0yLjUyOCw2LjM3Ny00LjMzLDEzLjAxOS01LjM3LDE5LjhjODIuODQ5LTQwLjMyOSwxMTcuMzE4LTE0MC4xODUsNzYuOTg5LTIyMy4wMzNDMjg5Ljg0OSw2MC43OSwyMzQuNjM1LDI0Ljc3NywxNzMuMTM2LDIyLjQzeiIvPgogICAgICAgIDxwYXRoIGNsYXNzPSJjb2xvciIgZD0iTTQ3LjA0NiwyNzMuNjA5di0wLjA4QzAuNDM1LDIwNy4zNTQsMTYuMjk2LDExNS45MjMsODIuNDcxLDY5LjMxM2MxNS4yNTQtMTAuNzQ0LDMyLjQyLTE4LjQ3Nyw1MC41NzUtMjIuNzgzYzAuMjEyLTQuOTYyLDAuMDA1LTkuOTMzLTAuNjItMTQuODZjLTAuMjUzLTEuODc1LTAuNjI0LTMuNzMxLTEuMTEtNS41NkM0MS4yOTksNDUuNzM4LTE1Ljc2MywxMzQuNjIzLDMuODY1LDIyNC42NGM3LjI4LDMzLjM5LDI0LjY0LDYzLjczOCw0OS43MzEsODYuOTRDNDkuNTU5LDI5OS4zMTQsNDcuMzUyLDI4Ni41Miw0Ny4wNDYsMjczLjYwOXoiLz4KICAgIDwvZz4KPC9zdmc+"
alt="version"
/></a>
<a href="./LICENSE">
Expand All @@ -22,10 +22,6 @@
/></a>
</h1>

[![PHPStan](https://github.com/The-FireHub-Project/Module/actions/workflows/PHPStan.yml/badge.svg?branch=develop)](https://github.com/The-FireHub-Project/Module/actions/workflows/PHPStan.yml)
[![PHPUnit](https://github.com/The-FireHub-Project/Module/actions/workflows/PHPUnit.yml/badge.svg?branch=develop)](https://github.com/The-FireHub-Project/Module/actions/workflows/PHPUnit.yml)
[![Codecov](https://codecov.io/gh/The-FireHub-Project/Module/branch/develop/graph/badge.svg?token=XW2YEONF51)](https://app.codecov.io/gh/The-FireHub-Project/Module/tree/develop)

<p>
<a href="https://github.com/The-FireHub-Project/Module">
<img
Expand Down Expand Up @@ -69,55 +65,84 @@
/></a>
</p>

Provides the dependency injection and service management foundation of the FireHub ecosystem. This repository contains the runtime components responsible for service registration, dependency resolution, instance creation, and service lifetime management, enabling consistent and loosely coupled application architectures.
FireHub Module provides modular application composition and lifecycle integration for The FireHub Project. It enables applications to organize related functionality into cohesive, reusable modules while maintaining clear architectural boundaries and separation of concerns.

FireHub Module is built around the contracts defined by FireHub Core and provides a modular implementation of the Inversion of Control principle. It separates service definitions from their runtime resolution, allowing applications and framework components to declare dependencies without managing their construction directly.
Built around the contracts defined by FireHub Core, FireHub Module provides the mechanisms for module registration, dependency coordination, initialization ordering, and integration with the application lifecycle. Modules can contribute services, configuration, and lifecycle behavior without introducing independent application runtimes.

This repository serves as a foundational runtime component for FireHub applications, adapters, and capabilities, supporting clean architecture, testability, extensibility, and predictable dependency management.
FireHub Module serves as an application composition and orchestration component within the FireHub ecosystem. It supports Clean Architecture and Domain-Driven Design by enabling applications to assemble independent functional units while preserving centralized lifecycle management through FireHub Application and execution infrastructure through FireHub Kernel.

---

## <img src="https://raw.githubusercontent.com/The-FireHub-Project/the-firehub-project.github.io/master/resources/graphics/icons/firehub.svg" width="15" alt="FireHub Icon"> Development Branch
## <img src="https://raw.githubusercontent.com/The-FireHub-Project/the-firehub-project.github.io/master/resources/graphics/icons/firehub.svg" width="15" alt="FireHub Icon"> Repository Purpose

FireHub Module is the modular application composition and orchestration component of the FireHub ecosystem.

Built on the contracts provided by FireHub Core, it supplies the mechanisms required to organize, register, coordinate, and integrate functional modules within FireHub applications.

The purpose of this repository is to provide a consistent modular architecture while preserving separation of concerns between application composition, dependency management, and runtime execution.

⚠️ **This is the `develop` branch**
The Module architecture is designed to support:

- Unstable
- APIs may change without notice
- Not intended for production use
* Modular organization of application functionality
* Registration and management of application modules
* Module dependency declaration and resolution
* Dependency ordering and circular dependency detection
* Integration with application initialization and disposal
* Module-specific service registration and configuration
* Shared application dependency injection infrastructure
* Reusable and independently developed functional modules
* Predictable module initialization and disposal ordering
* Compatibility with Clean Architecture and Domain-Driven Design

## <img src="https://raw.githubusercontent.com/The-FireHub-Project/the-firehub-project.github.io/master/resources/graphics/icons/firehub.svg" width="15" alt="FireHub Icon"> Branch Purpose
FireHub Module follows the architectural principles of The FireHub Project by separating responsibilities between module composition, application lifecycle orchestration, dependency injection, and runtime execution.

The `develop` branch is the **primary integration branch** for all ongoing development.
Modules do not own independent application kernels or lifecycle state machines. Instead, they participate in the lifecycle of their hosting application through well-defined initialization and disposal mechanisms.

It serves as the staging area where:
- Feature branches are merged
- Bug fixes are integrated
- Experimental work is stabilized
- Code is prepared for upcoming releases
The Module component does not control application execution, dependency injection scopes, or kernel lifecycle transitions. These responsibilities remain with FireHub Application, FireHub Container, and FireHub Kernel.

All **release branches** are created **from `develop`**.
This separation enables applications to organize functionality into modular units without introducing unnecessary runtime complexity or coupling between modules and execution infrastructure.

## Stability Guarantee
## <img src="https://raw.githubusercontent.com/The-FireHub-Project/the-firehub-project.github.io/master/resources/graphics/icons/firehub.svg" width="15" alt="FireHub Icon"> Security

❌ No backward compatibility guarantee
❌ APIs may change without notice
❌ Behavior may be incomplete or inconsistent
❌ Breaking changes are expected
For security reporting and guidelines, please refer to our [SECURITY.md](https://github.com/The-FireHub-Project/.github/blob/master/.github/SECURITY.md) file.

This branch is intended **only for contributors and advanced testers**.
## <img src="https://raw.githubusercontent.com/The-FireHub-Project/the-firehub-project.github.io/master/resources/graphics/icons/firehub.svg" width="15" alt="FireHub Icon"> Community

## <img src="https://raw.githubusercontent.com/The-FireHub-Project/the-firehub-project.github.io/master/resources/graphics/icons/firehub.svg" width="15" alt="FireHub Icon"> Composer Usage (Not Recommended)
![GitHub watchers](https://img.shields.io/github/watchers/The-FireHub-Project/Module?style=social)
![GitHub Repo stars](https://img.shields.io/github/stars/The-FireHub-Project/Module?style=social)
![GitHub forks](https://img.shields.io/github/forks/The-FireHub-Project/Module?style=social)

- Be sure to review the [Code of Conduct](https://github.com/The-FireHub-Project/.github/blob/master/.github/CODE_OF_CONDUCT.md).
- Read a [Contributing](https://github.com/The-FireHub-Project/.github/blob/master/.github/CONTRIBUTING.md) file to see how you can contribute to this project.
- Read our [Security policy](https://github.com/The-FireHub-Project/.github/blob/master/.github/SECURITY.md) file to see how you can report a vulnerability.
- Review the project [Governance model](https://github.com/The-FireHub-Project/.github/blob/master/.github/GOVERNANCE.md), including roles, decision-making, RFC process, and releases.

## <img src="https://raw.githubusercontent.com/The-FireHub-Project/the-firehub-project.github.io/master/resources/graphics/icons/firehub.svg" width="15" alt="FireHub Icon"> Support

<p>
<a href="https://github.com/The-FireHub-Project/Module/issues?q=is%3Aissue%20state%3Aopen">
<img
src="https://img.shields.io/github/issues/The-FireHub-Project/Module?style=flat&logo=github&logoColor=959da5&label=in%20progress%20issues&labelColor=31373e"
alt="GitHub in-progress issues"
/></a>
<a href="https://github.com/The-FireHub-Project/Module/issues?q=is%3Aissue">
<img
src="https://img.shields.io/github/issues-search?query=repo%3AThe-FireHub-Project%Modulo&style=flat&logo=github&logoColor=959da5&label=total%20issues&labelColor=31373e"
alt="GitHub total issues"
/></a>
<a href="https://github.com/The-FireHub-Project/Module/issues?q=is%3Apr%20is%3Aopen">
<img
src="https://img.shields.io/github/issues-pr/The-FireHub-Project/Module?style=flat&logo=github&logoColor=959da5&labelColor=31373e"
alt="GitHub opened pull requests"
/></a>
</p>

For internal testing only:
For help with FireHub products, please refer to the following resources:

```json
{
"require": {
"the-firehub-project/module": "dev-develop"
}
}
```
⚠️ Never use dev-develop in production.
- **General questions & discussions**: [GitHub Discussions](https://github.com/orgs/The-FireHub-Project/discussions)
- **Bug reports & issues**: [Support](https://github.com/The-FireHub-Project/Module/issues)
- **Documentation & guides**: [FireHub Docs](https://the-firehub-project.github.io)
- **Commercial support** (Pro/Enterprise): contact your account manager

## <img src="https://raw.githubusercontent.com/The-FireHub-Project/the-firehub-project.github.io/master/resources/graphics/icons/firehub.svg" width="15" alt="FireHub Icon"> Authors and Contributors

Expand All @@ -134,4 +159,4 @@ Architecture guidelines, design principles, and ecosystem documentation are avai

This software is licensed under the Apache-2.0 License.

For more details, read the full license [here](./LICENSE).
For more details, read the full license [here](./LICENSE).
5 changes: 5 additions & 0 deletions src/Exception/CircularModuleDependencyException.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
*/
final class CircularModuleDependencyException extends RuntimeException {

/**
* @inheritDoc
*
* @since 1.0.0
*/
protected const string DEFAULT_MESSAGE = 'Circular module dependency detected';

}
5 changes: 5 additions & 0 deletions src/Exception/ModuleAlreadyRegisteredException.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
*/
final class ModuleAlreadyRegisteredException extends RuntimeException {

/**
* @inheritDoc
*
* @since 1.0.0
*/
protected const string DEFAULT_MESSAGE = 'The module identifier is already registered';

}
5 changes: 5 additions & 0 deletions src/Exception/ModuleDependencyNotFoundException.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
*/
final class ModuleDependencyNotFoundException extends RuntimeException {

/**
* @inheritDoc
*
* @since 1.0.0
*/
protected const string DEFAULT_MESSAGE = 'The module dependency was not found';

}
5 changes: 5 additions & 0 deletions src/Exception/ModuleManagerFrozenException.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
*/
final class ModuleManagerFrozenException extends RuntimeException {

/**
* @inheritDoc
*
* @since 1.0.0
*/
protected const string DEFAULT_MESSAGE = 'The module manager is frozen';

}
5 changes: 5 additions & 0 deletions src/Exception/ModuleNotFoundException.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
*/
final class ModuleNotFoundException extends OutOfBoundsException {

/**
* @inheritDoc
*
* @since 1.0.0
*/
protected const string DEFAULT_MESSAGE = 'The module identifier was not found';

}
21 changes: 21 additions & 0 deletions src/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,27 @@ public function registerServices (Registrar $registrar):void {

}

/**
* ### Checks whether modules provide service registrations
*
* Determines whether at least one registered module supports dependency injection service registration.
* @since 1.0.0
*
* @return bool True if service registration is required.
*/
public function hasServiceRegistrations ():bool {

foreach ($this->modules as $module) {

if ($module instanceof RegistersServices)
return true;

}

return false;

}

/**
* ### Freezes the module registry
*
Expand Down
Loading