liberusoftware/analytics-core-api
Core API layer for the Liberu analytics platform, offering shared contracts and endpoints for collecting and querying analytics data in Laravel applications. Part of the Liberu Software suite of modular PHP packages.
What this package actually is. The name — liberusoftware/analytics-core-api with the description "Analytics Core api presentation adapter" — tells you most of what you need to know before installing: this is the HTTP/presentation layer for an analytics domain package, not the analytics engine itself. Expect thin controllers, form requests, API resources, and route definitions that translate a analytics-core domain service into JSON. If you are looking for aggregation logic, storage drivers, or metric definitions, look at the sibling core package, not here.
Pre-flight checks (do these before composer require).
NOASSERTION, which is not a licence. Treat it as no licence granted until someone publishes a LICENSE file. For internal tooling that may be fine; for anything distributed or client-facing, get written clarification first.2026-10-26 — in the future. That is almost always a mistagged version, a manually pushed composer.json version, or a clock/CI quirk. Verify with composer show -a liberusoftware/analytics-core-api and prefer a commit hash or a dev-main constraint pinned to a SHA over a version range you don't trust.require in the package's composer.json — you will almost certainly need the core analytics package installed and configured first, otherwise container bindings will fail at boot or at first request.Install and publish.
composer require liberusoftware/analytics-core-api
# Check what is publishable
php artisan vendor:publish --provider="LiberuSoftware\\Analytics\\Core\\Api\\AnalyticsCoreApiServiceProvider"
# Inspect registered routes before writing any code against them
php artisan route:list --path=analytics
Laravel package auto-discovery should register the provider; if it does not, add it manually to bootstrap/providers.php (Laravel 11+) or config/app.php. If this package is built on nwidart/laravel-modules (likely given the module- repo naming), it may instead be enabled via modules_statuses.json plus php artisan module:enable AnalyticsCoreApi — check for a module.json in the repo root to disambiguate.
Where to look first, in order:
composer.json → required core package + PHP/Laravel constraints
routes/ → the actual API surface; this is your real documentation
src/Http/Controllers/ → request → domain → response flow
src/Http/Resources/ → the JSON contract you will be coupling to
src/Http/Requests/ → validation rules and authorization hooks
config/ → publishable config, route prefix, middleware stack
src/Providers/ → bindings and extension points
tests/ → if present, the best spec of intended behaviour
First use case. Authenticate a request to the read endpoint and dump the payload shape:
curl -s -H "Accept: application/json" \
-H "Authorization: Bearer $TOKEN" \
https://app.test/api/analytics/metrics | jq
Do this before writing integration code. The response envelope (top-level data vs bare array, pagination keys, date formats, null-vs-absent semantics) is the thing you'll be locked into, so confirm it early and write it down.
Treat it as an adapter, and put your own seam in front of it. The single most valuable pattern with a zero-adoption presentation package is to never let its controllers/resources be the only path into analytics from your app. Introduce one thin client or service class of your own that calls the package (or the underlying domain service), and have your code depend on that. When the package's contract shifts, you edit one file.
final class AnalyticsQuery
{
public function __construct(private AnalyticsApiClient $client) {}
/** @return array<int, MetricDto> */
public function metrics(MetricQuery $q): array
{
$response = $this->client->get('/api/analytics/metrics', $q->toQuery());
return collect($response->json('data'))
->map(fn (array $row) => MetricDto::fromArray($row))
->all();
}
}
Prefer in-process calls over self-HTTP when both are viable. A presentation adapter is designed to be hit over HTTP, but if the core package is installed in the same app you usually get better latency, better tracing, and no auth round-trip by injecting the domain service directly and using the adapter only as a reference for how to shape the response. Reserve real HTTP calls for cases where analytics is a separate deployment.
Bind your own implementations via the container. Presentation packages almost always app()->make() an interface for the underlying query object. If you need tenancy scoping, caching, or a fake in tests, bind a decorator in a register() method of a dedicated AnalyticsServiceProvider that runs after the package provider:
public function register(): void
{
$this->app->extend(MetricRepository::class, function (MetricRepository $inner) {
return new CachedMetricRepository($inner, cache()->store('analytics'), ttl: 300);
});
}
Apply tenancy and auth with middleware, not controllers. Since the routes are owned by the package, the cleanest override is configuration. Publish the config and set the middleware group/prefix so tenant scoping and authorization attach globally:
// config/analytics-core-api.php (after publishing)
return [
'prefix' => 'api/analytics',
'middleware' => ['api', 'auth:sanctum', 'tenant', 'can:view-analytics'],
];
If the package hardcodes its route group in the provider instead, fall back to a Route::group with your own middleware in routes/api.php and disable the package's route registration via its config flag (or ->except() in a route service provider).
Assert the contract with tests against the real routes. Because you cannot trust upstream stability, pin the payload with a feature test so a composer update that breaks the shape fails CI rather than production:
it('keeps the metrics response contract', function () {
$this->actingAs(User::factory()->create())
->getJson('/api/analytics/metrics?from=2024-01-01&to=2024-01-31')
->assertOk()
->assertJsonStructure(['data' => [['key', 'value', 'period']]]);
});
Fake it at the boundary in your own test suite. Point your AnalyticsQuery seam at Http::fake() (or a stub binding) rather than trying to instantiate the package's internals — this keeps your tests decoupled from a package you don't control.
Feature-flag rollout. Since you're the first dependents of this package, wrap it behind a config toggle so you can disable the integration without a deploy:
if (! config('features.analytics_api')) {
return collect();
}
NOASSERTION is the biggest risk here. Composer's metadata means the package declares no recognisable OSI licence. Do not assume MIT because the rest of the Liberu ecosystem uses it — check the repository for a LICENSE file and treat absence as "all rights reserved."2026-10-26 tag strongly suggests an incorrect version tag or a manual version field in composer.json. Pin explicitly ("dev-main#<sha>" or an exact version) and lock your composer.lock; do not rely on ranges like ^1.0.php artisan route:list, hit every route by hand, and read every controller before shipping. There is no Stack Overflow escape hatch for this package.route:list or the wrong middleware winning. Fix by enabling the routes in exactly one place, then php artisan route:clear && php artisan optimize:clear.optimize:clear after config changes, and make sure the package's config key name is correct — a typo'd key silently falls back to defaults.extend() or override a binding from the package, your provider must be registered after it. In a big app with many providers this is easy to get wrong; if your override "does nothing", ordering is the first suspect.Target [X] is not instantiable at request time rather than at boot. Install the core package, publish its config first, then this one.src/Http/Requests/ for required date-range parameters and maximum span. Analytics endpoints are expensive; an unbounded from can be a denial-of-service vector on your own infrastructure. Add a FormRequest or middleware clamp on the range regardless of upstream.data wrapper present/absent, ISO strings vs Carbon serialisation, null vs omitted keys — all common churn in young adapter packages. Pin the shape with the contract test above.Http\Resources (subclass and swap via binding) → route disabling in favour of your own controllers. Subclassing the controller is the last resort; you inherit its dependencies and lose on every update.dd(config('analytics-core-api')) and dd(app()->getBindings()) are faster than reading source. And check vendor/liberusoftware/analytics-core-api/ directly — composer show and the README frequently disagree with the actual code.How can I help you explore Laravel packages today?