121 lines
3.0 KiB
JavaScript
121 lines
3.0 KiB
JavaScript
/**
|
|
@license
|
|
Copyright (c) 2025 trading_peter
|
|
This program is available under Apache License Version 2.0
|
|
*/
|
|
|
|
export class Store {
|
|
constructor() {
|
|
this._data = new Map();
|
|
this._instancesPerKey = new Map();
|
|
}
|
|
|
|
/**
|
|
* Subscribe instance properties to store changes
|
|
* @param {Object} instance - Instance to subscribe
|
|
* @param {string|Array<string|Object>} keys - Keys to subscribe to
|
|
*/
|
|
subscribe(instance, keys) {
|
|
if (!Array.isArray(keys)) {
|
|
keys = [keys];
|
|
}
|
|
|
|
keys.forEach(key => {
|
|
let targetProperty;
|
|
if (typeof key === 'object') {
|
|
targetProperty = key.targetProperty;
|
|
key = key.key;
|
|
}
|
|
this._addInstance(instance, key, targetProperty);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Write a value to the store
|
|
* @param {string} key - Key to write to
|
|
* @param {any} value - Value to store
|
|
*/
|
|
write(key, value) {
|
|
this._data.set(key, value);
|
|
|
|
const instances = this._instancesPerKey.get(key);
|
|
if (Array.isArray(instances)) {
|
|
instances.forEach(entry => {
|
|
this._notifyInstance(entry.instance, key, value, entry.targetProperty);
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Read a value from the store
|
|
* @param {string} key - Key to read
|
|
* @returns {any} Stored value
|
|
*/
|
|
read(key) {
|
|
return this._data.get(key);
|
|
}
|
|
|
|
/**
|
|
* Unsubscribe an instance from all store changes
|
|
* @param {Object} instance - Instance to unsubscribe
|
|
*/
|
|
unsubscribe(instance) {
|
|
this._instancesPerKey.forEach((instances, key) => {
|
|
const remainingInstances = instances.filter(entry => entry.instance !== instance);
|
|
if (remainingInstances.length === 0) {
|
|
this._instancesPerKey.delete(key);
|
|
} else {
|
|
this._instancesPerKey.set(key, remainingInstances);
|
|
}
|
|
});
|
|
}
|
|
|
|
_addInstance(instance, key, targetProperty) {
|
|
if (!this._instancesPerKey.has(key)) {
|
|
this._instancesPerKey.set(key, [{ instance, targetProperty }]);
|
|
} else {
|
|
this._instancesPerKey.get(key).push({ instance, targetProperty });
|
|
}
|
|
|
|
if (this._data.has(key)) {
|
|
this._notifyInstance(instance, key, this._data.get(key), targetProperty);
|
|
}
|
|
}
|
|
|
|
_notifyInstance(instance, key, value, targetProperty) {
|
|
if (instance.storeUpdated) {
|
|
instance.storeUpdated(key, value, targetProperty);
|
|
} else {
|
|
instance[targetProperty || key] = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Backwards compatibility layer for the mixin
|
|
export const StoreSubcriber = function(superClass) {
|
|
return class extends superClass {
|
|
constructor() {
|
|
super();
|
|
this._store = window.defaultStore = window.defaultStore || new Store();
|
|
}
|
|
|
|
storeSubscribe(keys) {
|
|
this._store.subscribe(this, keys);
|
|
}
|
|
|
|
storeWrite(key, value) {
|
|
this._store.write(key, value);
|
|
}
|
|
|
|
disconnectedCallback() {
|
|
if (super.disconnectedCallback) {
|
|
super.disconnectedCallback();
|
|
}
|
|
this._store.unsubscribe(this);
|
|
}
|
|
|
|
storeUpdated(key, newValue, targetProperty) {
|
|
this[targetProperty || key] = newValue;
|
|
}
|
|
};
|
|
}; |