feat: Twitch Plugin (#1612)
* wip * copy polugin files * wip type changes * refactor: improve Twitch plugin code quality and fix all tests - Extract client manager registry for centralized lifecycle management - Refactor to use early returns and reduce mutations - Fix status check logic for clientId detection - Add comprehensive test coverage for new modules - Remove tests for unimplemented features (index.test.ts, resolver.test.ts) - Fix mock setup issues in test suite (149 tests now passing) - Improve error handling with errorResponse helper in actions.ts - Normalize token handling to eliminate duplication Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * use accountId * delete md file * delte tsconfig * adjust log level * fix probe logic * format * fix monitor * code review fixes * format * no mutation * less mutation * chain debug log * await authProvider setup * use uuid * use spread * fix tests * update docs and remove bot channel fallback * more readme fixes * remove comments + fromat * fix tests * adjust access control logic * format * install * simplify config object * remove duplicate log tags + log received messages * update docs * update tests * format * strip markdown in monitor * remove strip markdown config, enabled by default * default requireMention to true * fix store path arg * fix multi account id + add unit test * fix multi account id + add unit test * make channel required and update docs * remove whisper functionality * remove duplicate connect log * update docs with convert twitch link * make twitch message processing non blocking * schema consistent casing * remove noisy ignore log * use coreLogger --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
115
extensions/twitch/src/client-manager-registry.ts
Normal file
115
extensions/twitch/src/client-manager-registry.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* Client manager registry for Twitch plugin.
|
||||
*
|
||||
* Manages the lifecycle of TwitchClientManager instances across the plugin,
|
||||
* ensuring proper cleanup when accounts are stopped or reconfigured.
|
||||
*/
|
||||
|
||||
import { TwitchClientManager } from "./twitch-client.js";
|
||||
import type { ChannelLogSink } from "./types.js";
|
||||
|
||||
/**
|
||||
* Registry entry tracking a client manager and its associated account.
|
||||
*/
|
||||
type RegistryEntry = {
|
||||
/** The client manager instance */
|
||||
manager: TwitchClientManager;
|
||||
/** The account ID this manager is for */
|
||||
accountId: string;
|
||||
/** Logger for this entry */
|
||||
logger: ChannelLogSink;
|
||||
/** When this entry was created */
|
||||
createdAt: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Global registry of client managers.
|
||||
* Keyed by account ID.
|
||||
*/
|
||||
const registry = new Map<string, RegistryEntry>();
|
||||
|
||||
/**
|
||||
* Get or create a client manager for an account.
|
||||
*
|
||||
* @param accountId - The account ID
|
||||
* @param logger - Logger instance
|
||||
* @returns The client manager
|
||||
*/
|
||||
export function getOrCreateClientManager(
|
||||
accountId: string,
|
||||
logger: ChannelLogSink,
|
||||
): TwitchClientManager {
|
||||
const existing = registry.get(accountId);
|
||||
if (existing) {
|
||||
return existing.manager;
|
||||
}
|
||||
|
||||
const manager = new TwitchClientManager(logger);
|
||||
registry.set(accountId, {
|
||||
manager,
|
||||
accountId,
|
||||
logger,
|
||||
createdAt: Date.now(),
|
||||
});
|
||||
|
||||
logger.info(`Registered client manager for account: ${accountId}`);
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an existing client manager for an account.
|
||||
*
|
||||
* @param accountId - The account ID
|
||||
* @returns The client manager, or undefined if not registered
|
||||
*/
|
||||
export function getClientManager(accountId: string): TwitchClientManager | undefined {
|
||||
return registry.get(accountId)?.manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect and remove a client manager from the registry.
|
||||
*
|
||||
* @param accountId - The account ID
|
||||
* @returns Promise that resolves when cleanup is complete
|
||||
*/
|
||||
export async function removeClientManager(accountId: string): Promise<void> {
|
||||
const entry = registry.get(accountId);
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Disconnect the client manager
|
||||
await entry.manager.disconnectAll();
|
||||
|
||||
// Remove from registry
|
||||
registry.delete(accountId);
|
||||
entry.logger.info(`Unregistered client manager for account: ${accountId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect and remove all client managers from the registry.
|
||||
*
|
||||
* @returns Promise that resolves when all cleanup is complete
|
||||
*/
|
||||
export async function removeAllClientManagers(): Promise<void> {
|
||||
const promises = [...registry.keys()].map((accountId) => removeClientManager(accountId));
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of registered client managers.
|
||||
*
|
||||
* @returns The count of registered managers
|
||||
*/
|
||||
export function getRegisteredClientManagerCount(): number {
|
||||
return registry.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all client managers without disconnecting.
|
||||
*
|
||||
* This is primarily for testing purposes.
|
||||
*/
|
||||
export function _clearAllClientManagersForTest(): void {
|
||||
registry.clear();
|
||||
}
|
||||
Reference in New Issue
Block a user