import { Observable } from "rxjs"; import { RBEvent } from "../models/event.model"; export interface ClassType { build(): T; } export declare abstract class Service { protected static create(name: string, _class: ClassType): T; static build(): Service; } /** * A utility type that validates and preserves object properties while filtering out invalid types. * * This type is designed to be used as a constraint (e.g., `T extends OnlyObjectOrNever`) * to enforce that a generic type parameter `T` has a specific format where all properties * are valid object-like structures. * * @typeParam T - The type to validate and transform * * @example * ```typescript * // Valid usage - enforces proper object structure * function processData>(data: T): void { * // T is guaranteed to be a proper object type * } * * // This will work * processData({ name: "John", age: 30 }); * * // This might cause type errors if structure is invalid * processData(someInvalidType); * ``` */ type OnlyObjectOrNever = { [K in (keyof T) & string]: T[K] extends unknown ? T[K] : never; }; /** * Transforms a service events type definition into a discriminated union of RBEvent types. * * This utility type takes an interface where keys represent event names and values represent * event payload types, and converts it into a union of RBEvent instances. Each RBEvent in * the resulting union is typed with its corresponding event name and payload type. * * @typeParam EventTypes - An interface mapping event names to their payload types. Must be an object type. * * @example * ```typescript * interface MyEvents { * userLoggedIn: { userId: string }; * dataReceived: { data: number[] }; * } * * // Results in: RBEvent<'userLoggedIn', { userId: string }> | RBEvent<'dataReceived', { data: number[] }> * type MyEventUnion = ServiceEventsToUnion; * ``` * * @remarks * This type is useful for creating discriminated unions where the event name (K) can be used * as a discriminator to narrow down the payload type (V) in type-safe event handling patterns. */ export type ServiceEventsToUnion> = { [K in keyof EventTypes & string]: RBEvent; }[keyof EventTypes & string]; /** * Interface for services that can emit events of specified names. * * Services should implement this interface to ensure they respect the event contract * and provide type-safe event emission capabilities. This interface enables consumers * to subscribe to specific events with full type safety on the event payloads. * * @typeParam EventTypes - An object type mapping event names to their payload types * * @example * ```typescript * interface MyServiceEvents { * userLoggedIn: { userId: string }; * dataReceived: { data: number[] }; * } * * class MyService implements EventableService { * private readonly rxSubject = new Subject>(); * * public events(...eventNames: EventNames[]) { * return makeServiceEvent(this.rxSubject, ...eventNames); * } * } * ``` */ export interface EventableService> { /** * Returns an Observable that emits events matching the specified event names. * * @remarks * The `events()` methods expose a RxJS {@link https://rxjs.dev/guide/observable | Observable}. You will be able to subscribe * from it and manipulate it using `.pipe()`. If you have any doubt, we highly recommand to check the * {@link https://rxjs.dev/guide/overview | RxJS Documentation} for more informations.
* * @param eventNames - The names of events to filter and subscribe to * @returns An Observable emitting events of the specified types * * @example * ```typescript * // Consumer code * const service = new MyService(); * service.events('userLoggedIn', 'errorOccurred').subscribe(event => { * if (event.name === 'userLoggedIn') { * console.log('User logged in:', event.data.userId); * } * }); * ``` * */ events(...eventNames: EventNames[]): Observable>>; } /** * Interface for services that can emit events of specified names. * * Services should implement this interface to ensure they respect the event contract * and provide type-safe event emission capabilities. This interface enables services * to send events with full type safety on the event payloads. * * @typeParam EventTypes - An object type mapping event names to their payload types * * @example * ```typescript * interface MyServiceEvents { * userLoggedIn: { userId: string }; * dataReceived: { data: number[] }; * } * * class MyService implements EmitableService { * private readonly rxSubject = new Subject>(); * * public sendEvent( * eventName: EventName, * data: MyServiceEvents[EventName] * ): void { * // Emit the event with type-safe payload * this.rxSubject.next(RBEvent.create(eventName, data)); * } * } * * ``` */ export interface EmitableService> { /** * Sends an event with the specified name and associated data. * * @param eventName - The name of the event to emit * @param data - The payload data associated with the event, typed according to the event name * * @example * ```typescript * interface MyServiceEvents { * userLoggedIn: { userId: string }; * dataReceived: { data: number[] }; * } * * class MyService implements EmitableService { * private readonly rxSubject = new Subject>(); * * public login(userId: string): void { * // Emit a userLoggedIn event * this.sendEvent('userLoggedIn', { userId }); * } * } * ``` */ sendEvent(eventName: EventName, data: EventTypes[EventName]): void; } /** * Combined interface for services that can both emit and subscribe to events. * * This type combines {@link EventableService} (for subscribing to events) and * {@link EmitableService} (for emitting events), providing a complete event-driven * service interface. Services implementing this type can both publish events to * subscribers and allow external consumers to listen for those events in a type-safe manner. * * @typeParam EventTypes - An object type mapping event names to their payload types * * @example * ```typescript * interface MyServiceEvents { * userLoggedIn: { userId: string; timestamp: number }; * dataReceived: { data: number[]; source: string }; * errorOccurred: { message: string; code: number }; * } * * class MyService implements EventEmitableService { * private readonly rxSubject = new Subject>(); * * // Implementation of EventableService * public events( * ...eventNames: EventNames[] * ) { * return makeServiceEvent(this.rxSubject, ...eventNames); * } * * // Implementation of EmitableService * public sendEvent( * eventName: EventName, * data: MyServiceEvents[EventName] * ): void { * this.rxSubject.next(RBEvent.create(eventName, data)); * } * * // Example usage * public login(userId: string): void { * // Emit an event * this.sendEvent('userLoggedIn', { userId, timestamp: Date.now() }); * } * } * * // Consumer code * const service = new MyService(); * service.events('userLoggedIn', 'errorOccurred').subscribe(event => { * if (event.name === 'userLoggedIn') { * console.log('User logged in:', event.data.userId); * } * }); * ``` * * @see {@link EventableService} for event subscription capabilities * @see {@link EmitableService} for event emission capabilities */ export type EventEmitableService> = EventableService & EmitableService; /** * Generate allowed {@link RBEvent} for a specific service events interface. * * @typeParam EventTypes - An object type mapping event names to their corresponding event data types. * Must be an interface type or never. * @typeParam EventName - A specific event name from the EventTypes keys, constrained to string keys. * Defaults to all string keys of EventTypes. * * @example * ```typescript * interface MyEvents { * userConnected: { userId: string; timestamp: number }; * userDisconnected: { userId: string }; * } * * type UserConnectedEvent = RbServiceEvent; * // Resolves to: RBEvent<'userConnected', { userId: string; timestamp: number }> * ``` */ export type RbServiceEvent, EventName extends keyof EventTypes & string = keyof EventTypes & string> = RBEvent; /** * Creates an observable that filters events by their names from a service event stream. * * This utility function is designed to be used by {@link EventableService} implementations * to filter events based on specified event names. It ensures type-safe event filtering * with proper narrowing of the event union type based on the selected event names. * * @typeParam EventTypes - An object type mapping event names to their payload types * @typeParam SelectedNames - The subset of event names to filter for * * @param obs - The source RxJS Observable emitting all service events * @param eventNames - One or more event names to filter for. If none provided, returns all events. * * @returns An Observable that only emits events matching the specified names, with the return * type narrowed to only include the selected event types. * * @see {@link EventableService} for usage examples in service implementations */ export declare function makeServiceEvent, const SelectedNames extends keyof EventTypes & string>(obs: Observable>, ...eventNames: SelectedNames[]): Observable>>; export {}; //# sourceMappingURL=service.d.ts.map