xPulse
πŸ‡©πŸ‡ͺ DE

@xpulse/debug – Component Concept

Status: STABLE · Aktualisiert MÀrz 2026 Übergeordnet: GLOBAL_concept-ecosystem.md


Vision

@xpulse/debug ist ein optionales, rein entwicklungsseitiges Package das Debugging-Werkzeuge fΓΌr alle Ebenen des xPulse Γ–kosystems bereitstellt: CLI-Commands, die Template-Methode {% debug() %}, Collectors, eine Debug Toolbar und eine separate Web Profiler OberflΓ€che.

Nur als devDependency installiert – in Produktion nicht vorhanden, alle Debug-Features damit automatisch nicht verfΓΌgbar.


Prinzip

@xpulse/debug
β”œβ”€β”€ CLI Layer ← debug:* Commands fΓΌr das Terminal
β”œβ”€β”€ Template Layer ← {% debug(variable) %} direkt im Template
β”œβ”€β”€ Collector Layer ← DataCollector Basisklasse + Discovery
β”œβ”€β”€ Toolbar ← schlanke Browser-Leiste mit Badges + Link zum Profiler
└── Web Profiler ← separate OberflΓ€che mit Panels, Sub-Panels, Areas

Discovery-Prinzip

@xpulse/debug folgt demselben Discovery-Prinzip wie @xpulse/cli (Commands) und @xpulse/controller (Controller) – kein manuelles Registrieren, kein registerPanel(), kein Event zum Anmelden. Filesystem ist die Wahrheit.

Collectors werden automatisch discovert aus:

1. node_modules/@xpulse/debug/src/datacollectors/*.js ← @xpulse/debug built-ins
2. node_modules/@xpulse/*/src/datacollectors/*.js ← andere @xpulse Packages
3. src/datacollectors/*.js ← die App selbst

Jedes @xpulse/* Package bietet seinen Collector unter src/datacollectors/ an – @xpulse/debug lΓ€dt ihn, wenn debug installiert ist. Das Package selbst importiert @xpulse/debug nie; es listet es nur als optionalDependencies.


Styling

@xpulse/debug verwendet konsequent die xPulse Brand-Styles – identisch mit xpulse-chat und xpulse-web. Keine eigenen Design-Entscheidungen.

CSS Custom Properties

:root {
--bg: #0d0d0d;
--surface: #141414;
--border: #222;
--muted: #444;
--text: #c8c8c8;
--text-dim: #555;
--accent: #8703b0;
--accent2: #7eb8a4;
--danger: #c0606a;
--mono: 'JetBrains Mono', ui-monospace, 'Cascadia Code', 'Fira Code', Consolas, monospace;
--serif: 'Fraunces', Georgia, ui-serif, serif;
}

Design-Regeln


Dependencies

@xpulse/debug
β”œβ”€β”€ @xpulse/event ← Collectors lauschen via this.on()
β”œβ”€β”€ @xpulse/config ← debug.enabled prΓΌfen
β”œβ”€β”€ @xpulse/router ← Profiler-Routes registrieren
β”œβ”€β”€ @xpulse/template ← Panel-Rendering + {% debug() %} registrieren
└── @xpulse/cli ← debug:* Commands via Autodiscovery

Keine Circular Reference – @xpulse/debug hΓ€ngt von allen ab, nichts hΓ€ngt von @xpulse/debug ab.


Aktivierung

// xpulse.json
{
"debug": {
"enabled": true,
"toolbar": true,
"web-profiler": {
"enabled": true,
"excluded-routes": ["/_debug/*"]
}
}
}
# .env.development
DEBUG=true

@xpulse/debug wird nie in Produktion aktiv. Das Receipt legt .env.development mit DEBUG=true automatisch an.

Flag-Übersicht

Flag Default Beschreibung
debug.enabled false Debug-System insgesamt ein/aus
debug.toolbar true Toolbar in HTML-Responses injizieren
debug.web-profiler.enabled true Web Profiler Routes registrieren
debug.web-profiler.excluded-routes ["/_debug/*"] Routes die nicht getrackt werden

toolbar: false ist sinnvoll wenn man den Profiler nur via URL nutzen will ohne die Toolbar im Browser zu sehen – z.B. bei API-lastigen Apps oder wenn die Toolbar das Layout stΓΆrt.


CLI Layer

Commands unter dem debug: Namespace, automatisch discovert via @xpulse/cli.

npx xpulse debug:events:list # alle registrierten Events mit Listener-Anzahl
npx xpulse debug:config:show # geladene Konfiguration (xpulse.json + .env)
npx xpulse debug:routes:list # registrierte Routen mit Name + Methode
npx xpulse debug:packages:list # installierte @xpulse/* Packages mit Versionen

Template Layer – `{% debug() %}`

Custom Template-Methode die beim Init von @xpulse/debug automatisch in @xpulse/template registriert wird. Nur aktiv wenn debug.enabled: true.

{% debug(variable) %}
{% debug(config) %}
{% debug(_route) %}

Gibt im Browser eine formatierte Ausgabe aus – Γ€hnlich Symfony's dump(). Type-spezifische Darstellung:

Typ Darstellung
string Wert mit Typ-Label
number / boolean Wert mit Typ-Label
Array Aufklappbare Liste mit Index + Wert
Object Aufklappbarer Baum mit Key + Wert, rekursiv (max. 3 Ebenen)
null / undefined Explizit dargestellt
Error Stack Trace formatiert

In Produktion β†’ leerer String, kein HTML, kein Overhead.


Collector Layer

Verantwortung & Separation of Concerns

Jedes @xpulse/* Package kennt seine eigenen Events am besten – daher liegt der zugehΓΆrige Collector im jeweiligen Package unter src/datacollectors/. @xpulse/debug discovert und initialisiert diese Collector-Dateien, importiert sie aber nie direkt.

Packages mit Collectors mΓΌssen @xpulse/debug als optionalDependencies listen – so kann der Collector import { DataCollector } from '@xpulse/debug/collector' auflΓΆsen, wenn debug installiert ist:

// package.json eines @xpulse/* Packages mit Collector
"optionalDependencies": {
"@xpulse/debug": "^1.0.0"
}

Der ./collector Subpath-Export ist in @xpulse/debug/package.json definiert:

"exports": {
".": "./src/index.js",
"./collector": "./src/collector.js"
}

DataCollector Basisklasse

Jeder Collector extendiert DataCollector – die Basisklasse ΓΌbernimmt Event-Registrierung, traceId-Zuordnung, Panel-JSON-Aufbau und das Schreiben in den Trace-Cache. Der Collector selbst kennt nur seine eigene Logik.

FΓΌr Collectors in externen Packages:

import { DataCollector } from '@xpulse/debug/collector';

FΓΌr Collectors innerhalb von @xpulse/debug selbst:

import { DataCollector } from '../collector.js';

Concurrent-Request-Safety

Per-Request-State muss als Map mit traceId als Key gespeichert werden – niemals als nackte Instanzvariable. Parallele Requests ΓΌberschreiben sich sonst gegenseitig:

// βœ— Falsch – bricht bei concurrent requests
export default class MyCollector extends DataCollector {
_data = null; // ← wird vom nΓ€chsten Request ΓΌberschrieben
async collect() {
this.on('my:event', (payload) => { this._data = payload; });
this.on('http:response', () => { this.addArea({ value: this._data }); });
}
}
// βœ“ Richtig – jeder Request hat seinen eigenen State
export default class MyCollector extends DataCollector {
_data = new Map(); // traceId β†’ data
async collect() {
this.on('my:event', (payload, traceId) => {
this._data.set(traceId, payload);
});
this.on('http:response', (payload, traceId) => {
this.addArea({ value: this._data.get(traceId) });
this._data.delete(traceId);
});
}
}

VollstΓ€ndiges Beispiel

// src/datacollectors/HttpCollector.js
import { DataCollector } from '@xpulse/debug/collector';
export default class HttpCollector extends DataCollector {
_reqs = new Map(); // traceId β†’ { req, startedAt }
configure() {
this
.setName('http')
.setIcon('🌐')
.setPackage('@xpulse/http');
}
async collect() {
this.on('http:request', (payload, traceId) => {
this._reqs.set(traceId, { req: payload, startedAt: Date.now() });
});
this.on('http:response', (payload, traceId) => {
const { status, duration } = payload;
const entry = this._reqs.get(traceId);
this._reqs.delete(traceId);
this.setBadge(`${status} Β· ${duration}ms`);
this.addArea({
title: 'Request',
type: 'kv',
value: {
Method: entry?.req?.method ?? '-',
Path: entry?.req?.path ?? '-',
Status: status,
Duration: `${duration}ms`,
},
});
this.addSpan({
kind: 'http',
label: 'http',
start: entry?.startedAt ?? (Date.now() - duration),
duration: duration ?? 0,
});
});
}
}

DataCollector API

configure() – Fluent Setup:

Methode Beschreibung
setName(name) Panel-Name + Dateiname unter packages/{name}.json
setIcon(icon) Emoji-Icon fΓΌr Toolbar-Badge + Sidebar
setPackage(pkg) Package-ZugehΓΆrigkeit – fΓΌr Sidebar-Gruppierung

collect() – Daten sammeln:

Methode Signatur Beschreibung
this.on(event, handler) (name, (payload, traceId) => void) traceId-aware Event-Listener
this.setBadge(text) (string) Badge-Text fΓΌr Toolbar
this.addArea(area) (Area) Strukturierten Bereich zum Panel hinzufΓΌgen
this.addSubPanel(panel) ({ title, areas[] }) Sub-Panel mit eigenem Titel
this.addSpan(span) ({ kind, label, start, duration }) Zeitspanne in den Waterfall
this.addTraceEvent(evt) ({ name, ts, data }) Einzelnes Event in die Events-Liste

Context – this._ctx:

Collector haben lesenden Zugriff auf den Profiler-Context:

Property Typ Beschreibung
this._ctx.config Config @xpulse/config Instanz
this._ctx.router Router @xpulse/router Instanz
this._ctx.controller Controller @xpulse/controller Instanz
this._ctx.event Event @xpulse/event Instanz
this._ctx.traces Map Aktive Traces (traceId β†’ Trace-Objekt)
this._ctx.version string @xpulse/debug Version
this._ctx.toolbarEnabled boolean Toolbar ein/aus
this._ctx.profilerConfig object AufgelΓΆste Profiler-Konfiguration
this._ctx.collectorCount number Anzahl erfolgreich geladener Collectors

Intern ΓΌbernimmt die Basisklasse:

Area-Typen

Type Value-Format Beschreibung
text string Einfacher Text
raw string | object JSON / Code – formatiert als <pre>
kv { key: value, ... } Key-Value Paare untereinander
table { headers[], rows[][] } Tabelle mit Kopfzeile
list string[] Einfache Auflistung
badge { label, value, status? }[] Status-Badges nebeneinander
timeline { label, timestamp, duration? }[] Zeitstrahl
logger-lines { line, level, color }[] Farbige Log-Zeilen (Logger-Panel)

Sub-Panels

Ein Collector kann sein Panel in Sub-Panels unterteilen – z.B. der TemplateCollector mit einem Sub-Panel pro gerendertem Template:

this.addSubPanel({
title: payload.view,
areas: [
{ title: 'Info', type: 'kv', value: { View: payload.view, Duration: `${payload.duration}ms` } },
{ title: 'Template Data', type: 'kv', value: payload.data },
{ title: 'Extends Chain', type: 'list', value: payload.chain.map(c => c.view ?? c) },
],
});

Sub-Panels erscheinen in der Sidebar als eingerΓΌckte Links unter dem Panel.

Panel-JSON Format (Cache)

Das von der Basisklasse generierte JSON unter packages/{name}.json:

{
"panel-name": "http",
"icon": "🌐",
"package": "@xpulse/http",
"badge": "200 Β· 12ms",
"areas": [
{
"title": "Request",
"type": "kv",
"value": { "Method": "GET", "Path": "/info", "Status": 200, "Duration": "12ms" }
}
],
"sub-panels": []
}

Collectors nach Package

Collectors liegen in ihren jeweiligen Packages – @xpulse/debug enthΓ€lt nur den DebugCollector fΓΌr Profiler-Eigeninfos:

Package Collector Name Icon Lauscht auf
@xpulse/debug DebugCollector debug πŸ› http:response (Snapshot)
@xpulse/http HttpCollector http 🌐 http:request, http:response
@xpulse/router RouterCollector router πŸ”€ router:matched, router:not-found
@xpulse/controller ControllerCollector controller βš™οΈ http:request, controller:called
@xpulse/template TemplateCollector template πŸ“‹ template:render:after, http:response
@xpulse/event EventsCollector events ⚑ alle Events via event.emit-Intercept
@xpulse/logger LoggerCollector logger πŸ“ logger:write, http:response
@xpulse/config ConfigCollector config πŸ”§ http:response (Snapshot)
@xpulse/dotenv EnvCollector env 🌍 http:response (Snapshot)

@xpulse/theme hat keinen Collector – alle Theme-Events sind Startup/Lifecycle-Events, die außerhalb des Request-Zyklus feuern.

EventsCollector – emit-Intercept

Der EventsCollector nutzt eine besondere Strategie: statt einzelne Events zu hooken, wird event.emit direkt umschlossen. Damit werden alle gefeuerten Events during a request erfasst – auch solche die nicht via event.register() registriert wurden (z.B. template:render:after):

const origEmit = event.emit;
event.emit = (name, data) => {
if (!SKIP.has(name)) {
const traceId = this._ctx.extractTraceId?.(data) ?? this._ctx.getCurrentTraceId?.();
if (traceId) this._ctx.addEvent?.(traceId, { name, ts: Date.now(), data });
}
return origEmit.call(event, name, data);
};

Ausgenommen (SKIP): http:response:before (zirkulΓ€re Payload) und logger:write (zu viele EintrΓ€ge).

Das Panel zeigt zwei Bereiche:

  1. Registered Events – alle via event.register() bekannten Events mit Listener-Count
  2. Emitted During Request – alle tatsΓ€chlich gefeuerten Events dieses Requests

Trace-Cache Struktur

var/cache/debug/
_{traceId}/
trace.json ← Basis: method, path, status, duration, spans[], events[]
packages/
debug.json ← DebugCollector
http.json ← HttpCollector
router.json ← RouterCollector
controller.json ← ControllerCollector
template.json ← TemplateCollector
events.json ← EventsCollector
logger.json ← LoggerCollector
config.json ← ConfigCollector
env.json ← EnvCollector
my-cache.json ← App-eigener Collector

Cache-Verwaltung: Der Trace-Cache wird automatisch bereinigt – nach jedem Request werden die Γ€ltesten EintrΓ€ge gelΓΆscht wenn mehr als 200 Traces vorhanden sind (pruneOldTraces, fire-and-forget, blockiert nie den Request).

Eigenen Collector schreiben

Jedes @xpulse/* Package oder die App selbst legt einen Collector unter src/datacollectors/ ab:

// src/datacollectors/MyCacheCollector.js
import { DataCollector } from '@xpulse/debug/collector';
export default class MyCacheCollector extends DataCollector {
_hits = new Map(); // traceId β†’ string[]
configure() {
this
.setName('my-cache')
.setIcon('πŸ’Ύ')
.setPackage('my-app');
}
async collect() {
this.on('cache:hit', (payload, traceId) => {
if (!this._hits.has(traceId)) this._hits.set(traceId, []);
this._hits.get(traceId).push(payload.key);
});
this.on('http:response', (payload, traceId) => {
const keys = this._hits.get(traceId) ?? [];
this._hits.delete(traceId);
this.setBadge(`${keys.length} hits`);
this.addArea({ title: 'Cache Hits', type: 'list', value: keys });
});
}
}

Toolbar

Die Debug Toolbar ist eine schlanke, fixierte Leiste am unteren Rand des Browsers. Sie wird via http:response:before in jede HTML-Response injiziert.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ my-app Β· GET /info Β· 200 Β· 12ms β”‚ ⚑ 18 β”‚ πŸ“‹ 3 β”‚ Profiler β†’ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Inhalt

Bereich Quelle
App-Name config.name
Method + Path trace.json
Status + Duration trace.json
Badges packages/*.json β†’ badge Feld, nur wenn gesetzt
Profiler-Link Γ–ffnet Web Profiler fΓΌr diesen Trace in neuem Tab

Badges

Badges werden dynamisch aus den packages/*.json Dateien des aktuellen Trace gelesen – jedes Panel das ein badge Feld gesetzt hat erscheint in der Toolbar. Kein Hardcoding, keine Konfiguration nΓΆtig. Das title-Attribut des Badge-Spans zeigt den Panel-Namen als Tooltip.

Einklappen

Zustand wird in localStorage unter xpulseProfilerCollapsed gespeichert. Eingeklappt: kleiner Tab-Button unten rechts.


Web Profiler

Der Web Profiler ist eine separate OberflΓ€che die ΓΌber die Toolbar erreichbar ist. Sie ΓΆffnet sich in einem neuen Tab und zeigt alle Trace-Daten strukturiert in Panels und Sub-Panels an.

Klick auf "Profiler β†’" in der Toolbar
↓
/_debug/web-profiler/{traceId}/summary/

Layout

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ xPulse Profiler v1.0.0 trace abc123 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ β”‚
β”‚ @xpulse/debug β”‚ Panel-Inhalt β”‚
β”‚ Summary β”‚ ────────────────────────────────────────────── β”‚
β”‚ Waterfall β”‚ Areas mit strukturierten Daten β”‚
β”‚ @xpulse/http β”‚ β”‚
β”‚ Http ← β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ @xpulse/router β”‚ β”‚ Request [kv] β”‚ β”‚
β”‚ Router β”‚ β”‚ Method GET β”‚ β”‚
β”‚ @xpulse/controller β”‚ β”‚ Path /info β”‚ β”‚
β”‚ Controller β”‚ β”‚ Status 200 β”‚ β”‚
β”‚ @xpulse/template β”‚ β”‚ Duration 12ms β”‚ β”‚
β”‚ Template β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β€Ί index β”‚ β”‚
β”‚ β€Ί base β”‚ β”‚
β”‚ @xpulse/event β”‚ β”‚
β”‚ Events β”‚ β”‚
β”‚ @xpulse/logger β”‚ β”‚
β”‚ Logger β”‚ β”‚
β”‚ @xpulse/config β”‚ β”‚
β”‚ Config β”‚ β”‚
β”‚ my-app β”‚ β”‚
β”‚ My Cache β”‚ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Sidebar ist vollstΓ€ndig dynamisch – aufgebaut aus den packages/*.json Dateien des Trace, gruppiert nach package Feld. Sub-Panels erscheinen als eingerΓΌckte EintrΓ€ge. Panel-Namen werden mit großem Anfangsbuchstaben angezeigt.

Panel Discovery

GET /_debug/web-profiler/{traceId}/{panelId}/
↓
Profiler liest var/cache/debug/_{traceId}/packages/*.json
↓
Baut Sidebar dynamisch aus panel-name + package + sub-panels
↓
Rendert das aktive Panel via @xpulse/template
↓
Areas werden inline via renderArea() in profiler.js gerendert

Spezialbehandlung fΓΌr summary und waterfall – diese werden ΓΌber eigene Template-Dateien gerendert und stehen immer als erste EintrΓ€ge unter @xpulse/debug in der Sidebar.

Waterfall

Der Waterfall zeigt alle Spans des Requests als horizontale Balken mit Zeitachse – so ist auf einen Blick erkennbar wo die Zeit verbracht wird.

Aufbau:

Sortierung: Spans werden nach Startzeitpunkt aufsteigend sortiert. Bei gleichem Startzeitpunkt erscheinen breitere Balken zuerst (http vor controller).

Farben nach kind:

Kind Farbe Verwendung
http Violett var(--accent) Gesamter HTTP-Request
controller Mint var(--accent2) Dispatch-Zeit bis Controller-Call
template Lila #b06ad4 Template-Render-Dauer
router Blau #4a9eff Router-Matching
other Grau var(--muted) Sonstige

Hinweis zur Controller-Span-Zeit: Der Controller-Span misst die Zeit von http:request bis controller:called – das beinhaltet Routing und Dispatch, nicht die reine Execution-Zeit des Controller-Handlers. Dies wird im Panel als Dispatch Time (request start β†’ controller called) ausgewiesen.

Logger Panel

Das Logger-Panel zeigt alle Log-EintrΓ€ge dieses Traces:

[2026-03-24T09:12:34.123Z] (info ) [http] GET /info 200 12ms
[2026-03-24T09:12:34.119Z] (debug) [controller] InfoController@index aufgerufen
[2026-03-24T09:12:34.115Z] (debug) [template] render info/index 4ms

Template-Struktur

@xpulse/debug/src/templates/web-profiler/
dashboard.tpl.html ← Haupt-Layout: Topbar + Sidebar + Content
toolbar.tpl.html ← Toolbar-HTML (wird in App injiziert)
panels/
summary.tpl.html ← Trace-Infos + App-Name/ENV
waterfall.tpl.html ← Zeitachse + Span-Balken
panel.tpl.html ← Generisches Panel: gibt areasHtml aus

Area-Rendering erfolgt nicht ΓΌber separate Partial-Templates, sondern ΓΌber renderArea() und renderAreaKv() etc. direkt in profiler.js. Das hΓ€lt die Template-Logik minimal und vermeidet viele kleine Dateien fΓΌr triviales HTML.


Gefeuerte Events

Event Payload Wann
debug:init { enabled, profiler } Debug-Initialisierung beginnt
debug:ready { enabled, profiler, routes } Debug bereit

Paket-Struktur

@xpulse/debug/
src/
collector.js ← DataCollector Basisklasse (export via ./collector)
index.js ← init(), bootstrapDebug(), event.emit-Hook fΓΌr Logging
profiler.js ← Collector-Discovery, Toolbar-Inject, Routes, Cache
commands/
ConfigShowCommand.js
EventsListCommand.js
PackagesListCommand.js
RoutesListCommand.js
datacollectors/
DebugCollector.js ← Profiler-Metadaten (Version, Collectors, Config)
template-methods/
debug.js ← {% debug() %} Registrierung + Type-Rendering
templates/
web-profiler/
dashboard.tpl.html
toolbar.tpl.html
panels/
summary.tpl.html
waterfall.tpl.html
panel.tpl.html
receipt/
up.js
down.js
test/
package.json
xpulse.json

Die Collectors der anderen Packages liegen jeweils bei ihrem Package:

@xpulse/http/src/datacollectors/HttpCollector.js
@xpulse/router/src/datacollectors/RouterCollector.js
@xpulse/controller/src/datacollectors/ControllerCollector.js
@xpulse/template/src/datacollectors/TemplateCollector.js
@xpulse/event/src/datacollectors/EventsCollector.js
@xpulse/logger/src/datacollectors/LoggerCollector.js
@xpulse/config/src/datacollectors/ConfigCollector.js
@xpulse/dotenv/src/datacollectors/EnvCollector.js

Offene Punkte

Thema Stand
{% debug() %} Type-spezifisches Rendering (aufklappbar) Offen
Secrets in EnvCollector filtern TBD – Keys mit SECRET, KEY, TOKEN, PASS
Max. Rekursionstiefe bei {% debug() %} TBD – 3 Ebenen sinnvoll
Router-Span mit echtem Timing TBD – router:matched Payload hat keine Start-Zeit
de/concept.md 2026-03-27