x-fidelity 3.10.0 → 3.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/.github/CODEOWNERS +15 -0
  2. package/.xfi-config.json +19 -1
  3. package/CHANGELOG.md +49 -0
  4. package/dist/core/cli.js +2 -1
  5. package/dist/core/engine/analyzer.js +3 -1
  6. package/dist/demoConfig/node-fullstack.json +15 -1
  7. package/dist/demoConfig/rules/newSdkFeatureNotAdoped-global-rule.json +2 -2
  8. package/dist/demoConfig/rules/noDatabases-iterative-rule.json +5 -1
  9. package/dist/demoConfig/rules/sensitiveLogging-iterative-rule.json +1 -3
  10. package/dist/facts/repoFilesystemFacts.js +7 -7
  11. package/dist/index.js +26 -0
  12. package/dist/index.test.js +1 -0
  13. package/dist/notifications/index.d.ts +3 -0
  14. package/dist/notifications/index.js +120 -0
  15. package/dist/notifications/notificationManager.d.ts +19 -0
  16. package/dist/notifications/notificationManager.js +344 -0
  17. package/dist/notifications/notifications.test.d.ts +1 -0
  18. package/dist/notifications/notifications.test.js +100 -0
  19. package/dist/notifications/providers/emailProvider.d.ts +17 -0
  20. package/dist/notifications/providers/emailProvider.js +94 -0
  21. package/dist/notifications/providers/slackProvider.d.ts +11 -0
  22. package/dist/notifications/providers/slackProvider.js +67 -0
  23. package/dist/notifications/providers/teamsProvider.d.ts +10 -0
  24. package/dist/notifications/providers/teamsProvider.js +95 -0
  25. package/dist/types/notificationTypes.d.ts +22 -0
  26. package/dist/types/notificationTypes.js +2 -0
  27. package/dist/types/typeDefs.d.ts +11 -0
  28. package/dist/utils/jsonSchemas.js +53 -0
  29. package/dist/xfidelity +26 -0
  30. package/package.json +4 -1
  31. package/src/core/cli.ts +2 -1
  32. package/src/core/engine/analyzer.ts +3 -1
  33. package/src/demoConfig/node-fullstack.json +15 -1
  34. package/src/demoConfig/rules/newSdkFeatureNotAdoped-global-rule.json +2 -2
  35. package/src/demoConfig/rules/noDatabases-iterative-rule.json +5 -1
  36. package/src/demoConfig/rules/sensitiveLogging-iterative-rule.json +1 -3
  37. package/src/facts/repoFilesystemFacts.ts +7 -7
  38. package/src/index.test.ts +1 -0
  39. package/src/index.ts +35 -1
  40. package/src/notifications/index.ts +119 -0
  41. package/src/notifications/notificationManager.ts +381 -0
  42. package/src/notifications/notifications.test.ts +116 -0
  43. package/src/notifications/providers/emailProvider.ts +98 -0
  44. package/src/notifications/providers/slackProvider.ts +63 -0
  45. package/src/notifications/providers/teamsProvider.ts +89 -0
  46. package/src/types/notificationTypes.ts +25 -0
  47. package/src/types/typeDefs.ts +11 -0
  48. package/src/utils/jsonSchemas.ts +53 -0
@@ -0,0 +1,15 @@
1
+ # Default owners for everything in the repo
2
+ * @zotoio/core-team
3
+
4
+ # Specific ownership rules
5
+ /src/core/ @zotoio/core-team
6
+ /src/facts/ @zotoio/rules-team
7
+ /src/operators/ @zotoio/rules-team
8
+ /src/plugins/ @zotoio/plugin-team
9
+ /src/server/ @zotoio/api-team
10
+ /src/types/ @zotoio/core-team
11
+ /src/utils/ @zotoio/core-team
12
+ /website/ @zotoio/docs-team
13
+
14
+ # Notification test team
15
+ /src/notifications/ @zotoio/notification-team
package/.xfi-config.json CHANGED
@@ -34,5 +34,23 @@
34
34
  ],
35
35
  "additionalFacts": ["customFact"],
36
36
  "additionalOperators": ["customOperator"],
37
- "additionalPlugins": ["xfiPluginSimpleExample"]
37
+ "additionalPlugins": ["xfiPluginSimpleExample"],
38
+ "notifications": {
39
+ "recipients": {
40
+ "email": [
41
+ "io@zoto.io"
42
+ ],
43
+ "slack": [
44
+ "U123456",
45
+ "U789012"
46
+ ],
47
+ "teams": [
48
+ "user1@example.com",
49
+ "user2@example.com"
50
+ ]
51
+ },
52
+ "codeOwners": true,
53
+ "notifyOnSuccess": false,
54
+ "notifyOnFailure": true
55
+ }
38
56
  }
package/CHANGELOG.md CHANGED
@@ -1,3 +1,52 @@
1
+ # [3.12.0](https://github.com/zotoio/x-fidelity/compare/v3.11.0...v3.12.0) (2025-03-10)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * add HTML email support with plain text fallback ([ec0f252](https://github.com/zotoio/x-fidelity/commit/ec0f2529d4f05ca570cd4b11db07ede2d4d21113))
7
+ * correct string interpolation syntax in notification template ([092b64d](https://github.com/zotoio/x-fidelity/commit/092b64d3f614d505c7a792bd7a559e10aed3192c))
8
+ * correct template literal syntax in notification manager ([f5720c2](https://github.com/zotoio/x-fidelity/commit/f5720c230051d8e38bbc95024a02d7298d2299f5))
9
+ * escape nested template literals in notification template ([4feb497](https://github.com/zotoio/x-fidelity/commit/4feb497255615b93655ba7bba8729e55b56b4016))
10
+ * **notify:** email formatting fixes ([06e80a8](https://github.com/zotoio/x-fidelity/commit/06e80a81bab30c1ab03d202d0649306fe331debd))
11
+ * remove duplicate fileIssues declaration in notification manager ([d5678a1](https://github.com/zotoio/x-fidelity/commit/d5678a1620fae5b78ee475b95ee2248051d17c8f))
12
+ * remove local directory paths from notification file links ([d55da96](https://github.com/zotoio/x-fidelity/commit/d55da9637477b0b14acb45d99a8a1a4b9e661c30))
13
+ * remove trailing comma in .xfi-config.json ([41c7368](https://github.com/zotoio/x-fidelity/commit/41c7368a7e7ba8b989f3d8bf2fc0ce9e3e4d1183))
14
+ * replace nested template literals with string concatenation ([89712cf](https://github.com/zotoio/x-fidelity/commit/89712cf77e231863e5bcb6c214fedf5b9f0d1f3f))
15
+ * resolve TypeScript errors with yaml imports and variable declarations ([af2ea8e](https://github.com/zotoio/x-fidelity/commit/af2ea8ee80d48b9dddb1f586d61285518aee0b1c))
16
+ * use repoPath from results metadata instead of undefined variable ([36b42fa](https://github.com/zotoio/x-fidelity/commit/36b42fae14895ba147955806efcf3cc94ec1d306))
17
+
18
+
19
+ ### Features
20
+
21
+ * add failed rule names to notification template for each file ([d09d019](https://github.com/zotoio/x-fidelity/commit/d09d019bc1f9eff2f5c375185aec7f8f54fb7f96))
22
+ * add severity levels to failed rules in notification output ([a90ffe7](https://github.com/zotoio/x-fidelity/commit/a90ffe724c440f60f1f1c59be0ec3074316c28c1))
23
+ * add YAML results attachment to email notifications ([e2671b4](https://github.com/zotoio/x-fidelity/commit/e2671b46081168b1ac911f595a05f3301f8df780))
24
+ * enhance notification formatting with HTML and color-coded severity ([f034a85](https://github.com/zotoio/x-fidelity/commit/f034a858c0da629d7fc134818babcbf28fa7b03e))
25
+ * enhance notification templates with clickable links and emojis ([3afbd5d](https://github.com/zotoio/x-fidelity/commit/3afbd5db68cfbb604407e791f58c184961e7dc78))
26
+ * support GitHub Enterprise links in notifications ([092867f](https://github.com/zotoio/x-fidelity/commit/092867fd3948e1bfcc10e8ecfc312686f37c9afa))
27
+ * use git commands to extract GitHub repo details ([8f35471](https://github.com/zotoio/x-fidelity/commit/8f3547145a612444b9320c0b5d1b75529edfaa4a))
28
+
29
+ # [3.11.0](https://github.com/zotoio/x-fidelity/compare/v3.10.0...v3.11.0) (2025-03-09)
30
+
31
+
32
+ ### Bug Fixes
33
+
34
+ * Remove duplicate import statement in notifications test ([f5c6468](https://github.com/zotoio/x-fidelity/commit/f5c6468063c1575610cd4b54aad84b97d4884437))
35
+ * **results:** fix missing filesystem match details ([bc62faf](https://github.com/zotoio/x-fidelity/commit/bc62faff20e69fa6977e1ceee1bc22ad578cf2ba))
36
+ * update NotificationManager mock to properly handle registerProvider ([6102837](https://github.com/zotoio/x-fidelity/commit/6102837f206938500885faf33560a91235a41885))
37
+
38
+
39
+ ### Features
40
+
41
+ * add CODEOWNERS and notification test config ([5dc2904](https://github.com/zotoio/x-fidelity/commit/5dc29047d86f33b27fc9603077884b4df3f37330))
42
+ * add debug logging for notification flow ([0e6af6b](https://github.com/zotoio/x-fidelity/commit/0e6af6b1583636935561f85a33c0bbea830905a5))
43
+ * add detailed debug logging for email notifications ([18d929b](https://github.com/zotoio/x-fidelity/commit/18d929b3cc49b538c6ea3330d51d2670b090f7ba))
44
+ * add email notification configuration to node-fullstack archetype ([424c5a0](https://github.com/zotoio/x-fidelity/commit/424c5a007c1b9eabeaffbca375cac131142ff7c9))
45
+ * add notification system with email, slack and teams providers ([95d4ade](https://github.com/zotoio/x-fidelity/commit/95d4ade7de8db30c1592087ffa8dd78845c4ee47))
46
+ * add notification team to CODEOWNERS file ([edb648e](https://github.com/zotoio/x-fidelity/commit/edb648e7378239ae7b6f672b9ce73c97e820a82a))
47
+ * add package version to XFI_RESULT metadata ([1ee061a](https://github.com/zotoio/x-fidelity/commit/1ee061a971bbf63d18014f529a3353d4efb63482))
48
+ * add xfiVersion field to ResultMetadata interface ([e59b187](https://github.com/zotoio/x-fidelity/commit/e59b18725b98781f547e58c5d9581d2ad7d5949f))
49
+
1
50
  # [3.10.0](https://github.com/zotoio/x-fidelity/compare/v3.9.1...v3.10.0) (2025-03-08)
2
51
 
3
52
 
package/dist/core/cli.js CHANGED
@@ -35,7 +35,8 @@ function initCLI() {
35
35
  info: (obj) => console.log(JSON.stringify(obj)),
36
36
  error: (obj) => console.error(JSON.stringify(obj)),
37
37
  warn: (obj) => console.warn(JSON.stringify(obj)),
38
- debug: (obj) => console.debug(JSON.stringify(obj))
38
+ debug: (obj) => console.debug(JSON.stringify(obj)),
39
+ trace: (obj) => console.trace(JSON.stringify(obj))
39
40
  };
40
41
  global.logger = fallbackLogger;
41
42
  }
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.analyzeCodebase = analyzeCodebase;
13
13
  const logger_1 = require("../../utils/logger");
14
14
  const configManager_1 = require("../configManager");
15
+ const package_json_1 = require("../../../package.json");
15
16
  const openaiUtils_1 = require("../../utils/openaiUtils");
16
17
  const telemetry_1 = require("../../utils/telemetry");
17
18
  const repoFilesystemFacts_1 = require("../../facts/repoFilesystemFacts");
@@ -172,7 +173,8 @@ function analyzeCodebase(params) {
172
173
  exemptCount: exemptCount,
173
174
  options: cli_1.options,
174
175
  repoPath,
175
- repoUrl
176
+ repoUrl,
177
+ xfiVersion: package_json_1.version
176
178
  }
177
179
  };
178
180
  // Send telemetry for analysis end
@@ -59,6 +59,20 @@
59
59
  ".*\\.(ts|tsx|js|jsx)$",
60
60
  ".*\\/xfiTestMatch\\.json$",
61
61
  ".*\\/README\\.md$"
62
- ]
62
+ ],
63
+ "notifications": {
64
+ "enabled": true,
65
+ "providers": ["email"],
66
+ "recipients": {
67
+ "email": ["io@zoto.io"]
68
+ },
69
+ "codeOwners": true,
70
+ "notifyOnSuccess": true,
71
+ "notifyOnFailure": true,
72
+ "customTemplates": {
73
+ "success": "All checks passed successfully! 🎉\n\nArchetype: ${archetype}\nFiles analyzed: ${fileCount}\nExecution time: ${executionTime}s",
74
+ "failure": "Issues found in codebase:\n\nArchetype: ${archetype}\nTotal issues: ${totalIssues}\n- Warnings: ${warningCount}\n- Errors: ${errorCount}\n- Fatalities: ${fatalityCount}\n\nAffected files:\n${affectedFiles}"
75
+ }
76
+ }
63
77
  }
64
78
  }
@@ -12,10 +12,10 @@
12
12
  "fact": "globalFileAnalysis",
13
13
  "params": {
14
14
  "newPatterns": [
15
- "logger\\.info\\("
15
+ "const plugin: XFiPlugin = {"
16
16
  ],
17
17
  "legacyPatterns": [
18
- "logger\\.debug\\("
18
+ "import {.*FactDefn.*} from '\\.\\./types/typeDefs';"
19
19
  ],
20
20
  "fileFilter": ".*\\.(ts|js)$",
21
21
  "resultFact": "sdkUsageAnalysis"
@@ -11,7 +11,11 @@
11
11
  {
12
12
  "fact": "repoFileAnalysis",
13
13
  "params": {
14
- "checkPattern": ["oracle", "mysql", "mssql", "postgres", "sqlite", "mongodb", "cassandra", "redis", "rethinkdb", "neo4j", "couchdb"],
14
+ "checkPattern": [
15
+ "[\\s\\'\\\"\\.](oracle)[\\s\\'\\\"\\.]",
16
+ "[\\s\\'\\\"\\.](postgres)[\\s\\'\\\"\\.]",
17
+ "[\\s\\'\\\"\\.](mongodb)[\\s\\'\\\"\\.]"
18
+ ],
15
19
  "resultFact": "fileResultsDB"
16
20
  },
17
21
  "operator": "fileContains",
@@ -23,11 +23,9 @@
23
23
  "checkPattern": [
24
24
  "(api[_-]?key|auth[_-]?token|access[_-]?token|secret[_-]?key)",
25
25
  "(aws[_-]?access[_-]?key[_-]?id|aws[_-]?secret[_-]?access[_-]?key)",
26
- "(password|passphrase)",
27
26
  "(private[_-]?key|ssh[_-]?key)",
28
27
  "(oauth[_-]?token|jwt[_-]?token)",
29
- "db[_-]?password",
30
- "(declare)"
28
+ "db[_-]?password"
31
29
  ],
32
30
  "resultFact": "fileResults"
33
31
  },
@@ -130,11 +130,11 @@ function repoFileAnalysis(params, almanac) {
130
130
  return result;
131
131
  }
132
132
  //if there is already a resultFact for this file, we need to append
133
- // const existingResult = almanac.factValue(params.resultFact);
134
- // if (Object.keys(existingResult).includes('result')) {
135
- // logger.error(JSON.stringify(existingResult));
136
- // result.result = existingResult.result;
137
- // }
133
+ const existingResult = almanac.factValue(params.resultFact);
134
+ if (Object.keys(existingResult).includes('result')) {
135
+ logger_1.logger.error(JSON.stringify(existingResult));
136
+ result.result = existingResult.result;
137
+ }
138
138
  const analysis = [];
139
139
  const lines = fileContent.split('\n');
140
140
  logger_1.logger.debug({ lineCount: lines.length }, 'Processing file lines');
@@ -196,8 +196,8 @@ function repoFileAnalysis(params, almanac) {
196
196
  result.result[resultLength + i] = fileAnalysis[i];
197
197
  }
198
198
  }
199
- //result.result. = analysis;
200
- almanac.addRuntimeFact(params.resultFact, result);
199
+ result.result = analysis;
200
+ almanac.addRuntimeFact(params.resultFact, result.result);
201
201
  return result;
202
202
  // testing match on 'oracle'
203
203
  // testing match on 'declare'
package/dist/index.js CHANGED
@@ -62,6 +62,7 @@ const prettyjson_1 = __importDefault(require("prettyjson"));
62
62
  const analyzer_1 = require("./core/engine/analyzer");
63
63
  const configServer_1 = require("./server/configServer");
64
64
  const telemetry_1 = require("./utils/telemetry");
65
+ const notifications_1 = require("./notifications");
65
66
  // Function to handle errors and send telemetry
66
67
  const handleError = (error) => __awaiter(void 0, void 0, void 0, function* () {
67
68
  yield (0, telemetry_1.sendTelemetry)({
@@ -85,6 +86,16 @@ logger_1.logger.debug({ options: cli_1.options }, 'Startup options');
85
86
  function main() {
86
87
  return __awaiter(this, void 0, void 0, function* () {
87
88
  try {
89
+ // Initialize notification system
90
+ const notificationConfig = {
91
+ enabled: process.env.NOTIFICATIONS_ENABLED === 'true',
92
+ providers: (process.env.NOTIFICATION_PROVIDERS || '').split(',').filter(Boolean),
93
+ codeOwnersPath: process.env.CODEOWNERS_PATH || '.github/CODEOWNERS',
94
+ codeOwnersEnabled: process.env.CODEOWNERS_ENABLED !== 'false', // Default to true
95
+ notifyOnSuccess: process.env.NOTIFY_ON_SUCCESS === 'true',
96
+ notifyOnFailure: process.env.NOTIFY_ON_FAILURE !== 'false', // Default to true
97
+ };
98
+ const notificationManager = yield (0, notifications_1.initializeNotifications)(notificationConfig);
88
99
  if (cli_1.options.examine && process.env.NODE_ENV !== 'test') {
89
100
  const { validateArchetypeConfig } = yield Promise.resolve().then(() => __importStar(require('./core/validateConfig')));
90
101
  validateArchetypeConfig();
@@ -103,6 +114,21 @@ function main() {
103
114
  });
104
115
  const resultString = JSON.stringify(resultMetadata);
105
116
  const prettyResult = prettyjson_1.default.render(resultMetadata.XFI_RESULT);
117
+ // Add debug logging before notification check
118
+ logger_1.logger.debug({
119
+ notificationsEnabled: process.env.NOTIFICATIONS_ENABLED,
120
+ notificationConfig: notificationConfig,
121
+ hasNotificationManager: !!notificationManager
122
+ }, 'Checking notification status');
123
+ // Send notifications if enabled
124
+ if (notificationConfig.enabled) {
125
+ logger_1.logger.debug('Notifications are enabled, preparing to send report');
126
+ logger_1.logger.debug({
127
+ affectedFilesCount: resultMetadata.XFI_RESULT.issueDetails.length
128
+ }, 'Preparing notification data');
129
+ // Pass the repo config to the notification manager
130
+ yield notificationManager.sendReport(resultMetadata);
131
+ }
106
132
  // if results are found, there were issues found in the codebase
107
133
  if (resultMetadata.XFI_RESULT.totalIssues > 0) {
108
134
  logger_1.logger.warn(`WARNING: lo-fi attributes detected in codebase. ${resultMetadata.XFI_RESULT.warningCount} are warnings, ${resultMetadata.XFI_RESULT.fatalityCount} are fatal.`);
@@ -56,6 +56,7 @@ jest.mock('./utils/logger', () => ({
56
56
  warn: jest.fn(),
57
57
  error: jest.fn(),
58
58
  debug: jest.fn(),
59
+ trace: jest.fn()
59
60
  },
60
61
  setLogPrefix: jest.fn(),
61
62
  setLogLevel: jest.fn(),
@@ -0,0 +1,3 @@
1
+ import { NotificationManager } from './notificationManager';
2
+ import { NotificationConfig } from '../types/notificationTypes';
3
+ export declare function initializeNotifications(config: NotificationConfig): Promise<NotificationManager>;
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.initializeNotifications = initializeNotifications;
13
+ const notificationManager_1 = require("./notificationManager");
14
+ const emailProvider_1 = require("./providers/emailProvider");
15
+ const slackProvider_1 = require("./providers/slackProvider");
16
+ const teamsProvider_1 = require("./providers/teamsProvider");
17
+ const logger_1 = require("../utils/logger");
18
+ function initializeNotifications(config) {
19
+ return __awaiter(this, void 0, void 0, function* () {
20
+ if (!config.enabled) {
21
+ logger_1.logger.info('Notifications are disabled');
22
+ return notificationManager_1.NotificationManager.getInstance(config);
23
+ }
24
+ const notificationManager = notificationManager_1.NotificationManager.getInstance(config);
25
+ // Register configured providers
26
+ for (const providerName of config.providers) {
27
+ switch (providerName) {
28
+ case 'email':
29
+ const emailConfig = loadEmailConfig();
30
+ if (emailConfig) {
31
+ notificationManager.registerProvider(new emailProvider_1.EmailProvider(emailConfig));
32
+ }
33
+ break;
34
+ case 'slack':
35
+ const slackConfig = loadSlackConfig();
36
+ if (slackConfig) {
37
+ notificationManager.registerProvider(new slackProvider_1.SlackProvider(slackConfig));
38
+ }
39
+ break;
40
+ case 'teams':
41
+ const teamsConfig = loadTeamsConfig();
42
+ if (teamsConfig) {
43
+ notificationManager.registerProvider(new teamsProvider_1.TeamsProvider(teamsConfig));
44
+ }
45
+ break;
46
+ default:
47
+ logger_1.logger.warn(`Unknown notification provider: ${providerName}`);
48
+ }
49
+ }
50
+ return notificationManager;
51
+ });
52
+ }
53
+ function loadEmailConfig() {
54
+ try {
55
+ const config = {
56
+ host: process.env.NOTIFICATION_EMAIL_HOST || '',
57
+ port: parseInt(process.env.NOTIFICATION_EMAIL_PORT || '587'),
58
+ secure: process.env.NOTIFICATION_EMAIL_SECURE === 'true',
59
+ auth: {
60
+ user: process.env.NOTIFICATION_EMAIL_USER || '',
61
+ pass: process.env.NOTIFICATION_EMAIL_PASS || '',
62
+ },
63
+ from: process.env.NOTIFICATION_EMAIL_FROM || 'x-fidelity@noreply.com',
64
+ };
65
+ // Add debug logging
66
+ logger_1.logger.debug({
67
+ emailConfig: Object.assign(Object.assign({}, config), { auth: {
68
+ user: config.auth.user,
69
+ pass: '****' // Mask password
70
+ } })
71
+ }, 'Email configuration loaded');
72
+ // Validate required fields
73
+ if (!config.host || !config.auth.user || !config.auth.pass) {
74
+ logger_1.logger.warn('Missing required email configuration fields', {
75
+ hasHost: !!config.host,
76
+ hasUser: !!config.auth.user,
77
+ hasPass: !!config.auth.pass
78
+ });
79
+ return null;
80
+ }
81
+ return config;
82
+ }
83
+ catch (error) {
84
+ logger_1.logger.error(error, 'Failed to load email configuration');
85
+ return null;
86
+ }
87
+ }
88
+ function loadSlackConfig() {
89
+ try {
90
+ const webhookUrl = process.env.NOTIFICATION_SLACK_WEBHOOK;
91
+ if (!webhookUrl) {
92
+ logger_1.logger.warn('Slack webhook URL not configured');
93
+ return null;
94
+ }
95
+ return {
96
+ webhookUrl,
97
+ channel: process.env.NOTIFICATION_SLACK_CHANNEL,
98
+ };
99
+ }
100
+ catch (error) {
101
+ logger_1.logger.error(error, 'Failed to load Slack configuration');
102
+ return null;
103
+ }
104
+ }
105
+ function loadTeamsConfig() {
106
+ try {
107
+ const webhookUrl = process.env.NOTIFICATION_TEAMS_WEBHOOK;
108
+ if (!webhookUrl) {
109
+ logger_1.logger.warn('Teams webhook URL not configured');
110
+ return null;
111
+ }
112
+ return {
113
+ webhookUrl
114
+ };
115
+ }
116
+ catch (error) {
117
+ logger_1.logger.error(error, 'Failed to load Teams configuration');
118
+ return null;
119
+ }
120
+ }
@@ -0,0 +1,19 @@
1
+ import { ResultMetadata } from '../types/typeDefs';
2
+ import { NotificationProvider, NotificationConfig } from '../types/notificationTypes';
3
+ export declare class NotificationManager {
4
+ private static instance;
5
+ private providers;
6
+ private config;
7
+ private codeOwners;
8
+ private constructor();
9
+ static getInstance(config: NotificationConfig): NotificationManager;
10
+ registerProvider(provider: NotificationProvider): void;
11
+ sendReport(results: ResultMetadata): Promise<void>;
12
+ private mergeNotificationConfig;
13
+ private getRecipients;
14
+ private loadCodeOwners;
15
+ private getCodeOwnersForFiles;
16
+ private matchesGlob;
17
+ private getAffectedFiles;
18
+ private generateReportContent;
19
+ }