libxa/toolkit

Debugger, profiler and code generators for LibxaFrame.

Maintainers

Package info

github.com/libxa-framework/toolkit

pkg:composer/libxa/toolkit

Transparency log

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.1 2026-08-12 21:00 UTC

This package is auto-updated.

Last update: 2026-08-12 21:00:32 UTC


README

A debugger, a profiler and code generators for LibxaFrame.

composer require libxa/toolkit --dev

Requires LibxaFrame ^0.10.1 and PHP 8.3.

Profiler

Records the spans you open, rather than instrumenting everything. The cost is proportional to what you asked for, and an unmeasured section shows up as a gap instead of as time attributed to whatever happened to be nearby.

$result = tk_measure('render invoice', fn () => $renderer->render($invoice));

Timings come from hrtime, not microtime. The system clock can move backwards, and a negative duration in a profiler sends people looking for a bug in their own code.

Nested spans record their depth, so the output reads as a tree. A span whose callable throws is still closed: without that, one exception leaves it open and everything after it is nested a level too deep, which makes the output unreadable exactly when something has gone wrong.

It reports through Server-Timing

Server-Timing: request0;dur=42.11, database1;dur=8.02, db;dur=8.02;desc="3 queries", total;dur=42.30

Browsers show this natively in the network panel, which means it works for JSON responses, redirects and downloads, none of which have anywhere to put a debug bar. It also cannot alter the response body, so switching the profiler on cannot change what your application returns.

$router->group(['middleware' => [ProfilerMiddleware::class]], function ($router) {
    // every response carries its own profile
});

Off by default outside local

TOOLKIT_PROFILER left unset follows the environment: on in local, testing and development, off everywhere else. Doing nothing gives you the safe answer. A developer tool that leaves itself on in production leaks timings, memory figures and occasionally more than that to anyone who asks for a page.

Dumper

tk_dump($value);   // print and carry on
tk_dd($value);     // print and stop

var_dump is unreadable at any depth and print_r loses types, which is usually the thing being checked:

null
true
"" (0)
" " (1)
1.0
array(2) [
  "name" => "Ada" (3),
  "roles" => array(1) [
    0 => "admin" (5)
  ]
]

Every string reports its length, because "" and " " look identical otherwise. Whole floats print as 1.0 so they are not mistaken for the integer 1. NAN and INF are shown rather than silently breaking the output.

Private and protected properties are included, since the interesting state is almost always what the class was hiding. Depth, item count and string length are all capped, so dumping something enormous while investigating a memory problem does not make the problem worse.

The helpers are prefixed tk_ so installing this cannot fatally redeclare a dump() your application already has.

Generators

php libxa toolkit:make service Invoice          # App\Services\InvoiceService
php libxa toolkit:make action SendInvoice       # App\Actions\SendInvoiceAction
php libxa toolkit:make dto InvoiceData          # App\DTO\InvoiceData
php libxa toolkit:make repository User          # App\Repositories\UserRepository
php libxa toolkit:make service Billing/Invoice  # App\Services\Billing\InvoiceService

Services, actions, DTOs and repositories are structure rather than framework features, which is why the framework has no make: for them. They are still written by hand a hundred times per project, always slightly differently.

The suffix is added when missing and never twice, so service Invoice and service InvoiceService both produce InvoiceService. Subdirectories work in either slash and appear in the namespace as well as the path.

DTOs come out final readonly, since a DTO you can modify after construction is a mutable array with extra steps. Actions get one method: an action that grows a second one is a service, and having to rename it is the signal.

Configuration

php libxa vendor:publish --tag=toolkit-config

Tests

composer test

42 tests. Every generated stub is written to disk and run through php -l, because generating code that does not parse is the one failure a generator must never have and is invisible until someone opens the file.

Licence

MIT.