Files
agentic-dev/packages/core-events/src/in-memory-event-bus.ts
Danijel Martinek fc13424e9d feat(core-events): scaffold events optional core
Scaffolded via pnpm turbo gen core-package events (generator-first,
ADR-022 pre-shipped zod trace landed in docs/library-decisions/).
Generator wired transpilePackages + E1/J eslint rule block. Two
story-00-precedent additions so the coverage gates pass: the
@vitest/coverage-v8 devDep (L0 sweep) and the honest symbols.ts
exclude (mirroring core-shared/vitest.config.ts) plus its missing
ALLOWED_GLOBS mirror in scripts/coverage/diff.mjs (L1 gate). No
consumers wired — compile-green floor for the walking-skeleton
PRD (ADR-027).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 20:35:09 +02:00

43 lines
1.5 KiB
TypeScript

import type { z } from "zod";
import type { EventDescriptor } from "./event-descriptor";
import type { EventHandler, IEventBus } from "./event-bus.interface";
export type InMemoryEventBusOptions = {
/** When true, rethrow the first handler error (default: false — errors swallowed). */
failFast?: boolean;
};
export class InMemoryEventBus implements IEventBus {
private readonly handlers = new Map<string, EventHandler<unknown>[]>();
constructor(private readonly options: InMemoryEventBusOptions = {}) {}
async publish<T>(
descriptor: EventDescriptor<string, z.ZodType<T>>,
payload: T,
): Promise<void> {
descriptor.schema.parse(payload);
const subscribers = this.handlers.get(descriptor.name) ?? [];
if (subscribers.length === 0) return;
const settled = await Promise.allSettled(
subscribers.map((h) => h(payload)),
);
if (this.options.failFast) {
const failure = settled.find((s) => s.status === "rejected");
// Only the first rejection is rethrown. Other failures are intentionally
// dropped — `failFast` is a test-affordance, not a fault-tolerance design.
if (failure && failure.status === "rejected") throw failure.reason;
}
}
subscribe<T>(
descriptor: EventDescriptor<string, z.ZodType<T>>,
_consumerFeature: string,
handler: EventHandler<T>,
): void {
const arr = this.handlers.get(descriptor.name) ?? [];
arr.push(handler as EventHandler<unknown>);
this.handlers.set(descriptor.name, arr);
}
}