### Installation Source: https://github.com/constantiner/zohar/blob/main/README.md Instructions for installing the Zohar library using npm or yarn package managers. ```bash npm install zohar ``` ```bash yarn add zohar ``` -------------------------------- ### Module-Specific Event Management Example Source: https://github.com/constantiner/zohar/blob/main/README.md Shows a practical example of using `subscriber` and `emitter` for managing events within a specific module, such as a chat application. This helps in centralizing and organizing event-driven logic for a feature. ```typescript // In a chat module const onMessageReceived = createSubscriber('messageReceived'); const emitMessageReceived = createEmitter('messageReceived'); // Handle incoming messages onMessageReceived((data) => { // Process message console.log(`New message from ${data.sender}: ${data.content}`); }); // Send messages emitMessageReceived({ sender: 'user123', content: 'Hello, world!', timestamp: new Date() }); ``` -------------------------------- ### Node.js EventEmitter Example Source: https://github.com/constantiner/zohar/blob/main/README.md Demonstrates how to use the Node.js EventEmitter for event handling, including subscribing, emitting, and unsubscribing from events. ```typescript import { EventEmitter } from 'node:events'; // Create an instance of EventEmitter const eventEmitter = new EventEmitter(); // Define listener functions so they can be referenced later const onEventA = (data: { message: string }) => { console.log(`Event A: ${data.message}`); }; const onEventB = (data: { value: number }) => { console.log(`Event B: ${data.value}`); }; // Subscribe to events eventEmitter.on('eventA', onEventA); eventEmitter.on('eventB', onEventB); // Emit events eventEmitter.emit('eventA', { message: 'Hello World' }); eventEmitter.emit('eventB', { value: 42 }); // Unsubscribe when done eventEmitter.off('eventA', onEventA); eventEmitter.off('eventB', onEventB); ``` -------------------------------- ### Zohar Usage Example Source: https://github.com/constantiner/zohar/blob/main/README.md Demonstrates how to use the Zohar event emitter for type-safe event handling, including defining events, subscribing, emitting, and unsubscribing. ```typescript import { EventDescription, createEventEmitter } from 'zohar'; // Define event descriptions with specific types type MyEvents = EventDescription<'eventA', { message: string }> & EventDescription<'eventB', { value: number }>; // Create an event emitter const [subscribe, emit] = createEventEmitter(); // Subscribe to events const unsubscribeEventA = subscribe('eventA', (eventName, data) => { console.log(`Event A: ${data.message}`); }); const unsubscribeEventB = subscribe('eventB', (eventName, data) => { console.log(`Event B: ${data.value}`); }); // Emit eventsemit('eventA', { message: 'Hello World' });emit('eventB', { value: 42 }); // Unsubscribe when done unsubscribeEventA(); unsubscribeEventB(); ``` -------------------------------- ### Component-Specific Event Handling Example Source: https://github.com/constantiner/zohar/blob/main/README.md Illustrates how to use `subscriber` and `emitter` within a component context to manage component-specific events. This promotes modularity and clear event flow within a UI component. ```typescript // In a user profile component const onUserProfileUpdate = createSubscriber('userProfileUpdate'); const emitUserProfileUpdate = createEmitter('userProfileUpdate'); // Subscribe to profile updates onUserProfileUpdate((data) => { // Handle profile update console.log(`Profile updated: ${data.name}`); }); // Emit profile updates emitUserProfileUpdate({ name: 'John Doe', age: 30 }); ``` -------------------------------- ### Subscribing to Chat Events Source: https://github.com/constantiner/zohar/blob/main/README.md Example of subscribing to events emitted by the chat module, including filtering with predicates. ```typescript import { emitter } from "zohar"; type ChatEvents = { "message-sent": { sender: string; content: string; timestamp: Date }; "user-joined": { userId: string; timestamp: Date }; "user-left": { userId: string; timestamp: Date }; }; // Assuming chatEmitter is defined and exported from the chat module // const chatEmitter = emitter(); // Example: Subscribe to all messages // chatEmitter.on("message-sent", (data) => { // console.log(`[${data.timestamp.toLocaleTimeString()}] ${data.sender}: ${data.content}`); // }); // Example: Subscribe only to messages from a specific user // const specificUserMessages = ({ sender }: { sender: string }) => sender === "Alice"; // chatEmitter.on("message-sent", (data) => { // console.log(`[Alice's Message] ${data.content}`); // }, specificUserMessages); // Example: Subscribe to user join events // chatEmitter.on("user-joined", (data) => { // console.log(`User ${data.userId} joined at ${data.timestamp}`); // }); ``` -------------------------------- ### Subscribing to Chat Events Source: https://github.com/constantiner/zohar/blob/main/README.md This example demonstrates how to subscribe to various chat events (`userConnected`, `userDisconnected`, `messageReceived`) exposed by the chat module. It shows how to use the `onChatEvent` function and defines handlers for each event type. ```typescript import { onChatEvent } from './chatService'; // Listen for user connection const unsubscribeUserConnected = onChatEvent('userConnected', (eventName, data) => { console.log(`User ${data.userId} connected at ${data.timestamp}`); }); // Listen for user disconnection const unsubscribeUserDisconnected = onChatEvent('userDisconnected', (eventName, data) => { console.log(`User ${data.userId} disconnected at ${data.timestamp}`); }); // Listen for messages received const unsubscribeMessageReceived = onChatEvent('messageReceived', (eventName, data) => { console.log(`Message from ${data.userId}: "${data.message}" at ${data.timestamp}`); }); ``` -------------------------------- ### Chat Module Implementation Source: https://github.com/constantiner/zohar/blob/main/README.md Example implementation of a chat module using Zohar for event handling, including defining events and emitting them. ```typescript import { emitter, subscriber } from "zohar"; type ChatEvents = { "message-sent": { sender: string; content: string; timestamp: Date }; "user-joined": { userId: string; timestamp: Date }; "user-left": { userId: string; timestamp: Date }; }; const chatEmitter = emitter(); // Specialized emit functions const sendMessage = subscriber(chatEmitter, "message-sent"); const userJoined = subscriber(chatEmitter, "user-joined"); const userLeft = subscriber(chatEmitter, "user-left"); // Example usage within a chat module function handleNewMessage(sender: string, content: string) { sendMessage({ sender, content, timestamp: new Date() }); } function handleUserJoin(userId: string) { userJoined({ userId, timestamp: new Date() }); } function handleUserLeave(userId: string) { userLeft({ userId, timestamp: new Date() }); } ``` -------------------------------- ### Consumer Usage: Handling One-Time Login Event with `awaited` Source: https://github.com/constantiner/zohar/blob/main/README.md This TypeScript example shows how a consumer can utilize Zohar's `awaited` function to handle a one-time login event. It calls the `login` function to initiate the process and then uses `awaited(onLoginEvent)` to create a promise that resolves with the login result. The code checks the `success` property of the result to either return the user data or throw an error. ```typescript import { onLoginEvent, login } from './loginService'; import { awaited } from 'zohar'; async function attemptLogin(username: string, password: string): Promise<{ userId: string; token: string }> { // Trigger the login process login(username, password); // Use the `awaited` function to wait for the `login` event const awaitLoginEvent = awaited(onLoginEvent); const result = await awaitLoginEvent('login'); // Throw an error if the login failed if (!result.success) { throw new Error(result.error); // Reject with the error message } // Return the successful login data return { userId: result.userId, token: result.token }; } // Usage example attemptLogin('correctUser', 'correctPassword') .then((data) => { console.log('Login successful!', data); }) .catch((error) => { console.error('Login failed:', error.message); }); ``` -------------------------------- ### Defining Events with Different Data Types Source: https://github.com/constantiner/zohar/blob/main/README.md Example of defining events where each event has a unique data type. ```typescript import { emitter } from "zohar"; type Events = { "message": string; "count": number; "user-info": { name: string; age: number }; }; const mixedEmitter = emitter(); ``` -------------------------------- ### Defining Generic Events Source: https://github.com/constantiner/zohar/blob/main/README.md Example of defining a generic event emitter where events can carry any data type. ```typescript import { emitter } from "zohar"; type Events = { "user-logged-in": { userId: string; timestamp: Date }; "user-logged-out": { userId: string }; }; const myEmitter = emitter(); ``` -------------------------------- ### Defining Events with Same Data Type Source: https://github.com/constantiner/zohar/blob/main/README.md Example of defining multiple events that share the same data type structure. ```typescript import { emitter } from "zohar"; type CommonData = { id: number }; type Events = { "item-created": CommonData; "item-updated": CommonData; }; const itemEmitter = emitter(); ``` -------------------------------- ### Unsubscribing from Events Source: https://github.com/constantiner/zohar/blob/main/README.md Provides examples of how to manage event subscriptions in Zohar, including unsubscribing individual listeners, all listeners for a specific event, or all listeners across all events. ```typescript // Unsubscribe from a specific listener const unsubscribe = subscribe('userLogin', (eventName, data) => { console.log(`User ${data.userId} logged in`); }); unsubscribe(); // This removes the listener // Unsubscribe all listeners for 'userLogin' unsubscribeAll('userLogin'); // Unsubscribe all listeners for all events unsubscribeAll(); ``` -------------------------------- ### Complex Event Types with Multiple Events Source: https://github.com/constantiner/zohar/blob/main/README.md Demonstrates handling multiple, distinct event types within a single event emitter using intersection types for `EventDescription`. This example covers chat-related events like messages, user joins, and user leaves. ```typescript type ChatEvents = EventDescription<'messageReceived', { sender: string; content: string; timestamp: Date }> & EventDescription<'userJoined', { userId: string; username: string; timestamp: Date }> & EventDescription<'userLeft', { userId: string; reason: 'disconnected' | 'kicked' | 'banned'; timestamp: Date }>; const [subscribe, emit] = createEventEmitter(); const createSubscriber = subscriber(subscribe); const createEmitter = emitter(emit); // Create specialized functions for each event type const onMessageReceived = createSubscriber('messageReceived'); const onUserJoined = createSubscriber('userJoined'); const onUserLeft = createSubscriber('userLeft'); const emitMessageReceived = createEmitter('messageReceived'); const emitUserJoined = createEmitter('userJoined'); const emitUserLeft = createEmitter('userLeft'); // Use the specialized functions onMessageReceived((data) => { console.log(`${data.sender}: ${data.content}`); }); onUserJoined((data) => { console.log(`${data.username} joined the chat`); }); onUserLeft((data) => { console.log(`User left: ${data.reason}`); }); // Emit events emitMessageReceived({ sender: 'user123', content: 'Hello!', timestamp: new Date() }); emitUserJoined({ userId: 'user123', username: 'John', timestamp: new Date() }); emitUserLeft({ userId: 'user123', reason: 'disconnected', timestamp: new Date() }); ``` -------------------------------- ### Subscribing to Events Source: https://github.com/constantiner/zohar/blob/main/README.md Demonstrates how to subscribe to events using the `on` method. It shows basic subscription and subscription with a predicate. ```typescript import { emitter, Predicate } from "zohar"; type Events = { "data-received": { value: number }; }; const dataEmitter = emitter(); // Basic subscription dataEmitter.on("data-received", ({ value }) => { console.log(`Received data: ${value}`); }); // Subscription with a predicate const isEven: Predicate<{ value: number }> = ({ value }) => value % 2 === 0; dataEmitter.on("data-received", ({ value }) => { console.log(`Received even data: ${value}`); }, isEven); ``` -------------------------------- ### Login Module Implementation with `awaited` and `once` Source: https://github.com/constantiner/zohar/blob/main/README.md Demonstrates handling a one-time login event using both `awaited` for asynchronous waiting and `once` for single-triggering. ```typescript import { emitter } from "zohar"; type AuthEvents = { "login-success": { userId: string; token: string }; "logout": { userId: string }; }; const authEmitter = emitter(); // Simulate a login process function simulateLogin(userId: string, token: string) { console.log(`Simulating login for ${userId}...`); authEmitter.emit("login-success", { userId, token }); } // Consumer using awaited async function waitForLogin(expectedUserId: string) { console.log(`Waiting for login event for ${expectedUserId}...`); try { const loginData = await authEmitter.awaited("login-success", ({ userId }) => userId === expectedUserId); console.log(`Login successful for ${expectedUserId}. Token: ${loginData.token}`); // Proceed with actions requiring authentication } catch (error) { console.error("Login wait timed out or failed:", error); } } // Consumer using once function setupSingleLoginListener(expectedUserId: string) { authEmitter.once("login-success", ({ userId, token }) => { if (userId === expectedUserId) { console.log(`(Once) Login successful for ${expectedUserId}. Token: ${token}`); // Perform actions that should only happen on the first successful login } }); } // Example Usage: // simulateLogin("user-101", "jwt-token-123"); // waitForLogin("user-101"); // setupSingleLoginListener("user-101"); ``` -------------------------------- ### Basic Emitter and Subscriber Usage Source: https://github.com/constantiner/zohar/blob/main/README.md Demonstrates the fundamental usage of `createEventEmitter`, `subscriber`, and `emitter` to define events, subscribe to them, and emit them with type safety. It shows how to create specialized functions for specific event types. ```typescript import { EventDescription, createEventEmitter, subscriber, emitter } from 'zohar'; // Define event descriptions with different data types using intersection types type MyEvents = EventDescription<'userConnected', { userId: string; timestamp: Date }> & EventDescription<'userDisconnected', { userId: string; timestamp: Date; reason: 'timeout' | 'manual' | 'error' }>; // Create an event emitter const [subscribe, emit] = createEventEmitter(); // Create factory functions for specialized subscribers and emitters const createSubscriber = subscriber(subscribe); const createEmitter = emitter(emit); // Create specialized subscription and emit functions for different events const onUserConnected = createSubscriber('userConnected'); const emitUserConnected = createEmitter('userConnected'); const onUserDisconnected = createSubscriber('userDisconnected'); const emitUserDisconnected = createEmitter('userDisconnected'); // Use the specialized subscription functions onUserConnected((data) => { console.log(`User ${data.userId} connected at ${data.timestamp}`); }); onUserDisconnected((data) => { console.log(`User ${data.userId} disconnected at ${data.timestamp} due to ${data.reason}`); }); // Use the specialized emit functions emitUserConnected({ userId: 'user123', timestamp: new Date() }); emitUserDisconnected({ userId: 'user123', timestamp: new Date(), reason: 'timeout' // TypeScript ensures this is one of: 'timeout' | 'manual' | 'error' }); ``` -------------------------------- ### Subscribing Once to an Event (`once`) Source: https://github.com/constantiner/zohar/blob/main/README.md Shows how to subscribe to an event that will only be triggered once using the `once` method. ```typescript import { emitter } from "zohar"; type Events = { "first-connection": { sessionId: string }; }; const connectionEmitter = emitter(); connectionEmitter.once("first-connection", ({ sessionId }) => { console.log(`First connection established with session: ${sessionId}`); }); connectionEmitter.emit("first-connection", { sessionId: "abc" }); connectionEmitter.emit("first-connection", { sessionId: "def" }); // This will not trigger the listener ``` -------------------------------- ### Comparison: Zohar vs. Node.js EventEmitter Source: https://github.com/constantiner/zohar/blob/main/README.md Illustrates the usage of Zohar and Node.js EventEmitter side-by-side for common event handling tasks, highlighting differences in API and type safety. ```javascript // Example: Using Zohar import { emitter } from "zohar"; type ZoharEvents = { "data": { value: number }; }; const zoharEmitter = emitter(); zoharEmitter.on("data", ({ value }) => { console.log(`Zohar received: ${value}`); }); zoharEmitter.emit("data", { value: 42 }); // Example: Using Node.js EventEmitter import { EventEmitter } from 'events'; const nodeEmitter = new EventEmitter(); nodeEmitter.on('data', (value) => { console.log(`Node EventEmitter received: ${value}`); }); nodeEmitter.emit('data', 42); // Type safety difference: // Zohar allows defining expected data types for events, preventing runtime errors. // Node.js EventEmitter does not enforce data types at compile time. ``` -------------------------------- ### Creating Specialized Subscription Functions (`subscriber`) Source: https://github.com/constantiner/zohar/blob/main/README.md Explains how to create custom, type-safe subscription functions for specific events using the `subscriber` utility. ```typescript import { emitter, subscriber } from "zohar"; type Events = { "user-event": { userId: string; action: string }; }; const userEmitter = emitter(); const onUserAction = subscriber(userEmitter, "user-event"); onUserAction(({ userId, action }) => { console.log(`User ${userId} performed action: ${action}`); }); userEmitter.emit("user-event", { userId: "user-456", action: "login" }); ``` -------------------------------- ### Login Module Implementation with Zohar Source: https://github.com/constantiner/zohar/blob/main/README.md This TypeScript code demonstrates how to create an event emitter for login events using Zohar's `createEventEmitter`. It defines a discriminated union for login results (success or failure) and simulates an asynchronous login API request. The module exposes a `login` function to trigger the process and a `subscribe` function aliased as `onLoginEvent` for consumers. ```typescript import { EventDescription, createEventEmitter } from 'zohar'; // Define event descriptions with a discriminated union for login results type LoginResult = | { success: true; userId: string; token: string } | { success: false; error: string }; type LoginEvents = EventDescription<'login', LoginResult>; // Create an event emitter for login events (and potentially other events) const [subscribe, emit] = createEventEmitter(); // Simulated login function that interacts with an APIasync function login(username: string, password: string) { try { // Simulate an API request with a timeout const response = await fakeApiLoginRequest(username, password); // Emit a successful login event emit('login', { success: true, userId: response.userId, token: response.token }); } catch (error) { // Emit a failed login event emit('login', { success: false, error: error.message }); } } // Simulated API login request function function fakeApiLoginRequest(username: string, password: string): Promise<{ userId: string; token: string }> { return new Promise((resolve, reject) => { setTimeout(() => { if (username === 'correctUser' && password === 'correctPassword') { resolve({ userId: 'user123', token: 'abcdef' }); } else { reject(new Error('Invalid credentials')); } }, 1000); // Simulate a 1-second API response time }); } // Expose the subscribe function specifically for the login event export { subscribe as onLoginEvent, login }; ``` -------------------------------- ### Handle Login Event Once with `once` Source: https://github.com/constantiner/zohar/blob/main/README.md This snippet demonstrates how to use the `once` function from the zohar library to subscribe to the `login` event. The `once` function ensures that the event listener is automatically removed after the event is triggered, providing a clean callback-based approach to handle the login outcome. ```typescript import { onLoginEvent, login } from './loginService'; import { once } from 'zohar'; // Use the `once` function to handle the `login` event const onceSubscribe = once(onLoginEvent); onceSubscribe('login', (eventName, result) => { if (result.success) { console.log('Login successful!', result.userId, result.token); } else { console.error('Login failed:', result.error); } }); // Trigger the login process login('correctUser', 'correctPassword'); ``` -------------------------------- ### Zohar Event Emitter API Reference Source: https://github.com/constantiner/zohar/blob/main/README.md Defines the core types and functions for the Zohar event emitter library, enabling type-safe event handling. Includes event descriptions, subscription, emission, and unsubscription mechanisms. ```APIDOC EventDescription Describes an event mapping where each event type is associated with a data type. createEventEmitter = EventDescription>() Creates an event emitter providing `subscribe`, `emit`, and `unsubscribeAll` functions. Returns: A tuple containing the subscribe, emit, and unsubscribeAll functions. SubscribeEvent> (Function Type) Function type to subscribe to an event, optionally with a predicate. Signature: (eventType: keyof Event & string, listener: (eventName: keyof Event & string, data: Event[keyof Event & string]) => void, predicate?: (eventName: keyof Event & string, data: Event[keyof Event & string]) => boolean) => UnsubscribeEvent EmitEvent> (Function Type) Function type to emit an event with the associated data. Signature: (eventType: keyof Event & string, data: Event[keyof Event & string]) => void UnsubscribeEvent (Function Type) Function type to unsubscribe a specific event listener. Signature: () => void UnsubscribeAllEvents> (Function Type) Function type to unsubscribe all listeners for a specific event or all events. Signature: (eventType?: keyof Event & string) => void SubscribeOnce> (Function Type) Function type to subscribe to an event that automatically unsubscribes after being triggered once. Signature: (eventType: keyof Event & string, listener: (eventName: keyof Event & string, data: Event[keyof Event & string]) => void, predicate?: (eventName: keyof Event & string, data: Event[keyof Event & string]) => boolean) => UnsubscribeEvent once>(subscribe: SubscribeEvent): SubscribeOnce Utility function to create a subscription that triggers only once and then automatically unsubscribes. Parameters: subscribe: The subscribe function returned by createEventEmitter. Returns: A function compatible with SubscribeOnce. SubscribeAwaited> (Function Type) Function type to subscribe to an event and return a promise that resolves when the event is triggered. Signature: (eventType: keyof Event & string, predicate?: (eventName: keyof Event & string, data: Event[keyof Event & string]) => boolean) => Promise awaited>(subscribe: SubscribeEvent): SubscribeAwaited Utility function that returns a promise that resolves when the specified event is triggered, automatically unsubscribing afterward. Parameters: subscribe: The subscribe function returned by createEventEmitter. Returns: A function compatible with SubscribeAwaited. SpecializedEventListener, EventType extends keyof Event & string> (Type) Type for a specialized event listener that doesn't include the event name parameter. EventSubscriber, EventType extends keyof Event & string> (Type) Type for a specialized subscription function for a specific event type. Signature: (listener: (data: Event[EventType]) => void, predicate?: (data: Event[EventType]) => boolean) => UnsubscribeEvent EventSubscriberFactory> (Type) Type for a factory function that creates specialized subscription functions for specific event types. Signature: (eventType: EventType) => EventSubscriber subscriber>(subscribe: SubscribeEvent): EventSubscriberFactory Creates a factory function that can create specialized subscription functions for specific event types. Parameters: subscribe: The subscribe function returned by createEventEmitter. Returns: A factory function compatible with EventSubscriberFactory. EventEmitter, EventType extends keyof Event & string> (Type) Type for a specialized emit function for a specific event type. Signature: (data: Event[EventType]) => void EventEmitterFactory> (Type) Type for a factory function that creates specialized emit functions for specific event types. Signature: (eventType: EventType) => EventEmitter emitter>(emit: EmitEvent): EventEmitterFactory Creates a factory function that can create specialized emit functions for any event type. Parameters: emit: The emit function returned by createEventEmitter. Returns: A factory function compatible with EventEmitterFactory. ``` -------------------------------- ### Creating Specialized Emit Functions (`emitter`) Source: https://github.com/constantiner/zohar/blob/main/README.md Demonstrates how to create custom, type-safe emitter functions for specific events using the `emitter` utility. ```typescript import { emitter, subscriber } from "zohar"; type Events = { "notification": { message: string; level: "info" | "warn" | "error" }; }; const notificationEmitter = emitter(); const emitNotification = subscriber(notificationEmitter, "notification"); // Using the specialized emit function emitNotification({ message: "System is running smoothly", level: "info" }); // You can also create specialized listeners const onInfoNotification = subscriber(notificationEmitter, "notification", ({ level }) => level === "info"); onInfoNotification(({ message }) => { console.log(`[INFO] ${message}`); }); ``` -------------------------------- ### Different Events with Different Data Types Source: https://github.com/constantiner/zohar/blob/main/README.md Shows how to combine multiple `EventDescription` types to create an event emitter that handles various events with distinct data structures. This allows for a flexible and type-safe event management system. ```typescript import { EventDescription, createEventEmitter } from 'zohar'; // Define event descriptions with varying data types type UserEvents = EventDescription<'userLogin' | 'userLogout', { userId: string; timestamp: Date }> & EventDescription<'userRegister', { email: string; password: string; timestamp: Date }>; // Create an event emitter const [subscribe, emit, unsubscribeAll] = createEventEmitter(); // Subscribe to 'userLogin' event subscribe('userLogin', (eventName, data) => { console.log(`User ${data.userId} logged in at ${data.timestamp}`); }); // Subscribe to 'userLogout' event subscribe('userLogout', (eventName, data) => { console.log(`User ${data.userId} logged out at ${data.timestamp}`); }); // Subscribe to 'userRegister' event subscribe('userRegister', (eventName, data) => { console.log(`User registered with email ${data.email} at ${data.timestamp}`); }); // Emit the eventsemit('userLogin', { userId: 'user123', timestamp: new Date() });emit('userLogout', { userId: 'user123', timestamp: new Date() });emit('userRegister', { email: 'user@example.com', password: 'securePassword', timestamp: new Date() }); ``` -------------------------------- ### Waiting for an Event with a Promise (`awaited`) Source: https://github.com/constantiner/zohar/blob/main/README.md Demonstrates how to asynchronously wait for an event to occur using the `awaited` method, which returns a Promise. ```typescript import { emitter } from "zohar"; type Events = { "task-completed": { taskId: string; result: any }; }; const taskEmitter = emitter(); async function waitForTask(taskId: string) { console.log(`Waiting for task ${taskId}...`); const eventData = await taskEmitter.awaited("task-completed", ({ taskId: completedTaskId }) => completedTaskId === taskId); console.log(`Task ${taskId} completed with result:`, eventData.result); } waitForTask("task-1"); // Simulate task completion after some time setTimeout(() => { taskEmitter.emit("task-completed", { taskId: "task-1", result: { status: "success" } }); }, 1000); ``` -------------------------------- ### Chat Module Implementation with Zohar Source: https://github.com/constantiner/zohar/blob/main/README.md This snippet shows how to implement a chat module using zohar's `createEventEmitter`. It defines custom event types for user connections, disconnections, and messages, and demonstrates emitting these events internally. The module exposes a `subscribe` function for external event listening. ```typescript import { EventDescription, createEventEmitter } from 'zohar'; // Define distinct event descriptions for the chat application type ChatEvents = EventDescription<'userConnected', { userId: string; timestamp: Date }> & EventDescription<'userDisconnected', { userId: string; timestamp: Date }> & EventDescription<'messageReceived', { userId: string; message: string; timestamp: Date }>; // Create an event emitter for chat events const [subscribe, emit] = createEventEmitter(); // Internal logic that might use something like Redis events, databases, etc. // Pseudocode for event handling // Simulate user connection setTimeout(() => { const userId = 'user123'; const timestamp = new Date(); emit('userConnected', { userId, timestamp }); }, 1000); // Simulate user connection after 1 second // Simulate user message setTimeout(() => { const userId = 'user123'; const message = 'Hello World!'; const timestamp = new Date(); emit('messageReceived', { userId, message, timestamp }); }, 2000); // Simulate message after 2 seconds // Simulate user disconnection setTimeout(() => { const userId = 'user123'; const timestamp = new Date(); emit('userDisconnected', { userId, timestamp }); }, 3000); // Simulate user disconnection after 3 seconds // Expose the subscribe function directly export { subscribe as onChatEvent }; ``` -------------------------------- ### Generic Events with Any Data Type Source: https://github.com/constantiner/zohar/blob/main/README.md Demonstrates how to create an event emitter for events with string names and any data type using Zohar. This is useful when the event payload structure is not strictly defined or can vary. ```typescript import { EventDescription, createEventEmitter } from 'zohar'; // Define a generic event description type GenericEvents = EventDescription; // Create an event emitter const [subscribe, emit, unsubscribeAll] = createEventEmitter(); // Subscribe to any event with string-based event names subscribe('someEvent', (eventName, data) => { console.log(`Received ${eventName} with data:`, data); }); // Emit the eventemit('someEvent', { message: 'Hello World!' }); ``` -------------------------------- ### Create Specialized Subscription Functions Source: https://github.com/constantiner/zohar/blob/main/README.md The `subscriber` helper function creates specialized subscription functions for specific event types, making the API more ergonomic by removing the need to specify the event name in the listener. It takes the generic subscribe function and returns a factory function to create event-specific subscribers. ```typescript import { EventDescription, createEventEmitter, subscriber } from 'zohar'; type MyEvents = EventDescription<'userConnected', { userId: string; timestamp: Date }> & EventDescription<'userDisconnected', { userId: string; timestamp: Date; reason: 'timeout' | 'manual' | 'error' }>; const [subscribe, emit] = createEventEmitter(); const createSubscriber = subscriber(subscribe); const onUserConnected = createSubscriber('userConnected'); const onUserDisconnected = createSubscriber('userDisconnected'); onUserConnected((data) => { console.log(`User ${data.userId} connected at ${data.timestamp}`); }); onUserDisconnected((data) => { console.log(`User ${data.userId} disconnected at ${data.timestamp} due to ${data.reason}`); }); emit('userConnected', { userId: 'user123', timestamp: new Date() }); emit('userDisconnected', { userId: 'user123', timestamp: new Date(), reason: 'timeout' }); ``` -------------------------------- ### Different Events with the Same Data Type Source: https://github.com/constantiner/zohar/blob/main/README.md Illustrates how to define an event emitter for multiple distinct events that share a common data structure. This promotes type safety and code organization when events have similar payloads. ```typescript import { EventDescription, createEventEmitter } from 'zohar'; // Define event descriptions for user events type UserEvents = EventDescription<'userLogin' | 'userLogout', { userId: string; timestamp: Date }>; // Create an event emitter const [subscribe, emit, unsubscribeAll] = createEventEmitter(); // Subscribe to 'userLogin' event subscribe('userLogin', (eventName, data) => { console.log(`User ${data.userId} logged in at ${data.timestamp}`); }); // Subscribe to 'userLogout' event subscribe('userLogout', (eventName, data) => { console.log(`User ${data.userId} logged out at ${data.timestamp}`); }); // Emit the eventsemit('userLogin', { userId: 'user123', timestamp: new Date() });emit('userLogout', { userId: 'user123', timestamp: new Date() }); ``` -------------------------------- ### Subscribe Once to an Event Source: https://github.com/constantiner/zohar/blob/main/README.md The `once` utility function subscribes to an event and automatically unsubscribes after the first trigger. It's useful for handling events that should only occur once. It takes the generic subscribe function and returns a new function that subscribes to a specific event type. ```typescript import { EventDescription, createEventEmitter, once } from 'zohar'; type UserEvents = EventDescription<'userLogin', { userId: string; timestamp: Date }>; const [subscribe, emit] = createEventEmitter(); const onceSubscribe = once(subscribe); onceSubscribe('userLogin', (eventName, data) => { console.log(`User ${data.userId} logged in at ${data.timestamp}`); }); emit('userLogin', { userId: 'user123', timestamp: new Date() }); emit('userLogin', { userId: 'user123', timestamp: new Date() }); ``` -------------------------------- ### Unsubscribing from Events Source: https://github.com/constantiner/zohar/blob/main/README.md Illustrates how to unsubscribe from events using the `off` method, removing specific listeners or all listeners for an event. ```typescript import { emitter } from "zohar"; type Events = { "update": { id: string }; }; const updateEmitter = emitter(); const listener1 = ({ id }: { id: string }) => console.log(`Listener 1: Updated ${id}`); const listener2 = ({ id }: { id: string }) => console.log(`Listener 2: Updated ${id}`); updateEmitter.on("update", listener1); updateEmitter.on("update", listener2); // Unsubscribe a specific listener updateEmitter.off("update", listener1); // Unsubscribe all listeners for an event // updateEmitter.off("update"); updateEmitter.emit("update", { id: "123" }); // Only listener2 will be called ``` -------------------------------- ### Wait for an Event with a Promise Source: https://github.com/constantiner/zohar/blob/main/README.md The `awaited` utility function subscribes to an event and returns a promise that resolves when the event is triggered. This is ideal for asynchronous workflows where you need to wait for an event to occur. It takes the generic subscribe function and returns a new function that returns a promise for a specific event type. ```typescript import { EventDescription, createEventEmitter, awaited } from 'zohar'; type UserEvents = EventDescription<'userLogin', { userId: string; timestamp: Date }>; const [subscribe, emit] = createEventEmitter(); const awaitedSubscribe = awaited(subscribe); awaitedSubscribe('userLogin').then((data) => { console.log(`User ${data.userId} logged in at ${data.timestamp}`); }); emit('userLogin', { userId: 'user123', timestamp: new Date() }); ``` -------------------------------- ### Subscribing to Events with a Predicate Source: https://github.com/constantiner/zohar/blob/main/README.md Demonstrates how to subscribe to events with a predicate function in Zohar. The predicate acts as a filter, ensuring that the listener is only invoked when the event data satisfies the specified condition. ```typescript import { EventDescription, createEventEmitter } from 'zohar'; // Define event descriptions for user events type UserEvents = EventDescription<'userLogin' | 'userLogout', { userId: string; timestamp: Date }>; // Create an event emitter const [subscribe, emit, unsubscribeAll] = createEventEmitter(); // Predicate function to filter for a specific user ID const predicate = (data: { userId: string }) => data.userId === 'user123'; // Subscribe to the 'userLogin' event with the predicate subscribe('userLogin', (eventName, data) => { console.log(`Specific user ${data.userId} logged in at ${data.timestamp}`); }, predicate); // Emit eventsemit('userLogin', { userId: 'user123', timestamp: new Date() }); // This will trigger the listeneremit('userLogin', { userId: 'anotherUser', timestamp: new Date() }); // This will not trigger the listener ``` -------------------------------- ### Unsubscribing from Chat Events Source: https://github.com/constantiner/zohar/blob/main/README.md This snippet illustrates how to unsubscribe from specific events after subscribing. It shows the pattern of receiving an unsubscribe function upon subscription and calling it to stop event listeners, preventing memory leaks and optimizing resource usage. ```typescript import { onChatEvent } from './chatService'; // Subscribe to the messageReceived event const unsubscribeMessageReceived = onChatEvent('messageReceived', (eventName, data) => { console.log(`Message from ${data.userId}: "${data.message}" at ${data.timestamp}`); }); // Unsubscribe after 2.5 seconds setTimeout(() => { console.log('Unsubscribing from messageReceived event'); unsubscribeMessageReceived(); // Stop listening to messages }, 2500); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.