diff --git a/lib/util/settings.js b/lib/util/settings.js index a4e1911e..be6d752c 100644 --- a/lib/util/settings.js +++ b/lib/util/settings.js @@ -325,15 +325,27 @@ function write() { } } - if (typeof actual.devices === 'string') { - yaml.writeIfChanged(data.joinPath(actual.devices), settings.devices); - toWrite.devices = actual.devices; - } + // Write devices/groups to separate file if required. + const writeDevicesOrGroups = (type) => { + if (typeof actual[type] === 'string' || Array.isArray(actual[type])) { + const fileToWrite = Array.isArray(actual[type]) ? actual[type][0] : actual[type]; + const content = objectAssignDeep.noMutate(settings[type]); - if (typeof actual.groups === 'string') { - yaml.writeIfChanged(data.joinPath(actual.groups), settings.groups); - toWrite.groups = actual.groups; - } + // If an array, only write to first file and only devices which are not in the other files. + if (Array.isArray(actual[type])) { + actual[type].filter((f, i) => i !== 0) + .map((f) => yaml.readIfExists(data.joinPath(f), {})) + .map((c) => Object.keys(c)) + .forEach((k) => delete content[k]); + } + + yaml.writeIfChanged(data.joinPath(fileToWrite), content); + toWrite[type] = actual[type]; + } + }; + + writeDevicesOrGroups('devices'); + writeDevicesOrGroups('groups'); yaml.writeIfChanged(file, toWrite); @@ -428,16 +440,20 @@ function read() { s.advanced.network_key = interpetValue(s.advanced.network_key); } - // Read devices/groups configuration from separate file. - if (typeof s.devices === 'string') { - const file = data.joinPath(s.devices); - s.devices = yaml.readIfExists(file) || {}; - } + // Read devices/groups configuration from separate file if specified. + const readDevicesOrGroups = (type) => { + if (typeof s[type] === 'string' || Array.isArray(s[type])) { + const files = Array.isArray(s[type]) ? s[type] : [s[type]]; + s[type] = {}; + for (const file of files) { + const content = yaml.readIfExists(data.joinPath(file), {}); + s[type] = objectAssignDeep.noMutate(s[type], content); + } + } + }; - if (typeof s.groups === 'string') { - const file = data.joinPath(s.groups); - s.groups = yaml.readIfExists(file) || {}; - } + readDevicesOrGroups('devices'); + readDevicesOrGroups('groups'); return s; } diff --git a/lib/util/yaml.js b/lib/util/yaml.js index 7b1cf038..c7deeef6 100644 --- a/lib/util/yaml.js +++ b/lib/util/yaml.js @@ -14,8 +14,8 @@ function read(file) { } } -function readIfExists(file) { - return fs.existsSync(file) ? read(file) : null; +function readIfExists(file, default_=null) { + return fs.existsSync(file) ? read(file) : default_; } function writeIfChanged(file, content) { diff --git a/test/settings.test.js b/test/settings.test.js index d9367182..97240fdb 100644 --- a/test/settings.test.js +++ b/test/settings.test.js @@ -6,6 +6,7 @@ const settings = require('../lib/util/settings.js'); const fs = require('fs'); const configurationFile = data.joinPath('configuration.yaml'); const devicesFile = data.joinPath('devices.yaml'); +const devicesFile2 = data.joinPath('devices2.yaml'); const groupsFile = data.joinPath('groups.yaml'); const secretFile = data.joinPath('secret.yaml'); const yaml = require('js-yaml'); @@ -197,6 +198,32 @@ describe('Settings', () => { expect(device).toStrictEqual(expected); }); + it('Should read devices form 2 separate files', () => { + const contentConfiguration = { + devices: ['devices.yaml', 'devices2.yaml'] + }; + + const contentDevices = { + '0x12345678': { + friendly_name: '0x12345678', + retain: false, + }, + }; + + const contentDevices2 = { + '0x87654321': { + friendly_name: '0x87654321', + retain: false, + }, + }; + + write(configurationFile, contentConfiguration); + write(devicesFile, contentDevices); + write(devicesFile2, contentDevices2); + expect(settings.getDevice('0x12345678').friendly_name).toStrictEqual('0x12345678'); + expect(settings.getDevice('0x87654321').friendly_name).toStrictEqual('0x87654321'); + }); + it('Should add devices to a separate file', () => { const contentConfiguration = { devices: 'devices.yaml', @@ -229,6 +256,47 @@ describe('Settings', () => { expect(read(devicesFile)).toStrictEqual(expected); }); + it('Should add devices for first file when using 2 separates file', () => { + const contentConfiguration = { + devices: ['devices.yaml', 'devices2.yaml'] + }; + + const contentDevices = { + '0x12345678': { + friendly_name: '0x12345678', + retain: false, + }, + }; + + const contentDevices2 = { + '0x87654321': { + friendly_name: '0x87654321', + retain: false, + }, + }; + + write(configurationFile, contentConfiguration); + write(devicesFile, contentDevices); + write(devicesFile2, contentDevices2); + + settings.addDevice('0x1234'); + + expect(read(configurationFile)).toStrictEqual({devices: ['devices.yaml', 'devices2.yaml']}); + + const expected = { + '0x12345678': { + friendly_name: '0x12345678', + retain: false, + }, + '0x1234': { + friendly_name: '0x1234', + }, + }; + + expect(read(devicesFile)).toStrictEqual(expected); + expect(read(devicesFile2)).toStrictEqual(contentDevices2); + }); + it('Should add devices to a separate file if devices.yaml doesnt exist', () => { const contentConfiguration = { devices: 'devices.yaml',