@smplkit/sdk 3.0.84 → 3.0.85
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +152 -163
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +80 -78
- package/dist/index.d.ts +80 -78
- package/dist/index.js +152 -163
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -17486,47 +17486,15 @@ var Config = class {
|
|
|
17486
17486
|
};
|
|
17487
17487
|
|
|
17488
17488
|
// src/config/proxy.ts
|
|
17489
|
-
function _unflattenDotNotation(flat) {
|
|
17490
|
-
const nested = {};
|
|
17491
|
-
for (const [key, value] of Object.entries(flat)) {
|
|
17492
|
-
const parts = key.split(".");
|
|
17493
|
-
let current = nested;
|
|
17494
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
17495
|
-
const part = parts[i];
|
|
17496
|
-
if (current[part] === void 0 || typeof current[part] !== "object" || current[part] === null) {
|
|
17497
|
-
current[part] = {};
|
|
17498
|
-
}
|
|
17499
|
-
current = current[part];
|
|
17500
|
-
}
|
|
17501
|
-
current[parts[parts.length - 1]] = value;
|
|
17502
|
-
}
|
|
17503
|
-
return nested;
|
|
17504
|
-
}
|
|
17505
17489
|
var LiveConfigProxy = class {
|
|
17506
17490
|
/** @internal */
|
|
17507
17491
|
_client;
|
|
17508
17492
|
/** @internal */
|
|
17509
17493
|
_key;
|
|
17510
|
-
|
|
17511
|
-
_model;
|
|
17512
|
-
constructor(client, key, model) {
|
|
17494
|
+
constructor(client, key) {
|
|
17513
17495
|
this._client = client;
|
|
17514
17496
|
this._key = key;
|
|
17515
|
-
|
|
17516
|
-
const ownMethods = /* @__PURE__ */ new Set([
|
|
17517
|
-
"keys",
|
|
17518
|
-
"values",
|
|
17519
|
-
"items",
|
|
17520
|
-
"get",
|
|
17521
|
-
"onChange",
|
|
17522
|
-
"getBool",
|
|
17523
|
-
"getInt",
|
|
17524
|
-
"getFloat",
|
|
17525
|
-
"getString",
|
|
17526
|
-
"getJson",
|
|
17527
|
-
"_currentValues",
|
|
17528
|
-
"_registerItem"
|
|
17529
|
-
]);
|
|
17497
|
+
const ownMethods = /* @__PURE__ */ new Set(["keys", "values", "items", "get", "onChange", "_currentValues"]);
|
|
17530
17498
|
return new Proxy(this, {
|
|
17531
17499
|
get(target, prop, receiver) {
|
|
17532
17500
|
if (typeof prop === "symbol" || prop === "constructor" || prop === "toJSON") {
|
|
@@ -17536,17 +17504,9 @@ var LiveConfigProxy = class {
|
|
|
17536
17504
|
return Reflect.get(target, prop, receiver);
|
|
17537
17505
|
}
|
|
17538
17506
|
const values = target._currentValues();
|
|
17539
|
-
if (target._model) {
|
|
17540
|
-
const nested = _unflattenDotNotation(values);
|
|
17541
|
-
const instance = new target._model(nested);
|
|
17542
|
-
return instance[prop];
|
|
17543
|
-
}
|
|
17544
17507
|
return values[prop];
|
|
17545
17508
|
},
|
|
17546
|
-
set(
|
|
17547
|
-
if (typeof prop === "string" && prop.startsWith("_")) {
|
|
17548
|
-
return Reflect.set(target, prop, value, receiver);
|
|
17549
|
-
}
|
|
17509
|
+
set(_target, prop) {
|
|
17550
17510
|
throw new Error(
|
|
17551
17511
|
`LiveConfigProxy is read-only; cannot set ${JSON.stringify(String(prop))}. Mutate config values via client.manage.config.*`
|
|
17552
17512
|
);
|
|
@@ -17601,74 +17561,6 @@ var LiveConfigProxy = class {
|
|
|
17601
17561
|
const values = this._currentValues();
|
|
17602
17562
|
return key in values ? values[key] : defaultValue;
|
|
17603
17563
|
}
|
|
17604
|
-
// ------------------------------------------------------------------
|
|
17605
|
-
// Typed getters (ADR-037 §2.13)
|
|
17606
|
-
//
|
|
17607
|
-
// Each registers the item (key, type, default, description) on first
|
|
17608
|
-
// call within the process, then returns the resolved value. When the
|
|
17609
|
-
// resolved value cannot be coerced to the getter's type — including
|
|
17610
|
-
// the "not yet set on the server" case — the in-code default is
|
|
17611
|
-
// returned and a structured warning is logged.
|
|
17612
|
-
// ------------------------------------------------------------------
|
|
17613
|
-
/** @internal */
|
|
17614
|
-
_registerItem(itemKey, itemType, defaultValue, description) {
|
|
17615
|
-
this._client._observeItemDeclaration(this._key, itemKey, itemType, defaultValue, description);
|
|
17616
|
-
}
|
|
17617
|
-
/** Read a BOOLEAN item, registering the declaration on first call. */
|
|
17618
|
-
getBool(key, defaultValue, options = {}) {
|
|
17619
|
-
this._registerItem(key, "BOOLEAN", defaultValue, options.description);
|
|
17620
|
-
const values = this._currentValues();
|
|
17621
|
-
if (!(key in values)) return defaultValue;
|
|
17622
|
-
const value = values[key];
|
|
17623
|
-
if (typeof value === "boolean") return value;
|
|
17624
|
-
console.warn(
|
|
17625
|
-
`[smplkit] config ${JSON.stringify(this._key)} item ${JSON.stringify(key)}: expected BOOLEAN, got ${typeof value}; returning default`
|
|
17626
|
-
);
|
|
17627
|
-
return defaultValue;
|
|
17628
|
-
}
|
|
17629
|
-
/** Read a NUMBER item as int, registering the declaration on first call. */
|
|
17630
|
-
getInt(key, defaultValue, options = {}) {
|
|
17631
|
-
this._registerItem(key, "NUMBER", defaultValue, options.description);
|
|
17632
|
-
const values = this._currentValues();
|
|
17633
|
-
if (!(key in values)) return defaultValue;
|
|
17634
|
-
const value = values[key];
|
|
17635
|
-
if (typeof value === "number" && Number.isInteger(value)) return value;
|
|
17636
|
-
console.warn(
|
|
17637
|
-
`[smplkit] config ${JSON.stringify(this._key)} item ${JSON.stringify(key)}: expected NUMBER (int), got ${typeof value}; returning default`
|
|
17638
|
-
);
|
|
17639
|
-
return defaultValue;
|
|
17640
|
-
}
|
|
17641
|
-
/** Read a NUMBER item as float, registering the declaration on first call. */
|
|
17642
|
-
getFloat(key, defaultValue, options = {}) {
|
|
17643
|
-
this._registerItem(key, "NUMBER", defaultValue, options.description);
|
|
17644
|
-
const values = this._currentValues();
|
|
17645
|
-
if (!(key in values)) return defaultValue;
|
|
17646
|
-
const value = values[key];
|
|
17647
|
-
if (typeof value === "number") return value;
|
|
17648
|
-
console.warn(
|
|
17649
|
-
`[smplkit] config ${JSON.stringify(this._key)} item ${JSON.stringify(key)}: expected NUMBER (float), got ${typeof value}; returning default`
|
|
17650
|
-
);
|
|
17651
|
-
return defaultValue;
|
|
17652
|
-
}
|
|
17653
|
-
/** Read a STRING item, registering the declaration on first call. */
|
|
17654
|
-
getString(key, defaultValue, options = {}) {
|
|
17655
|
-
this._registerItem(key, "STRING", defaultValue, options.description);
|
|
17656
|
-
const values = this._currentValues();
|
|
17657
|
-
if (!(key in values)) return defaultValue;
|
|
17658
|
-
const value = values[key];
|
|
17659
|
-
if (typeof value === "string") return value;
|
|
17660
|
-
console.warn(
|
|
17661
|
-
`[smplkit] config ${JSON.stringify(this._key)} item ${JSON.stringify(key)}: expected STRING, got ${typeof value}; returning default`
|
|
17662
|
-
);
|
|
17663
|
-
return defaultValue;
|
|
17664
|
-
}
|
|
17665
|
-
/** Read a JSON item, registering the declaration on first call. */
|
|
17666
|
-
getJson(key, defaultValue, options = {}) {
|
|
17667
|
-
this._registerItem(key, "JSON", defaultValue, options.description);
|
|
17668
|
-
const values = this._currentValues();
|
|
17669
|
-
if (!(key in values)) return defaultValue;
|
|
17670
|
-
return values[key];
|
|
17671
|
-
}
|
|
17672
17564
|
onChange(callbackOrItemKey, callback) {
|
|
17673
17565
|
if (typeof callbackOrItemKey === "function") {
|
|
17674
17566
|
this._client.onChange(this._key, callbackOrItemKey);
|
|
@@ -17721,6 +17613,7 @@ var ConfigChangeEvent = class {
|
|
|
17721
17613
|
}
|
|
17722
17614
|
};
|
|
17723
17615
|
var BASE_URL = "https://config.smplkit.com";
|
|
17616
|
+
var MISSING = /* @__PURE__ */ Symbol("smplkit.config.get.MISSING");
|
|
17724
17617
|
function extractItemValues(items) {
|
|
17725
17618
|
if (!items) return {};
|
|
17726
17619
|
const result = {};
|
|
@@ -17760,6 +17653,40 @@ function resourceToConfig(resource) {
|
|
|
17760
17653
|
updatedAt: attrs.updated_at ?? null
|
|
17761
17654
|
});
|
|
17762
17655
|
}
|
|
17656
|
+
function valueToItemType(value) {
|
|
17657
|
+
if (typeof value === "boolean") return "BOOLEAN";
|
|
17658
|
+
if (typeof value === "number") return "NUMBER";
|
|
17659
|
+
if (typeof value === "string") return "STRING";
|
|
17660
|
+
return "STRING";
|
|
17661
|
+
}
|
|
17662
|
+
function isPlainObject(value) {
|
|
17663
|
+
if (value === null || typeof value !== "object") return false;
|
|
17664
|
+
const proto = Object.getPrototypeOf(value);
|
|
17665
|
+
return proto === Object.prototype || proto === null;
|
|
17666
|
+
}
|
|
17667
|
+
function iterObjectItems(obj, prefix = "") {
|
|
17668
|
+
const out = [];
|
|
17669
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
17670
|
+
const flatKey = `${prefix}${key}`;
|
|
17671
|
+
if (isPlainObject(value)) {
|
|
17672
|
+
out.push(...iterObjectItems(value, `${flatKey}.`));
|
|
17673
|
+
continue;
|
|
17674
|
+
}
|
|
17675
|
+
out.push([flatKey, valueToItemType(value), value]);
|
|
17676
|
+
}
|
|
17677
|
+
return out;
|
|
17678
|
+
}
|
|
17679
|
+
function applyChangeToTarget(target, dottedKey, value) {
|
|
17680
|
+
const parts = dottedKey.split(".");
|
|
17681
|
+
let current = target;
|
|
17682
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
17683
|
+
const part = parts[i];
|
|
17684
|
+
if (current === null || typeof current !== "object" || !(part in current)) return;
|
|
17685
|
+
current = current[part];
|
|
17686
|
+
}
|
|
17687
|
+
if (current === null || typeof current !== "object") return;
|
|
17688
|
+
current[parts[parts.length - 1]] = value;
|
|
17689
|
+
}
|
|
17763
17690
|
var ConfigClient = class {
|
|
17764
17691
|
/** @internal */
|
|
17765
17692
|
_apiKey;
|
|
@@ -17780,10 +17707,11 @@ var ConfigClient = class {
|
|
|
17780
17707
|
* without a full re-list. Mirrors Python's `_raw_config_cache`. */
|
|
17781
17708
|
_configStore = {};
|
|
17782
17709
|
/** Cache of LiveConfigProxy instances by config id — ensures repeat
|
|
17783
|
-
* `
|
|
17784
|
-
* handle so callers can reference it as a parent via direct ref.
|
|
17785
|
-
* Mirrors Python's `_proxies`. */
|
|
17710
|
+
* `get(id)` calls return the same handle. */
|
|
17786
17711
|
_proxies = {};
|
|
17712
|
+
/** Bound targets (plain objects or class instances) keyed by config
|
|
17713
|
+
* id. WebSocket dispatch mutates these in place when values change. */
|
|
17714
|
+
_bindings = /* @__PURE__ */ new Map();
|
|
17787
17715
|
_initialized = false;
|
|
17788
17716
|
_listeners = [];
|
|
17789
17717
|
/** @internal */
|
|
@@ -17816,66 +17744,126 @@ var ConfigClient = class {
|
|
|
17816
17744
|
});
|
|
17817
17745
|
}
|
|
17818
17746
|
// ------------------------------------------------------------------
|
|
17819
|
-
//
|
|
17747
|
+
// Public API: bind, get
|
|
17820
17748
|
// ------------------------------------------------------------------
|
|
17821
17749
|
/**
|
|
17822
|
-
*
|
|
17750
|
+
* Bind an object to a config id; return the same object back, live.
|
|
17751
|
+
*
|
|
17752
|
+
* Declarative, code-first API. The object's keys are the schema; its
|
|
17753
|
+
* values are the in-code defaults. On first boot:
|
|
17823
17754
|
*
|
|
17824
|
-
*
|
|
17825
|
-
*
|
|
17826
|
-
*
|
|
17827
|
-
*
|
|
17755
|
+
* 1. Every leaf (recursively, through nested plain objects) is
|
|
17756
|
+
* registered with the server as a config item, with its value as
|
|
17757
|
+
* the in-code default and a type inferred from `typeof value`.
|
|
17758
|
+
* 2. After the SDK's cache is populated, any server-side overrides for
|
|
17759
|
+
* this config are applied to the bound object in place.
|
|
17828
17760
|
*
|
|
17829
|
-
*
|
|
17830
|
-
*
|
|
17831
|
-
*
|
|
17832
|
-
* in
|
|
17761
|
+
* On every WebSocket-delivered change thereafter the bound object is
|
|
17762
|
+
* mutated in place — readers of `obj.foo` and `obj["foo"]` always see
|
|
17763
|
+
* the current resolved value. The returned object is the same one you
|
|
17764
|
+
* passed in (referential identity preserved).
|
|
17833
17765
|
*
|
|
17834
|
-
*
|
|
17835
|
-
*
|
|
17766
|
+
* Idempotent. Repeated calls with the same id return the originally-
|
|
17767
|
+
* bound object; the new `config` argument is ignored.
|
|
17768
|
+
*
|
|
17769
|
+
* **Plain object literals vs. class instances.** Plain object literals
|
|
17770
|
+
* (e.g., `{ a: 1, b: { c: 2 } }`) are the recommended input shape —
|
|
17771
|
+
* their keys are the explicit override set, and omitted keys inherit
|
|
17772
|
+
* from `parent`. Class instances are also accepted, but every
|
|
17773
|
+
* enumerable property is registered as an explicit override (there is
|
|
17774
|
+
* no JS equivalent of Python's `model_fields_set`); to get omit-to-
|
|
17775
|
+
* inherit semantics, use a plain object literal.
|
|
17776
|
+
*
|
|
17777
|
+
* @param id - The config id to register under.
|
|
17778
|
+
* @param config - A plain object literal (recommended) or class
|
|
17779
|
+
* instance carrying the in-code defaults.
|
|
17780
|
+
* @param options - Optional `parent`: another object previously
|
|
17781
|
+
* returned from a {@link bind} call. Activates parent-chain
|
|
17782
|
+
* inheritance for keys the caller omitted.
|
|
17783
|
+
* @returns The same `config` object, registered and live.
|
|
17784
|
+
* @throws TypeError if `config` is not an object.
|
|
17785
|
+
* @throws Error if `parent` was not previously bound via {@link bind}.
|
|
17836
17786
|
*/
|
|
17837
|
-
async
|
|
17787
|
+
async bind(id, config, options = {}) {
|
|
17788
|
+
if (config === null || typeof config !== "object") {
|
|
17789
|
+
throw new TypeError(`bind() requires an object; got ${typeof config}`);
|
|
17790
|
+
}
|
|
17791
|
+
const existing = this._bindings.get(id);
|
|
17792
|
+
if (existing !== void 0) {
|
|
17793
|
+
return existing;
|
|
17794
|
+
}
|
|
17795
|
+
let parentId = null;
|
|
17796
|
+
if (options.parent !== void 0 && options.parent !== null) {
|
|
17797
|
+
parentId = this._configIdFor(options.parent);
|
|
17798
|
+
if (parentId === null) {
|
|
17799
|
+
throw new Error(
|
|
17800
|
+
"bind(): parent must be an object previously returned from client.config.bind(). Bind the parent first."
|
|
17801
|
+
);
|
|
17802
|
+
}
|
|
17803
|
+
}
|
|
17804
|
+
const ctor = config.constructor;
|
|
17805
|
+
const className = typeof ctor === "function" && ctor !== Object && typeof ctor.name === "string" && ctor.name ? ctor.name : null;
|
|
17806
|
+
this._observeConfigDeclaration(id, parentId, className, null);
|
|
17807
|
+
for (const [itemKey, itemType, value] of iterObjectItems(config)) {
|
|
17808
|
+
this._observeItemDeclaration(id, itemKey, itemType, value, void 0);
|
|
17809
|
+
}
|
|
17810
|
+
this._bindings.set(id, config);
|
|
17811
|
+
await this._ensureInitialized();
|
|
17812
|
+
this._syncTargetFromCache(config, id);
|
|
17813
|
+
return config;
|
|
17814
|
+
}
|
|
17815
|
+
async get(id, key, defaultValue = MISSING) {
|
|
17838
17816
|
await this._ensureInitialized();
|
|
17817
|
+
if (key === void 0) {
|
|
17818
|
+
if (!(id in this._configCache)) {
|
|
17819
|
+
throw new SmplNotFoundError(`Config with id '${id}' not found in cache`);
|
|
17820
|
+
}
|
|
17821
|
+
const metrics = this._parent?._metrics;
|
|
17822
|
+
if (metrics) {
|
|
17823
|
+
metrics.record("config.resolutions", 1, "resolutions", { config: id });
|
|
17824
|
+
}
|
|
17825
|
+
return this._cachedProxy(id);
|
|
17826
|
+
}
|
|
17827
|
+
const hasDefault = defaultValue !== MISSING;
|
|
17828
|
+
if (hasDefault) {
|
|
17829
|
+
this._observeConfigDeclaration(id, null, null, null);
|
|
17830
|
+
this._observeItemDeclaration(id, key, valueToItemType(defaultValue), defaultValue, void 0);
|
|
17831
|
+
}
|
|
17839
17832
|
if (!(id in this._configCache)) {
|
|
17833
|
+
if (hasDefault) return defaultValue;
|
|
17840
17834
|
throw new SmplNotFoundError(`Config with id '${id}' not found in cache`);
|
|
17841
17835
|
}
|
|
17842
|
-
const
|
|
17843
|
-
if (
|
|
17844
|
-
|
|
17836
|
+
const values = this._configCache[id];
|
|
17837
|
+
if (!(key in values)) {
|
|
17838
|
+
if (hasDefault) return defaultValue;
|
|
17839
|
+
throw new SmplNotFoundError(`Config item '${key}' not found in config '${id}'`);
|
|
17845
17840
|
}
|
|
17846
|
-
return
|
|
17841
|
+
return values[key];
|
|
17847
17842
|
}
|
|
17848
|
-
|
|
17849
|
-
|
|
17850
|
-
|
|
17851
|
-
|
|
17852
|
-
|
|
17853
|
-
|
|
17854
|
-
|
|
17855
|
-
|
|
17856
|
-
|
|
17857
|
-
|
|
17858
|
-
|
|
17859
|
-
|
|
17860
|
-
|
|
17861
|
-
|
|
17862
|
-
|
|
17863
|
-
|
|
17864
|
-
|
|
17865
|
-
const parent = options.parent;
|
|
17866
|
-
const parentId = parent instanceof LiveConfigProxy ? parent._key : parent ?? null;
|
|
17867
|
-
this._observeConfigDeclaration(id, parentId, options.name ?? null, options.description ?? null);
|
|
17868
|
-
await this._ensureInitialized();
|
|
17869
|
-
return this._cachedProxy(id, options.model);
|
|
17843
|
+
// ------------------------------------------------------------------
|
|
17844
|
+
// Internal: binding helpers
|
|
17845
|
+
// ------------------------------------------------------------------
|
|
17846
|
+
/** @internal — return the config_id this object was bound under, or null. */
|
|
17847
|
+
_configIdFor(target) {
|
|
17848
|
+
for (const [cid, bound] of this._bindings) {
|
|
17849
|
+
if (bound === target) return cid;
|
|
17850
|
+
}
|
|
17851
|
+
return null;
|
|
17852
|
+
}
|
|
17853
|
+
/** @internal — apply current cached values to a freshly-bound target. */
|
|
17854
|
+
_syncTargetFromCache(target, configId) {
|
|
17855
|
+
const cache = this._configCache[configId];
|
|
17856
|
+
if (!cache) return;
|
|
17857
|
+
for (const [dottedKey, value] of Object.entries(cache)) {
|
|
17858
|
+
applyChangeToTarget(target, dottedKey, value);
|
|
17859
|
+
}
|
|
17870
17860
|
}
|
|
17871
17861
|
/** @internal — return (and cache) the canonical proxy for a config id. */
|
|
17872
|
-
_cachedProxy(id
|
|
17862
|
+
_cachedProxy(id) {
|
|
17873
17863
|
let proxy = this._proxies[id];
|
|
17874
17864
|
if (!proxy) {
|
|
17875
|
-
proxy = new LiveConfigProxy(this, id
|
|
17865
|
+
proxy = new LiveConfigProxy(this, id);
|
|
17876
17866
|
this._proxies[id] = proxy;
|
|
17877
|
-
} else if (model !== void 0 && proxy._model === void 0) {
|
|
17878
|
-
proxy._model = model;
|
|
17879
17867
|
}
|
|
17880
17868
|
return proxy;
|
|
17881
17869
|
}
|
|
@@ -17943,7 +17931,7 @@ var ConfigClient = class {
|
|
|
17943
17931
|
*/
|
|
17944
17932
|
async refresh() {
|
|
17945
17933
|
if (!this._initialized) {
|
|
17946
|
-
throw new SmplError("Config not initialized. Call get() first.");
|
|
17934
|
+
throw new SmplError("Config not initialized. Call get() or bind() first.");
|
|
17947
17935
|
}
|
|
17948
17936
|
const environment = this._parent?._environment;
|
|
17949
17937
|
if (!environment) {
|
|
@@ -17967,10 +17955,6 @@ var ConfigClient = class {
|
|
|
17967
17955
|
* (set via `_resolveManagement`) so runtime + management share one HTTP
|
|
17968
17956
|
* client; falls back to a direct GET when running without `SmplClient`
|
|
17969
17957
|
* bootstrap (e.g. unit tests that construct `ConfigClient` directly).
|
|
17970
|
-
*
|
|
17971
|
-
* Pages through the server until a short page (less than the requested
|
|
17972
|
-
* size) is returned — accounts with more than 1000 configs would
|
|
17973
|
-
* otherwise silently lose everything past page one.
|
|
17974
17958
|
*/
|
|
17975
17959
|
async _listConfigs() {
|
|
17976
17960
|
const PAGE_SIZE = 1e3;
|
|
@@ -18012,7 +17996,8 @@ var ConfigClient = class {
|
|
|
18012
17996
|
* Eagerly initialize the config subclient — fetch all configs, resolve
|
|
18013
17997
|
* environment-scoped values into the local cache, and subscribe to the
|
|
18014
17998
|
* shared WebSocket for live updates. Idempotent. Called automatically
|
|
18015
|
-
* on first `client.config.get(...)` if not
|
|
17999
|
+
* on first `client.config.get(...)` / `client.config.bind(...)` if not
|
|
18000
|
+
* invoked manually.
|
|
18016
18001
|
*/
|
|
18017
18002
|
async start() {
|
|
18018
18003
|
return this._ensureInitialized();
|
|
@@ -18148,10 +18133,14 @@ var ConfigClient = class {
|
|
|
18148
18133
|
const oldItems = oldCache[cfgKey] ?? {};
|
|
18149
18134
|
const newItems = newCache[cfgKey] ?? {};
|
|
18150
18135
|
const allItemKeys = /* @__PURE__ */ new Set([...Object.keys(oldItems), ...Object.keys(newItems)]);
|
|
18136
|
+
const target = this._bindings.get(cfgKey);
|
|
18151
18137
|
for (const iKey of allItemKeys) {
|
|
18152
18138
|
const oldVal = iKey in oldItems ? oldItems[iKey] : null;
|
|
18153
18139
|
const newVal = iKey in newItems ? newItems[iKey] : null;
|
|
18154
18140
|
if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {
|
|
18141
|
+
if (target !== void 0) {
|
|
18142
|
+
applyChangeToTarget(target, iKey, newVal);
|
|
18143
|
+
}
|
|
18155
18144
|
const metrics = this._parent?._metrics;
|
|
18156
18145
|
if (metrics) {
|
|
18157
18146
|
metrics.record("config.changes", 1, "changes", { config: cfgKey });
|