UNPKG

alepha

Version:

Alepha is a convention-driven TypeScript framework for building robust, end-to-end type-safe applications, from serverless APIs to full-stack React apps.

954 lines (953 loc) 33.1 kB
import * as _alepha_core1 from "alepha"; import { Alepha, Descriptor, KIND, Service, Static, TSchema } from "alepha"; import { DateTimeProvider, DurationLike } from "alepha/datetime"; import * as _alepha_logger0 from "alepha/logger"; //#region src/providers/TopicProvider.d.ts /** * Base class for topic providers. */ declare abstract class TopicProvider { protected readonly alepha: Alepha; /** * Publish a message to a topic. * * @param topic - The topic to publish to. * @param message - The message to publish. */ abstract publish(topic: string, message: string): Promise<void>; /** * Subscribe to a topic. * * @param topic - The topic to subscribe to. * @param callback - The callback to call when a message is received. */ abstract subscribe(topic: string, callback: SubscribeCallback): Promise<UnSubscribeFn>; /** * Unsubscribe from a topic. * * @param topic - The topic to unsubscribe from. */ abstract unsubscribe(topic: string): Promise<void>; /** * Returns the list of $subscribers for this provider. */ protected subscribers(): Array<() => Promise<unknown>>; } type SubscribeCallback = (message: string) => Promise<void> | void; type UnSubscribeFn = () => Promise<void>; //#endregion //#region src/descriptors/$topic.d.ts /** * Creates a topic descriptor for pub/sub messaging and event-driven architecture. * * This descriptor provides a powerful publish/subscribe system that enables decoupled communication * between different parts of your application. Topics allow multiple publishers to send messages * and multiple subscribers to receive them, creating flexible event-driven architectures with * support for real-time messaging and asynchronous event processing. * * **Key Features** * * - **Publish/Subscribe Pattern**: Decoupled communication between publishers and subscribers * - **Multiple Subscribers**: One-to-many message distribution with automatic fan-out * - **Type-Safe Messages**: Full TypeScript support with schema validation using TypeBox * - **Real-time Processing**: Immediate message delivery to active subscribers * - **Event Filtering**: Subscribe to specific message types using filter functions * - **Timeout Support**: Wait for specific messages with configurable timeouts * - **Multiple Backends**: Support for in-memory, Redis, and custom topic providers * - **Error Resilience**: Built-in error handling and message processing recovery * * **Use Cases** * * Perfect for event-driven architectures and real-time communication: * - User activity notifications * - Real-time chat and messaging systems * - System event broadcasting * - Microservice communication * - Live data updates and synchronization * - Application state change notifications * - Webhook and external API event handling * * @example * **Basic topic with publish/subscribe:** * ```ts * import { $topic } from "alepha/topic"; * import { t } from "alepha"; * * class NotificationService { * userActivity = $topic({ * name: "user-activity", * schema: { * payload: t.object({ * userId: t.string(), * action: t.enum(["login", "logout", "purchase"]), * timestamp: t.number(), * metadata: t.optional(t.record(t.string(), t.any())) * }) * }, * handler: async (message) => { * // This subscriber runs automatically for all messages * console.log(`User ${message.payload.userId} performed ${message.payload.action}`); * } * }); * * async trackUserLogin(userId: string) { * // Publish event - all subscribers will receive it * await this.userActivity.publish({ * userId, * action: "login", * timestamp: Date.now(), * metadata: { source: "web", ip: "192.168.1.1" } * }); * } * * async setupAdditionalSubscriber() { * // Add another subscriber dynamically * await this.userActivity.subscribe(async (message) => { * if (message.payload.action === "purchase") { * await this.sendPurchaseConfirmation(message.payload.userId); * } * }); * } * } * ``` * * @example * **Real-time chat system with multiple subscribers:** * ```ts * class ChatService { * messagesTopic = $topic({ * name: "chat-messages", * description: "Real-time chat messages for all rooms", * schema: { * payload: t.object({ * messageId: t.string(), * roomId: t.string(), * userId: t.string(), * content: t.string(), * timestamp: t.number(), * messageType: t.enum(["text", "image", "file"]) * }) * } * }); * * async sendMessage(roomId: string, userId: string, content: string) { * await this.messagesTopic.publish({ * messageId: generateId(), * roomId, * userId, * content, * timestamp: Date.now(), * messageType: "text" * }); * } * * // Different services can subscribe to the same topic * async setupMessageLogging() { * await this.messagesTopic.subscribe(async (message) => { * // Log all messages for compliance * await this.auditLogger.log({ * action: "message_sent", * roomId: message.payload.roomId, * userId: message.payload.userId, * timestamp: message.payload.timestamp * }); * }); * } * * async setupNotificationService() { * await this.messagesTopic.subscribe(async (message) => { * // Send push notifications to offline users * const offlineUsers = await this.getOfflineUsersInRoom(message.payload.roomId); * await this.sendPushNotifications(offlineUsers, { * title: `New message in ${message.payload.roomId}`, * body: message.payload.content * }); * }); * } * } * ``` * * @example * **Event filtering and waiting for specific messages:** * ```ts * class OrderService { * orderEvents = $topic({ * name: "order-events", * schema: { * payload: t.object({ * orderId: t.string(), * status: t.union([ * t.literal("created"), * t.literal("paid"), * t.literal("shipped"), * t.literal("delivered"), * t.literal("cancelled") * ]), * timestamp: t.number(), * data: t.optional(t.record(t.string(), t.any())) * }) * } * }); * * async processOrder(orderId: string) { * // Publish order created event * await this.orderEvents.publish({ * orderId, * status: "created", * timestamp: Date.now() * }); * * // Wait for payment confirmation with timeout * try { * const paymentEvent = await this.orderEvents.wait({ * timeout: [5, "minutes"], * filter: (message) => * message.payload.orderId === orderId && * message.payload.status === "paid" * }); * * console.log(`Order ${orderId} was paid at ${paymentEvent.payload.timestamp}`); * * // Continue with shipping... * await this.initiateShipping(orderId); * * } catch (error) { * if (error instanceof TopicTimeoutError) { * console.log(`Payment timeout for order ${orderId}`); * await this.cancelOrder(orderId); * } * } * } * * async setupOrderTracking() { * // Subscribe only to shipping events * await this.orderEvents.subscribe(async (message) => { * if (message.payload.status === "shipped") { * await this.updateTrackingInfo(message.payload.orderId, message.payload.data); * await this.notifyCustomer(message.payload.orderId, "Your order has shipped!"); * } * }); * } * } * ``` * * @example * **Redis-backed topic for distributed systems:** * ```ts * class DistributedEventSystem { * systemEvents = $topic({ * name: "system-events", * provider: RedisTopicProvider, // Use Redis for cross-service communication * schema: { * payload: t.object({ * eventType: t.string(), * serviceId: t.string(), * data: t.record(t.string(), t.any()), * timestamp: t.number(), * correlationId: t.optional(t.string()) * }) * }, * handler: async (message) => { * // Central event handler for all system events * await this.processSystemEvent(message.payload); * } * }); * * async publishServiceHealth(serviceId: string, healthy: boolean) { * await this.systemEvents.publish({ * eventType: "service.health", * serviceId, * data: { healthy, checkedAt: new Date().toISOString() }, * timestamp: Date.now() * }); * } * * async setupHealthMonitoring() { * await this.systemEvents.subscribe(async (message) => { * if (message.payload.eventType === "service.health") { * await this.updateServiceStatus( * message.payload.serviceId, * message.payload.data.healthy * ); * * if (!message.payload.data.healthy) { * await this.alertOnCall(`Service ${message.payload.serviceId} is down`); * } * } * }); * } * } * ``` */ declare const $topic: { <T extends TopicMessageSchema>(options: TopicDescriptorOptions<T>): TopicDescriptor<T>; [KIND]: typeof TopicDescriptor; }; interface TopicDescriptorOptions<T extends TopicMessageSchema> { /** * Unique name identifier for the topic. * * This name is used for: * - Topic identification across the pub/sub system * - Message routing between publishers and subscribers * - Logging and debugging topic-related operations * - Provider-specific topic management (channels, keys, etc.) * * If not provided, defaults to the property key where the topic is declared. * * **Naming Conventions**: * - Use descriptive, hierarchical names: "user.activity", "order.events" * - Avoid spaces and special characters * - Consider using dot notation for categorization * - Keep names concise but meaningful * * @example "user-activity" * @example "chat.messages" * @example "system.health.checks" * @example "payment.webhooks" */ name?: string; /** * Human-readable description of the topic's purpose and usage. * * Used for: * - Documentation generation and API references * - Developer onboarding and understanding * - Monitoring dashboards and admin interfaces * - Team communication about system architecture * * **Description Best Practices**: * - Explain what events/messages this topic handles * - Mention key use cases and subscribers * - Include any important timing or ordering guarantees * - Note any special processing requirements * * @example "Real-time user activity events for analytics and notifications" * @example "Order lifecycle events from creation to delivery" * @example "Chat messages broadcast to all room participants" * @example "System health checks and service status updates" */ description?: string; /** * Topic provider configuration for message storage and delivery. * * Options: * - **"memory"**: In-memory provider (default for development, lost on restart) * - **Service<TopicProvider>**: Custom provider class (e.g., RedisTopicProvider) * - **undefined**: Uses the default topic provider from dependency injection * * **Provider Selection Guidelines**: * - **Development**: Use "memory" for fast, simple testing without external dependencies * - **Production**: Use Redis or message brokers for persistence and scalability * - **Distributed systems**: Use Redis/RabbitMQ for cross-service communication * - **High-throughput**: Use specialized providers with connection pooling * - **Real-time**: Ensure provider supports low-latency message delivery * * **Provider Capabilities**: * - Message persistence and durability * - Subscriber management and connection handling * - Message ordering and delivery guarantees * - Horizontal scaling and load distribution * * @default Uses injected TopicProvider * @example "memory" * @example RedisTopicProvider * @example RabbitMQTopicProvider */ provider?: "memory" | Service<TopicProvider>; /** * TypeBox schema defining the structure of messages published to this topic. * * The schema must include: * - **payload**: Required schema for the main message data * - **headers**: Optional schema for message metadata * * This schema: * - Validates all messages published to the topic * - Provides full TypeScript type inference for subscribers * - Ensures type safety between publishers and subscribers * - Enables automatic serialization/deserialization * * **Schema Design Best Practices**: * - Keep payload schemas focused and cohesive * - Use optional fields for data that might not always be present * - Include timestamp fields for event ordering * - Consider versioning for schema evolution * - Use union types for different event types in the same topic * * @example * ```ts * { * payload: t.object({ * eventId: t.string(), * eventType: t.enum(["created", "updated"]), * data: t.record(t.string(), t.any()), * timestamp: t.number(), * userId: t.optional(t.string()) * }), * headers: t.optional(t.object({ * source: t.string(), * correlationId: t.string() * })) * } * ``` */ schema: T; /** * Default subscriber handler function that processes messages published to this topic. * * This handler: * - Automatically subscribes when the topic is initialized * - Receives all messages published to the topic * - Runs for every message without additional subscription setup * - Can be supplemented with additional subscribers via `subscribe()` method * - Should handle errors gracefully to avoid breaking other subscribers * * **Handler Design Guidelines**: * - Keep handlers focused on a single responsibility * - Use proper error handling and logging * - Consider performance impact for high-frequency topics * - Make handlers idempotent when possible * - Validate business rules within the handler logic * - Log important processing steps for debugging * * **Error Handling Strategy**: * - Log errors but don't re-throw to avoid affecting other subscribers * - Use try-catch blocks for external service calls * - Consider implementing circuit breakers for resilience * - Monitor error rates and patterns for system health * * @param message - The topic message with validated payload and headers * @param message.payload - The typed message data based on the schema * @returns Promise that resolves when processing is complete * * @example * ```ts * handler: async (message) => { * const { eventType, data, timestamp } = message.payload; * * try { * // Log message receipt * this.logger.info(`Processing ${eventType} event`, { timestamp, data }); * * // Process based on event type * switch (eventType) { * case "created": * await this.handleCreation(data); * break; * case "updated": * await this.handleUpdate(data); * break; * default: * this.logger.warn(`Unknown event type: ${eventType}`); * } * * this.logger.info(`Successfully processed ${eventType} event`); * * } catch (error) { * // Log error but don't re-throw to avoid affecting other subscribers * this.logger.error(`Failed to process ${eventType} event`, { * error: error.message, * eventType, * timestamp, * data * }); * } * } * ``` */ handler?: TopicHandler<T>; } declare class TopicDescriptor<T extends TopicMessageSchema> extends Descriptor<TopicDescriptorOptions<T>> { protected readonly log: _alepha_logger0.Logger; protected readonly dateTimeProvider: DateTimeProvider; readonly provider: TopicProvider; get name(): string; publish(payload: TopicMessage<T>["payload"]): Promise<void>; subscribe(handler: TopicHandler<T>): Promise<UnSubscribeFn>; wait(options?: TopicWaitOptions<T>): Promise<TopicMessage<T>>; protected $provider(): TopicProvider; protected parseMessage(message: string): TopicMessage<T>; } interface TopicMessage<T extends TopicMessageSchema> { payload: Static<T["payload"]>; } interface TopicWaitOptions<T extends TopicMessageSchema> { timeout?: DurationLike; filter?: (message: { payload: Static<T["payload"]>; }) => boolean; } interface TopicMessageSchema { payload: TSchema; } type TopicHandler<T extends TopicMessageSchema = TopicMessageSchema> = (message: TopicMessage<T>) => unknown; //#endregion //#region src/descriptors/$subscriber.d.ts /** * Creates a subscriber descriptor to listen for messages from a specific topic. * * This descriptor creates a dedicated message subscriber that connects to a topic and processes * its messages using a custom handler function. Subscribers provide a clean way to separate * message publishing from consumption, enabling scalable pub/sub architectures where multiple * subscribers can react to the same events independently. * * ## Key Features * * - **Topic Integration**: Seamlessly connects to any $topic descriptor * - **Type Safety**: Full TypeScript support inherited from the connected topic's schema * - **Dedicated Processing**: Isolated message processing logic separate from the topic * - **Real-time Processing**: Immediate message delivery when events are published * - **Error Isolation**: Subscriber errors don't affect other subscribers or the topic * - **Scalability**: Multiple subscribers can listen to the same topic independently * * ## Use Cases * * Perfect for creating specialized event handlers: * - Notification services for user events * - Analytics and logging systems * - Data synchronization between services * - Real-time UI updates * - Event-driven workflow triggers * - Audit and compliance logging * * @example * **Basic subscriber setup:** * ```ts * import { $topic, $subscriber } from "alepha/topic"; * import { t } from "alepha"; * * class UserActivityService { * // Define the topic * userEvents = $topic({ * name: "user-activity", * schema: { * payload: t.object({ * userId: t.string(), * action: t.enum(["login", "logout", "purchase"]), * timestamp: t.number(), * metadata: t.optional(t.record(t.string(), t.any())) * }) * } * }); * * // Create a dedicated subscriber for this topic * activityLogger = $subscriber({ * topic: this.userEvents, * handler: async (message) => { * const { userId, action, timestamp } = message.payload; * * await this.auditLogger.log({ * event: 'user_activity', * userId, * action, * timestamp, * source: 'user-activity-topic' * }); * * this.log.info(`User ${userId} performed ${action} at ${new Date(timestamp).toISOString()}`); * } * }); * * async trackUserLogin(userId: string, metadata: Record<string, any>) { * // Publish to topic - subscriber will automatically process it * await this.userEvents.publish({ * userId, * action: "login", * timestamp: Date.now(), * metadata * }); * } * } * ``` * * @example * **Multiple specialized subscribers for different concerns:** * ```ts * class OrderEventHandlers { * orderEvents = $topic({ * name: "order-events", * schema: { * payload: t.object({ * orderId: t.string(), * customerId: t.string(), * status: t.union([ * t.literal("created"), * t.literal("paid"), * t.literal("shipped"), * t.literal("delivered") * ]), * data: t.optional(t.record(t.string(), t.any())) * }) * } * }); * * // Analytics subscriber * analyticsSubscriber = $subscriber({ * topic: this.orderEvents, * handler: async (message) => { * await this.analytics.track('order_status_changed', { * orderId: message.payload.orderId, * customerId: message.payload.customerId, * status: message.payload.status, * timestamp: Date.now() * }); * } * }); * * // Email notification subscriber * emailSubscriber = $subscriber({ * topic: this.orderEvents, * handler: async (message) => { * const { customerId, orderId, status } = message.payload; * * const templates = { * 'paid': 'order-confirmation', * 'shipped': 'order-shipped', * 'delivered': 'order-delivered' * }; * * const template = templates[status]; * if (template) { * await this.emailService.send({ * customerId, * template, * data: { orderId, status } * }); * } * } * }); * * // Inventory management subscriber * inventorySubscriber = $subscriber({ * topic: this.orderEvents, * handler: async (message) => { * if (message.payload.status === 'paid') { * await this.inventoryService.reserveItems(message.payload.orderId); * } else if (message.payload.status === 'delivered') { * await this.inventoryService.confirmDelivery(message.payload.orderId); * } * } * }); * } * ``` * * @example * **Subscriber with advanced error handling and filtering:** * ```ts * class NotificationSubscriber { * systemEvents = $topic({ * name: "system-events", * schema: { * payload: t.object({ * eventType: t.string(), * severity: t.enum(["info", "warning", "error"]), * serviceId: t.string(), * message: t.string(), * data: t.optional(t.record(t.string(), t.any())) * }) * } * }); * * alertSubscriber = $subscriber({ * topic: this.systemEvents, * handler: async (message) => { * const { eventType, severity, serviceId, message: eventMessage, data } = message.payload; * * try { * // Only process error events for alerting * if (severity !== 'error') { * return; * } * * // Log the event * this.logger.error(`System alert from ${serviceId}`, { * eventType, * message: eventMessage, * data * }); * * // Send alerts based on service criticality * const criticalServices = ['payment', 'auth', 'database']; * const isCritical = criticalServices.includes(serviceId); * * if (isCritical) { * // Immediate alert for critical services * await this.alertService.sendImmediate({ * title: `Critical Error in ${serviceId}`, * message: eventMessage, * severity: 'critical', * metadata: { eventType, serviceId, data } * }); * } else { * // Queue non-critical alerts for batching * await this.alertService.queueAlert({ * title: `Error in ${serviceId}`, * message: eventMessage, * severity: 'error', * metadata: { eventType, serviceId, data } * }); * } * * // Update service health status * await this.healthMonitor.recordError(serviceId, eventType); * * } catch (error) { * // Log subscriber errors but don't re-throw * // This prevents one failing subscriber from affecting others * this.log.error(`Alert subscriber failed`, { * originalEvent: { eventType, serviceId, severity }, * subscriberError: error.message * }); * } * } * }); * } * ``` * * @example * **Subscriber for real-time data aggregation:** * ```ts * class MetricsAggregator { * userActivityTopic = $topic({ * name: "user-metrics", * schema: { * payload: t.object({ * userId: t.string(), * sessionId: t.string(), * eventType: t.string(), * timestamp: t.number(), * duration: t.optional(t.number()), * metadata: t.optional(t.record(t.string(), t.any())) * }) * } * }); * * metricsSubscriber = $subscriber({ * topic: this.userActivityTopic, * handler: async (message) => { * const { userId, sessionId, eventType, timestamp, duration, metadata } = message.payload; * * // Update real-time metrics * await Promise.all([ * // Update user activity counters * this.metricsStore.increment(`user:${userId}:events:${eventType}`, 1), * this.metricsStore.increment(`global:events:${eventType}`, 1), * * // Track session activity * this.sessionStore.updateActivity(sessionId, timestamp), * * // Record duration metrics if provided * duration ? this.metricsStore.recordDuration(`events:${eventType}:duration`, duration) : Promise.resolve(), * * // Update time-based aggregations * this.timeSeriesStore.addPoint({ * metric: `user_activity.${eventType}`, * timestamp, * value: 1, * tags: { userId, sessionId } * }) * ]); * * // Trigger real-time dashboard updates * await this.dashboardService.updateRealTimeStats({ * eventType, * userId, * timestamp * }); * * this.logger.debug(`Processed metrics for ${eventType}`, { * userId, * eventType, * timestamp * }); * } * }); * } * ``` */ declare const $subscriber: { <T extends TopicMessageSchema>(options: SubscriberDescriptorOptions<T>): SubscriberDescriptor<T>; [KIND]: typeof SubscriberDescriptor; }; interface SubscriberDescriptorOptions<T extends TopicMessageSchema> { /** * The topic descriptor that this subscriber will listen to for messages. * * This establishes the connection between the subscriber and its source topic: * - The subscriber inherits the topic's message schema for type safety * - Messages published to the topic will be automatically delivered to this subscriber * - Multiple subscribers can listen to the same topic independently * - The subscriber will use the topic's provider and configuration settings * * **Topic Integration Benefits**: * - Type safety: Subscriber handler gets fully typed message payloads * - Schema validation: Messages are validated before reaching the subscriber * - Real-time delivery: Messages are delivered immediately upon publication * - Error isolation: Subscriber errors don't affect the topic or other subscribers * - Monitoring: Topic metrics include subscriber processing statistics * * @example * ```ts * // First, define a topic * userEvents = $topic({ * name: "user-activity", * schema: { * payload: t.object({ userId: t.string(), action: t.string() }) * } * }); * * // Then, create a subscriber for that topic * activitySubscriber = $subscriber({ * topic: this.userEvents, // Reference the topic descriptor * handler: async (message) => { } // Process messages here * }); * ``` */ topic: TopicDescriptor<T>; /** * Message handler function that processes individual messages from the topic. * * This function: * - Receives fully typed and validated message payloads from the connected topic * - Executes immediately when messages are published to the topic * - Should implement the core business logic for reacting to these events * - Runs independently of other subscribers to the same topic * - Should handle errors gracefully to avoid affecting other subscribers * - Has access to the full Alepha dependency injection container * * **Handler Design Guidelines**: * - Keep handlers focused on a single responsibility * - Use proper error handling and logging * - Consider performance impact for high-frequency topics * - Make handlers idempotent when possible for reliability * - Validate business rules within the handler logic * - Log important processing steps for debugging and monitoring * * **Error Handling Strategy**: * - Log errors but don't re-throw to avoid affecting other subscribers * - Use try-catch blocks for external service calls * - Implement circuit breakers for resilience with external systems * - Monitor error rates and patterns for system health * - Consider implementing retry logic for temporary failures * * **Performance Considerations**: * - Keep handler execution time minimal for high-throughput topics * - Use background queues for heavy processing triggered by events * - Implement batching for efficiency when processing many similar events * - Consider async processing patterns for non-critical operations * * @param message - The topic message with validated payload and optional headers * @param message.payload - The typed message data based on the topic's schema * @returns Promise that resolves when processing is complete * * @example * ```ts * handler: async (message) => { * const { userId, eventType, timestamp } = message.payload; * * try { * // Log event receipt * this.logger.info(`Processing ${eventType} event for user ${userId}`, { * timestamp, * userId, * eventType * }); * * // Perform event-specific processing * switch (eventType) { * case 'user.login': * await this.updateLastLogin(userId, timestamp); * await this.sendWelcomeNotification(userId); * break; * case 'user.logout': * await this.updateSessionDuration(userId, timestamp); * break; * case 'user.purchase': * await this.updateRewardsPoints(userId, message.payload.purchaseAmount); * await this.triggerRecommendations(userId); * break; * default: * this.logger.warn(`Unknown event type: ${eventType}`); * } * * // Update analytics * await this.analytics.track(eventType, { * userId, * timestamp, * source: 'topic-subscriber' * }); * * this.logger.info(`Successfully processed ${eventType} for user ${userId}`); * * } catch (error) { * // Log error but don't re-throw to avoid affecting other subscribers * this.logger.error(`Failed to process ${eventType} for user ${userId}`, { * error: error.message, * stack: error.stack, * userId, * eventType, * timestamp * }); * * // Optionally send to error tracking service * await this.errorTracker.captureException(error, { * context: { userId, eventType, timestamp }, * tags: { component: 'topic-subscriber' } * }); * } * } * ``` */ handler: TopicHandler<T>; } declare class SubscriberDescriptor<T extends TopicMessageSchema> extends Descriptor<SubscriberDescriptorOptions<T>> {} //#endregion //#region src/errors/TopicTimeoutError.d.ts declare class TopicTimeoutError extends Error { readonly topic: string; readonly timeout: number; constructor(topic: string, timeout: number); } //#endregion //#region src/providers/MemoryTopicProvider.d.ts declare class MemoryTopicProvider extends TopicProvider { protected readonly log: _alepha_logger0.Logger; protected readonly subscriptions: Record<string, SubscribeCallback[]>; protected readonly start: _alepha_core1.HookDescriptor<"start">; /** * Publish a message to a topic. * * @param topic * @param message */ publish(topic: string, message: string): Promise<void>; /** * Subscribe to a topic. * * @param topic - The topic to subscribe to. * @param callback */ subscribe(topic: string, callback: SubscribeCallback): Promise<UnSubscribeFn>; /** * Unsubscribe from a topic. * * @param topic - The topic to unsubscribe from. */ unsubscribe(topic: string): Promise<void>; } //#endregion //#region src/index.d.ts /** * Generic interface for pub/sub messaging. * Gives you the ability to create topics and subscribers. * This module provides only a memory implementation of the topic provider. * * @see {@link $topic} * @see {@link $subscriber} * @module alepha.topic */ declare const AlephaTopic: _alepha_core1.Service<_alepha_core1.Module>; //#endregion export { $subscriber, $topic, AlephaTopic, MemoryTopicProvider, SubscribeCallback, SubscriberDescriptor, SubscriberDescriptorOptions, TopicDescriptor, TopicDescriptorOptions, TopicHandler, TopicMessage, TopicMessageSchema, TopicProvider, TopicTimeoutError, TopicWaitOptions, UnSubscribeFn }; //# sourceMappingURL=index.d.ts.map