danielcoulbourne/verbs-sync
A Laravel package for syncing verbs—the actions and events that drive your application—so their definitions and dispatches stay consistent across your codebase, with simple integration into Laravel's container and event system.
verbs-sync is at v0.1.0 — an initial tag with no migration guide, no prior assessment, and a changelog that points only at the commit list. Treat everything below as "verify against source before relying on it," because a 0.1.0 API is explicitly unstable.
composer require danielcoulbourne/verbs-sync then immediately open vendor/danielcoulbourne/verbs-sync/ and read, in this order: composer.json (constraints, Laravel version support, whether a service provider is auto-discovered), README.md, src/, config/, database/migrations/, tests/.php artisan vendor:publish --provider="DanielCoulbourne\VerbsSync\VerbsSyncServiceProvider" (confirm the exact FQCN from composer.json's extra.laravel.providers) and php artisan migrate. Do this before writing any application code — the published config is the contract you'll be configuring against.If step 4 fails, stop and check whether the package actually supports your Laravel version — the commit list is the only compatibility signal at this tag.
Wrap the package behind your own service. At 0.1.0 the public API will churn. Define an app-level interface (VerbSync contract) with the two or three methods you actually call, bind the package implementation in a service provider, and depend on your interface everywhere else. Upgrading then means editing one binding rather than grepping for class names.
Resolve everything from the container. Don't new package classes. Use constructor injection or app(...) so any constructor-signature changes in a patch release surface as a container error you can fix in one place.
Keep verb definitions declarative and centralised. Whatever the package's registration surface is (a config array, an attribute, a registry call), put all verb definitions in one class or config file rather than scattering them across models. Syncing logic tends to grow into "which verbs are allowed where," and that's much easier to reason about as a single map.
Test the sync boundary with Http::fake() / Queue::fake(). Any package named "sync" is either hitting a remote or coordinating local state — possibly both. Fake the outgoing transport in every feature test and assert on the payload the package builds, not just that a request happened. That payload is your real integration contract and the thing most likely to break silently between versions.
Use it in jobs, not in request cycles. If syncing touches a network or iterates a collection, dispatch a job. This also makes failures retryable and keeps the 0.1.0 behaviour from blocking user requests while you're still learning its edge cases.
Integrate with events. Have the package's operations wrapped in your own domain events so you can log, observe, and later swap implementations without touching call sites.
Pin the version. "danielcoulbourne/verbs-sync": "0.1.*" — or an exact tag — and do not use ^0.1. Composer's caret rule on a 0.x version allows 0.1.x only, but an exact pin makes the intent obvious to the next developer.
composer update, and keep the package out of your automated dependency-bump PRs until it reaches 1.0.extra.laravel.providers in the package's composer.json. If it's absent you must register the provider manually in bootstrap/providers.php (Laravel 11+) or config/app.php, and the failure mode is a confusing "class not found" or a silently unregistered facade.vendor/. Config values you change in vendor/ vanish on composer update and will cause a mystery regression at the worst time. If no config is publishable, note that as a limitation and keep your own config file that feeds the package.migrate and migrate:rollback on a copy of real data shape before it touches staging.dd(). app()->make(TheClass::class) inside tinker will reveal constructor dependencies and confirm which config the instance received.src/ before designing around them — early packages often document intent that isn't wired up. Anything you must customise, do it via your own wrapper class instead of relying on a hook.How can I help you explore Laravel packages today?