Rewrite to allow for multiple, independent stores.
This commit is contained in:
parent
1bcdb09b54
commit
cc3a5054e5
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tp/tp-store",
|
||||
"version": "1.1.2",
|
||||
"version": "2.0.0",
|
||||
"description": "",
|
||||
"main": "tp-store.js",
|
||||
"scripts": {
|
||||
|
142
store.js
142
store.js
@ -1,22 +1,23 @@
|
||||
/**
|
||||
@license
|
||||
Copyright (c) 2022 trading_peter
|
||||
Copyright (c) 2025 trading_peter
|
||||
This program is available under Apache License Version 2.0
|
||||
*/
|
||||
|
||||
const data = new Map();
|
||||
const instancesPerKey = new Map();
|
||||
export class Store {
|
||||
constructor() {
|
||||
this._data = new Map();
|
||||
this._instancesPerKey = new Map();
|
||||
}
|
||||
|
||||
/**
|
||||
* # Store
|
||||
*
|
||||
* A simple key value store.
|
||||
/**
|
||||
* Subscribe instance properties to store changes
|
||||
* @param {Object} instance - Instance to subscribe
|
||||
* @param {string|Array<string|Object>} keys - Keys to subscribe to
|
||||
*/
|
||||
export const Store = function(superClass) {
|
||||
return class extends superClass {
|
||||
storeSubscribe(keys) {
|
||||
if (Array.isArray(keys) === false) {
|
||||
keys = [ keys ];
|
||||
subscribe(instance, keys) {
|
||||
if (!Array.isArray(keys)) {
|
||||
keys = [keys];
|
||||
}
|
||||
|
||||
keys.forEach(key => {
|
||||
@ -25,48 +26,19 @@ export const Store = function(superClass) {
|
||||
targetProperty = key.targetProperty;
|
||||
key = key.key;
|
||||
}
|
||||
this._addInstance(this, key, targetProperty);
|
||||
this._addInstance(instance, key, targetProperty);
|
||||
});
|
||||
}
|
||||
|
||||
storeUpdated(key, newValue, targetProperty) {
|
||||
this[targetProperty || key] = newValue;
|
||||
}
|
||||
/**
|
||||
* 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);
|
||||
|
||||
storeWrite(key, value) {
|
||||
this._writeKey(key, value);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
|
||||
// Clean up all references to this instance.
|
||||
instancesPerKey.forEach((instances, key) => {
|
||||
const remainingInstances = instances.filter(entry => entry.instance !== this);
|
||||
if (remainingInstances.length === 0) {
|
||||
instancesPerKey.delete(key);
|
||||
} else {
|
||||
instancesPerKey.set(key, remainingInstances);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_addInstance(instance, key, targetProperty) {
|
||||
if (instancesPerKey.has(key) === false) {
|
||||
instancesPerKey.set(key, [ { instance, targetProperty } ]);
|
||||
} else {
|
||||
instancesPerKey.get(key).push({ instance, targetProperty });
|
||||
}
|
||||
|
||||
if (data.has(key)) {
|
||||
this._notifyInstance(instance, key, data.get(key), targetProperty);
|
||||
}
|
||||
}
|
||||
|
||||
_writeKey(key, value) {
|
||||
data.set(key, value);
|
||||
|
||||
const instances = instancesPerKey.get(key);
|
||||
const instances = this._instancesPerKey.get(key);
|
||||
if (Array.isArray(instances)) {
|
||||
instances.forEach(entry => {
|
||||
this._notifyInstance(entry.instance, key, value, entry.targetProperty);
|
||||
@ -74,8 +46,76 @@ export const Store = function(superClass) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user