/** * Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved. */ import { Channel, Channels } from '@techniker-me/pcast-api'; import PCastApiService from './PCastApi.service'; import LoggerFactory from './logger/LoggerFactory'; const logger = LoggerFactory.getLogger('services/channel.service'); export interface CreateChannelParams { name: string; description?: string; options?: string[]; } export interface UpdateChannelParams { channelId: string; name?: string; alias?: string; description?: string; tags?: string[]; capabilities?: string[]; } export interface ForkChannelParams { sourceChannelId: string; destinationChannelId: string; streamCapabilities?: string[]; streamTags?: string[]; options?: string[]; } export interface DeleteChannelParams { channelId: string; alias: string; } export interface KillChannelParams { channelId: string; reason?: string; options?: string[]; enteredAlias?: string; } /** * Channel Service providing CRUD operations for channels */ class ChannelService { private phenixChannelService: PhenixChannelService | null = null; public async initializeWithPCastApi(channels: Channels) { try { // Wait for PCastApiService to be initialized this.phenixChannelService = channels; } catch (error) { logger.error('Failed to initialize ChannelService', error); } } /** * Get all channels */ async listChannels(): Promise { try { logger.debug('Fetching channel list'); if (!this.phenixChannelService) { return PCastApiService.channels.list(); } return await this.phenixChannelService.list(); } catch (error) { logger.error('Failed to list channels', error); throw error; } } /** * Create a new channel */ async createChannel(params: CreateChannelParams): Promise { try { logger.debug('Creating channel', params); const channelData = { name: params.name, alias: params.alias, description: params.description || '', tags: params.tags || [], capabilities: params.capabilities || [] }; if (!this.phenixChannelService) { return PCastApiService.channels.create(name, description, options); } return await this.phenixChannelService.create(channelData); } catch (error) { logger.error('Failed to create channel', error); throw error; } } /** * Update an existing channel */ async updateChannel(params: UpdateChannelParams): Promise { try { logger.debug('Updating channel', params); const updateData = { ...params.name && { name: params.name }, ...params.alias && { alias: params.alias }, ...params.description && { description: params.description }, ...params.tags && { tags: params.tags }, ...params.capabilities && { capabilities: params.capabilities } }; if (!this.phenixChannelService) { return PCastApiService.channels.update(params.channelId, updateData); } return await this.phenixChannelService.update(params.channelId, updateData); } catch (error) { logger.error('Failed to update channel', error); throw error; } } /** * Delete a channel */ async deleteChannel(params: DeleteChannelParams): Promise { try { logger.debug('Deleting channel', params); if (!this.phenixChannelService) { return PCastApiService.channels.delete(params.channelId); } await this.phenixChannelService.delete(params.channelId); } catch (error) { logger.error('Failed to delete channel', error); throw error; } } /** * Fork a channel */ async forkChannel(params: ForkChannelParams): Promise { try { logger.debug('Forking channel', params); const forkData = { destinationChannelId: params.destinationChannelId, streamCapabilities: params.streamCapabilities || [], streamTags: params.streamTags || [], options: params.options || [] }; // Phenix SDK fork method if (!this.phenixChannelService) { return PCastApiService.channels.fork(params.sourceChannelId, forkData); } await this.phenixChannelService.fork(params.sourceChannelId, forkData); } catch (error) { logger.error('Failed to fork channel', error); throw error; } } /** * Kill a channel */ async killChannel(params: KillChannelParams): Promise { try { logger.debug('Killing channel', params); const killData = { reason: params.reason || 'portal:killed', options: params.options || [] }; if (!this.phenixChannelService) { return PCastApiService.channels.kill(params.channelId, killData); } await this.phenixChannelService.kill(params.channelId, killData); } catch (error) { logger.error('Failed to kill channel', error); throw error; } } /** * Get channel by ID */ async getChannel(channelId: string): Promise { try { logger.debug('Getting channel', { channelId }); if (!this.phenixChannelService) { return PCastApiService.channels.get(channelId); } return await this.phenixChannelService.get(channelId); } catch (error) { logger.error('Failed to get channel', error); throw error; } } /** * Get publisher count for a channel */ async getPublisherCount(channelId: string): Promise { try { logger.debug('Getting publisher count', { channelId }); if (!this.phenixChannelService) { return PCastApiService.channels.getPublisherCount(channelId); } return await this.phenixChannelService.getPublisherCount(channelId); } catch (error) { logger.error('Failed to get publisher count', error); return 0; } } } // Export singleton instance const channelService = new ChannelService(); // Named exports for individual operations export const listChannels = channelService.listChannels.bind(channelService); export const createChannel = channelService.createChannel.bind(channelService); export const updateChannel = channelService.updateChannel.bind(channelService); export const deleteChannel = channelService.deleteChannel.bind(channelService); export const forkChannel = channelService.forkChannel.bind(channelService); export const killChannel = channelService.killChannel.bind(channelService); export const getChannel = channelService.getChannel.bind(channelService); export const getPublisherCount = channelService.getPublisherCount.bind(channelService); export default channelService;