@smplkit/sdk 3.0.84 → 3.0.86
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.js
CHANGED
|
@@ -17416,47 +17416,15 @@ var Config = class {
|
|
|
17416
17416
|
};
|
|
17417
17417
|
|
|
17418
17418
|
// src/config/proxy.ts
|
|
17419
|
-
function _unflattenDotNotation(flat) {
|
|
17420
|
-
const nested = {};
|
|
17421
|
-
for (const [key, value] of Object.entries(flat)) {
|
|
17422
|
-
const parts = key.split(".");
|
|
17423
|
-
let current = nested;
|
|
17424
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
17425
|
-
const part = parts[i];
|
|
17426
|
-
if (current[part] === void 0 || typeof current[part] !== "object" || current[part] === null) {
|
|
17427
|
-
current[part] = {};
|
|
17428
|
-
}
|
|
17429
|
-
current = current[part];
|
|
17430
|
-
}
|
|
17431
|
-
current[parts[parts.length - 1]] = value;
|
|
17432
|
-
}
|
|
17433
|
-
return nested;
|
|
17434
|
-
}
|
|
17435
17419
|
var LiveConfigProxy = class {
|
|
17436
17420
|
/** @internal */
|
|
17437
17421
|
_client;
|
|
17438
17422
|
/** @internal */
|
|
17439
17423
|
_key;
|
|
17440
|
-
|
|
17441
|
-
_model;
|
|
17442
|
-
constructor(client, key, model) {
|
|
17424
|
+
constructor(client, key) {
|
|
17443
17425
|
this._client = client;
|
|
17444
17426
|
this._key = key;
|
|
17445
|
-
|
|
17446
|
-
const ownMethods = /* @__PURE__ */ new Set([
|
|
17447
|
-
"keys",
|
|
17448
|
-
"values",
|
|
17449
|
-
"items",
|
|
17450
|
-
"get",
|
|
17451
|
-
"onChange",
|
|
17452
|
-
"getBool",
|
|
17453
|
-
"getInt",
|
|
17454
|
-
"getFloat",
|
|
17455
|
-
"getString",
|
|
17456
|
-
"getJson",
|
|
17457
|
-
"_currentValues",
|
|
17458
|
-
"_registerItem"
|
|
17459
|
-
]);
|
|
17427
|
+
const ownMethods = /* @__PURE__ */ new Set(["keys", "values", "items", "get", "onChange", "_currentValues"]);
|
|
17460
17428
|
return new Proxy(this, {
|
|
17461
17429
|
get(target, prop, receiver) {
|
|
17462
17430
|
if (typeof prop === "symbol" || prop === "constructor" || prop === "toJSON") {
|
|
@@ -17466,17 +17434,9 @@ var LiveConfigProxy = class {
|
|
|
17466
17434
|
return Reflect.get(target, prop, receiver);
|
|
17467
17435
|
}
|
|
17468
17436
|
const values = target._currentValues();
|
|
17469
|
-
if (target._model) {
|
|
17470
|
-
const nested = _unflattenDotNotation(values);
|
|
17471
|
-
const instance = new target._model(nested);
|
|
17472
|
-
return instance[prop];
|
|
17473
|
-
}
|
|
17474
17437
|
return values[prop];
|
|
17475
17438
|
},
|
|
17476
|
-
set(
|
|
17477
|
-
if (typeof prop === "string" && prop.startsWith("_")) {
|
|
17478
|
-
return Reflect.set(target, prop, value, receiver);
|
|
17479
|
-
}
|
|
17439
|
+
set(_target, prop) {
|
|
17480
17440
|
throw new Error(
|
|
17481
17441
|
`LiveConfigProxy is read-only; cannot set ${JSON.stringify(String(prop))}. Mutate config values via client.manage.config.*`
|
|
17482
17442
|
);
|
|
@@ -17531,74 +17491,6 @@ var LiveConfigProxy = class {
|
|
|
17531
17491
|
const values = this._currentValues();
|
|
17532
17492
|
return key in values ? values[key] : defaultValue;
|
|
17533
17493
|
}
|
|
17534
|
-
// ------------------------------------------------------------------
|
|
17535
|
-
// Typed getters (ADR-037 §2.13)
|
|
17536
|
-
//
|
|
17537
|
-
// Each registers the item (key, type, default, description) on first
|
|
17538
|
-
// call within the process, then returns the resolved value. When the
|
|
17539
|
-
// resolved value cannot be coerced to the getter's type — including
|
|
17540
|
-
// the "not yet set on the server" case — the in-code default is
|
|
17541
|
-
// returned and a structured warning is logged.
|
|
17542
|
-
// ------------------------------------------------------------------
|
|
17543
|
-
/** @internal */
|
|
17544
|
-
_registerItem(itemKey, itemType, defaultValue, description) {
|
|
17545
|
-
this._client._observeItemDeclaration(this._key, itemKey, itemType, defaultValue, description);
|
|
17546
|
-
}
|
|
17547
|
-
/** Read a BOOLEAN item, registering the declaration on first call. */
|
|
17548
|
-
getBool(key, defaultValue, options = {}) {
|
|
17549
|
-
this._registerItem(key, "BOOLEAN", defaultValue, options.description);
|
|
17550
|
-
const values = this._currentValues();
|
|
17551
|
-
if (!(key in values)) return defaultValue;
|
|
17552
|
-
const value = values[key];
|
|
17553
|
-
if (typeof value === "boolean") return value;
|
|
17554
|
-
console.warn(
|
|
17555
|
-
`[smplkit] config ${JSON.stringify(this._key)} item ${JSON.stringify(key)}: expected BOOLEAN, got ${typeof value}; returning default`
|
|
17556
|
-
);
|
|
17557
|
-
return defaultValue;
|
|
17558
|
-
}
|
|
17559
|
-
/** Read a NUMBER item as int, registering the declaration on first call. */
|
|
17560
|
-
getInt(key, defaultValue, options = {}) {
|
|
17561
|
-
this._registerItem(key, "NUMBER", defaultValue, options.description);
|
|
17562
|
-
const values = this._currentValues();
|
|
17563
|
-
if (!(key in values)) return defaultValue;
|
|
17564
|
-
const value = values[key];
|
|
17565
|
-
if (typeof value === "number" && Number.isInteger(value)) return value;
|
|
17566
|
-
console.warn(
|
|
17567
|
-
`[smplkit] config ${JSON.stringify(this._key)} item ${JSON.stringify(key)}: expected NUMBER (int), got ${typeof value}; returning default`
|
|
17568
|
-
);
|
|
17569
|
-
return defaultValue;
|
|
17570
|
-
}
|
|
17571
|
-
/** Read a NUMBER item as float, registering the declaration on first call. */
|
|
17572
|
-
getFloat(key, defaultValue, options = {}) {
|
|
17573
|
-
this._registerItem(key, "NUMBER", defaultValue, options.description);
|
|
17574
|
-
const values = this._currentValues();
|
|
17575
|
-
if (!(key in values)) return defaultValue;
|
|
17576
|
-
const value = values[key];
|
|
17577
|
-
if (typeof value === "number") return value;
|
|
17578
|
-
console.warn(
|
|
17579
|
-
`[smplkit] config ${JSON.stringify(this._key)} item ${JSON.stringify(key)}: expected NUMBER (float), got ${typeof value}; returning default`
|
|
17580
|
-
);
|
|
17581
|
-
return defaultValue;
|
|
17582
|
-
}
|
|
17583
|
-
/** Read a STRING item, registering the declaration on first call. */
|
|
17584
|
-
getString(key, defaultValue, options = {}) {
|
|
17585
|
-
this._registerItem(key, "STRING", defaultValue, options.description);
|
|
17586
|
-
const values = this._currentValues();
|
|
17587
|
-
if (!(key in values)) return defaultValue;
|
|
17588
|
-
const value = values[key];
|
|
17589
|
-
if (typeof value === "string") return value;
|
|
17590
|
-
console.warn(
|
|
17591
|
-
`[smplkit] config ${JSON.stringify(this._key)} item ${JSON.stringify(key)}: expected STRING, got ${typeof value}; returning default`
|
|
17592
|
-
);
|
|
17593
|
-
return defaultValue;
|
|
17594
|
-
}
|
|
17595
|
-
/** Read a JSON item, registering the declaration on first call. */
|
|
17596
|
-
getJson(key, defaultValue, options = {}) {
|
|
17597
|
-
this._registerItem(key, "JSON", defaultValue, options.description);
|
|
17598
|
-
const values = this._currentValues();
|
|
17599
|
-
if (!(key in values)) return defaultValue;
|
|
17600
|
-
return values[key];
|
|
17601
|
-
}
|
|
17602
17494
|
onChange(callbackOrItemKey, callback) {
|
|
17603
17495
|
if (typeof callbackOrItemKey === "function") {
|
|
17604
17496
|
this._client.onChange(this._key, callbackOrItemKey);
|
|
@@ -17651,6 +17543,7 @@ var ConfigChangeEvent = class {
|
|
|
17651
17543
|
}
|
|
17652
17544
|
};
|
|
17653
17545
|
var BASE_URL = "https://config.smplkit.com";
|
|
17546
|
+
var MISSING = /* @__PURE__ */ Symbol("smplkit.config.get.MISSING");
|
|
17654
17547
|
function extractItemValues(items) {
|
|
17655
17548
|
if (!items) return {};
|
|
17656
17549
|
const result = {};
|
|
@@ -17690,6 +17583,40 @@ function resourceToConfig(resource) {
|
|
|
17690
17583
|
updatedAt: attrs.updated_at ?? null
|
|
17691
17584
|
});
|
|
17692
17585
|
}
|
|
17586
|
+
function valueToItemType(value) {
|
|
17587
|
+
if (typeof value === "boolean") return "BOOLEAN";
|
|
17588
|
+
if (typeof value === "number") return "NUMBER";
|
|
17589
|
+
if (typeof value === "string") return "STRING";
|
|
17590
|
+
return "STRING";
|
|
17591
|
+
}
|
|
17592
|
+
function isPlainObject(value) {
|
|
17593
|
+
if (value === null || typeof value !== "object") return false;
|
|
17594
|
+
const proto = Object.getPrototypeOf(value);
|
|
17595
|
+
return proto === Object.prototype || proto === null;
|
|
17596
|
+
}
|
|
17597
|
+
function iterObjectItems(obj, prefix = "") {
|
|
17598
|
+
const out = [];
|
|
17599
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
17600
|
+
const flatKey = `${prefix}${key}`;
|
|
17601
|
+
if (isPlainObject(value)) {
|
|
17602
|
+
out.push(...iterObjectItems(value, `${flatKey}.`));
|
|
17603
|
+
continue;
|
|
17604
|
+
}
|
|
17605
|
+
out.push([flatKey, valueToItemType(value), value]);
|
|
17606
|
+
}
|
|
17607
|
+
return out;
|
|
17608
|
+
}
|
|
17609
|
+
function applyChangeToTarget(target, dottedKey, value) {
|
|
17610
|
+
const parts = dottedKey.split(".");
|
|
17611
|
+
let current = target;
|
|
17612
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
17613
|
+
const part = parts[i];
|
|
17614
|
+
if (current === null || typeof current !== "object" || !(part in current)) return;
|
|
17615
|
+
current = current[part];
|
|
17616
|
+
}
|
|
17617
|
+
if (current === null || typeof current !== "object") return;
|
|
17618
|
+
current[parts[parts.length - 1]] = value;
|
|
17619
|
+
}
|
|
17693
17620
|
var ConfigClient = class {
|
|
17694
17621
|
/** @internal */
|
|
17695
17622
|
_apiKey;
|
|
@@ -17710,10 +17637,11 @@ var ConfigClient = class {
|
|
|
17710
17637
|
* without a full re-list. Mirrors Python's `_raw_config_cache`. */
|
|
17711
17638
|
_configStore = {};
|
|
17712
17639
|
/** Cache of LiveConfigProxy instances by config id — ensures repeat
|
|
17713
|
-
* `
|
|
17714
|
-
* handle so callers can reference it as a parent via direct ref.
|
|
17715
|
-
* Mirrors Python's `_proxies`. */
|
|
17640
|
+
* `get(id)` calls return the same handle. */
|
|
17716
17641
|
_proxies = {};
|
|
17642
|
+
/** Bound targets (plain objects or class instances) keyed by config
|
|
17643
|
+
* id. WebSocket dispatch mutates these in place when values change. */
|
|
17644
|
+
_bindings = /* @__PURE__ */ new Map();
|
|
17717
17645
|
_initialized = false;
|
|
17718
17646
|
_listeners = [];
|
|
17719
17647
|
/** @internal */
|
|
@@ -17746,66 +17674,126 @@ var ConfigClient = class {
|
|
|
17746
17674
|
});
|
|
17747
17675
|
}
|
|
17748
17676
|
// ------------------------------------------------------------------
|
|
17749
|
-
//
|
|
17677
|
+
// Public API: bind, get
|
|
17750
17678
|
// ------------------------------------------------------------------
|
|
17751
17679
|
/**
|
|
17752
|
-
*
|
|
17680
|
+
* Bind an object to a config id; return the same object back, live.
|
|
17681
|
+
*
|
|
17682
|
+
* Declarative, code-first API. The object's keys are the schema; its
|
|
17683
|
+
* values are the in-code defaults. On first boot:
|
|
17753
17684
|
*
|
|
17754
|
-
*
|
|
17755
|
-
*
|
|
17756
|
-
*
|
|
17757
|
-
*
|
|
17685
|
+
* 1. Every leaf (recursively, through nested plain objects) is
|
|
17686
|
+
* registered with the server as a config item, with its value as
|
|
17687
|
+
* the in-code default and a type inferred from `typeof value`.
|
|
17688
|
+
* 2. After the SDK's cache is populated, any server-side overrides for
|
|
17689
|
+
* this config are applied to the bound object in place.
|
|
17758
17690
|
*
|
|
17759
|
-
*
|
|
17760
|
-
*
|
|
17761
|
-
*
|
|
17762
|
-
* in
|
|
17691
|
+
* On every WebSocket-delivered change thereafter the bound object is
|
|
17692
|
+
* mutated in place — readers of `obj.foo` and `obj["foo"]` always see
|
|
17693
|
+
* the current resolved value. The returned object is the same one you
|
|
17694
|
+
* passed in (referential identity preserved).
|
|
17763
17695
|
*
|
|
17764
|
-
*
|
|
17765
|
-
*
|
|
17696
|
+
* Idempotent. Repeated calls with the same id return the originally-
|
|
17697
|
+
* bound object; the new `config` argument is ignored.
|
|
17698
|
+
*
|
|
17699
|
+
* **Plain object literals vs. class instances.** Plain object literals
|
|
17700
|
+
* (e.g., `{ a: 1, b: { c: 2 } }`) are the recommended input shape —
|
|
17701
|
+
* their keys are the explicit override set, and omitted keys inherit
|
|
17702
|
+
* from `parent`. Class instances are also accepted, but every
|
|
17703
|
+
* enumerable property is registered as an explicit override (there is
|
|
17704
|
+
* no JS equivalent of Python's `model_fields_set`); to get omit-to-
|
|
17705
|
+
* inherit semantics, use a plain object literal.
|
|
17706
|
+
*
|
|
17707
|
+
* @param id - The config id to register under.
|
|
17708
|
+
* @param config - A plain object literal (recommended) or class
|
|
17709
|
+
* instance carrying the in-code defaults.
|
|
17710
|
+
* @param options - Optional `parent`: another object previously
|
|
17711
|
+
* returned from a {@link bind} call. Activates parent-chain
|
|
17712
|
+
* inheritance for keys the caller omitted.
|
|
17713
|
+
* @returns The same `config` object, registered and live.
|
|
17714
|
+
* @throws TypeError if `config` is not an object.
|
|
17715
|
+
* @throws Error if `parent` was not previously bound via {@link bind}.
|
|
17766
17716
|
*/
|
|
17767
|
-
async
|
|
17717
|
+
async bind(id, config, options = {}) {
|
|
17718
|
+
if (config === null || typeof config !== "object") {
|
|
17719
|
+
throw new TypeError(`bind() requires an object; got ${typeof config}`);
|
|
17720
|
+
}
|
|
17721
|
+
const existing = this._bindings.get(id);
|
|
17722
|
+
if (existing !== void 0) {
|
|
17723
|
+
return existing;
|
|
17724
|
+
}
|
|
17725
|
+
let parentId = null;
|
|
17726
|
+
if (options.parent !== void 0 && options.parent !== null) {
|
|
17727
|
+
parentId = this._configIdFor(options.parent);
|
|
17728
|
+
if (parentId === null) {
|
|
17729
|
+
throw new Error(
|
|
17730
|
+
"bind(): parent must be an object previously returned from client.config.bind(). Bind the parent first."
|
|
17731
|
+
);
|
|
17732
|
+
}
|
|
17733
|
+
}
|
|
17734
|
+
const ctor = config.constructor;
|
|
17735
|
+
const className = typeof ctor === "function" && ctor !== Object && typeof ctor.name === "string" && ctor.name ? ctor.name : null;
|
|
17736
|
+
this._observeConfigDeclaration(id, parentId, className, null);
|
|
17737
|
+
for (const [itemKey, itemType, value] of iterObjectItems(config)) {
|
|
17738
|
+
this._observeItemDeclaration(id, itemKey, itemType, value, void 0);
|
|
17739
|
+
}
|
|
17740
|
+
this._bindings.set(id, config);
|
|
17741
|
+
await this._ensureInitialized();
|
|
17742
|
+
this._syncTargetFromCache(config, id);
|
|
17743
|
+
return config;
|
|
17744
|
+
}
|
|
17745
|
+
async get(id, key, defaultValue = MISSING) {
|
|
17768
17746
|
await this._ensureInitialized();
|
|
17747
|
+
if (key === void 0) {
|
|
17748
|
+
if (!(id in this._configCache)) {
|
|
17749
|
+
throw new SmplNotFoundError(`Config with id '${id}' not found in cache`);
|
|
17750
|
+
}
|
|
17751
|
+
const metrics = this._parent?._metrics;
|
|
17752
|
+
if (metrics) {
|
|
17753
|
+
metrics.record("config.resolutions", 1, "resolutions", { config: id });
|
|
17754
|
+
}
|
|
17755
|
+
return this._cachedProxy(id);
|
|
17756
|
+
}
|
|
17757
|
+
const hasDefault = defaultValue !== MISSING;
|
|
17758
|
+
if (hasDefault) {
|
|
17759
|
+
this._observeConfigDeclaration(id, null, null, null);
|
|
17760
|
+
this._observeItemDeclaration(id, key, valueToItemType(defaultValue), defaultValue, void 0);
|
|
17761
|
+
}
|
|
17769
17762
|
if (!(id in this._configCache)) {
|
|
17763
|
+
if (hasDefault) return defaultValue;
|
|
17770
17764
|
throw new SmplNotFoundError(`Config with id '${id}' not found in cache`);
|
|
17771
17765
|
}
|
|
17772
|
-
const
|
|
17773
|
-
if (
|
|
17774
|
-
|
|
17766
|
+
const values = this._configCache[id];
|
|
17767
|
+
if (!(key in values)) {
|
|
17768
|
+
if (hasDefault) return defaultValue;
|
|
17769
|
+
throw new SmplNotFoundError(`Config item '${key}' not found in config '${id}'`);
|
|
17775
17770
|
}
|
|
17776
|
-
return
|
|
17771
|
+
return values[key];
|
|
17777
17772
|
}
|
|
17778
|
-
|
|
17779
|
-
|
|
17780
|
-
|
|
17781
|
-
|
|
17782
|
-
|
|
17783
|
-
|
|
17784
|
-
|
|
17785
|
-
|
|
17786
|
-
|
|
17787
|
-
|
|
17788
|
-
|
|
17789
|
-
|
|
17790
|
-
|
|
17791
|
-
|
|
17792
|
-
|
|
17793
|
-
|
|
17794
|
-
|
|
17795
|
-
const parent = options.parent;
|
|
17796
|
-
const parentId = parent instanceof LiveConfigProxy ? parent._key : parent ?? null;
|
|
17797
|
-
this._observeConfigDeclaration(id, parentId, options.name ?? null, options.description ?? null);
|
|
17798
|
-
await this._ensureInitialized();
|
|
17799
|
-
return this._cachedProxy(id, options.model);
|
|
17773
|
+
// ------------------------------------------------------------------
|
|
17774
|
+
// Internal: binding helpers
|
|
17775
|
+
// ------------------------------------------------------------------
|
|
17776
|
+
/** @internal — return the config_id this object was bound under, or null. */
|
|
17777
|
+
_configIdFor(target) {
|
|
17778
|
+
for (const [cid, bound] of this._bindings) {
|
|
17779
|
+
if (bound === target) return cid;
|
|
17780
|
+
}
|
|
17781
|
+
return null;
|
|
17782
|
+
}
|
|
17783
|
+
/** @internal — apply current cached values to a freshly-bound target. */
|
|
17784
|
+
_syncTargetFromCache(target, configId) {
|
|
17785
|
+
const cache = this._configCache[configId];
|
|
17786
|
+
if (!cache) return;
|
|
17787
|
+
for (const [dottedKey, value] of Object.entries(cache)) {
|
|
17788
|
+
applyChangeToTarget(target, dottedKey, value);
|
|
17789
|
+
}
|
|
17800
17790
|
}
|
|
17801
17791
|
/** @internal — return (and cache) the canonical proxy for a config id. */
|
|
17802
|
-
_cachedProxy(id
|
|
17792
|
+
_cachedProxy(id) {
|
|
17803
17793
|
let proxy = this._proxies[id];
|
|
17804
17794
|
if (!proxy) {
|
|
17805
|
-
proxy = new LiveConfigProxy(this, id
|
|
17795
|
+
proxy = new LiveConfigProxy(this, id);
|
|
17806
17796
|
this._proxies[id] = proxy;
|
|
17807
|
-
} else if (model !== void 0 && proxy._model === void 0) {
|
|
17808
|
-
proxy._model = model;
|
|
17809
17797
|
}
|
|
17810
17798
|
return proxy;
|
|
17811
17799
|
}
|
|
@@ -17873,7 +17861,7 @@ var ConfigClient = class {
|
|
|
17873
17861
|
*/
|
|
17874
17862
|
async refresh() {
|
|
17875
17863
|
if (!this._initialized) {
|
|
17876
|
-
throw new SmplError("Config not initialized. Call get() first.");
|
|
17864
|
+
throw new SmplError("Config not initialized. Call get() or bind() first.");
|
|
17877
17865
|
}
|
|
17878
17866
|
const environment = this._parent?._environment;
|
|
17879
17867
|
if (!environment) {
|
|
@@ -17897,10 +17885,6 @@ var ConfigClient = class {
|
|
|
17897
17885
|
* (set via `_resolveManagement`) so runtime + management share one HTTP
|
|
17898
17886
|
* client; falls back to a direct GET when running without `SmplClient`
|
|
17899
17887
|
* bootstrap (e.g. unit tests that construct `ConfigClient` directly).
|
|
17900
|
-
*
|
|
17901
|
-
* Pages through the server until a short page (less than the requested
|
|
17902
|
-
* size) is returned — accounts with more than 1000 configs would
|
|
17903
|
-
* otherwise silently lose everything past page one.
|
|
17904
17888
|
*/
|
|
17905
17889
|
async _listConfigs() {
|
|
17906
17890
|
const PAGE_SIZE = 1e3;
|
|
@@ -17942,7 +17926,8 @@ var ConfigClient = class {
|
|
|
17942
17926
|
* Eagerly initialize the config subclient — fetch all configs, resolve
|
|
17943
17927
|
* environment-scoped values into the local cache, and subscribe to the
|
|
17944
17928
|
* shared WebSocket for live updates. Idempotent. Called automatically
|
|
17945
|
-
* on first `client.config.get(...)` if not
|
|
17929
|
+
* on first `client.config.get(...)` / `client.config.bind(...)` if not
|
|
17930
|
+
* invoked manually.
|
|
17946
17931
|
*/
|
|
17947
17932
|
async start() {
|
|
17948
17933
|
return this._ensureInitialized();
|
|
@@ -18078,10 +18063,14 @@ var ConfigClient = class {
|
|
|
18078
18063
|
const oldItems = oldCache[cfgKey] ?? {};
|
|
18079
18064
|
const newItems = newCache[cfgKey] ?? {};
|
|
18080
18065
|
const allItemKeys = /* @__PURE__ */ new Set([...Object.keys(oldItems), ...Object.keys(newItems)]);
|
|
18066
|
+
const target = this._bindings.get(cfgKey);
|
|
18081
18067
|
for (const iKey of allItemKeys) {
|
|
18082
18068
|
const oldVal = iKey in oldItems ? oldItems[iKey] : null;
|
|
18083
18069
|
const newVal = iKey in newItems ? newItems[iKey] : null;
|
|
18084
18070
|
if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {
|
|
18071
|
+
if (target !== void 0) {
|
|
18072
|
+
applyChangeToTarget(target, iKey, newVal);
|
|
18073
|
+
}
|
|
18085
18074
|
const metrics = this._parent?._metrics;
|
|
18086
18075
|
if (metrics) {
|
|
18087
18076
|
metrics.record("config.changes", 1, "changes", { config: cfgKey });
|