@constructorfleet/ultimate-govee
Version:
Library for interacting with Govee devices written in Typescript.
206 lines • 6.17 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DeltaMap = void 0;
const rxjs_1 = require("rxjs");
class DeltaMap extends Map {
constructor(itemsOrSettings, settings) {
super();
this.deltaSubject$ = new rxjs_1.ReplaySubject(1);
this.delta$ = this.deltaSubject$.asObservable();
this.publishEmpty = true;
this.publish = true;
this.copyAll = false;
this.clearDelta();
if (itemsOrSettings && Symbol.iterator in Object(itemsOrSettings)) {
this.initializeContent(itemsOrSettings);
this.publishDelta();
}
if (!settings) {
settings = itemsOrSettings;
}
if (settings) {
this.initializeSettings(settings);
}
}
/**
* Process constructor content, can be overriden and extended in subclasses
*/
initializeContent(entries) {
Array.from(entries).forEach((entry) => this.doSet(entry[0], entry[1]));
}
/**
* Process constructor settings, can be overriden and extended in subclasses
*/
initializeSettings(settings) {
this.isUpdated = settings.isModified;
this.publishEmpty = settings.publishEmpty ?? true;
this.copyAll = settings.copyAll ?? false;
}
/**
* Publish modification to delta$ if there are changes or if it is the first time called.
*/
publishDelta() {
if (this.publish &&
(this.added.size > 0 ||
this.modified.size > 0 ||
this.deleted.size > 0 ||
this.publishEmpty)) {
this.deltaSubject$.next(this.getDelta());
this.publishEmpty = false;
this.clearDelta();
}
}
/**
* @returns _true_ if the ObservableMap _delta$_ has subscribers
*/
get observed() {
return this.deltaSubject$.observed;
}
/**
* Pauses and combines all delta updates until _resumeDelta_ is called.
*/
pauseDelta() {
this.publish = false;
}
/**
* Publishes all pending _added_, _modified_ or _deleted_ entries if there are any.
*/
resumeDelta() {
this.publish = true;
this.publishDelta();
}
/**
* Return current value of the delta
*/
getDelta() {
return {
all: this.copyAll ? new Map(this) : this,
added: this.added,
modified: this.modified,
deleted: this.deleted,
};
}
/**
* Clears the current delta without publishing updates to subscribers.
*
* WARNING: This method can mess up publication integrity,
* only use in DeltaMaps without subscriptions.
*/
clearDelta() {
this.added = new Map();
this.deleted = new Map();
this.modified = new Map();
this.existedBeforeDelta = undefined;
}
/**
* Adds or modifies an entry and notifies changes through _delta$_.
*
* If an existing entry is the same according to the _compare_ function, nothing is changed
* @override
*/
set(id, value) {
this.doSet(id, value);
this.publishDelta();
return this;
}
/**
* _set_ delta logic.
* Determines if it is an _add_ or a _modify_ and updates the delta.
* Can be extended and/or overridden in subclasses
*/
doSet(id, value) {
if (this.added.has(id)) {
// already in added, update add
super.set(id, value);
this.added.set(id, value);
}
else {
this.deleted.delete(id);
const prevEntry = this.get(id);
if (prevEntry) {
// existing entry
if (!this.isUpdated || this.isUpdated(value, prevEntry)) {
// modified entry
super.set(id, value);
this.modified.set(id, value);
}
}
else {
// new entry
super.set(id, value);
if (this.existedBeforeDelta?.has(id)) {
this.modified.set(id, value);
}
else {
this.added.set(id, value);
}
}
}
}
/**
* Deletes an entry and notifies deletions through _delta$_ if the entry exists.
* @override
*/
delete(id) {
const deleted = this.doDelete(id);
this.publishDelta();
return deleted;
}
/**
* _delete_ delta logic.
* Determines if it exists and updates the delta.
* Can be extended and/or overridden in subclasses
*/
doDelete(id) {
const deletedItem = this.get(id);
super.delete(id);
if (this.added.has(id)) {
this.added.delete(id);
return true;
}
if (deletedItem) {
if (!this.publish) {
if (!this.existedBeforeDelta) {
this.existedBeforeDelta = new Set();
}
this.existedBeforeDelta.add(id);
}
this.modified.delete(id);
this.deleted.set(id, deletedItem);
return true;
}
return false;
}
/**
* Deletes multiple entries at once and notifies changes through _delta$_.
*/
deleteMultiple(entrieIds) {
Array.from(entrieIds).forEach((entryId) => this.doDelete(entryId));
this.publishDelta();
}
/**
* Clears all entries and notifies deletions through _delta$_.
* @override
*/
clear() {
if (this.deltaSubject$.observed) {
this.clearDelta();
this.forEach((value, key) => this.deleted.set(key, value));
super.clear();
this.publishDelta();
}
else {
super.clear();
}
}
/**
* Clears any remaining entries and completes the delta$ observable
*/
close() {
this.resumeDelta();
this.clear();
this.deltaSubject$.complete();
}
}
exports.DeltaMap = DeltaMap;
//# sourceMappingURL=delta-map.observable.js.map