1. /**
  2. * Diffs two datasets of log files for isolated environments.
  3. *
  4. * @param {string[]} dataset1 - Array of log file paths for the first environment.
  5. * @param {string[]} dataset2 - Array of log file paths for the second environment.
  6. * @param {object} [options] - Optional configuration object.
  7. * @param {string} [options.ignoreCase=true] - Whether to ignore case during comparison.
  8. * @param {string} [options.ignoreWhitespace=true] - Whether to ignore whitespace.
  9. * @returns {Promise<object>} - A promise that resolves to an object containing the diff results.
  10. * The object has the following structure:
  11. * {
  12. * added: string[],
  13. * removed: string[],
  14. * changed: { [logfile: string]: { added: string[], removed: string[] } }
  15. * }
  16. * Returns an error if invalid input is provided.
  17. */
  18. async function diffLogDatasets(dataset1, dataset2, options = {}) {
  19. const { ignoreCase = true, ignoreWhitespace = true } = options;
  20. if (!Array.isArray(dataset1) || !Array.isArray(dataset2)) {
  21. throw new Error("Datasets must be arrays.");
  22. }
  23. if (dataset1.length === 0 && dataset2.length === 0) {
  24. return { added: [], removed: [], changed: {} };
  25. }
  26. if (dataset1.length === 0) {
  27. return { added: dataset2, removed: [], changed: {} };
  28. }
  29. if (dataset2.length === 0) {
  30. return { added: [], removed: dataset1, changed: {} };
  31. }
  32. const diff = { added: [], removed: [], changed: {} };
  33. // Function to read a log file and return its content
  34. async function readLogFile(filePath) {
  35. try {
  36. const response = await fetch(filePath);
  37. if (!response.ok) {
  38. throw new Error(`Failed to fetch ${filePath}: ${response.status}`);
  39. }
  40. return await response.text();
  41. } catch (error) {
  42. console.error(`Error reading ${filePath}:`, error);
  43. return ""; // Return empty string on error to avoid crashing
  44. }
  45. }
  46. // Read log file contents
  47. const logFiles1 = await Promise.all(dataset1.map(readLogFile));
  48. const logFiles2 = await Promise.all(dataset2.map(readLogFile));
  49. // Find added files
  50. for (const fileContent of logFiles2) {
  51. if (!logFiles1.includes(fileContent)) {
  52. diff.added.push(fileContent);
  53. }
  54. }
  55. // Find removed files
  56. for (const fileContent of logFiles1) {
  57. if (!logFiles2.includes(fileContent)) {
  58. diff.removed.push(fileContent);
  59. }
  60. }
  61. // Find changed files
  62. for (let i = 0; i < Math.min(logFiles1.length, logFiles2.length); i++) {
  63. const file1 = logFiles1[i];
  64. const file2 = logFiles2[i];
  65. if (file1 !== file2) {
  66. diff.changed[dataset1[i]] = {
  67. added: [],
  68. removed: []
  69. };
  70. // Split the files into lines
  71. const lines1 = file1.split('\n');
  72. const lines2 = file2.split('\n');
  73. // Find added lines in file2
  74. for (const line of lines2) {
  75. if (!lines1.includes(line)) {
  76. diff.changed[dataset1[i]].added.push(line);
  77. }
  78. }
  79. // Find removed lines in file1
  80. for (const line of lines1) {
  81. if (!lines2.includes(line)) {
  82. diff.changed[dataset1[i]].removed.push(line);
  83. }
  84. }
  85. }
  86. }
  87. return diff;
  88. }

Add your comment