/ src / utils / coherence_beacon_utils.js
coherence_beacon_utils.js
  1  const fs = require('fs').promises;
  2  const path = require('path');
  3  const Store = require('electron-store');
  4  const store = new Store();
  5  
  6  async function readDreamSongCanvas(repoName) {
  7    const dreamVaultPath = store.get('dreamVaultPath');
  8    if (!dreamVaultPath) {
  9      throw new Error('Dream Vault path is not set in the application settings');
 10    }
 11    const canvasPath = path.join(dreamVaultPath, repoName, 'DreamSong.canvas');
 12    try {
 13      const data = await fs.readFile(canvasPath, 'utf8');
 14      return JSON.parse(data);
 15    } catch (error) {
 16      console.error(`Error reading DreamSong.canvas for ${repoName}:`, error);
 17      return null;
 18    }
 19  }
 20  
 21  async function parseGitModules(repoName) {
 22    const dreamVaultPath = store.get('dreamVaultPath');
 23    if (!dreamVaultPath) {
 24      throw new Error('Dream Vault path is not set in the application settings');
 25    }
 26    const gitmodulesPath = path.join(dreamVaultPath, repoName, '.gitmodules');
 27    try {
 28      const data = await fs.readFile(gitmodulesPath, 'utf8');
 29      // Simple parsing of .gitmodules file
 30      const submodules = data.match(/path = .+/g);
 31      return submodules ? submodules.map(line => line.split(' = ')[1].trim()) : [];
 32    } catch (error) {
 33      if (error.code === 'ENOENT') {
 34        // .gitmodules file doesn't exist, which is fine
 35        return [];
 36      }
 37      throw error;
 38    }
 39  }
 40  
 41  async function getDreamSongDependencies(repoName) {
 42    const dreamVaultPath = store.get('dreamVaultPath');
 43    if (!dreamVaultPath) {
 44      throw new Error('Dream Vault path is not set in the application settings');
 45    }
 46    const canvasData = await readDreamSongCanvas(repoName);
 47    if (!canvasData || !canvasData.nodes) {
 48      return [];
 49    }
 50  
 51    const fileNodes = canvasData.nodes.filter(node => node.type === 'file' && node.file);
 52    const externalDependencies = fileNodes
 53      .map(node => node.file)
 54      .filter(filePath => !filePath.startsWith(repoName + '/'))
 55      .map(filePath => filePath.split('/')[0]);
 56  
 57    return [...new Set(externalDependencies)]; // Remove duplicates
 58  }
 59  
 60  function computePositiveDelta(currentSubmodules, dreamSongDependencies) {
 61    return dreamSongDependencies.filter(dep => !currentSubmodules.includes(dep));
 62  }
 63  
 64  async function identifyFriendsToNotify(novelSubmodules) {
 65    const dreamVaultPath = store.get('dreamVaultPath');
 66    if (!dreamVaultPath) {
 67      throw new Error('Dream Vault path is not set in the application settings');
 68    }
 69  
 70    const friendsToNotify = new Map();
 71  
 72    for (const submodule of novelSubmodules) {
 73      const metadataPath = path.join(dreamVaultPath, submodule, '.pl');
 74      try {
 75        const data = await fs.readFile(metadataPath, 'utf8');
 76        const metadata = JSON.parse(data);
 77        
 78        if (metadata.relatedNodes && Array.isArray(metadata.relatedNodes)) {
 79          for (const friend of metadata.relatedNodes) {
 80            if (!friendsToNotify.has(friend)) {
 81              const friendMetadataPath = path.join(dreamVaultPath, friend, '.pl');
 82              try {
 83                const friendData = await fs.readFile(friendMetadataPath, 'utf8');
 84                const friendMetadata = JSON.parse(friendData);
 85                friendsToNotify.set(friend, {
 86                  email: friendMetadata.email || '',
 87                  commonSubmodules: [submodule]
 88                });
 89              } catch (error) {
 90                console.error(`Error reading metadata for friend ${friend}:`, error);
 91                friendsToNotify.set(friend, { email: '', commonSubmodules: [submodule] });
 92              }
 93            } else {
 94              friendsToNotify.get(friend).commonSubmodules.push(submodule);
 95            }
 96          }
 97        }
 98      } catch (error) {
 99        console.error(`Error reading metadata for ${submodule}:`, error);
100        // Continue to the next submodule if there's an error
101      }
102    }
103  
104    return Array.from(friendsToNotify.entries()).map(([name, data]) => ({
105      name,
106      email: data.email,
107      commonSubmodules: data.commonSubmodules
108    }));
109  }
110  
111  module.exports = {
112    parseGitModules,
113    getDreamSongDependencies,
114    computePositiveDelta,
115    identifyFriendsToNotify
116  };