From 9820cfee6d8b9e4c92562c5b5af96591a2d1edf2 Mon Sep 17 00:00:00 2001 From: Julien Finet Date: Wed, 5 Feb 2025 22:31:27 +0100 Subject: [PATCH] feat(state): add support for key chain to get() and set() This permits to support state variables with multiple nested dicts. --- js-lib/src/state.js | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/js-lib/src/state.js b/js-lib/src/state.js index f02dddb..6b207d7 100644 --- a/js-lib/src/state.js +++ b/js-lib/src/state.js @@ -116,14 +116,37 @@ export class State { }); } - async set(key, value) { - // Prevent triggering change when same value is set - if (this._state[key] === value) { + async set(...keyAndValue) { + if (keyAndValue.length < 2) { return; } + const value = keyAndValue.pop(); + const keys = keyAndValue; + let dirty = false; + keys.reduce((child, key, index) => { + if (typeof child !== "object") { + return child; + } + if (index === keys.length - 1) { + // Prevent triggering change when same value is set + if (this._state[key] !== value) { + child[key] = value; // Set the final value + dirty = true; + } + } else { + // Ensure each level exists + child[key] = child[key] ?? (typeof key == "string" ? {} : []); + } + return child[key]; + }, this._state); + + // Prevent triggering if there was an error or if same value is set + if (!dirty) { + return; + } + const key = keys[0]; this._mtime += 1; - this._state[key] = value; this._keyTS[key] = this._mtime; this.dirty(key); await this.flush(); @@ -145,11 +168,14 @@ export class State { await this.flush(); } - get(key) { - if (key === undefined) { - return this._state; - } - return this._state[key]; + /** + * @param {...any} key can be a single key, or a path of keys if each value is a dict + * If no param is given, the entire state is returned. + * @returns The state value identified by the key(s) + * @example get("a", "b", "c") will return state["a"]["b"]["c"] + */ + get(...key) { + return key.reduce((child, key) => child && child[key], this._state); } onChange(fn) {