@smplkit/sdk 3.0.1 → 3.0.2

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.d.cts CHANGED
@@ -1429,9 +1429,9 @@ declare class Config {
1429
1429
  */
1430
1430
  _buildChain(configs?: Config[]): Promise<Array<{
1431
1431
  id: string | null;
1432
- items: Record<string, Record<string, unknown>>;
1432
+ items: Record<string, unknown>;
1433
1433
  environments: Record<string, {
1434
- values: Record<string, Record<string, unknown>>;
1434
+ values: Record<string, unknown>;
1435
1435
  }>;
1436
1436
  }>>;
1437
1437
  toString(): string;
@@ -2409,6 +2409,11 @@ declare class ConfigClient {
2409
2409
  /** @internal — resolves the management config sub-client used by lazy-init/refresh. */
2410
2410
  _resolveManagement?: () => SmplManagementClient;
2411
2411
  private _configCache;
2412
+ /** Raw Config objects keyed by id, kept around so a single-config
2413
+ * change (WS event) can refetch one config and rebuild the resolved
2414
+ * cache for everyone (including descendants that inherit from it)
2415
+ * without a full re-list. Mirrors Python's `_raw_config_cache`. */
2416
+ private _configStore;
2412
2417
  private _initialized;
2413
2418
  private _listeners;
2414
2419
  /** @internal */
@@ -2464,12 +2469,10 @@ declare class ConfigClient {
2464
2469
  /** @internal — get resolved config from cache. Used by LiveConfigProxy. */
2465
2470
  _getCachedConfig(key: string): Record<string, unknown> | undefined;
2466
2471
  private _handleConfigChanged;
2467
- private _handleConfigDeleted;
2468
- private _handleConfigsChanged;
2469
2472
  /** Fetch a single config by key. Returns null if not found. @internal */
2470
2473
  private _fetchSingleConfig;
2471
- /** Resolve a config's values for an environment (no parent chain). @internal */
2472
- private _resolveConfigValues;
2474
+ private _handleConfigDeleted;
2475
+ private _handleConfigsChanged;
2473
2476
  /** @internal */
2474
2477
  private _diffAndFire;
2475
2478
  }
package/dist/index.d.ts CHANGED
@@ -1429,9 +1429,9 @@ declare class Config {
1429
1429
  */
1430
1430
  _buildChain(configs?: Config[]): Promise<Array<{
1431
1431
  id: string | null;
1432
- items: Record<string, Record<string, unknown>>;
1432
+ items: Record<string, unknown>;
1433
1433
  environments: Record<string, {
1434
- values: Record<string, Record<string, unknown>>;
1434
+ values: Record<string, unknown>;
1435
1435
  }>;
1436
1436
  }>>;
1437
1437
  toString(): string;
@@ -2409,6 +2409,11 @@ declare class ConfigClient {
2409
2409
  /** @internal — resolves the management config sub-client used by lazy-init/refresh. */
2410
2410
  _resolveManagement?: () => SmplManagementClient;
2411
2411
  private _configCache;
2412
+ /** Raw Config objects keyed by id, kept around so a single-config
2413
+ * change (WS event) can refetch one config and rebuild the resolved
2414
+ * cache for everyone (including descendants that inherit from it)
2415
+ * without a full re-list. Mirrors Python's `_raw_config_cache`. */
2416
+ private _configStore;
2412
2417
  private _initialized;
2413
2418
  private _listeners;
2414
2419
  /** @internal */
@@ -2464,12 +2469,10 @@ declare class ConfigClient {
2464
2469
  /** @internal — get resolved config from cache. Used by LiveConfigProxy. */
2465
2470
  _getCachedConfig(key: string): Record<string, unknown> | undefined;
2466
2471
  private _handleConfigChanged;
2467
- private _handleConfigDeleted;
2468
- private _handleConfigsChanged;
2469
2472
  /** Fetch a single config by key. Returns null if not found. @internal */
2470
2473
  private _fetchSingleConfig;
2471
- /** Resolve a config's values for an environment (no parent chain). @internal */
2472
- private _resolveConfigValues;
2474
+ private _handleConfigDeleted;
2475
+ private _handleConfigsChanged;
2473
2476
  /** @internal */
2474
2477
  private _diffAndFire;
2475
2478
  }
package/dist/index.js CHANGED
@@ -16838,6 +16838,13 @@ function environmentsToWire(environments) {
16838
16838
  }
16839
16839
  return out;
16840
16840
  }
16841
+ function environmentsForResolver(environments) {
16842
+ const out = {};
16843
+ for (const [envId, env] of Object.entries(environments)) {
16844
+ out[envId] = { values: env.values };
16845
+ }
16846
+ return out;
16847
+ }
16841
16848
  var Config = class {
16842
16849
  id;
16843
16850
  name;
@@ -17027,8 +17034,8 @@ var Config = class {
17027
17034
  const chain = [
17028
17035
  {
17029
17036
  id: this.id,
17030
- items: this._itemsRaw,
17031
- environments: environmentsToWire(this._environments)
17037
+ items: this.items,
17038
+ environments: environmentsForResolver(this._environments)
17032
17039
  }
17033
17040
  ];
17034
17041
  let current = this;
@@ -17050,8 +17057,8 @@ var Config = class {
17050
17057
  }
17051
17058
  chain.push({
17052
17059
  id: parentConfig.id,
17053
- items: parentConfig._itemsRaw,
17054
- environments: environmentsToWire(parentConfig._environments)
17060
+ items: parentConfig.items,
17061
+ environments: environmentsForResolver(parentConfig._environments)
17055
17062
  });
17056
17063
  current = parentConfig;
17057
17064
  }
@@ -17063,6 +17070,22 @@ var Config = class {
17063
17070
  };
17064
17071
 
17065
17072
  // src/config/proxy.ts
17073
+ function _unflattenDotNotation(flat) {
17074
+ const nested = {};
17075
+ for (const [key, value] of Object.entries(flat)) {
17076
+ const parts = key.split(".");
17077
+ let current = nested;
17078
+ for (let i = 0; i < parts.length - 1; i++) {
17079
+ const part = parts[i];
17080
+ if (current[part] === void 0 || typeof current[part] !== "object" || current[part] === null) {
17081
+ current[part] = {};
17082
+ }
17083
+ current = current[part];
17084
+ }
17085
+ current[parts[parts.length - 1]] = value;
17086
+ }
17087
+ return nested;
17088
+ }
17066
17089
  var LiveConfigProxy = class {
17067
17090
  /** @internal */
17068
17091
  _client;
@@ -17085,7 +17108,8 @@ var LiveConfigProxy = class {
17085
17108
  }
17086
17109
  const values = target._currentValues();
17087
17110
  if (target._model) {
17088
- const instance = new target._model(values);
17111
+ const nested = _unflattenDotNotation(values);
17112
+ const instance = new target._model(nested);
17089
17113
  return instance[prop];
17090
17114
  }
17091
17115
  return values[prop];
@@ -17247,6 +17271,11 @@ var ConfigClient = class {
17247
17271
  /** @internal — resolves the management config sub-client used by lazy-init/refresh. */
17248
17272
  _resolveManagement;
17249
17273
  _configCache = {};
17274
+ /** Raw Config objects keyed by id, kept around so a single-config
17275
+ * change (WS event) can refetch one config and rebuild the resolved
17276
+ * cache for everyone (including descendants that inherit from it)
17277
+ * without a full re-list. Mirrors Python's `_raw_config_cache`. */
17278
+ _configStore = {};
17250
17279
  _initialized = false;
17251
17280
  _listeners = [];
17252
17281
  /** @internal */
@@ -17355,12 +17384,15 @@ var ConfigClient = class {
17355
17384
  }
17356
17385
  const configs = await this._listConfigs();
17357
17386
  const newCache = {};
17387
+ const newStore = {};
17358
17388
  for (const cfg of configs) {
17359
17389
  const chain = await cfg._buildChain(configs);
17360
17390
  newCache[cfg.id] = resolveChain(chain, environment);
17391
+ newStore[cfg.id] = cfg;
17361
17392
  }
17362
17393
  const oldCache = this._configCache;
17363
17394
  this._configCache = newCache;
17395
+ this._configStore = newStore;
17364
17396
  this._diffAndFire(oldCache, newCache, "manual");
17365
17397
  }
17366
17398
  /**
@@ -17402,11 +17434,14 @@ var ConfigClient = class {
17402
17434
  }
17403
17435
  const configs = await this._listConfigs();
17404
17436
  const cache = {};
17437
+ const store = {};
17405
17438
  for (const cfg of configs) {
17406
17439
  const chain = await cfg._buildChain(configs);
17407
17440
  cache[cfg.id] = resolveChain(chain, environment);
17441
+ store[cfg.id] = cfg;
17408
17442
  }
17409
17443
  this._configCache = cache;
17444
+ this._configStore = store;
17410
17445
  this._initialized = true;
17411
17446
  if (this._getSharedWs) {
17412
17447
  const ws = this._getSharedWs();
@@ -17420,11 +17455,14 @@ var ConfigClient = class {
17420
17455
  if (this._initialized) return;
17421
17456
  const configs = await this._listConfigs();
17422
17457
  const cache = {};
17458
+ const store = {};
17423
17459
  for (const cfg of configs) {
17424
17460
  const chain = await cfg._buildChain(configs);
17425
17461
  cache[cfg.id] = resolveChain(chain, environment);
17462
+ store[cfg.id] = cfg;
17426
17463
  }
17427
17464
  this._configCache = cache;
17465
+ this._configStore = store;
17428
17466
  this._initialized = true;
17429
17467
  }
17430
17468
  /** @internal — get resolved config from cache. Used by LiveConfigProxy. */
@@ -17438,26 +17476,29 @@ var ConfigClient = class {
17438
17476
  debug("websocket", `config_changed event received: ${JSON.stringify(data)}`);
17439
17477
  const configKey = data.id;
17440
17478
  if (!configKey) return;
17479
+ const environment = this._parent?._environment;
17480
+ if (!environment) return;
17441
17481
  void this._fetchSingleConfig(configKey).then((newConfig) => {
17442
- const environment = this._parent?._environment;
17443
- if (!environment) return;
17444
- const oldValues = this._configCache[configKey];
17445
- let newValues;
17446
- if (newConfig !== null) {
17447
- newValues = this._resolveConfigValues(newConfig, environment);
17482
+ const newStore = { ...this._configStore };
17483
+ if (newConfig === null) {
17484
+ delete newStore[configKey];
17448
17485
  } else {
17449
- newValues = {};
17450
- }
17451
- const oldJson = JSON.stringify(oldValues ?? {});
17452
- const newJson = JSON.stringify(newValues);
17453
- if (oldJson === newJson) return;
17454
- const oldCache = { ...this._configCache };
17455
- if (newConfig !== null) {
17456
- this._configCache[configKey] = newValues;
17457
- } else {
17458
- delete this._configCache[configKey];
17459
- }
17460
- this._diffAndFire(oldCache, this._configCache, "websocket");
17486
+ newStore[configKey] = newConfig;
17487
+ }
17488
+ const allConfigs = Object.values(newStore);
17489
+ return Promise.all(
17490
+ allConfigs.map(async (cfg) => {
17491
+ const chain = await cfg._buildChain(allConfigs);
17492
+ return [cfg.id, resolveChain(chain, environment)];
17493
+ })
17494
+ ).then((entries) => ({ entries, newStore }));
17495
+ }).then(({ entries, newStore }) => {
17496
+ const newCache = {};
17497
+ for (const [id, values] of entries) newCache[id] = values;
17498
+ const oldCache = this._configCache;
17499
+ this._configCache = newCache;
17500
+ this._configStore = newStore;
17501
+ this._diffAndFire(oldCache, newCache, "websocket");
17461
17502
  }).catch((err) => {
17462
17503
  debug(
17463
17504
  "websocket",
@@ -17465,6 +17506,20 @@ var ConfigClient = class {
17465
17506
  );
17466
17507
  });
17467
17508
  };
17509
+ /** Fetch a single config by key. Returns null if not found. @internal */
17510
+ async _fetchSingleConfig(key) {
17511
+ debug("api", `GET /api/v1/configs/${key}`);
17512
+ try {
17513
+ const result = await this._http.GET("/api/v1/configs/{id}", {
17514
+ params: { path: { id: key } }
17515
+ });
17516
+ if (!result.response.ok) return null;
17517
+ if (!result.data?.data) return null;
17518
+ return resourceToConfig(result.data.data);
17519
+ } catch {
17520
+ return null;
17521
+ }
17522
+ }
17468
17523
  _handleConfigDeleted = (data) => {
17469
17524
  debug("websocket", `config_deleted event received: ${JSON.stringify(data)}`);
17470
17525
  const configKey = data.id;
@@ -17483,27 +17538,6 @@ var ConfigClient = class {
17483
17538
  // ------------------------------------------------------------------
17484
17539
  // Internal: change detection
17485
17540
  // ------------------------------------------------------------------
17486
- /** Fetch a single config by key. Returns null if not found. @internal */
17487
- async _fetchSingleConfig(key) {
17488
- debug("api", `GET /api/v1/configs/${key}`);
17489
- try {
17490
- const result = await this._http.GET("/api/v1/configs/{id}", {
17491
- params: { path: { id: key } }
17492
- });
17493
- if (!result.response.ok) return null;
17494
- if (!result.data?.data) return null;
17495
- return resourceToConfig(result.data.data);
17496
- } catch {
17497
- return null;
17498
- }
17499
- }
17500
- /** Resolve a config's values for an environment (no parent chain). @internal */
17501
- _resolveConfigValues(config, environment) {
17502
- const base = config.items ?? {};
17503
- const envEntry = config.environments?.[environment];
17504
- if (!envEntry?.values) return { ...base };
17505
- return { ...base, ...envEntry.values };
17506
- }
17507
17541
  /** @internal */
17508
17542
  _diffAndFire(oldCache, newCache, source) {
17509
17543
  const allConfigKeys = /* @__PURE__ */ new Set([...Object.keys(oldCache), ...Object.keys(newCache)]);