xPulse
🇩🇪 DE

@xpulse/event – Component Spec

Status: CONCEPT · Erstellt März 2026 Übergeordnet: GLOBAL_concept-ecosystem.md


Übersicht

Event-System – Fundament für alle @xpulse/* Pakete. Zero dependencies.

Erweitert Node's nativen EventEmitter um optionale Registrierung und Introspection – damit Events im Ökosystem dokumentiert und nachvollziehbar sind.


Konzept

Events können optional registriert werden – das ist keine Pflicht, aber eine Konvention. Ein emit() auf einem nicht-registrierten Event funktioniert, taucht aber nicht in event.list() auf.

register() → dokumentiert ein Event (optional)
on() → lauscht auf ein Event
once() → lauscht einmalig
off() → hört auf zu lauschen
emit() → feuert ein Event

API

Lauschen

import event from '@xpulse/event';
// Dauerhaft lauschen
event.on('page:ready', (data) => {
console.log(data.lang);
});
// Einmalig lauschen
event.once('project:ready', (data) => {
console.log('project geladen:', data.name);
});
// Aufhören zu lauschen
const handler = (data) => { ... };
event.on('page:ready', handler);
event.off('page:ready', handler);

Feuern

event.emit('page:ready', { lang: 'de', route: '/privacy/' });

Registrieren (optional)

// Dokumentiert ein Event – kein Pflichtaufruf vor emit()
event.register('page:ready', {
description: 'Seite fertig gerendert, i18n kann übernehmen',
emittedBy: '@xpulse/project',
payload: '{ lang: string, route: string }',
});

Introspection

// Alle registrierten Events
event.list();
// → [
// { name: 'page:ready', description: '...', emittedBy: '...', listeners: 2 },
// { name: 'project:ready', description: '...', emittedBy: '...', listeners: 1 },
// ]
// Aktive Listener für ein Event
event.listeners('page:ready');
// → [ [Function: handler1], [Function: handler2] ]
// Anzahl Listener
event.listenerCount('page:ready');
// → 2

Event-Naming Convention

namespace:event
namespace:area:event
Beispiel Bedeutung
project:ready project wurde geladen
project:reloaded project wurde neu geladen
page:ready Seite gerendert, bereit für i18n
i18n:ready Übersetzungen eingesetzt
http:request eingehender Request
http:response Response gesendet

Paket-Struktur

@xpulse/event/
index.jsdefault export: event-Objekt
README.md
package.json

Intern

Basiert auf Node's EventEmitter – kein eigener Event-Loop, keine Queues, kein Persistence. Fired and forgotten. Die Registrierungs-Map ist ein einfaches Map<name, metadata> on top.

// Intern
import { EventEmitter } from 'events';
const emitter = new EventEmitter();
const registry = new Map(); // name → { description, emittedBy, payload }
// Limit auf 50 — im Ökosystem hören viele Packages auf dieselben Events
emitter.setMaxListeners(50);

Dependencies

Keine.


Debug Integration

Wenn @xpulse/debug als devDependency installiert ist, stellt @xpulse/event automatisch einen DataCollector bereit. @xpulse/debug discovert ihn via node_modules/@xpulse/event/src/datacollectors/ – keine Konfiguration nötig.

"optionalDependencies": {
"@xpulse/debug": "^1.0.0"
}

Der EventsCollector (name: 'events', icon: '⚡') zeigt im Web Profiler:

Strategie: Der EventsCollector umschließt event.emit direkt, statt für jedes Event einen eigenen Listener zu registrieren. Damit werden auch Events erfasst die nie via event.register() registriert wurden (z.B. template:render:after). Ausgenommen sind http:response:before (zirkuläre Payload) und logger:write (zu viele Einträge).

Badge in der Toolbar: Anzahl emittierter Events während des Requests (z.B. 7)


Offene Fragen

Frage Stand
event.listAll() auch nicht-registrierte (aber aktive) Events? TBD
de/spec.md 2026-04-13