UNPKG

@profullstack/therapy

Version:

CLI tool for interacting with an AI therapist

374 lines (331 loc) 9.31 kB
// Example of event handling in Node.js modules import { EventEmitter } from 'events'; /** * Basic EventEmitter example * This shows how to create and use a simple event emitter */ export function createBasicEmitter() { const emitter = new EventEmitter(); // Setup a timer that emits an event every second const timer = setInterval(() => { emitter.emit('tick', new Date()); }, 1000); // Method to stop the timer const stop = () => { clearInterval(timer); emitter.emit('stop'); }; return { emitter, stop }; } /** * Example usage of basic emitter: * * import { createBasicEmitter } from './event-examples.js'; * * const { emitter, stop } = createBasicEmitter(); * * // Listen for the 'tick' event * emitter.on('tick', (date) => { * console.log(`Tick at ${date}`); * }); * * // Listen for the 'stop' event * emitter.on('stop', () => { * console.log('Timer stopped'); * }); * * // Stop the timer after 5 seconds * setTimeout(stop, 5000); */ /** * Class-based EventEmitter example * This shows how to extend EventEmitter to create a class with built-in events */ export class TherapyEventEmitter extends EventEmitter { constructor() { super(); this.sessionActive = false; } startSession() { this.sessionActive = true; this.emit('sessionStart', { time: new Date() }); // Emit thinking events periodically this.thinkingInterval = setInterval(() => { this.emit('thinking', { duration: Math.random() * 3 + 1 }); }, 5000); } receiveUserInput(input) { // Validate input if (!input || typeof input !== 'string') { this.emit('error', new Error('Invalid input')); return; } // Emit the input event this.emit('userInput', { text: input, time: new Date() }); // Simulate processing time setTimeout(() => { // Emit response event this.emit('response', { text: `Processed: ${input}`, time: new Date() }); }, 1000); } endSession() { if (this.thinkingInterval) { clearInterval(this.thinkingInterval); } this.sessionActive = false; this.emit('sessionEnd', { time: new Date() }); } } /** * Example usage of class-based emitter: * * import { TherapyEventEmitter } from './event-examples.js'; * * const therapySession = new TherapyEventEmitter(); * * // Set up event listeners * therapySession.on('sessionStart', (data) => { * console.log(`Session started at ${data.time}`); * }); * * therapySession.on('thinking', (data) => { * console.log(`AI is thinking (${data.duration.toFixed(1)}s)`); * }); * * therapySession.on('userInput', (data) => { * console.log(`Received user input: ${data.text}`); * }); * * therapySession.on('response', (data) => { * console.log(`AI response: ${data.text}`); * }); * * therapySession.on('sessionEnd', (data) => { * console.log(`Session ended at ${data.time}`); * }); * * therapySession.on('error', (error) => { * console.error(`Error: ${error.message}`); * }); * * // Start the session * therapySession.startSession(); * * // Send some user input * therapySession.receiveUserInput("I've been feeling stressed lately"); * * // End the session after 10 seconds * setTimeout(() => therapySession.endSession(), 10000); */ /** * Factory function that creates a therapy session manager with event handling * This demonstrates a more complex module with internal state and events */ export function createTherapyEventManager(options = {}) { const emitter = new EventEmitter(); const { maxListeners = 10 } = options; // Set max listeners to avoid memory leaks emitter.setMaxListeners(maxListeners); // Internal state let sessionId = null; let messageCount = 0; let sessionStartTime = null; // Create a new session function startSession() { if (sessionId) { emitter.emit('warning', { message: 'Session already in progress' }); return sessionId; } sessionId = Date.now().toString(36) + Math.random().toString(36).substr(2); sessionStartTime = new Date(); messageCount = 0; emitter.emit('session:start', { sessionId, startTime: sessionStartTime }); return sessionId; } // Process a message function processMessage(message) { if (!sessionId) { emitter.emit('error', new Error('No active session')); return false; } messageCount++; emitter.emit('message:received', { sessionId, messageId: `msg_${messageCount}`, content: message, timestamp: new Date() }); // Simulate processing setTimeout(() => { emitter.emit('message:processed', { sessionId, messageId: `msg_${messageCount}`, timestamp: new Date() }); }, 500); return true; } // End the current session function endSession() { if (!sessionId) { emitter.emit('warning', { message: 'No active session to end' }); return false; } const sessionDuration = new Date() - sessionStartTime; emitter.emit('session:end', { sessionId, messageCount, duration: sessionDuration, endTime: new Date() }); // Reset state sessionId = null; messageCount = 0; sessionStartTime = null; return true; } // Get session stats function getSessionStats() { if (!sessionId) { return { active: false }; } return { active: true, sessionId, messageCount, duration: new Date() - sessionStartTime, startTime: sessionStartTime }; } // Return the public API return { // Event emitter for subscribing to events events: emitter, // Methods startSession, processMessage, endSession, getSessionStats, // Event names as constants (useful for consumers) EVENT_TYPES: { SESSION_START: 'session:start', SESSION_END: 'session:end', MESSAGE_RECEIVED: 'message:received', MESSAGE_PROCESSED: 'message:processed', WARNING: 'warning', ERROR: 'error' } }; } /** * Example usage of the therapy event manager: * * import { createTherapyEventManager } from './event-examples.js'; * * // Create a therapy session manager * const therapyManager = createTherapyEventManager(); * const { events, EVENT_TYPES } = therapyManager; * * // Set up event listeners using the constants * events.on(EVENT_TYPES.SESSION_START, (data) => { * console.log(`New session started: ${data.sessionId}`); * }); * * events.on(EVENT_TYPES.MESSAGE_RECEIVED, (data) => { * console.log(`Message received: ${data.content}`); * }); * * events.on(EVENT_TYPES.MESSAGE_PROCESSED, (data) => { * console.log(`Message ${data.messageId} processed`); * }); * * events.on(EVENT_TYPES.SESSION_END, (data) => { * console.log(`Session ended after ${data.duration}ms with ${data.messageCount} messages`); * }); * * events.on(EVENT_TYPES.WARNING, (data) => { * console.warn(`Warning: ${data.message}`); * }); * * events.on(EVENT_TYPES.ERROR, (error) => { * console.error(`Error: ${error.message}`); * }); * * // Start a session * therapyManager.startSession(); * * // Process some messages * therapyManager.processMessage("Hello, I need some help"); * * setTimeout(() => { * therapyManager.processMessage("I've been feeling anxious lately"); * }, 1000); * * // End the session after 5 seconds * setTimeout(() => { * therapyManager.endSession(); * }, 5000); */ /** * Example of using once() for one-time events */ export function createOneTimeEmitter() { const emitter = new EventEmitter(); // This function sets up a one-time event function waitForResponse(timeout = 5000) { return new Promise((resolve, reject) => { // Set up a timeout const timeoutId = setTimeout(() => { // Clean up the event listener to prevent memory leaks emitter.removeAllListeners('response'); reject(new Error('Response timeout')); }, timeout); // Use once() instead of on() for one-time event handling emitter.once('response', (data) => { clearTimeout(timeoutId); resolve(data); }); }); } // Function to simulate receiving a response function simulateResponse(data) { emitter.emit('response', data); } return { waitForResponse, simulateResponse }; } /** * Example usage of one-time events: * * import { createOneTimeEmitter } from './event-examples.js'; * * async function demonstrateOneTimeEvents() { * const { waitForResponse, simulateResponse } = createOneTimeEmitter(); * * // Set up a one-time event handler via Promise * const responsePromise = waitForResponse(3000); * * // Simulate getting a response after 1 second * setTimeout(() => { * simulateResponse({ text: 'This is a response', timestamp: new Date() }); * }, 1000); * * try { * // Wait for the response * const response = await responsePromise; * console.log(`Got response: ${response.text}`); * } catch (error) { * console.error(`Error: ${error.message}`); * } * } * * demonstrateOneTimeEvents(); */