You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

167 lines
4.5 KiB
JavaScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* Событие изменения конфигурации.
*/
class ConfigChangeEvent extends Event {
constructor(type, name, value) {
super(type);
this.name = name;
this.value = value;
}
}
/**
* Конфигурация.
*
* При любом изменении конфигурации вызывается событие {@link ConfigChangeEvent}
* с типом changed, а так же changed.путь.
*/
class Config extends EventEmitter {
#data;
constructor() {
super();
this.#data = {};
}
/**
* Получить значение из конфигурации.
*
* @example config.get('group', 'subgroup', 'name')
*/
get(...name) {
const lastName = name.pop();
let obj = this.#data;
for (const i of name) {
obj = (i in obj) ? obj[i] : {};
if (typeof obj !== 'object' || !obj)
return;
}
return obj[lastName];
}
/**
* Записать значение в конфигурацию. Последний аргумент - значение.
*
* @example config.set('group', 'subgroup', 'name', value)
*/
set(...name) {
const value = name.pop();
const lastName = name.pop();
let obj = this.#data;
for (const i of name) {
if (!(i in obj) || obj[i] === null)
obj[i] = {}
obj = obj[i];
if (typeof obj !== 'object')
return;
}
obj[lastName] = value;
name.push(lastName);
let path = 'changed';
this.dispatchEvent(new ConfigChangeEvent(path, name, value));
for (const i of name) {
path += '.' + i;
this.dispatchEvent(new ConfigChangeEvent(path, name, value));
}
}
/**
* Удалить значение из конфигурации
*/
delete(...name) {
const lastName = name.pop();
let obj = this.#data;
for (const i of name) {
if (!(i in obj) || obj[i] === null)
obj[i] = {}
obj = obj[i];
if (typeof obj !== 'object')
return;
}
delete obj[lastName];
let path = 'changed';
this.dispatchEvent(new ConfigChangeEvent(path, name, undefined));
for (const i of name) {
path += '.' + i;
this.dispatchEvent(new ConfigChangeEvent(path, name, undefined));
}
}
/**
* Зкспорт конфигурации в json строку.
* @returns {string}
*/
toJson() {
return JSON.stringify(this.#data);
}
/**
* Импорт конфигурации из json строки
* @param {string} data
*/
fromJson(data) {
this.#data = JSON.parse(data);
this.#dispatchRecurse(this.#data, 'changed');
}
#dispatchRecurse(obj, path) {
this.dispatchEvent(new ConfigChangeEvent(path, [], this.#data));
if (typeof obj !== 'object' || !obj) return;
for (const i in obj) if (obj.hasOwnProperty(i)) {
this.#dispatchRecurse(obj[i], path + '.' + i);
}
}
/**
* Создает прокси-объект для указанной группы.
*
* @example const proxy = config.createProxy('group', 'subgroup');
* proxy.name = value; // то же, что и config.set('group', 'subgroup', 'name', value);
*/
createProxy(...names) {
const self = this;
return new Proxy(Object.create(null), {
get(t, name, r) {
return self.get(...names, name);
},
set(t, name, value, r) {
self.set(...names, name, value);
return true;
}
});
}
/**
* Создает прокси для настроек соединения.
* @see {@link Config.createProxy}
* @param {string} connName Имя соединения
*/
getConnection(connName) {
return this.createProxy('connections', connName);
}
/**
* Создает прокси для настроек устройства.
* @see {@link Config.createProxy}
* @param {string} devId ID устройства
*/
getDevice(devId) {
return this.createProxy('devices', devId);
}
/**
* Глобальные настройки хаба.
* @see {@link Config.createProxy}
*/
get global() {
return this.createProxy('hub');
}
}