diff --git a/.gitignore b/.gitignore index 2d8273bb..5f347843 100644 --- a/.gitignore +++ b/.gitignore @@ -135,4 +135,5 @@ dist .flatfile .flatfilerc.json -*.code-workspace \ No newline at end of file +*.code-workspace +.aider* diff --git a/packages/listener/docs/Browser.md b/packages/listener/docs/Browser.md new file mode 100644 index 00000000..d198e852 --- /dev/null +++ b/packages/listener/docs/Browser.md @@ -0,0 +1,435 @@ +# Browser + +The `Browser` class is a concrete implementation of the `EventDriver` abstract class, specifically designed for browser-based environments. It provides functionality to handle Flatfile events in web applications. + +## Class: Browser + +### Properties + +- `public _accessToken?: string`: The access token for authentication. +- `public _apiUrl?: string`: The URL of the API. +- `public _environmentId?: string`: The ID of the environment. + +### Constructor + +```typescript +constructor({ + apiUrl, + accessToken, + environmentId, + fetchApi, +}: { + apiUrl: string + accessToken: string + environmentId?: string + fetchApi: any +}) +``` + +Creates a new Browser instance. + +- **Parameters:** + - `apiUrl: string`: The URL of the API. + - `accessToken: string`: The access token for authentication. + - `environmentId?: string`: Optional. The ID of the environment. + - `fetchApi: any`: Deprecated. The fetch API to use. + +**Example:** +```typescript +const browserDriver = new Browser({ + apiUrl: 'https://api.flatfile.com', + accessToken: 'your-access-token', + environmentId: 'env-123456', +}); +``` + +### Methods + +#### `mountEventHandler(handler: EventHandler): this` + +Mounts an EventHandler and sets necessary variables. + +- **Parameters:** + - `handler: EventHandler`: The EventHandler instance to mount. +- **Returns:** The Browser instance (for method chaining). + +**Example:** +```typescript +const handler = new EventHandler(); +const browserDriver = new Browser({ + apiUrl: 'https://api.flatfile.com', + accessToken: 'your-access-token', +}); + +browserDriver.mountEventHandler(handler); +``` + +## Usage + +The `Browser` class is used to create an event driver for browser-based applications that interact with the Flatfile API. Here's a more comprehensive example of how you might use the `Browser` class in a web application: + +```typescript +import { Browser, EventHandler, FlatfileEvent } from '@flatfile/listener'; + +// Create a Browser instance +const browserDriver = new Browser({ + apiUrl: 'https://api.flatfile.com', + accessToken: 'your-access-token', + environmentId: 'env-123456', +}); + +// Create an EventHandler +const eventHandler = new EventHandler(); + +// Add event listeners +eventHandler.on('file:created', (event: FlatfileEvent) => { + console.log('New file created:', event.payload); +}); + +eventHandler.on('data:imported', (event: FlatfileEvent) => { + console.log('Data imported:', event.payload); +}); + +// Mount the event handler to the browser driver +browserDriver.mountEventHandler(eventHandler); + +// Example of dispatching an event (this would typically be done by the Flatfile SDK) +browserDriver.dispatchEvent({ + topic: 'file:created', + payload: { + fileId: 'file-123', + fileName: 'example.csv', + createdAt: new Date().toISOString(), + }, +}); + +// Later, if you need to unmount the handler +browserDriver.unmountEventHandler(eventHandler); +``` + +In this example, we create a `Browser` instance with the necessary configuration. We then create an `EventHandler` and add listeners for specific Flatfile events. The event handler is mounted to the browser driver, allowing it to receive and process events. + +The `Browser` class acts as a bridge between the Flatfile SDK (which would typically dispatch events) and your application's event handling logic. It ensures that the correct access token and API URL are used when interacting with the Flatfile API. + +Note that in a real-world scenario, you wouldn't typically dispatch events manually as shown in the example. Instead, the Flatfile SDK would dispatch events based on user actions and server responses, and your event listeners would react to these events to update your application's state or perform other actions. +# Using `listener.use()` in Flatfile Listener + +The `use()` method in the Flatfile Listener provides a powerful way to extend and customize the listener's functionality. It allows you to add middleware or plugins to your listener instance, enabling more complex event handling and processing. + +## Basic Usage + +The `use()` method takes a function as an argument. This function receives the listener instance as its parameter, allowing you to add event listeners, set up custom logic, or modify the listener's behavior. + +```typescript +import { FlatfileListener } from '@flatfile/listener'; + +const listener = new FlatfileListener(); + +listener.use((handler) => { + // Add custom logic here +}); +``` + +## Examples + +### 1. Adding Multiple Event Listeners + +You can use the `use()` method to group related event listeners: + +```typescript +listener.use((handler) => { + handler.on('file:created', (event) => { + console.log('File created:', event.payload); + }); + + handler.on('file:updated', (event) => { + console.log('File updated:', event.payload); + }); + + handler.on('file:deleted', (event) => { + console.log('File deleted:', event.payload); + }); +}); +``` + +### 2. Setting Up Custom Logic + +You can implement custom logic that runs for multiple events: + +```typescript +listener.use((handler) => { + const logEvent = (event) => { + console.log(`Event received: ${event.topic}`); + console.log('Payload:', JSON.stringify(event.payload, null, 2)); + }; + + handler.on('*', logEvent); // Log all events +}); +``` + +### 3. Creating Reusable Plugins + +You can create reusable plugins to share functionality across different listener instances: + +```typescript +function createErrorHandler(errorCallback) { + return (handler) => { + handler.on('error', (event) => { + console.error('An error occurred:', event.payload); + errorCallback(event); + }); + }; +} + +// Usage +const errorCallback = (event) => { + // Send error to a logging service +}; + +listener.use(createErrorHandler(errorCallback)); +``` + +### 4. Chaining Multiple `use()` Calls + +You can chain multiple `use()` calls to organize your code better: + +```typescript +listener + .use((handler) => { + // Set up file event handlers + }) + .use((handler) => { + // Set up user event handlers + }) + .use((handler) => { + // Set up error handlers + }); +``` + +## Best Practices + +1. **Modularity**: Use the `use()` method to create modular, reusable pieces of functionality. + +2. **Separation of Concerns**: Group related event listeners or logic within a single `use()` call. + +3. **Plugin Architecture**: Create plugins that can be easily shared across different parts of your application or even different projects. + +4. **Error Handling**: Implement error handling logic using `use()` to ensure consistent error management across your listener. + +5. **Performance**: Be mindful of the order of your `use()` calls, as they are executed in the order they are added. + +By leveraging the `use()` method effectively, you can create more maintainable, modular, and extensible event handling systems with the Flatfile Listener. +# Using `listener.use()` in Flatfile Listener + +The `use()` method in the Flatfile Listener provides a powerful way to extend and customize the listener's functionality. It allows you to add middleware or plugins to your listener instance, enabling more complex event handling and processing. + +## Basic Usage + +The `use()` method takes a function as an argument. This function receives the listener instance as its parameter, allowing you to add event listeners, set up custom logic, or modify the listener's behavior. + +```typescript +import { FlatfileListener } from '@flatfile/listener'; + +const listener = new FlatfileListener(); + +listener.use((handler) => { + // Add custom logic here +}); +``` + +## Examples + +### 1. Adding Multiple Event Listeners + +You can use the `use()` method to group related event listeners: + +```typescript +listener.use((handler) => { + handler.on('file:created', (event) => { + console.log('File created:', event.payload); + }); + + handler.on('file:updated', (event) => { + console.log('File updated:', event.payload); + }); + + handler.on('file:deleted', (event) => { + console.log('File deleted:', event.payload); + }); +}); +``` + +### 2. Setting Up Custom Logic + +You can implement custom logic that runs for multiple events: + +```typescript +listener.use((handler) => { + const logEvent = (event) => { + console.log(`Event received: ${event.topic}`); + console.log('Payload:', JSON.stringify(event.payload, null, 2)); + }; + + handler.on('*', logEvent); // Log all events +}); +``` + +### 3. Creating Reusable Plugins + +You can create reusable plugins to share functionality across different listener instances: + +```typescript +function createErrorHandler(errorCallback) { + return (handler) => { + handler.on('error', (event) => { + console.error('An error occurred:', event.payload); + errorCallback(event); + }); + }; +} + +// Usage +const errorCallback = (event) => { + // Send error to a logging service +}; + +listener.use(createErrorHandler(errorCallback)); +``` + +### 4. Chaining Multiple `use()` Calls + +You can chain multiple `use()` calls to organize your code better: + +```typescript +listener + .use((handler) => { + // Set up file event handlers + }) + .use((handler) => { + // Set up user event handlers + }) + .use((handler) => { + // Set up error handlers + }); +``` + +## Best Practices + +1. **Modularity**: Use the `use()` method to create modular, reusable pieces of functionality. + +2. **Separation of Concerns**: Group related event listeners or logic within a single `use()` call. + +3. **Plugin Architecture**: Create plugins that can be easily shared across different parts of your application or even different projects. + +4. **Error Handling**: Implement error handling logic using `use()` to ensure consistent error management across your listener. + +5. **Performance**: Be mindful of the order of your `use()` calls, as they are executed in the order they are added. + +By leveraging the `use()` method effectively, you can create more maintainable, modular, and extensible event handling systems with the Flatfile Listener. +# Using `listener.use()` in Flatfile Listener + +The `use()` method in the Flatfile Listener provides a powerful way to extend and customize the listener's functionality. It allows you to add middleware or plugins to your listener instance, enabling more complex event handling and processing. + +## Basic Usage + +The `use()` method takes a function as an argument. This function receives the listener instance as its parameter, allowing you to add event listeners, set up custom logic, or modify the listener's behavior. + +```typescript +import { FlatfileListener } from '@flatfile/listener'; + +const listener = new FlatfileListener(); + +listener.use((handler) => { + // Add custom logic here +}); +``` + +## Examples + +### 1. Adding Multiple Event Listeners + +You can use the `use()` method to group related event listeners: + +```typescript +listener.use((handler) => { + handler.on('file:created', (event) => { + console.log('File created:', event.payload); + }); + + handler.on('file:updated', (event) => { + console.log('File updated:', event.payload); + }); + + handler.on('file:deleted', (event) => { + console.log('File deleted:', event.payload); + }); +}); +``` + +### 2. Setting Up Custom Logic + +You can implement custom logic that runs for multiple events: + +```typescript +listener.use((handler) => { + const logEvent = (event) => { + console.log(`Event received: ${event.topic}`); + console.log('Payload:', JSON.stringify(event.payload, null, 2)); + }; + + handler.on('*', logEvent); // Log all events +}); +``` + +### 3. Creating Reusable Plugins + +You can create reusable plugins to share functionality across different listener instances: + +```typescript +function createErrorHandler(errorCallback) { + return (handler) => { + handler.on('error', (event) => { + console.error('An error occurred:', event.payload); + errorCallback(event); + }); + }; +} + +// Usage +const errorCallback = (event) => { + // Send error to a logging service +}; + +listener.use(createErrorHandler(errorCallback)); +``` + +### 4. Chaining Multiple `use()` Calls + +You can chain multiple `use()` calls to organize your code better: + +```typescript +listener + .use((handler) => { + // Set up file event handlers + }) + .use((handler) => { + // Set up user event handlers + }) + .use((handler) => { + // Set up error handlers + }); +``` + +## Best Practices + +1. **Modularity**: Use the `use()` method to create modular, reusable pieces of functionality. + +2. **Separation of Concerns**: Group related event listeners or logic within a single `use()` call. + +3. **Plugin Architecture**: Create plugins that can be easily shared across different parts of your application or even different projects. + +4. **Error Handling**: Implement error handling logic using `use()` to ensure consistent error management across your listener. + +5. **Performance**: Be mindful of the order of your `use()` calls, as they are executed in the order they are added. + +By leveraging the `use()` method effectively, you can create more maintainable, modular, and extensible event handling systems with the Flatfile Listener. diff --git a/packages/listener/docs/Event.Topics.md b/packages/listener/docs/Event.Topics.md new file mode 100644 index 00000000..e2903bbd --- /dev/null +++ b/packages/listener/docs/Event.Topics.md @@ -0,0 +1,101 @@ +# Event Topics + +Flatfile Listeners can listen to any Flatfile event. Here is a list of all the event topics and their descriptions. + +## Agent Events + +- `agent:created`: When a new agent is created +- `agent:updated`: When an existing agent is modified +- `agent:deleted`: When an agent is removed from the system + +## Space Events + +- `space:created`: When a new workspace is created +- `space:updated`: When workspace details are modified +- `space:deleted`: When a workspace is removed +- `space:archived`: When a workspace is archived +- `space:expired`: When a workspace reaches its expiration date +- `space:guestAdded`: When a new guest user is added to a workspace +- `space:guestRemoved`: When a guest user is removed from a workspace + +## Document Events + +- `document:created`: When a new document is added to a workspace +- `document:updated`: When an existing document is modified +- `document:deleted`: When a document is removed from a workspace + +## Workbook Events + +- `workbook:created`: When a new workbook is created +- `workbook:updated`: When workbook details are modified +- `workbook:deleted`: When a workbook is removed +- `workbook:expired`: When a workbook reaches its expiration date + +## Sheet Events + +- `sheet:created`: When a new sheet is added to a workbook +- `sheet:updated`: When sheet details are modified +- `sheet:deleted`: When a sheet is removed from a workbook +- `sheet:counts-updated`: When the record counts in a sheet are updated + +## Snapshot Events + +- `snapshot:created`: When a new snapshot of data is created + +## Record Events + +- `records:created`: When new records are added to a sheet +- `records:updated`: When existing records are modified +- `records:deleted`: When records are removed from a sheet + +## File Events + +- `file:created`: When a new file is uploaded +- `file:updated`: When file details are modified +- `file:deleted`: When a file is removed +- `file:expired`: When a file reaches its expiration date + +## Job Events + +- `job:created`: When a new job is created +- `job:updated`: When job details are modified +- `job:deleted`: When a job is removed +- `job:completed`: When a job finishes execution +- `job:ready`: When a job is ready to be processed +- `job:scheduled`: When a job is scheduled for future execution +- `job:outcome-acknowledged`: When the outcome of a job is acknowledged +- `job:parts-completed`: When parts of a job are completed +- `job:failed`: When a job fails to execute successfully + +## Mapping Events + +- `program:created`: When a new mapping program is created +- `program:updated`: When an existing mapping program is modified + +## Version Control Events + +- `commit:created`: When a new commit is made +- `commit:updated`: When commit details are modified +- `commit:completed`: When a commit operation is finished +- `layer:created`: When a new layer is added in version control + +## Secret Management Events + +- `secret:created`: When a new secret (e.g., API key) is added +- `secret:updated`: When an existing secret is modified +- `secret:deleted`: When a secret is removed + +## Scheduled Events + +- `cron:5-minutes`: Triggered every 5 minutes +- `cron:hourly`: Triggered every hour +- `cron:daily`: Triggered once a day +- `cron:weekly`: Triggered once a week + +## Environment Events + +- `environment:created`: When a new environment is set up +- `environment:updated`: When environment settings are modified +- `environment:deleted`: When an environment is removed + +These event topics cover a wide range of actions and states within the Flatfile platform, allowing for detailed tracking and response to various system activities. diff --git a/packages/listener/docs/EventCache.md b/packages/listener/docs/EventCache.md new file mode 100644 index 00000000..0957b64f --- /dev/null +++ b/packages/listener/docs/EventCache.md @@ -0,0 +1,130 @@ +# EventCache + +The `EventCache` class provides a simple caching mechanism for events in the Flatfile Listener system. It allows you to store, retrieve, and manage event data efficiently. + +## Class: EventCache + +### Properties + +- `private eventCache: Map`: A Map object that stores the cached events. + +### Methods + +#### `async init(key: string, callback: () => Promise): Promise` + +Initializes a cache entry if it doesn't exist, or returns the existing cached value. + +- **Parameters:** + - `key: string`: The unique identifier for the cache entry. + - `callback: () => Promise`: A function that returns a Promise resolving to the value to be cached. +- **Returns:** A Promise that resolves to the cached or newly computed value. + +**Example:** +```typescript +const cache = new EventCache(); +const data = await cache.init('user_data', async () => { + return await fetchUserData(); +}); +``` + +#### `async set(key: string, callback: () => Promise): Promise` + +Updates an existing cache entry with a new value. + +- **Parameters:** + - `key: string`: The unique identifier for the cache entry. + - `callback: () => Promise`: A function that returns a Promise resolving to the new value to be cached. +- **Returns:** A Promise that resolves to the newly cached value. +- **Throws:** An error if the cache key is not found. + +**Example:** +```typescript +try { + const updatedData = await cache.set('user_data', async () => { + return await updateUserData(); + }); +} catch (error) { + console.error('Failed to update cache:', error.message); +} +``` + +#### `get(key: string): T` + +Retrieves a value from the cache. + +- **Parameters:** + - `key: string`: The unique identifier for the cache entry. +- **Returns:** The cached value. +- **Throws:** An error if the cache key is not found. + +**Example:** +```typescript +try { + const userData = cache.get('user_data'); + console.log('User data:', userData); +} catch (error) { + console.error('Failed to get cache:', error.message); +} +``` + +#### `delete(key?: string | string[]): void` + +Deletes one or more entries from the cache, or clears the entire cache if no key is provided. + +- **Parameters:** + - `key?: string | string[]`: Optional. The key or array of keys to delete from the cache. +- **Throws:** An error if the cache key is not found. + +**Example:** +```typescript +// Delete a single entry +cache.delete('user_data'); + +// Delete multiple entries +cache.delete(['user_data', 'app_settings']); + +// Clear entire cache +cache.delete(); +``` + +## Usage + +The `EventCache` class is useful for storing and managing event-related data that you want to keep in memory for quick access. It's particularly helpful when you need to avoid redundant API calls or computations for frequently accessed data. + +Here's a more comprehensive example of how you might use the `EventCache` in a Flatfile Listener context: + +```typescript +import { EventCache } from './EventCache'; + +const eventCache = new EventCache(); + +async function handleUserEvent(userId: string) { + try { + // Try to get user data from cache, or fetch it if not present + const userData = await eventCache.init(`user_${userId}`, async () => { + console.log('Fetching user data from API...'); + return await fetchUserDataFromAPI(userId); + }); + + console.log('User data:', userData); + + // Update user data + const updatedUserData = await eventCache.set(`user_${userId}`, async () => { + console.log('Updating user data...'); + return await updateUserDataInAPI(userId, { lastActive: new Date() }); + }); + + console.log('Updated user data:', updatedUserData); + + // Clear user data from cache when no longer needed + eventCache.delete(`user_${userId}`); + } catch (error) { + console.error('Error handling user event:', error.message); + } +} + +// Usage +handleUserEvent('12345'); +``` + +This example demonstrates how to use the `EventCache` to efficiently manage user data in an event-driven system, reducing unnecessary API calls and improving performance. diff --git a/packages/listener/docs/EventDriver.md b/packages/listener/docs/EventDriver.md new file mode 100644 index 00000000..e1cde75c --- /dev/null +++ b/packages/listener/docs/EventDriver.md @@ -0,0 +1,114 @@ +# EventDriver + +The `EventDriver` class is an abstract base class that provides a foundation for implementing event-driven functionality in the Flatfile Listener system. It manages the connection between event handlers and the actual event sources. + +## Class: EventDriver + +### Properties + +- `protected _handler?: EventHandler`: An optional EventHandler instance that will process the events. + +### Methods + +#### `get handler(): EventHandler` + +A getter that returns the current EventHandler instance. + +- **Returns:** The current EventHandler instance. +- **Throws:** An error if the handler is not registered yet. + +**Example:** +```typescript +const driver = new ConcreteEventDriver(); +try { + const handler = driver.handler; + // Use the handler +} catch (error) { + console.error('Handler not registered:', error.message); +} +``` + +#### `mountEventHandler(handler: EventHandler): this` + +Mounts an EventHandler to the driver. + +- **Parameters:** + - `handler: EventHandler`: The EventHandler instance to mount. +- **Returns:** The EventDriver instance (for method chaining). + +**Example:** +```typescript +const handler = new EventHandler(); +const driver = new ConcreteEventDriver(); +driver.mountEventHandler(handler); +``` + +#### `unmountEventHandler(handler: EventHandler): this` + +Unmounts an EventHandler from the driver if it matches the current handler. + +- **Parameters:** + - `handler: EventHandler`: The EventHandler instance to unmount. +- **Returns:** The EventDriver instance (for method chaining). + +**Example:** +```typescript +const handler = new EventHandler(); +const driver = new ConcreteEventDriver(); +driver.mountEventHandler(handler); +// ... later ... +driver.unmountEventHandler(handler); +``` + +#### `dispatchEvent(e: any): this` + +Dispatches an event to the current handler. + +- **Parameters:** + - `e: any`: The event to dispatch. +- **Returns:** The EventDriver instance (for method chaining). + +**Example:** +```typescript +const driver = new ConcreteEventDriver(); +driver.mountEventHandler(new EventHandler()); +driver.dispatchEvent({ type: 'custom_event', data: { /* ... */ } }); +``` + +## Usage + +The `EventDriver` class is designed to be extended by concrete implementations that connect to specific event sources. Here's an example of how you might implement and use a concrete EventDriver: + +```typescript +import { EventDriver, EventHandler } from './path-to-flatfile-listener'; + +class WebSocketEventDriver extends EventDriver { + private socket: WebSocket; + + constructor(url: string) { + super(); + this.socket = new WebSocket(url); + this.socket.onmessage = (event) => { + this.dispatchEvent(JSON.parse(event.data)); + }; + } + + // Additional methods specific to WebSocket handling... +} + +// Usage +const wsDriver = new WebSocketEventDriver('wss://api.example.com/events'); +const eventHandler = new EventHandler(); + +eventHandler.on('custom_event', (event) => { + console.log('Received custom event:', event); +}); + +wsDriver.mountEventHandler(eventHandler); + +// The WebSocket will now dispatch events to the eventHandler +``` + +In this example, `WebSocketEventDriver` extends `EventDriver` to provide WebSocket-specific functionality. It creates a WebSocket connection and dispatches received messages as events to the mounted `EventHandler`. + +The `EventDriver` abstraction allows for different types of event sources (WebSocket, HTTP polling, server-sent events, etc.) to be implemented consistently and interchangeably in the Flatfile Listener system. diff --git a/packages/listener/docs/FlatfileListener.md b/packages/listener/docs/FlatfileListener.md new file mode 100644 index 00000000..264355e2 --- /dev/null +++ b/packages/listener/docs/FlatfileListener.md @@ -0,0 +1,119 @@ +# Flatfile Listener + +The Flatfile Listener is a powerful and flexible event handling system designed for the Flatfile platform. It provides a robust framework for subscribing to and processing events in various environments, including webhooks, websockets, and serverless functions. + +## Overview + +The Flatfile Listener is built on top of the `EventHandler` class and extends its functionality to provide a more specialized interface for Flatfile-specific events. It allows developers to easily subscribe to events, filter them based on various criteria, and respond to them in real-time. + +## Key Features + +1. **Flexible Event Subscription**: Subscribe to events using various patterns and filters. +2. **Namespace Support**: Group event listeners by namespace for better organization. +3. **Filtering Capabilities**: Apply filters to event listeners for more granular control. +4. **Driver-based Architecture**: Support for multiple event sources through different drivers. +5. **Chainable API**: Fluent interface for easy configuration and setup. + +## Usage + +### Creating a Listener + +You can create a new Flatfile Listener instance using the static `create` method: + +```typescript +const listener = FlatfileListener.create((client) => { + // Configure your listener here +}) +``` + +### Adding Event Listeners + +You can add event listeners using the `on` method: + +```typescript +listener.on('file:created', (event) => { + console.log('A new file was created:', event.payload) +}) +``` + +### Namespace Filtering + +You can listen to events within a specific namespace: + +```typescript +listener.namespace('my-namespace', (namespaced) => { + namespaced.on('record:created', (event) => { + console.log('A record was created in my-namespace:', event.payload) + }) +}) +``` + +### Advanced Filtering + +You can apply more complex filters to your listeners: + +```typescript +listener.filter( + { namespaces: ['namespace1', 'namespace2'], topic: 'file:*' }, + (filtered) => { + filtered.on('file:uploaded', (event) => { + console.log( + 'A file was uploaded in namespace1 or namespace2:', + event.payload + ) + }) + } +) +``` + +### Mounting to a Driver + +To start receiving events, you need to mount the listener to an event driver: + +```typescript +import { Browser } from '@flatfile/listener' + +const driver = new Browser({ + apiUrl: 'https://api.flatfile.com', + accessToken: 'your-access-token', + environmentId: 'env-123456', +}) + +listener.mount(driver) +``` + +## Advanced Features + +### Forking + +You can create a new instance of the listener with the same configuration using the `fork` method: + +```typescript +const forkedListener = listener.fork() +``` + +### Unmounting + +To stop receiving events, you can unmount the listener from its driver: + +```typescript +listener.unmount(driver) +``` + +## Best Practices + +1. **Error Handling**: Always include error handling in your event listeners to prevent unhandled exceptions. + +2. **Asynchronous Operations**: When performing asynchronous operations in your listeners, make sure to handle promises correctly. + +3. **Performance**: Be mindful of the performance impact of your event handlers, especially for high-frequency events. + +4. **Namespacing**: Use namespaces to organize your listeners, especially in large applications. + +5. **Cleanup**: Remember to unmount listeners when they're no longer needed to prevent memory leaks. + +## Conclusion + +The Flatfile Listener provides a powerful and flexible way to handle events in the Flatfile ecosystem. By leveraging its features, you can build robust, event-driven applications that react in real-time to changes in your Flatfile environment. + +For more detailed information on specific components, refer to the documentation for `EventHandler`, `EventDriver`, and other related classes. diff --git a/packages/listener/docs/ListenerUse.md b/packages/listener/docs/ListenerUse.md new file mode 100644 index 00000000..7d2b1187 --- /dev/null +++ b/packages/listener/docs/ListenerUse.md @@ -0,0 +1,107 @@ +# Using `listener.use()` in Flatfile Listener + +The `use()` method in the Flatfile Listener provides a powerful way to extend and customize the listener's functionality. It allows you to add middleware or plugins to your listener instance, enabling more complex event handling and processing. + +## Basic Usage + +The `use()` method takes a function as an argument. This function receives the listener instance as its parameter, allowing you to add event listeners, set up custom logic, or modify the listener's behavior. + +```typescript +import { FlatfileListener } from '@flatfile/listener' + +const listener = new FlatfileListener() + +listener.use((handler) => { + // Add custom logic here +}) +``` + +## Examples + +### 1. Adding Multiple Event Listeners + +You can use the `use()` method to group related event listeners: + +```typescript +listener.use((handler) => { + handler.on('file:created', (event) => { + console.log('File created:', event.payload) + }) + + handler.on('file:updated', (event) => { + console.log('File updated:', event.payload) + }) + + handler.on('file:deleted', (event) => { + console.log('File deleted:', event.payload) + }) +}) +``` + +### 2. Setting Up Custom Logic + +You can implement custom logic that runs for multiple events: + +```typescript +listener.use((handler) => { + const logEvent = (event) => { + console.log(`Event received: ${event.topic}`) + console.log('Payload:', JSON.stringify(event.payload, null, 2)) + } + + handler.on('*', logEvent) // Log all events +}) +``` + +### 3. Creating Reusable Plugins + +You can create reusable plugins to share functionality across different listener instances: + +```typescript +function createErrorHandler(errorCallback) { + return (handler) => { + handler.on('error', (event) => { + console.error('An error occurred:', event.payload) + errorCallback(event) + }) + } +} + +// Usage +const errorCallback = (event) => { + // Send error to a logging service +} + +listener.use(createErrorHandler(errorCallback)) +``` + +### 4. Chaining Multiple `use()` Calls + +You can chain multiple `use()` calls to organize your code better: + +```typescript +listener + .use((handler) => { + // Set up file event handlers + }) + .use((handler) => { + // Set up user event handlers + }) + .use((handler) => { + // Set up error handlers + }) +``` + +## Best Practices + +1. **Modularity**: Use the `use()` method to create modular, reusable pieces of functionality. + +2. **Separation of Concerns**: Group related event listeners or logic within a single `use()` call. + +3. **Plugin Architecture**: Create plugins that can be easily shared across different parts of your application or even different projects. + +4. **Error Handling**: Implement error handling logic using `use()` to ensure consistent error management across your listener. + +5. **Performance**: Be mindful of the order of your `use()` calls, as they are executed in the order they are added. + +By leveraging the `use()` method effectively, you can create more maintainable, modular, and extensible event handling systems with the Flatfile Listener.