Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Developer Experience Api Laravel Package

liberusoftware/developer-experience-api

A Laravel package that exposes an API for Liberu developer experience tooling, with endpoints and helpers intended to streamline local development workflows. Early-stage project with minimal adoption and limited documentation, so review the source before relying on it in production.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Confirm what you're actually installing.

At 0 stars and 0 dependents, this package has no downstream validation. Before composer require, open the repo and read these three files in order:

  • composer.json — check the require block for the Laravel version constraint (illuminate/*) and, critically, for sibling liberusoftware/* packages. Presentation adapters in this family almost always depend on a shared contracts/support package, which drags in a transitive graph you'll need to audit.
  • module.json (or the extra.laravel block) — tells you whether this is a module (registered by a module loader such as nwidart/laravel-modules or an in-house equivalent) or a plain service-provider package. This changes your registration step entirely.
  • src/Providers/ — find the main provider and read register()/boot() before you run anything. What it publishes, what it binds, and what routes it loads are all decided there.

2. Install and register.

composer require liberusoftware/developer-experience-api

If the package ships auto-discovery, the provider registers itself. If it's a module in the Liberu sense, you'll need the host app's module loader enabled and the module placed/registered in the modules path. Check with:

php artisan about
php artisan route:list --path=api
php artisan vendor:publish --provider="Liberu\DeveloperExperienceApi\...ServiceProvider"

3. Look at these locations first, in this order.

Path Why
routes/api.php (or routes/*.php) Reveals the actual URI surface, middleware stack, and versioning scheme — the single most informative file.
src/Http/Controllers Shows whether it's a thin controller over a service, or a resource controller over a repository.
src/Http/Resources / src/Presenters / src/Adapters This is the "presentation adapter" core — the mapping from domain object → API payload.
src/Contracts The extension points you're allowed to implement. Anything not behind a contract is internal.
config/*.php Feature flags, route prefixes, adapter bindings.
tests/ If present, the tests are the de facto documentation — read them before the README.

4. First use case: put a JSON façade over an existing module.

The intended day-to-day win of a presentation adapter is that you expose data from a domain module over HTTP without editing that module. Concretely:

  1. Identify the domain service or repository that already returns your data.
  2. Find (or create) an adapter that transforms that object into an API-shaped array.
  3. Bind the adapter in the package config.
  4. Hit the route and inspect the payload.

Do this on one trivial resource first (a show/index endpoint with no auth) so you learn the shape of the contract before wiring authentication, pagination, and filtering.


Implementation Patterns

Pattern: Adapter-as-translator (the core idiom)

Treat every adapter as a pure, side-effect-free function DomainObject → array. Keep it in one class, keep it dependency-light.

final class ProjectAdapter implements PresentsResource
{
    public function present(object $model): array
    {
        return [
            'id'         => $model->uuid,
            'name'       => $model->name,
            'status'     => $model->status->value,
            'owner'      => $model->owner?->only(['id', 'name']),
            'created_at' => $model->created_at?->toIso8601String(),
        ];
    }
}

The value of this indirection is that when the API shape and the domain shape diverge (they always do), only the adapter changes.

Pattern: Bind adapters in config, not in code

If the package exposes an adapter registry, use it. It gives you per-environment overrides and makes tests trivial.

// config/developer-experience-api.php
'adapters' => [
    \App\Models\Project::class => \App\Api\Adapters\ProjectAdapter::class,
],

Then in tests you can swap in a fixture adapter without touching the controller.

Pattern: Version via route prefix, not via adapter branching

If the package supports route groups, mount v1 and v2 as separate route files each pointing at separate adapter sets. Resist if ($version === 2) inside an adapter — it collapses the abstraction you installed the package for.

Route::prefix('v1')->group(base_path('routes/api/v1.php'));
Route::prefix('v2')->group(base_path('routes/api/v2.php'));

Pattern: Auth at the middleware layer, authorisation in policies

The adapter should never decide who can see what. Wire auth:sanctum (or the host app's guard) at the route group, then call $this->authorize() in the controller against an existing policy for the underlying model.

Pattern: Test the contract, not the implementation

Feature tests against the route are the highest-value tests here, because the adapter's only job is the response shape.

it('presents a project', function () {
    $project = Project::factory()->create();
    $this->actingAs(User::factory()->create())
        ->getJson("/api/v1/projects/{$project->id}")
        ->assertOk()
        ->assertExactJson([
            'data' => [
                'id'         => $project->uuid,
                'name'       => $project->name,
                'status'     => $project->status->value,
                'owner'      => null,
                'created_at' => $project->created_at->toIso8601String(),
            ],
        ]);
});

assertExactJson (not assertJson) is deliberate — it catches accidental field leakage, which is the most common bug in presentation layers.

Pattern: Use it as a reference implementation

With no community adoption, the honest highest-value use is as a pattern reference: read its adapter/contract pair, then reimplement the two or three classes you actually need in your own app/Http/Resources. That gives you Laravel's first-party JsonResource support (which the package may or may not use) and removes a dependency you cannot support.

Integration tips

  • Paginate at the query layer, not in the adapter. If the package has a paginated collection contract, implement it by delegating to ->paginate() so meta/links come from Laravel rather than hand-rolled arrays.
  • One adapter per resource, per version. No inheritance chains; duplication is cheaper than coupling here.
  • Keep domain queries out of the adapter. Adapters receive loaded models; eager-load (with()) in the controller or a repository.
  • Log at the boundary. If responses look wrong, dump the adapter's return value before the framework serialises it — that's where 90% of surprises live.

Gotchas and Tips

Licence is NOASSERTION. This is the single biggest blocker for production use. It means GitHub could not match a recognised licence file — the code may be proprietary, unlicensed, or have a malformed licence header. Run it past whoever owns legal at your org before it ships anywhere that matters. Absent an explicit licence, default copyright applies and you have no granted rights to redistribute.

Zero stars, zero dependents, no issue history. There is no one to ask. Treat every behaviour as undocumented and verify it yourself with a throwaway route. Budget for the possibility that you are the maintainer now.

The Last release: 2026-10-26 date is anomalous. Either the tag was created with a future-dated system clock or the metadata is unreliable. Pin to an explicit commit or tag in composer.json rather than ^x.y — you cannot trust the version graph.

Module loader vs. service provider confusion. This family of packages is inconsistent: some are nwidart/laravel-modules modules, some are plain providers. If auto-discovery "works" but routes 404, the module loader is probably required. Check bootstrap/cache/packages.php after install — if the package isn't listed there, discovery failed silently.

Provider boot order. If the package binds an adapter registry in register() and reads config in boot(), and your app's config is cached, you'll get stale bindings. php artisan config:clear after every config edit; never debug this with cache enabled.

Route collisions. An api prefix plus a host app that also owns /api is a classic 404/405 source. Run php artisan route:list --path=api -v and look for duplicate URIs and overlapping middleware. Prefer configuring a distinct prefix (api/dx) if the package allows it.

Middleware stack is inherited, not owned. The package's routes get whatever Route::middleware('api') resolves to in the host app. If auth "just works" in one project and 401s in another, this is why — check app/Http/Kernel.php / bootstrap/app.php.

Exception rendering is silent. Presentation adapters typically don't define their own exception handler, so a ModelNotFoundException may return an HTML error page inside a JSON API. Verify the 404/422 shapes explicitly and add a renderable handler if the package doesn't.

N+1 in adapters is invisible until production. An adapter that touches $model->owner->team per row will do 2 queries per item. DB::listen() or Laravel Debugbar on the index endpoint will show it immediately; the endpoint will look fine with 5 seeded rows.

Don't let the adapter become the domain. The moment an adapter contains a ->where() or a ->save(), you've recreated the coupling the package was supposed to remove. If you find yourself needing queries, the layering is wrong — push them into the controller or a repository.

Extension points are the contracts directory only. Anything else (src/Support, src/Concerns) is internal and may change in any commit, given there's no release discipline to speak of. If you must reach into internals, wrap the call in your own class so a future update touches one file.

Debugging checklist, in order: route:list → vendor:publish and read the config → dump the adapter output → config:clear → check packages.php. Most failures are step 2 or step 4.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle