@@ -3,21 +3,63 @@ import path from "path";
33import yaml from "js-yaml" ;
44import { defaultDir } from "../../params.js" ;
55import { readFile } from "../../utils/file.js" ;
6- import { NotificationsConfig , releaseFiles } from "@dappnode/types" ;
6+ import { NotificationsConfig , releaseFiles } from "@dappnode/types" ;
7+ import { merge } from "lodash-es" ;
8+ import { NotificationsPaths } from "./types.js" ;
79
8- export function readNotificationsIfExists ( dir ?: string ) : NotificationsConfig | null {
9- const dirPath = dir || defaultDir ;
10- const notificationsFileName = fs
11- . readdirSync ( dirPath )
12- . find ( file => releaseFiles . notifications . regex . test ( file ) ) ;
10+ /**
11+ * Reads one or multiple notifications YAML files and merges them. Returns null if none exist.
12+ * @param {NotificationsPaths[] } paths - Optional array of directory/file specs.
13+ * @returns {NotificationsConfig | null }
14+ * @throws {Error } Throws if parsing fails or non-YAML format is encountered.
15+ */
16+ export function readNotificationsIfExists (
17+ paths ?: NotificationsPaths [ ]
18+ ) : NotificationsConfig | null {
19+ try {
20+ // Determine list of specs (default single spec if none provided)
21+ const specs = paths && paths . length > 0 ? paths : [ { } ] ;
1322
14- if ( ! notificationsFileName ) return null ;
15- const data = readFile ( path . join ( dirPath , notificationsFileName ) ) ;
23+ // Resolve existing file paths
24+ const filePaths = specs
25+ . map ( spec => {
26+ try {
27+ return findNotificationsPath ( spec ) ;
28+ } catch {
29+ return undefined ;
30+ }
31+ } )
32+ . filter ( ( p ) : p is string => typeof p === "string" ) ;
1633
17- // Parse notifications in try catch block to show a comprehensive error message
18- try {
19- return yaml . load ( data ) ;
34+ if ( filePaths . length === 0 ) return null ;
35+
36+ // Load and validate YAML-only files
37+ const configs = filePaths . map ( fp => {
38+ if ( ! / \. ( y m l | y a m l ) $ / i. test ( fp ) )
39+ throw new Error ( "Only YAML format supported for notifications: " + fp ) ;
40+ const data = readFile ( fp ) ;
41+ const parsed = yaml . load ( data ) ;
42+ if ( ! parsed || typeof parsed === "string" )
43+ throw new Error ( `Could not parse notifications: ${ fp } ` ) ;
44+ return parsed as NotificationsConfig ;
45+ } ) ;
46+
47+ // Merge all configurations
48+ return merge ( { } , ...configs ) ;
2049 } catch ( e ) {
21- throw Error ( `Error parsing notifications: ${ e . message } ` ) ;
50+ throw new Error ( `Error parsing notifications: ${ e . message } ` ) ;
51+ }
52+ }
53+
54+ // Find a notifications file, throws if not found
55+ function findNotificationsPath ( spec ?: NotificationsPaths ) : string {
56+ const dirPath = spec ?. dir || defaultDir ;
57+ if ( spec ?. notificationsFileName ) {
58+ return path . join ( dirPath , spec . notificationsFileName ) ;
2259 }
60+ const files : string [ ] = fs . readdirSync ( dirPath ) ;
61+ const match = files . find ( f => releaseFiles . notifications . regex . test ( f ) ) ;
62+ if ( ! match )
63+ throw new Error ( `No notifications file found in directory ${ dirPath } ` ) ;
64+ return path . join ( dirPath , match ) ;
2365}
0 commit comments