saucebase/module-installer
A Laravel Composer installer for Saucebase modules that simplifies registering, installing, and organizing modular packages in your application. It streamlines module discovery and setup so you can add features without manual configuration.
What it is. A Composer plugin (not a runtime library) that registers a custom installer for packages declaring "type": "saucebase-module". Two moving parts: src/Installer.php (implements supports() / getInstallPath() to route installs to modules/<name> lowercased, with a configurable base directory) and src/Plugin.php (Composer plugin lifecycle: activate/deactivate/uninstall). Zero runtime footprint — it only executes during composer install / require / update.
Architecture fit. Fits only if Sauce Base has deliberately chosen an out-of-vendor module model — application code living in modules/, versioned and resolved by Composer. That is a legitimate and increasingly common pattern (Drupal, WordPress via composer/installers, Laravel modular monoliths), but the installer is the smallest piece of that architecture. It solves path placement only. It does not solve:
modules/* must be declared in the root composer.json or generated by a companion package),php artisan package:discover scans vendor/, so extra.laravel.providers in a module will not be auto-registered without a separate registration mechanism),Verdict: architecturally coherent as a building block, incoherent as a product on its own. Its value is entirely contingent on a companion runtime (saucebase/core or equivalent) that closes the autoload/discovery gap. Confirm that companion exists before evaluating further.
Integration feasibility. Low technical effort, moderate governance effort.
"type": "saucebase-module" to a package and running composer require is trivial. Configuring the base dir is presumably an extra key in the root composer.json — needs confirmation from source, as it is not documented in the provided excerpts."config": { "allow-plugins": { "saucebase/module-installer": true } }, otherwise installs silently place modules in vendor/ or fail. This is the single most common support ticket you will generate.--no-plugins and --no-scripts flags, hardened CI images, and some Docker build patterns will break module placement. Any environment with a locked-down Composer config is a blocker.Technical risk.
| Risk | Severity | Notes |
|---|---|---|
| Ecosystem immaturity | High | 1 star, 0 dependents, no external consumers, org-controlled. No evidence of production use outside the author's projects. |
| Build-vs-buy overlap | High | composer/installers already supports arbitrary custom types with installer-paths config, is battle-tested, and has thousands of dependents. A bespoke plugin must justify why configuration of an existing plugin was insufficient. |
| Autoload/discovery gap | Medium-High | Installer relocates files but does not make Laravel see service providers. Requires companion wiring; failure mode is silent (module installed, providers never registered). |
| Path/name handling | Medium | Lowercasing is a deliberate normalization but introduces collision risk on case-insensitive filesystems (macOS/Windows): two modules differing only in case map to one directory. Also verify path-traversal sanitization of the package name segment before joining to the base dir. |
| Plugin trust surface | Medium | Plugin code runs with full process privileges at install time — supply-chain consideration for a low-visibility, low-adoption package. Pin to a commit/tag and audit Plugin.php. |
| Bus factor / longevity | Medium | Single-org, single maintainer implied. MIT license mitigates abandonment (forkable, ~2 classes of code). |
| Metadata quality | Low-Medium | Release dated 2026-10-11 (forward-dated or unreliable metadata); score 19.1/opportunity 43.25 signals thin signal, not necessarily poor code. |
Key questions for the maintainer/architect.
saucebase/core package that handles PSR-4 autoloading, provider registration, migrations, and asset publishing? Without it, this package alone delivers no functional value.composer/installers with installer-paths ("modules/{$name}")? What does the bespoke plugin add — the lowercase normalization, the configurable base dir, or both?extra schema key, env var, CLI)? Is the schema documented and validated?composer-plugin-api constraints pinned to ^2.x? Is Composer 1 explicitly unsupported?modules/ → app-modules/)? Composer will not relocate already-installed paths.Plugin::uninstall implemented to remove empty parent directories, and is modules/ gitignored in the reference project?Stack fit. Appropriate only for Laravel/PHP 8.2+ (PHPUnit 12 and Pint/Laravel preset in the repo imply a modern runtime) projects that have already committed to a Composer-resolved, out-of-vendor module layout. It is a build-time dependency, so it does not constrain runtime framework versions, but it does constrain the project's Composer configuration and therefore its CI and developer onboarding.
Migration path. Treat this as a new-project-only decision first; retrofit is where cost lives.
allow-plugins, define the module base dir in extra, and — critically — pre-wire autoloading before the first module is installed. Validate with one throwaway module end-to-end (install → autoload → provider registered → route/migration works).vendor/ or in a hand-managed modules/ dir): requires a one-time relocation. composer.lock references vendor paths; a plain composer update after adding the plugin should re-place packages, but any local/non-published modules need a path repository entry plus explicit directory move. Expect a manual, reviewed commit — not an automated one. Do this on a branch, verify git status shows renames not deletions, and confirm no module was left orphaned in vendor/.path repository with explicit installer-paths or to composer/installers. Keep the module directory naming convention stable so a swap doesn't churn files.Compatibility.
| Dimension | Expectation | Action |
|---|---|---|
| Composer | 2.2+ required (plugin allow-list), composer-plugin-api ^2 |
Pin in CI; verify composer --version in every image |
| PHP | 8.2+ likely (PHPUnit 12, Pint) | Confirm from composer.json require before adopting |
| OS/filesystem | Lowercased paths → case-insensitive FS collision risk | Enforce a naming convention in module packages; add a CI check |
| CI mode | --no-plugins / --no-scripts environments break placement |
Audit pipelines before rollout |
| Laravel discovery | Not handled by this package | Pair with the companion registration mechanism |
Sequencing.
src/Installer.php and src/Plugin.php; confirm base-dir config key, name transformation, and traversal handling. Run the existing PHPUnit suite locally.composer/installers + installer-paths. Only proceed if the bespoke plugin demonstrably removes complexity.allow-plugins, IDE/indexing of modules/, and .gitignore; collect friction.allow-plugins, base-dir config, and module naming in the project template / scaffold repo so the decision is made once, not per-project.Maintenance. Low code surface, clear structure: src/ with Installer.php, Plugin.php, and src/Exceptions/; PHPUnit 12 suite under tests/ mirroring the namespace and mocking Composer collaborators; Pint (Laravel preset) for style; composer validate in the checks. Conventional Commits and focused PRs are documented in AGENTS.md. Ongoing cost is therefore small in absolute terms — but it is externally owned with ~1 star and 0 dependents, so you cannot rely on upstream responsiveness. Budget for the possibility of vendoring or forking (~a day of engineering) rather than assuming patches arrive. Recommended: pin to a tag, review diffs on upgrade, and keep an internal fork branch ready.
Support. The dominant support load will not be bugs — it will be configuration and comprehension:
vendor/" → missing allow-plugins entry.modules/" → missing PSR-4 mapping or excluded-folder settings.Each of these is a documentation problem. If the team cannot produce a one-page "modules layout" doc plus a scaffolded composer.json, support cost will exceed the plugin's value. Assign a named internal owner; there is no community to escalate to.
Scaling. Effectively unlimited — it is a build-time path resolver with no runtime cost, no database, no network, no concurrency. Scaling concerns are organizational rather than technical:
modules/ is fine for Composer, but IDE indexing, static analysis, and test-suite runtime become the real bottlenecks.Failure modes.
| Failure | Symptom | Blast radius | Mitigation |
|---|---|---|---|
| Plugin not allowed | Module lands in vendor/, silently "works" until it doesn't |
Dev machines, CI | allow-plugins in shared composer.json template; CI assertion that modules/<x> exists |
--no-plugins in build |
Same as above in production images | Deploy pipeline | Pipeline audit; explicit flag review |
| Composer plugin API mismatch | Hard failure at install | All installs | Pin composer-plugin-api ^2, pin Composer version in CI |
| Case collision | One module overwrites/aliases another | Data loss in working tree | Naming convention + CI lint; not solvable by this package |
| Provider not registered | Feature silently absent at runtime | Production behavior | Integration test asserting provider boot; companion package must own this |
| Base-dir reconfiguration | Already-installed modules not relocated | Local drift, noisy diffs | Document as a breaking change; manual migration note |
| Upstream abandonment | No fixes | Low — forkable, MIT, ~2 classes | Internal vendor/fork contingency |
Permission/traversal on modules/ |
Install error or unexpected path | Build failure | Verify sanitization in Installer.php pre-adoption |
Ramp-up. Very low for a developer who has seen Composer plugins before — under an hour including reading both source files. For everyone else, the ramp is about the convention, not the plugin: expect a half-day of orientation covering where modules live, why they are outside vendor/, how allow-plugins interacts with onboarding, how autoloading is wired, and how to create a new module from a template. The highest-leverage onboarding artifact is not documentation of this package — it is a working scaffold repo where composer install produces a functioning module-enabled application on the first try. Ship that before shipping the plugin.
How can I help you explore Laravel packages today?