/** * Actions entity class for GitHub workflow operations * @file companies.js * @license Apache-2.0 * @version 3.0.0 * * @author Michael Hay <michael.hay@mediumroast.io> * @copyright 2025 Mediumroast, Inc. All rights reserved. */ import { BaseObjects } from '../baseObjects.js'; import { Interactions } from './interactions.js'; import { logger } from '../logger.js'; export class Companies extends BaseObjects { constructor(token, org, processName) { super(token, org, processName, 'Companies'); // Add profile-specific cache settings this._cacheKeys.profile = `${this.objType}_profile`; this.cacheTimeouts.profile = 600000; // 10 minutes for profiles } /** * Generates company profile with analytics * @param {string} name - Company name * @returns {Promise<Array>} Company profile */ async generateCompanyProfile(name) { // Track this operation const tracking = logger.trackOperation ? logger.trackOperation(this.objType, 'generateCompanyProfile') : { end: () => {} }; // Validate parameter const validationError = this._validateParams( { name }, { name: 'string' } ); if (validationError) return validationError; try { // Use cache with dependency on both company and interactions data const profileCacheKey = `${this._cacheKeys.profile}_${name}`; return await this.cache.getOrFetch( profileCacheKey, async () => { // Find the company const companyResp = await this.findByName(name); if (!companyResp[0]) { return companyResp; } const company = companyResp[2][0]; // Get linked interactions let linkedInteractionDetails = []; if (company.linked_interactions && Object.keys(company.linked_interactions).length > 0) { // Instantiate Interactions class to get details const interactionsClass = new Interactions( this.serverCtl.token, this.serverCtl.orgName, 'profile-generator' ); // Get details for each interaction for (const interactionName of Object.keys(company.linked_interactions)) { const interactionResp = await interactionsClass.findByName(interactionName); if (interactionResp[0]) { linkedInteractionDetails.push(interactionResp[2][0]); } } } // Analyze the interactions const analytics = { interactionCount: linkedInteractionDetails.length, contentTypes: {}, totalFileSize: 0, avgReadingTime: 0, totalWordCount: 0, avgPageCount: 0, lastModified: null, oldestInteraction: null }; // Process each interaction linkedInteractionDetails.forEach(interaction => { // Track content types analytics.contentTypes[interaction.content_type] = (analytics.contentTypes[interaction.content_type] || 0) + 1; // Track file sizes if (interaction.file_size) { analytics.totalFileSize += interaction.file_size; } // Track reading time if (interaction.reading_time) { analytics.avgReadingTime += interaction.reading_time; } // Track word count if (interaction.word_count) { analytics.totalWordCount += interaction.word_count; } // Track page count if (interaction.page_count) { analytics.avgPageCount += interaction.page_count; } // Track modification dates const modDate = new Date(interaction.modification_date); if (!analytics.lastModified || modDate > new Date(analytics.lastModified)) { analytics.lastModified = interaction.modification_date; } if (!analytics.oldestInteraction || modDate < new Date(analytics.oldestInteraction)) { analytics.oldestInteraction = interaction.modification_date; } }); // Calculate averages if (linkedInteractionDetails.length > 0) { analytics.avgReadingTime /= linkedInteractionDetails.length; analytics.avgPageCount /= linkedInteractionDetails.length; } // Create company profile const profile = { ...company, analytics, interactionSummary: linkedInteractionDetails.map(i => ({ name: i.name, content_type: i.content_type, file_size: i.file_size, modification_date: i.modification_date, description: i.description })) }; return this._createSuccess( `Generated profile for company [${name}]`, profile ); }, this.cacheTimeouts.profile, [ this._cacheKeys.container, // Depends on company data 'container_Interactions' // Depends on interaction data ] ); } catch (error) { return this._createError( `Error generating company profile: ${error.message}`, error, 500 ); } finally { tracking.end(); } } /** * Link interactions to a company * @param {string} companyName - Name of the company * @param {Array<Object>} interactions - Interactions to link * @returns {Promise<Array>} Result of the operation */ async linkInteractions(companyName, interactions) { // Track this operation const tracking = logger.trackOperation ? logger.trackOperation(this.objType, 'linkInteractions') : { end: () => {} }; try { // Validate parameters const validationError = this._validateParams( { companyName, interactions }, { companyName: 'string', interactions: 'array' } ); if (validationError) return validationError; // Create linked objects hash const linkedInteractions = this.linkObj(interactions); // Update the company with linked interactions return await this.updateObj({ name: companyName, key: 'linked_interactions', value: linkedInteractions }); } catch (error) { return this._createError( `Error linking interactions to company: ${error.message}`, error, 500 ); } finally { tracking.end(); } } }